Here is a brief instruction of Makefile. Thanks the author.
$ ls foo.c $ make foo cc foo.c -o foo
make(1) will detect the type of file and compile it for you, automatically naming the executable the same as the input file (gcc(1) foo.c will give you a file called a.out unless you manually specify a name for it). If you need libraries, you can specify them by setting the LDFLAGS variable on the command line.
program: foo.o bar.o
$ make target
$ ls Makefile foo.c bar.c $ make cc bar.c -c -o bar.o cc foo.c -c -o foo.o cc foo.o bar.o -o program
See the CompilingHowto for more info on the steps required to turn source code into an executable.
program: foo.o bar.o bar.c: echo 'char *builddate="' `date` '";' >bar.c
Note that the line that begins "echo" must be indented by one tab. If this isn't done make(1) will abort with a weird error message like "Missing delimiter". The echo line makes a one line C file with a variable called "builddate", set to the current date and time. This is a useful thing to do for your program if you wanted to know when this particular version was compiled. (Not that this is the only way, or in fact the best way to get this information, but it's a good example.)
$ make echo 'char *builddate="' `date` '"' >bar.c cc -c -o bar.o bar.c cc -c -o foo.o foo.c cc foo.o bar.o -o program
clean: rm -f bar.o bar.c foo.o foo.c
.PHONY: all clean
Why use a makefile, instead of a script to rebuild everything from scratch?
objectfile.o: foo.c foo.h bar.c bar.h Makefile
then make(1) will check the last modification date of objectfile.o against the last modification date of all the files that follow it (foo.c, foo.h, bar.c, bar.h and the Makefile itself). If none of these things have changed, then it won't recompile objectfile.o.
Build lines like this with careful reference to #includes in your source - if your foo.h #includes bar.h, it has to be on the Makefile line - otherwise, changes to bar.h won't cause a recompile of objectfile.o and you might get confused as to why your constants aren't what you thought they should be.
executable: foo.o bar.o $(CC) foo.o bar.o -o executable foo.o: foo.c foo.h Makefile bar.o: bar.c bar.h Makefile foo.h: bar.h touch foo.h bar.h:
So if you edit bar.h to change some constants or function definitions, Make will see that foo.h needs to be updated and 'touch' it. Then it will know it must also update foo.o in (in addition to bar.o) since foo.h appears new. This way each target only lists files that it is directly dependent on. Let make figure out the rest -- that's what it's supposed to do!
Or you could decide that mindless drone work is a waste of time and just use makedepend to spare yourself the hassle. --AristotlePagaltzis
You should consider that using this touch could affect the configuration management system you are using (e.g. RCS or CVS), if it goes by the timestamp to determine the need to commit/checkin: you might suddenly have lots of files to commit, or lots of files locked! At the very least the new timestamp will confuse your friends and confound your enemies. However, makedepends can generate an unreadable and therefore unmaintainable monstrosity, partly because it cites every system dependency (e.g. stdio), and also as it recurses through the subdep files it cites each reference to stdio by the subdeps as if it were a separate dependency. So, depending on the size of your project, and how often you have to make major adjustments by hand to the makefiles, and how many headers each file uses, you may want to decide whether or not to use this touch method (which would indeed keep the dependencies nicely hierarchical), or use makedepends. To have it both ways, I believe you could precede the touch with "cp -p foo.h foo.h_preserveDate; touch foo.h" and then under the foo.o dependency you could after the compile then do "cc foo.c; mv foo.h_preserveDate foo.h" which would preserve the original date on the foo.h checked-out file. This would still keep the hierarchical nature, which is quite valuable because it eliminates redundancy in separate places (two distant places to maintain one fact is very bad). -- LindaBrock
Makefiles in subdirectories
With larger projects you often have subdirectories with their own Makefile. To allow make to run these Makefiles with the options passed to make use the $(MAKE) variable. This variable actually callse a second make process to make the Makefile in the subdirectory. To specify the Makefile's subdirectory use the -C option of make.
all: Documentation/latex/refman.pdf install: Documentation/latex/refman.pdf cp Documentation/latex/refman.pdf Documentation/!KeithleyMeter.pdf Documentation: Doxyfile Makefile src/keithleyMeter.cc hdr/keithleyMeter.h # Dosen't use all the options you passed to make make clean # make the Documentation folder /Applications/Doxygen.app/Contents/Resources/doxygen Documentation/latex/refman.pdf: Documentation # Uses the options you passed to make $(MAKE) -C Documentation/latex clean: rm -rf Documentation
For a counter-argument against having separate make processes for sub-directories (and instead using makefile fragments but only one make process), see Recursive Makefile considered harmful (PDF)
%.c: %.snoz snozzle $< -o [email protected]
$ ls Makefile foo.snoz $ make snozzle foo.snoz -o foo.c cc -c -o foo.o foo.c echo 'char *builddate="' `date` '"' >bar.c cc -c -o bar.o bar.c cc foo.o bar.o -o foo rm foo.c
Note that foo.c is removed by make at the end -- make(1) removes intermediate files itself when it's done. Smart, eh?
%c: %.snoz snozzle $(SNOZFLAGS) $<
would let you specify the arguments to snozzle. This is useful if you call snozzle in multiple places, but want to be able to make one change to update the flags.
CFLAGS=-g -Wall SNOZFLAGS=--with-extra-xyzzy all: program clean: rm -f foo.c foo.o bar.c bar.o .PHONY: clean all program: foo.o bar.o bar.c: echo 'char *builddate="' `date` '";' >bar.c %.c: %.snoz snozzle $(SNOZFLAGS) $< -o [email protected]
- ASFLAGS command line flags to as
If you specify your own command line you will have to explicitly include these variables in it.
DESTDIR ?= /usr/local
will set DESTDIR to /usr/local if it is not already defined
CFLAGS += -g -Wall
This allows the user to specify system specific optimizations in their shell environment.
Note : As you may have noticed, make uses $ to identify variables - both environment and defined in the file. To put a literal $ in a makefile, use $$. However, bash also uses $ to identify variables, and will consume the $ when it is passed to whatever program you're running. To therefore pass a literal $ to a program you must use \$$ - note the single \, not double. - OrionEdwards
An example makefile
1: CXXFLAGS=-g 2: 3: sim: car.o road.o sim.o event.o 4: g++ $(LDFLAGS) sim.o car.o road.o event.o -lm -o sim 5: 6: car.o: car.cc car.h sim.h event.h road.h Makefile 7: sim.o: sim.cc sim.h car.h road.h event.h Makefile 8: road.o: road.cc road.h sim.h event.h car.h Makefile 9: event.o: event.cc event.h sim.h Makefile
- Lines 6-9 are targets for the various object files that will be generated. They say that car.o is built from car.cc, car.h etc. This probably means that car.h somewhere #include's event.h, road.h... Every time you run 'make car.o', it will compare the last modification date on all the files listed against the modification date of car.o. If car.o is newer, it is up to date and no compiling is necessary. Otherwise, make will recompile everything it needs to.
It is possible to call some predefined functions in makefiles. A full list of them can be found in the manual, of course (http://www.gnu.org/software/make/manual/html_chapter/make_8.html#SEC83).
SOURCES := $(wildcard *.c)
OBJS := $(patsubst %.c, %.o, $(SOURCES))
LIBS := GL SDL stlport
in a later rule to add a -l prefix for every library mentioned in LIBS above.
DIRS := src obj headers FILES := $(foreach dir, $(DIRS), $(wildcard $(dir)/*))
Automatic dependency calculation
DEPS := $(patsubst %.o,%.d,$(OBJS))
deps: $(SOURCES) $(CC) -MD -E $(SOURCES) > /dev/null
'-E' tells gcc to stop after preprocessing. When using -E, the processed C file is sent to STDOUT. Therefore to avoid the mess on the screen, send it to /dev/null instead. Using this command all of the *.d files will be made.
deps: $(SOURCES) # the following line makes all of the .d files. $(CC) -MD -E $(SOURCES) > /dev/null
-include $(DEPS) # this includes everything in DEPS
make: Nothing to be done for install
This will tell make that the "install" target is a "phony" target, and doesn't actually refer to a file and should always be rebuilt.
Shell variables in Makefiles
for e in * ; do echo $e ; done
for e in * ; do echo $$e ; done
It's a simple change but I didn't see it written anywhere obvious :)
- http://www.gnu.org/software/make/manual/ - GNU make manual, warning this is huge.
I'd like to know something about makedepend and such things. Maybe some links to other or "official" make HOWTOs would be useful as well. Thanks. -- Someone
This isn't really anything to do with make. The autoconf/configure methods that many projects use take a template file (such as Makefile.in) and use that to create a makefile. autoconf uses things like @[email protected] for its variables, and should replace @[email protected] vars with something that makes sense to make. If you have a makefile that still has @[email protected] variables in it, then it's a bug and there is a bug in the package.
I have a question. I have a directory called src. Within this directory, a group publishes designs inside directories:
Release_010405 Release_010505 Release_010605 Release_032304 Release_082903
- If there is a file called baja.c inside one of these directories that is newer than baja.o, I want to compile. I was able to make a list of all the baja.c files within the Release directories using wildcard
- NEWSOURCES = $(wildcard Release_*/baja.c)
However, I don't know how to tell Make which is the latest file. The following grabs the first of the list.
You could try using $? which gives you the names of the prerequisites which are newer than the target. If there can be several of those and you only need the latest, though, you have to do it in the recipe, using shell tools. --AristotlePagaltzis