Professional Documents
Culture Documents
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
v1.0.1
1. Preface
2. The Structure Of A Makefile
3. Order Of Compilation
4. Starting Small - A Single-Source Makefile Example
5. Getting Bigger - A Multi-Source Makefile Example
6. Using Compiler And Linker Flags
7. A Rule For Everyone - Using "File Type" Rules
8. 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.
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 10/14/2004
PDF created with pdfFactory trial version www.softwarelabs.com
Automating Program Compilation - Writing Makefiles Page 2 of 7
l Dependency Rules - these lines define under what conditions a given file (or a type of file) needs
to be re-compiled, and how to compile it. For example:
main.o: main.c
gcc -g -Wall -c main.c
This rule means that "main.o" has to be recompiled whenever "main.c" is modified. The rule
continues to tell us that in order to compile "main.o", the command "gcc -g -Wall -c main.c"
needs to be executed.
Note that each line in the commands list must begin with a TAB character. "make" is quite picky
about the makefile's syntax.
l Comments - Any line beginning with a "#" sign, or any line that contains only white-space.
Order Of Compilation
When a makefile is executed, we tell the make command to compile a specific target. A target is just
some name that appears at the beginning of a rule. It can be a name of a file to create, or just a name that
is used as a starting point (such a target is also called a "phony" target).
When make Is invoked, it first evaluates all variable assignments, from top to bottom, and when it
encounters a rule "A" whose target matches the given target (or the first rule, if no target was supplied),
it tries to evaluate this rule. First, it tries to recursively handle the dependencies that appear in the rule. If
a given dependency has no matching rule, but there is a file in the disk with this name, the dependency
is assumed to be up-to-date. After all the dependencies were checked, and any of them required
handling, or refers to a file newer than the target, the command list for rule "A" is executed, one
command at a time.
This might appear a little complex, but the example in the next section will make things clear.
http://users.actcom.co.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.html 10/14/2004
PDF created with pdfFactory trial version www.softwarelabs.com
Automating Program Compilation - Writing Makefiles Page 3 of 7
1. Not all rules have to be used in every invocation of make. The "clean" rule, for example, is not
normally used when building the program, but it may be used to remove the object files created, to
save disk space.
2. A rule doesn't need to have any dependencies. This means if we tell make to handle its target, it
will always execute its commands list, as in the "clean" rule above.
3. A rule doesn't need to have any commands. For example, the "all" rule is just used to invoke other
rules, but does not need any commands of its own. It is just convenient to make sure that if
someone runs make without a target name, this rule will get executed, due to being the first rule
encountered.
4. We used the full path to the "rm" command, instead of just typing "rm", because many users have
this command aliased to something else (for example, "rm" aliased to "rm -i"). By using a full
path, we avoid any aliases.
http://users.actcom.co.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.html 10/14/2004
PDF created with pdfFactory trial version www.softwarelabs.com
Automating Program Compilation - Writing Makefiles Page 4 of 7
Few notes:
l There is one rule here for each source file. This causes some redundancy, but later on we'll see
how to get rid of it.
l We add dependency on included files (file1.h, file2.h) where applicable. If one of these interface-
definition files changes, the files that include it might need a re-compilation too. This is not
always true, but it is better to make a redundant compilation, than to have object files that are not
synchronized with the source code.
The solution to this problem is using variables to store various flags, and even command names. This is
especially useful when trying to compile the same source code with different compilers, or on different
platforms, where even a basic command such as "rm" might reside in a different directory on each
platform.
Lets see the same makefile, but this time with the introduction of variables:
http://users.actcom.co.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.html 10/14/2004
PDF created with pdfFactory trial version www.softwarelabs.com
Automating Program Compilation - Writing Makefiles Page 5 of 7
Few notes:
l We define many variables in this makefile. This will make it very easy to modify compile flags,
compiler used, etc. It is good practice to define even things that might seem like they'll never
change. In time - they will.
l We still have a problem with the fact that we define one rule for each source file. If we'll want to
change this rule's format, it will be rather tedious. The next section will show us how to avoid this
problem.
# we'll skip all the variable definitions, just take them from the previous
# makefile
.
.
# linking rule remains the same as before.
$(PROG): $(OBJS)
$(LD) $(LDFLAGS) $(OBJS) -o $(PROG)
1. The "%" character is a wildcard, that matches any part of a file's name. If we mention "%" several
times in a rule, they all must match the same value, for a given rule invocation. Thus, our rule here
means "A file with a '.o' suffix is dependent on a file with the same name, but a '.c' suffix".
2. The "$<" string refers to the dependency list that was matched by the rule (in our case - the full
name of the source file). There are other similar strings, such as "$@" which refers to the full
target name, or "$*", that refers the part that was matched by the "%" character.
http://users.actcom.co.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.html 10/14/2004
PDF created with pdfFactory trial version www.softwarelabs.com
Automating Program Compilation - Writing Makefiles Page 6 of 7
Now, if we run "make depend", the "makedepend" program will scan the given source files, create a
dependency list for each of them, and write appropriate rules to the file ".depend". Since this file is then
included by the makefile, when we'll compile the program itself, these dependencies will be checked
during program compilation.
There are many other ways to generate dependency lists. It is advised that programmers interested in this
issue read about the compiler's "-M" flag, and read the manual page of "makedepend" carefully. Also
note that gnu make's info pages suggest a different way of making dependency lists created
automatically when compiling a program. The advantage is that the dependency list never gets out of
date. The disadvantage is that many times it is being run for no reason, thus slowing down the
compilation phase. Only experimenting will show you exactly when to use each approach.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
The material in this document is provided AS IS, without any expressed or implied warranty, or claim of
fitness for a particular purpose. Neither the author nor any contributers shell be liable for any damages
incured directly or indirectly by using the material contained in this document.
permission to copy this document (electronically or on paper, for personal or organization internal use)
or publish it on-line is hereby granted, provided that the document is copied as-is, this copyright notice
is preserved, and a link to the original document is written in the document's body, or in the page linking
http://users.actcom.co.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.html 10/14/2004
PDF created with pdfFactory trial version www.softwarelabs.com
Automating Program Compilation - Writing Makefiles Page 7 of 7
Permission to make translations of this document is also granted, under these terms - assuming the
translation preserves the meaning of the text, the copyright notice is preserved as-is, and a link to the
original document is written in the document's body, or in the page linking to the copy of this document.
For any questions about the document and its license, please contact the author.
http://users.actcom.co.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.html 10/14/2004
PDF created with pdfFactory trial version www.softwarelabs.com