From: http://www.linuxdevcenter.com/pub/a/linux/2002/01/31/make_intro.html?page=1
--------------------------------------------------------------------------------------------------------------------------------
Make originated as a system for building compiled code. It is now used as a system for making changes across many files and directories. It is useful whenever a change in one file requires changes or actions elsewhere.
Make is useful for system administrators as well as developers. This article primarily discusses Make as a compilation tool, but it can be effective for program installation or system configuration changes.
Running Make
Make requires a configuration file. Once this file is constructed for your project, you usually type make
to build the changed files.
The usual name for this file is Makefile
; the capitalization lists the makefile with README
and other special files.
When run with no arguments, GNU Make looks for the configuration files named GNUmakefile
, Makefile
, and makefile
in the current working directory. If using other names, call Make with make -f filename
.
The makefile in this example displays make complete
and does nothing else. By default, Make lists the commands it runs. To have it run quietly, call Make with make -s
.
$ls
makefile renamed_makefile
$make
echo make complete
make complete
$make -f renamed_makefile
echo make complete
make complete
$make -s
make complete
Simple Makefiles
The examples in this article are written for C, and produce the sample
target file. Make can produce any target file, use any shell commands, and work from any source files. Make works best with languages where the compiler does not itself try to resolve dependencies.
Experienced users of Make will see redundant lines in the example makefile. Make already knows how to compile some types of files, and the rules for those files can be left out. (These are called implicit rules
.) For clarity, the examples show these rules.
# Linking object files
sample: main.o example.o
cc -o sample main.o example.o
echo sample: make complete
# Compiling source files
main.o: main.c main.h
cc -c main.c
example.o: example.c defs.h
cc -c example.c
A Make rule is composed of:
target: prerequisites
commands
A target is considered "up to date" if it exists and is newer than its prerequisites.
Make works backwards, starting with the target of the first rule in the file. In our example, that's sample
. Make checks the prerequisites for sample -- main.o
and example.o
-- to see if they have rules. If they do, it recursively checks their rules.
Make walks down the recursion chain until it finds a target that has no prerequisites, or whose prerequisites have no rules. Once it hits one of those, it walks back up its recursion chain and runs commands as necessary. It creates a recursion chain for every prerequisite it encounters that has a rule.
Once all of the prerequisite rules have been run, it eventually returns to sample
's rule. If the file doesn't exist, or is older than its prerequisites now are (after their rules have been recursively tested), it runs the commands to generate sample
.
In the example makefile, Make:
- Runs the first rule it sees --
sample
. - Checks to see whether
sample
's prerequisites have rules. They do. - Runs the rule for the first prerequisite --
main.o
. - Checks to see whether
main.o
's prerequisites have rules. They don't. - Checks whether
main.o
is up to date. If not, it runs the commands formain.o
. - Runs the rule for the second prerequisite --
example.o
. - Checks to see whether
example.o
's prerequisites have rules. They don't. - Checks whether or not
example.o
is up to date. If not, it runs the commands forexample.o
. - Returns to
sample
's rule - Checks whether or not
sample
is up to date. If not, it runs the commands to update it.
Make can run the prerequisites in any order. The important part of this sequence is that it runs recursively backwards from the first target (or the target named in the command parameters), and tests only the rules that it encounters in the prerequisites chain.
Make aborts compilation if it receives an error. This is usually useful behavior -- it lets you correct compiler-detected problems during a compile-and-test cycle. The option -i
tells Make to ignore errors.
Phony Targets
In software development, it's very convenient to create a script to remove old compiled code so that the next build recompiles everything. It's also convenient to have a script for installing the code. Make allows scripts like this to be included in the makefile, as phony targets. Phony targets may have prerequisites, and may themselves be prerequisites.
special rule .PHONY
tells Make which targets are not files. This avoids conflict with files of the same name, and improves performance.
If a phony target is included as a prerequisite for another target, it will be run every time that other target is required. Phony targets are never up-to-date.
To run a phony target from the command line, call Make with the name of the phony target, e.g.: make clean
.
# Naming our phony targets
.PHONY: clean install
# Removing the executable and the object files
clean:
rm sample main.o example.o
echo clean: make complete
# Installing the final product
install:
cp sample /usr/local
echo install: make complete
Makefile Variables
As a project gets larger, more files are usually added. If you repeat a list of files, you can accidentally leave files out of the list. It's simpler to make use of a variable that expands into the list.
The syntax for declaring and setting a makefile variable is varname = variable contents
. To call the variable, use $(varname)
.
# Defining the object files
objects = main.o example.o
# Linking object files
sample: $(objects)
cc -o sample $(objects)
echo sample: make complete
# Compiling source files
main.o: main.c main.h
cc -c main.c
example.o: example.c defs.h
cc -c example.c
# Removing the executable and the object files
clean:
rm sample $(objects)
echo clean: make complete
Final Touches
There are a few touches which make the difference between a usable and a professional makefile. The next example adds those extra touches.
# 1
# Defining the compiler:
CC=gcc
# Defining the object files:
objects = main.o example.o
# 2
# The default rule - compiling our main program:
all: sample
echo all: make complete
# 3
sample: $(objects)
# If we get here, all the dependencies are now built.
# Link it:
$(CC) -o $@ $+
# 4
# Tell make how to build .o files from .c files:
%.o:%.c
$(CC) -c $+
# 5
#Now make sure that make rebuilds files if included headers change:
main.o: main.h defs.h
example.o: example.h defs.h
-
Use a variable for the compiler, in case you want to use the same makefile with a different compiler.
-
When called without a rule parameter, Make runs the first rule it encounters. It is more human-readable to explicitly state your first rule.
all
is a common name for a first rule. -
The automatic variable
$@
means "the name of the target." The automatic variable$+
means "all prerequisites, space-separated." Automatic variables are pre-defined in Make. -
A pattern rule tells make how to convert the prerequisite to the target. The
%
in the pattern means "one or more characters," and refers to the same string in the prerequisite and the target. This particular pattern tells make how to convert a*.c
file to a*.o
file of the same name.The automatic variable
$+
means "all prerequisites, space-separated." -
These rules are relying on "implicit rules." Make has built-in patterns for converting a
*.h
file to the dependent*.o
. These rules are included to define the prerequisites for the relevant*.o
files.
Caveats and Gotchas
- This article is written about GNU Make. Other Unix systems use different versions of Make, which may have minor variations.
- Make rules require a tab at the beginning of each command. A series of spaces doesn't work.
- Make works backwards from the target to the prerequisites.
Final Words
Make has many features I haven't mentioned, and is useful in any situation where a file is dependent on files that may change. Experiment, and develop your own interesting variations on makefiles.
Further Reading
man make
info make
- The University of Utah's document on makefile conventions, at http://www.math.utah.edu/docs/info/make-stds_toc.html
- The University of Hawaii's makefile tutorial
- Run a Web search with the keyword "makefile."
留言列表