1. GNU的make工作时的执行步骤入下:
1. 读入所有的Makefile。
2. 读入被include的其它Makefile。
3. 初始化文件中的变量。
4. 推导隐晦规则,并分析所有规则。
5. 为所有的目标文件创建依赖关系链。
6. 根据依赖关系,决定哪些目标要重新生成。
7. 执行生成命令。
2. .PHONY 指明后面为伪目标
.SILENT 相当于make的-s参数,在执行前不显示要执行的命令
.IGNORE 相当于make的-i参数,当检测到错误,继续执行其他命令
make –n 参数,读取规则并显示,但是不执行
gcc –M 由编译器自动生成依赖关系
3. 判断:ifeq/ ifneq/ ifdef/ ifndef
ifeq ($(CC),gcc)
$(CC) -o foo $(objects) $(libs_for_gcc)
else
$(CC) -o foo $(objects) $(normal_libs)
endif
4. 可识别的后缀指的是特殊目标“.SUFFIXES”的所有依赖的名字。通过给特殊目标“SUFFIXES”添加依赖来增加一个可被识别的后缀:
.SUFFIXES: .hack .win
它所实现的功能是把后缀“.hack”和“.win”加入到可识别后缀列表的末尾。
如果需要重设默认所有的可识别后缀,可以这样来实现:
.SUFFIXES: #删除所有已定义的可识别后缀
.SUFFIXES: .c .o .h #重新定义
5. -include filename,包含文件
6. -M 生成文件的关联的信息,这样就可以知道源代码文件里面关联了哪些它所依赖的头文件。
-MD 跟-M相当,但是输出导入到.d文件中,如gcc -MD test.c,刚输出的依赖关系存放在test.d文件里。
7. $@ 代表规则中的目标文件名
$< 规则的第一个依赖文件名。如果是隐含规则,则它代表通过目标指定的第一个依赖文件。
$^ 规则的所有依赖文件列表,使用空格分隔。
8. 我们可以使用最终万用规则来实现。例如:在调试Makefile时(可能一些源文件还没有完成),我们所关心的是Makefile中规则的正确执行,而不关心源文件的内容。
%::
touch $@
9. 列出当前目录下所有符合模式“PATTERN”格式的文件名。
返回值:空格分割的、存在当前目录下的所有符合模式“PATTERN”的文件名。
$(wildcard *.c)
返回值为当前目录下所有.c源文件列表。
10. 目标总会被认为是最新的。就是说:这个规则一旦被执行,make就认为它的目标已经被更新过
clean: FORCE
rm $(objects)
FORCE:
11. subsystem:
cd subdir && $(MAKE)
其等价于规则:
subsystem:
$(MAKE) -C subdir
规则中“$(MAKE)”是对变量“MAKE" 的引用。第一个规则命令的意思是:进入子目录,然后在子目录下执行make。第二个规则时用了make的“-C”选项,同样是首先进入子目录而后再执行make。
12. -w选项
在多级make递归调用过程中,选项“-w”或者“--print-directory”可以让make在开始编译一个目录之前和完成此目录的编译之后给出相应的提示信息
以下是自己写的一个Makefile,目录结构为模块目录下存在inc、src、obj三个目录。由于用到了隐式规则,存在目录的一些限制,当前巴该Makefile放到子目录obj下:
====================================================
vpath %.c ../src
INCLUDE=../inc
CC=gcc
CFLAGS=-g -I$(INCLUDE)
TARGET=lib.a
DEPENDFILE=depend.dep
SRC_DIR=$(wildcard ../src/*.c)
OBJS=$(patsubst %.c,%.o,$(notdir $(SRC_DIR)))
all:$(TARGET)
$(TARGET):$(DEPENDFILE) $(OBJS)
ar -crv $@ $(OBJS)
$(DEPENDFILE):
$(CC) -M -I$(INCLUDE) $(SRC_DIR) > $@
.PHONY:clean
clean:
rm -rf $(TARGET) *.o $(DEPENDFILE)
-include depend.*
====================================================