Makefile的使用技巧
1、 makefile中的两种变量
Ø COMPILE=$(CC)$(CFLAGS) -c
在使用COMPILE的时候,CC和CFLAGS才会展开,并且是每次都会展开,所以当定义COMPILE的时候,即使CC和CFLAGS还没有值,都没有关系,只要当使用COMPILE时,CC和CFLAGS有值就可以了。
OBJS=$(wildcard *.o)
OBJS每次在引用的时候,获取目标文件的列表,每一次可能都不同,并且每次计算通配符导致运行速度变慢。
Ø COMPILE=:$(CC)$(CFLAGS) -c
在执行这行后,在使用COMPILE时,其值不会再变化,即使CC和CFLAGS变化了。当然可以显示的赋值给COMPILE来改变其值。
2、 使用函数
Ø wildcard
SRCS := $(wildcard *.c)
获得所有的C文件列表
Ø patsubst
OBJS := $(patsubst %.c,%.o,$( wildcard *.c ))
获得所有c文件对应的o文件列表
3、 特殊符号
%.o: %.c gcc -Wall -c -o $@ $< |
将所有的C文件编译成O文件。
4、 两种编译方式
Ø gcc -o myprogram 1.c 2.c
将1.c和2.c编译成myprogram程序。
Ø gcc -c -o 1.o 1.c
将1.c编译成O文件。
5、 依赖性计算
gcc -M init.c > init.d
将所有的依赖文件(包括系统文件)写入d文件
gcc -MM init.c > init.d
将不包括系统文件的依赖文件写入d文件
6、 智能makefile模板
# Lines starting with the pound sign are comments. # # This is one of two options you might need to tweak.
EXECUTABLE = myprogram
# You can modify the below as well, but probably # won't need to. #
# CC is for the name of the C compiler. CPPFLAGS denotes pre-processor # flags, such as -I options. CFLAGS denotes flags for the C compiler. # CXXFLAGS denotes flags for the C++ compiler. You may add additional # settings here, such as PFLAGS, if you are using other languages such # as Pascal.
CC = gcc CPPFLAGS = CFLAGS = -Wall -O2 CXXFLAGS = $(CFLAGS) COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) -c
SRCS := $(wildcard *.c) OBJS := $(patsubst %.c,%.o,$(SRCS)) DEPS := $(patsubst %.c,%.d,$(SRCS))
# "all" is the default target. Simply make it point to myprogram.
all: $(EXECUTABLE)
# Define the components of the program, and how to link them together. # These components are defined as dependencies; that is, they must be # made up-to-date before the code is linked.
#最终的二进制程序依赖于d文件和o文件 $(EXECUTABLE): $(DEPS) $(OBJS) $(CC) -o $(EXECUTABLE) $(OBJS)
# Specify that the dependency files depend on the C source files. #生成d文件,d文件内容包括两行,o文件的依赖关系,d文件的依赖关系 %.d: %.c $(CC) -M $(CPPFLAGS) $< > $@ $(CC) -M $(CPPFLAGS) $< | sed s///.o/.d/ >> $@
# Specify that all .o files depend on .c files, and indicate how # the .c files are converted (compiled) to the .o files. #由c文件生成o文件 %.o: %.c $(COMPILE) -o $@ $<
#删除四类文件 clean: -rm $(OBJS) $(EXECUTABLE) $(DEPS) *~
explain: @echo "The following information represents your program:" @echo "Final executable name: $(EXECUTABLE)" @echo "Source files: $(SRCS)" @echo "Object files: $(OBJS)" @echo "Dependency files: $(DEPS)"
depend: $(DEPS) @echo "Dependencies are now up-to-date."
#将d文件内容导入makefile中 -include $(DEPS) |
特点:
Ø 没有出现任何一个具体的文件名
Ø 采用依赖性文件确定依赖关系,并最后通过include将依赖关系导入
Ø 最终的二进制程序,不仅仅依赖于o文件,还依赖于d文件
具体见example4
7、 级联嵌套makefile
# Lines starting with the pound sign are comments. # # This is one of two options you might need to tweak.
EXECUTABLE = myprogram
# You can modify the below as well, but probably # won't need to. #
# CC is for the name of the C compiler. CPPFLAGS denotes pre-processor # flags, such as -I options. CFLAGS denotes flags for the C compiler. # CXXFLAGS denotes flags for the C++ compiler. You may add additional # settings here, such as PFLAGS, if you are using other languages such # as Pascal.
CC = gcc CPPFLAGS = CFLAGS = -Wall -O2 CXXFLAGS = $(CFLAGS) COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) -c
SRCS := $(wildcard *.c) OBJS := $(patsubst %.c,%.o,$(SRCS)) DEPS := $(patsubst %.c,%.d,$(SRCS))
DIRS= input format
# "all" is the default target. Simply make it point to myprogram.
all: $(EXECUTABLE)
subdirs: @for dir in $(DIRS); do $(MAKE) -C $$dir; done
# Define the components of the program, and how to link them together. # These components are defined as dependencies; that is, they must be # made up-to-date before the code is linked.
$(EXECUTABLE): subdirs $(DEPS) $(OBJS) $(CC) -o $(EXECUTABLE) $(OBJS)
# Specify that the dependency files depend on the C source files.
%.d: %.c $(CC) -M $(CPPFLAGS) $< > $@ $(CC) -M $(CPPFLAGS) $< | sed s///.o/.d/ >> $@
# Specify that all .o files depend on .c files, and indicate how # the .c files are converted (compiled) to the .o files.
%.o: %.c $(COMPILE) -o $@ $<
clean: -rm $(OBJS) $(EXECUTABLE) $(DEPS) *~ @for dir in $(DIRS); do $(MAKE) -C $$dir clean; done
explain: @echo "The following information represents your program:" @echo "Final executable name: $(EXECUTABLE)" @echo "Source files: $(SRCS)" @echo "Object files: $(OBJS)" @echo "Dependency files: $(DEPS)" @echo "Subdictionary: $(DIRS)"
depend: $(DEPS) @for dir in $(DIRS); do $(MAKE) -C $$dir; done @echo "Dependencies are now up-to-date."
-include $(DEPS) |
这是顶层makefile相对于标准智能模板进行的修改,input和format中的makefile为标准的模块。