Automating Program Compilation - Writing Makefiles

Page 1 of 7

[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]

v1.0.1

Automating Program Compilation - Writing Makefiles
Table Of Contents: 1. 2. 3. 4. 5. 6. 7. 8. Preface The Structure Of A Makefile Order Of Compilation Starting Small - A Single-Source Makefile Example Getting Bigger - A Multi-Source Makefile Example Using Compiler And Linker Flags A Rule For Everyone - Using "File Type" Rules Automatic Creation Of Dependencies

Preface
Compiling a program made of one source file is easy. Compiling one made of few sources is slightly annoying, but may be automated via a simple shell script. Anything larger than that would start to get on your nerves. This is where makefiles are helpful. A makefile is a collection of instructions that should be used to compile your program. Once you modify some source files, and type the command "make" (or "gmake" if using GNU's make), your program will be recompiled using as few compilation commands as possible. Only the files you modified and those dependent upon them will be recompiled. Of-course, this is not done via usage of magic. You need to supply the rules for compiling various files and file types, and the list of dependencies between files (if file "A" was changed, then files "B", "C" and "D" also need to be re-compiled), but that only has to be done once.

The Structure Of A Makefile
A typical makefile contains lines of the following types:
l

Variable Definitions - these lines define values for variables. For example:
CFLAGS = -g -Wall

http://users.actcom.co.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.html PDF created with pdfFactory trial version www.softwarelabs.com

10/14/2004

but the example in the next section will make things clear. This might appear a little complex.c file1. or just a name that is used as a starting point (such a target is also called a "phony" target). and any of them required handling. or refers to a file newer than the target. the command "gcc -g -Wall -c main.o: main.o". it tries to recursively handle the dependencies that appear in the rule. If a given dependency has no matching rule.these lines define under what conditions a given file (or a type of file) needs to be re-compiled.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles. When make Is invoked. "make" is quite picky about the makefile's syntax.c" needs to be executed. After all the dependencies were checked.co. we tell the make command to compile a specific target. the dependency is assumed to be up-to-date.Writing Makefiles SRCS = main. For example: main.c gcc -g -Wall -c main. The rule continues to tell us that in order to compile "main.o" has to be recompiled whenever "main. l Comments . or any line that contains only white-space.com 10/14/2004 . but there is a file in the disk with this name. if no target was supplied).c file2. and when it encounters a rule "A" whose target matches the given target (or the first rule.Any line beginning with a "#" sign.A Single-Source Makefile Example Lets first see a simple example of a makefile that is used to compile a program made of a single source file: # top-level rule to create the program. from top to bottom.html PDF created with pdfFactory trial version www.actcom. It can be a name of a file to create. First. A target is just some name that appears at the beginning of a rule. it first evaluates all variable assignments. Starting Small .Automating Program Compilation . Note that each line in the commands list must begin with a TAB character. and how to compile it. the command list for rule "A" is executed.c CC = gcc Page 2 of 7 l Dependency Rules .c" is modified. Order Of Compilation When a makefile is executed.softwarelabs. it tries to evaluate this rule.c This rule means that "main. all: main http://users. one command at a time.

We used the full path to the "rm" command. as in the "clean" rule above. This is where using a makefile starts to pay off.h file2. to save disk space.softwarelabs. all: prog # program is made of several source files. Here is an example of such a makefile: # top-level rule to compile the whole program.com 10/14/2004 . main: main.c # rule for file "file2.c gcc -g -Wall -c main. instead of just typing "rm".il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles. and then re-linking the program.o: main.o". The "clean" rule.o file1. because many users have this command aliased to something else (for example.c http://users. file2.h gcc -g -Wall -c file2. For example.co.o".A Multi-Source Makefile Example In anything but the simplest programs. we usually have more than one source file.o gcc main.h gcc -g -Wall -c file1. By using a full path.o file2. it will always execute its commands list.o gcc -g main.c # linking the program. Making a change to one file requires re-compilation of only the modified file.h gcc -g -Wall -c main. Not all rules have to be used in every invocation of make.o: file1.o: file2. 3.o file1. This means if we tell make to handle its target.o -o main # cleaning everything that can be automatically recreated with "make". It is just convenient to make sure that if someone runs make without a target name. the "all" rule is just used to invoke other rules.o -o prog # rule for file "main. due to being the first rule encountered.Writing Makefiles # compiling the source file. A rule doesn't need to have any commands. main. for example. but it may be used to remove the object files created. 4.Automating Program Compilation . main. A rule doesn't need to have any dependencies. we avoid any aliases.c file1.c # rule for file "file1.o".o: main.o Page 3 of 7 Few notes about this makefile: 1.html PDF created with pdfFactory trial version www.c file1. "rm" aliased to "rm -i").c file2.o file2. but does not need any commands of its own.actcom. is not normally used when building the program. 2. prog: main. file1. Getting Bigger . this rule will get executed. clean: /bin/rm -f main main.

Currently there aren't any.Writing Makefiles # rule for cleaning files generated during compilations. than to have object files that are not synchronized with the source code. and even command names. LD = gcc # Compiler flags go here. This causes some redundancy. We add dependency on included files (file1. where even a basic command such as "rm" might reside in a different directory on each platform. Using Compiler And Linker Flags As one could see. to use optimization (-O). all: $(PROG) # rule to link the program $(PROG): $(OBJS) $(LD) $(LDFLAGS) $(OBJS) -o $(PROG) # rule for file "main. but this time with the introduction of variables: # use "gcc" to compile source files. file2. http://users. RM = /bin/rm -f # list of generated object files. It might be something else with other compilers.Automating Program Compilation .co. This might not look like much work with 3 source files. possibly spread over few directories.com 10/14/2004 . but if we'll switch to # code optimization. CC = gcc # the linker is also "gcc". or on different platforms.o # program executable file name. Lets see the same makefile.o file2.o". This is not always true. LDFLAGS = # use this command to erase files. OBJS = main. clean: /bin/rm -f prog main.h. but it will be tedious when we have few tens of files.o file1. If one of these interfacedefinition files changes.h) where applicable. but it is better to make a redundant compilation. there are many repetitive patterns in the rules for our makefile. to compile everything. PROG = prog # top-level rule. the files that include it might need a re-compilation too. This is especially useful when trying to compile the same source code with different compilers.o Page 4 of 7 Few notes: l l There is one rule here for each source file.softwarelabs.html PDF created with pdfFactory trial version www.actcom. we might add "-s" here to strip debug info and symbols. For example.o file2. CFLAGS = -g -Wall # Linker flags go here.o file1. instead of add debug info (-g)? we would need to go and change this flag for each rule. but later on we'll see how to get rid of it.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles. The solution to this problem is using variables to store various flags. what if we wanted to change the flags for compilation.

softwarelabs. A Rule For Everyone . for a given rule invocation.c file1.c file2. they are all compiled in the same way.h file2. In time . If we mention "%" several times in a rule.co. It is good practice to define even things that might seem like they'll never change.c # rule for cleaning re-compilable files.h $(CC) $(CFLAGS) -c file1.h $(CC) $(CFLAGS) -c main.html PDF created with pdfFactory trial version www. There are other similar strings. it will be rather tedious. file1. that matches any part of a file's name. our rule here means "A file with a '. # linking rule remains the same as before. $(PROG): $(OBJS) $(LD) $(LDFLAGS) $(OBJS) -o $(PROG) # now comes a meta-rule for compiling any "C" source file.o: %.o: main.o". but a '.c # rule for file "file1. . compiler used.the full name of the source file). This will make it very easy to modify compile flags. After all. The "%" character is a wildcard. We still have a problem with the fact that we define one rule for each source file. The next section will show us how to avoid this problem.h $(CC) $(CFLAGS) -c file2. the next phase would be to eliminate the redundant rules. just take them from the previous # makefile . file2. 2. clean: $(RM) $(PROG) $(OBJS) Page 5 of 7 Few notes: l l We define many variables in this makefile.actcom. that refers the part that was matched by the "%" character.com 10/14/2004 .o: file2.Using "File Type" Rules So. %. and try to use one rule for all source files. http://users.they will. Thus.c' suffix".o' suffix is dependent on a file with the same name. etc. Here is a modified makefile: # we'll skip all the variable definitions.o".Automating Program Compilation .c file1. they all must match the same value. or "$*".c $(CC) $(CFLAGS) -c $< We should explain two things about our meta-rule: 1.Writing Makefiles main.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.c # rule for file "file2. The "$<" string refers to the dependency list that was matched by the rule (in our case .o: file1. If we'll want to change this rule's format. such as "$@" which refers to the full target name.

c . or be automated in one of various ways. SRCS = main.depend makedepend -f. It is advised that programmers interested in this issue read about the compiler's "-M" flag. and a link to the original document is written in the document's body. without any expressed or implied warranty.depend Now.-. or claim of fitness for a particular purpose. when we'll compile the program itself. depend: $(RM) . This can be overcome by using extra rules for each file. The material in this document is provided AS IS.softwarelabs.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.com 10/14/2004 . This can be added manually.depend".Automating Program Compilation . # define the list of source files. thus slowing down the compilation phase. include . the "makedepend" program will scan the given source files. we add these lines: # rule for building dependency lists. that only contain dependencies. [LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments] This document is copyright (c) 1998-2002 by guy keren. or in the page linking http://users.co. There are many other ways to generate dependency lists. Neither the author nor any contributers shell be liable for any damages incured directly or indirectly by using the material contained in this document. provided that the document is copied as-is.c file1. The advantage is that the dependency list never gets out of date. Also note that gnu make's info pages suggest a different way of making dependency lists created automatically when compiling a program. # at the bottom.$(CFLAGS) -. and writing them to a file # named ". is that we lost the full list of dependencies. using the "makedepend" Unix program. # most of the makefile remains as it was before. and write appropriate rules to the file ". create a dependency list for each of them.c file2.$(SRCS) > .actcom. Here is one example.Writing Makefiles Page 6 of 7 Automatic Creation Of Dependencies One problem with the usage of implicit rules. these dependencies will be checked during program compilation.depend". and read the manual page of "makedepend" carefully. that are unique to each file. but no commands. this copyright notice is preserved. if we run "make depend". .depend # now add a line to include the dependency list. for personal or organization internal use) or publish it on-line is hereby granted.html PDF created with pdfFactory trial version www. The disadvantage is that many times it is being run for no reason. Since this file is then included by the makefile. permission to copy this document (electronically or on paper. Only experimenting will show you exactly when to use each approach.

the copyright notice is preserved as-is.html PDF created with pdfFactory trial version www. or in the page linking to the copy of this document.co. please contact the author.Automating Program Compilation . and a link to the original document is written in the document's body. For any questions about the document and its license.Writing Makefiles to the copy of this document.softwarelabs.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.com 10/14/2004 .actcom.assuming the translation preserves the meaning of the text. http://users. Page 7 of 7 Permission to make translations of this document is also granted. under these terms .

Sign up to vote on this title
UsefulNot useful