Make
1):The Makefile is often used not only to control the compilation of source code, but also to prepare manual pages and to install the application into a target directory.
2):The makefile is read by the make command, which determines the target file or files that are to be made and then compares the dates and times of the source files to decide which rules need to be invoked to construct the target.
3):The make program itself has several options. The three most commonly used are
❑ -k, which tells make to keep going when an error is found, rather than stopping as soon as the first problem is detected. You can use this, for example, to find out in one go which source files fail to compile.
❑ -n, which tells make to print out what it would have done without actually doing it.
❑ -f <filename> which allows you to tell make which file to use as its makefile. If you don’t use this option, the standard version of make looks first for a file called makefile in the current directory. If that doesn’t exist, it looks for a file called Makefile. However if you are using GNU Make, which you probably are on Linux, that version of make looks for GNUmakefile first, before searching for makefile and then Makefile. By convention, many Linux programmers use Makefile; this allows the makefile to appear first in a directory listing of a directory filled with lowercase-named files.
4):To tell make to build a particular target, which is usually an executable file, you can pass the target name to make as a parameter. If you don’t, make will try to make the first target listed in the makefile.
5):Many programmers specify all as the first target in their makefile and then list the other targets as being dependencies
for all. This convention makes it clear which target the makefile should attempt to build by default when no target is specified. We suggest you stick to this convention.
6):If you want to make several files, you can use the phony target all.
7):All rules must be on lines that start with a tab; a space won’t do.Also, a space at the end of a line in the makefile may cause a make command to fail.
8):The make command has read your makefile, determined the minimum number of commands required to rebuild myapp, and carried them out in the correct order.
9):You define a macro in a makefile by writing MACRONAME=value, then accessing the value of MACRONAME by writing either $(MACRONAME) or ${MACRONAME}.Some versions of make may also accept $MACRONAME. You can set the value of a macro to blank (which expands to nothing) by leaving the rest of the line after the = blank
10):Another problem with Makefile1 is that it assumes the compiler is called gcc. On other UNIX systems, you might be using cc or c89. If you ever wanted to take your makefile to a different version of UNIX,or even if you obtained a different compiler to use on your existing system, you would have to change several lines of your makefile to make it work.
11):Macros are normally defined inside the makefile itself, but they can be specified by calling make with the macro definition, for example, make CC=c89. Command-line definitions like this override defines in the makefile. When used outside makefiles, macro definitions must be passed as a single argument, so either avoid spaces or use quotes like this:make “CC = c89 “
12):In fact, make has several special internal macros that you can use to make makefiles even more succinct. We list the more common ones in the following table; Each of these macros is only expanded just before it’s used, so the meaning of the macro may vary as the makefile progresses. In fact, these macros would be of very little use if they didn’t work this way.
$? List of prerequisites (files the target depends on) changed more recently than the current target
$@ Name of the current target
$< Name of the current prerequisite
$* Name of the current prerequisite, without any suffix
13):There are two other useful special characters you may see in a makefile, preceding a command:
❑ - tells make to ignore any errors. For example, if you wanted to make a directory but wished to
ignore any errors, perhaps because the directory might already exist, you just precede mkdir
with a minus sign. You will see - in use a bit later in this chapter.
❑ @ tells make not to print the command to standard output before executing it. This character is
handy if you want to use echo to display some instructions.
14):
clean:
-rm main.o 2.o 3.o The rules for making the target “clean” don’t specify clean as depending on anything; the rest of the line after clean: is blank. Thus the target is always considered out of date, and its rule is always executed if clean is specified as a target
15):
install: myapp
@if [ -d $(INSTDIR) ]; \
then \
cp myapp $(INSTDIR);\
chmod a+x $(INSTDIR)/myapp;\
chmod og-w $(INSTDIR)/myapp;\
echo “Installed in $(INSTDIR)“;\
else \
echo “Sorry, $(INSTDIR) does not exist”;\
fi
The rules for making install consist of some shell script commands. Because make invokes a shell for executing rules and uses a new shell for each rule, you must add backslashes so that all the script commands are on one logical line and are all passed together to a single invocation of the shell for execution.
If it was very important that subsequent commands executed only if the previous one had succeeded, you could have
written the commands joined by &&
@if [ -d $(INSTDIR) ]; \
then \
cp myapp $(INSTDIR) &&\
chmod a+x $(INSTDIR)/myapp && \
chmod og-w $(INSTDIR/myapp && \
echo “Installed in $(INSTDIR)“ ;\
else \
echo “Sorry, $(INSTDIR) does not exist” ; false ; \
fi
16):In fact, make has a large number of built-in rules that can significantly simplify makefiles, particularly if you have many
source files.these built-in rules are referred to as inference rules. The default rules use macros, so by specifying some new values for the macros you can change the default behavior.You can ask make to print its built-in rules with the -p option.
17):The built-in rules that you’ve seen work by using suffixes (similar to Windows and MS-DOS filename extensions so that when it’s given a file with one ending, make knows which rule can be used to create a file with a different ending. The most common rule here is the one used to create a file ending in .o from a file ending in .c.
18):If the version of make being used with Linux at the time didn’t have a built-in rule for compiling .cpp files.So we needed to teach make a new rule for creating objects from files with the extension .cpp.The special dependency .cpp.o: tells make that the rules that follow are for translating from a file with a suffix of .cpp to a file with a suffix of .o.Notice that you tell make how to get only from a .cpp to a .o file; make already knows how to get from an object file to a binary executable file.
When you invoke make, it uses your new rule to get from bar.cpp to bar.o, then uses its built-in rules
to get from the .o to an executable file. The extra -xc++ flag is to tell gcc that this is a C++ source file.
.SUFFIXES: .cpp
.cpp.o:
$(CC) -xc++ $(CFLAGS) -I$(INCLUDE) -c $<
%.cpp: %.o
$(CC) -xc++ $(CFLAGS) -I$(INCLUDE) -c $<
19):Libraries are files, conventionally with the extension .a(for archive), that contain a collection of object files.The makecommand has a special syntax for dealing with libraries that makes them very easy to manage The syntax is lib(file.o) which means the object file file.o, as stored in the library lib.a. The make command has a built-in rule for managing libraries that is usually equivalent to something like this:
.c.a:
$(CC) -c $(CFLAGS) $<
$(AR) $(ARFLAGS) $@ $*.o
The macros $(AR) and $(ARFLAGS) normally default to the command arand the options rv, respectively. The rather terse syntax tells make that to get from a .c file to an .a library it must apply two rules:
❑ The first rule says that it must compile the source file and generate an object.
❑ The second rule says to use the ar command to revise the library, adding the new object file.
So, if you have a library fud, containing the file bas.o, in the first rule $< is replaced by bas.c. In the
second rule $@ is replaced by the library fud.a and $* is replaced by the name bas
20):The main makefile in the higher-level directory then has a rule for making the library, which invokes the second makefile like this:a new shell is invoked for this, the program using the makefile doesn’t execute the cd. However, the shell invoked to carry out the rule to build the library is in a different directory. The brackets ensure that it’s all processed by a single shell
mylib.a:
(cd mylibdirectory;$(MAKE))
21):gcc -MM main.c 2.c 3.c
The gcccompiler simply scans the source files looking for includes and outputs the required depend-ency lines in a format ready for insertion into a makefile All you have to do is save the output into a temporary file and then insert it into the makefile for a perfect set of dependency rules.If you really feel confident about makefiles, you might try using the makedepend tool, which performs a function similar to the -MMoption but actually appends the dependencies at the end of the specified makefile.
4.5 Phony Targets
A phony target is one that is not really the name of a file; rather it is just a name for a
recipe to be executed when you make an explicit request. There are two reasons to use a
phony target: to avoid a conflict with a file of the same name, and to improve performance.
If you write a rule whose recipe will not create the target file, the recipe will be executed
every time the target comes up for remaking. Here is an example:
clean:
rm *.o temp
Because the rm command does not create a file named ‘clean’, probably no such file will
ever exist. Therefore, the rm command will be executed every time you say ‘make clean’.
The phony target will cease to work if anything ever does create a file named ‘clean’ in
this directory. Since it has no prerequisites, the file ‘clean’ would inevitably be considered
up to date, and its recipe would not be executed. To avoid this problem, you can explicitly
declare the target to be phony, using the special target .PHONY as follows:
.PHONY : clean
Once this is done, ‘make clean’ will run the recipe regardless of whether there is a file
named ‘clean’.
Since it knows that phony targets do not name actual files that could be remade from
other files, make skips the implicit rule search for phony targets This is why declaring a
target phony is good for performance, even if you are not worried about the actual file existing.
Thus, you first write the line that states that clean is a phony target, then you write the rule, like this:
.PHONY: clean
clean:
rm *.o temp
Another example of the usefulness of phony targets is in conjunction with recursive
invocations of make .In this case the makefile will often contain a variable which lists a number of subdirectories
to be built. One way to handle this is with one rule whose recipe is a shell loop over the
subdirectories, like this:
SUBDIRS = foo bar baz
subdirs:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir; \
done
There are problems with this method, however. First, any error detected in a submake
is ignored by this rule, so it will continue to build the rest of the directories even when one
fails. This can be overcome by adding shell commands to note the error and exit, but then
it will do so even if make is invoked with the -k option, which is unfortunate. Second, and
perhaps more importantly, you cannot take advantage of make’s ability to build targets in
parallel ,since there is only one rule.
By declaring the subdirectories as phony targets (you must do this as the subdirectory
obviously always exists; otherwise it won’t be built) you can remove these problems:
SUBDIRS = foo bar baz
.PHONY: subdirs $(SUBDIRS)
subdirs: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@
foo: baz
Here we’ve also declared that the ‘foo’ subdirectory cannot be built until after the ‘baz’
subdirectory is complete; this kind of relationship declaration is particularly important
when attempting parallel builds.
A phony target should not be a prerequisite of a real target file; if it is, its recipe will
be run every time make goes to update that file. As long as a phony target is never a
prerequisite of a real target, the phony target recipe will be executed only when the phony
target is a specified goal Phony targets can have prerequisites. When one directory contains multiple programs,
it is most convenient to describe all of the programs in one makefile ‘./Makefile’. Since
the target remade by default will be the first one in the makefile, it is common to make this
a phony target named ‘all’ and give it, as prerequisites, all the individual programs. For
example:
all : prog1 prog2 prog3
.PHONY : all
prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o
prog2 : prog2.o
cc -o prog2 prog2.o
prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o utils.o
Now you can say just ‘make’ to remake all three programs, or specify as arguments the ones
to remake (as in ‘make prog1 prog3’). Phoniness is not inherited: the prerequisites of a
phony target are not themselves phony, unless explicitly declared to be so.
When one phony target is a prerequisite of another, it serves as a subroutine of the other.
For example, here ‘make cleanall’ will delete the object files, the difference files, and the
file ‘program’:
.PHONY: cleanall cleanobj cleandiff
cleanall : cleanobj cleandiff
rm program
cleanobj :
rm *.o
cleandiff :
rm *.diff
######################################################################################
Sample
######################################################################################
1: a simple example
1 include http://www.cnblogs.com/http://www.cnblogs.com/build/Makefile.inc 2 3 EXEC=mculink_d 4 OBJS= main.o mculink.o mculink_protocol.o 5 6 INCLUDE += -I../h -Ihttp://www.cnblogs.com/../export/interprocess -Ihttp://www.cnblogs.com/http://www.cnblogs.com/common/h 7 LDLIBS+=-lpthread -lipc_evt_api -L$(LIBDIR) 8 9 all: $(EXEC) 10 cp -f mculink_d ../; 11 12 $(EXEC): $(OBJS) 13 $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS) $(INCLUDES) $(LIBPATH) 14 cp -f $(EXEC) $(BINDIR) 15 rm -f *.o 16 17 clean: 18 $(RM) $(EXEC) *.o 19 20 %.o: %.cpp 21 $(CXX) -c -o $@ $< $(INCLUDE)
2:when a blank space appears after writer in the first line.It always reporting the below error:
1 EXEC=writer 2 OBJ=$(EXEC).o 3 SRC=$(EXEC).c 4 CFLAG = -lpthread 5 6 all:$(EXEC) 7 cp -f $(EXEC) ../ 8 rm -f *.o 9 10 $(EXEC):$(OBJ) 11 gcc -o $@ $(OBJ) $(CFLAG) 12 13 $(OBJ):$(SRC) 14 echo $(EXEC) $(OBJ) $(SRC) 15 gcc -c -o $@ $< 16 17 clean: 18 rm -f $(EXEC)
3.A sample to Make several target in the same directory.
Rember to make clean before make ,or it may fail.
1 include /build/Makefile.inc 2 3 INCLUDE += -I/common/h -I/export/interprocess 4 LDLIBS += -lpthread -lipc_evt_api -L$(LIBDIR) 5 6 EXEC1=public_xxx 7 EXEC2=handle_xxx 8 9 EXEC=$(EXEC1) $(EXEC2) 10 OBJ1=$(EXEC1).o 11 OBJ2=$(EXEC2).o 12 13 .PHONY:all clean 14 15 all:$(EXEC) 16 @cp -f $(EXEC) /; 17 18 $(EXEC1):$(OBJ1) 19 $(CXX) -o $@ $(OBJ1) $(LDLIBS) 20 21 $(EXEC2):$(OBJ2) 22 $(CXX) -o $@ $(OBJ2) $(LDLIBS) 23 24 %.o:%.cpp 25 $(CXX) -c -o $@ $< $(INCLUDE) 26 27 clean: 28 rm -f *.o $(EXEC)