Penguin
Diff: MakefileHowto
EditPageHistoryDiffInfoLikePages

Differences between version 62 and predecessor to the previous major change of MakefileHowto.

Other diffs: Previous Revision, Previous Author, or view the Annotated Edit History

Newer page: version 62 Last edited on Thursday, November 10, 2005 2:24:49 pm by IanMcDonald Revert
Older page: version 58 Last edited on Thursday, January 13, 2005 2:34:59 pm by AristotlePagaltzis Revert
@@ -1,11 +1,4 @@
-!![PerryLorier]'s Introduction to Makefiles  
-(edited by CraigBox and later SamJansen)  
-  
-Note: a lot of people are finding this page thanks to Google. Remember, this is a wiki! If you have something you want to add or change, just click the Edit button at the bottom of the page, enter a valid WikiWord (YourName is a good bet) as a user ID (no password required) and go for it. If this page doesn't answer your question, PLEASE add your question to the bottom of the page and we'll try hard to answer it.  
-  
------  
-  
 __Makefiles are easy.__ In fact, to build a simple program that doesn't depend on any libraries, you don't even need a makefile. make(1) is smart enough to figure it all out itself. For instance, if you have a file "foo.c" in the current directory: 
  
  $ ls 
  foo.c 
@@ -33,8 +26,10 @@
  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. 
+  
+You can get your Makefiles made automatigically for you using AutoTools.  
 ----- 
 !!Dynamic updating 
  
 Occasionally you might want to specify something special to happen, for a specific file. This can be done by providing some rules to build that target. This is done indented, on the next line after the dependancies are listed. Our sample make file again: 
@@ -54,9 +49,10 @@
  cc -c -o foo.o foo.c 
  cc foo.o bar.o -o program 
  
 ----- 
-!!Phony targets 
+  
+ !! Phony targets 
  
 You can have "phony" targets -- targets which don't actually create a file, but do something. These are created like normal targets: for instance, to add a "all" target to our makefile we'd add (probably at the top, so it becomes the default target): 
  
  all: foo 
@@ -74,24 +70,25 @@
  
  .PHONY: all clean 
  
 ----- 
-!!Selective building 
+  
+ !! Selective building 
  
 Why use a makefile, instead of a script to rebuild everything from scratch? 
  
 If you have a rule that reads 
  
  objectfile.o: foo.c foo.h bar.c bar.h Makefile 
  
-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. 
+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. 
  
 Or, you could have make determine all your header file dependencies for you! If foo.h #includes bar.h, and bar.h #includes another.h, which #includes etc.h, it could very quickly become difficult to keep track of it all. Not to mention it may result in huge dependency lines! Instead, you can have a header file as a target and list its #included files as its dependencies. Then use the 'touch' command to update the timestamp. For example, if foo.c #includes foo.h, and both foo.h and bar.c #include bar.h, we could use this Makefile: 
  
  executable: foo.o bar.o 
- gcc foo.o bar.o -o executable 
+ $(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 
@@ -103,9 +100,10 @@
  
 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 
+  
+ !! 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. 
  
 Example Makefile: 
@@ -128,11 +126,13 @@
  rm -rf Documentation 
  
  
 ----- 
-!!Rules 
+  
+ !! Rules 
  
 The real power from makefiles comes when you want to add your own "rules" for files. If we have a program called "snozzle" that takes a ".snoz" file and produces a ".c" file we can add: 
+  
  %.c: %.snoz 
  snozzle $< -o $@ 
  
 $< expands to the first dependancy, and $@ the target. So, if foo.c is built from foo.snoz we can now: 
@@ -149,9 +149,10 @@
  
 Note that foo.c is removed by make at the end -- make(1) removes intermediate files itself when it's done. Smart, eh? 
  
 ----- 
-!!Environment variables  
+  
+ !! EnvironmentVariable~s  
  
 The only other major thing left to mention about Make is environmental variables. It uses $(''variable'') as an expando. thus the rule: 
  
  %c: %.snoz 
@@ -191,19 +192,24 @@
  
 If you specify your own command line you will have to explicitly include these variables in it. 
  
 You can also check if an environment variable has been set and initialise it to something if it has not. ie. 
+  
  DESTDIR ?= /usr/local 
+  
 will set DESTDIR to /usr/local if it is not already defined 
  
 To append to the environment variables use the += operator: 
  
  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 
+  
+ !! An example makefile 
  
  1: CXXFLAGS=-g 
  2: 
  3: sim: car.o road.o sim.o event.o 
@@ -221,9 +227,10 @@
 * Line 4 is indented; because we want to add extra smarts to the compiling of sim (we want to link to the math library libm.a); so when 'make sim' is executed and the .o's are up to date, that line will be executed. 
 * 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. 
  
 ---- 
-!!Functions 
+  
+ !! Functions 
  
 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). 
  
 Perhaps you want to find all the .c files in directory for later use: 
@@ -285,24 +292,33 @@
  
 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. 
  
 If you are on an [OS] such as [FreeBSD] you might need to invoke 'gmake' for a GNU compatible make. 
+  
+Shell variables in Makefiles  
+  
+There may come a time you need to use shell scripting complicated enough to require shell vars in a Makefile but make has issues since $ is the prefix for Make vars too, to escape the $, just use $$, so this:  
+ for e in * ; do echo $e ; done  
+becomes:  
+ for e in * ; do echo $$e ; done  
+It's a simple change but I didn't see it written anywhere obvious :)  
  
 ---- 
 See Also: 
 * MakefileVariables 
 * [Recursive Makefile considered harmful (PDF) | http://aegis.sourceforge.net/auug97.pdf] 
-  
  
 ---- 
-!!Requests 
+  
+ !! Requests 
  
 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 
  
 Dear Someone, 
 Take a look at [the make manual | http://www.gnu.org/software/make/manual/html_chapter/make.html], especially [section 4.14 | http://www.gnu.org/software/make/manual/html_chapter/make_4.html#SEC51]. Basically 'make depend' is not really needed anymore. 
  
 ---- 
+  
 I cannot find info about the meaning of '@AMDEP_TRUE@' variables in a Makefile. At the moment i get the error: 
  make: AMDEP_TRUE@: Kommando nicht gefunden 
  make: *** [[arandom.lo] Fehler 127 
 thx, !FlorianKonnertz