1. basic
1.1 规则: obj.o: x.c y.h
<tab>command
obj.o 依赖x.c和y.h,一旦make发现前提(x.c y.h)比目标(obj.o)新或者obj.o根本不存在,则执行command
2. make 只处理“第一个”目标和与之相关的目标,对由此建立的依赖树做后序处理, 如上例中,如果x.c有其他依赖,则先处理x.c,再处理y.h, 最后是obj.o
3. make 错误有两类
1) 依赖文件找不到或者无法推出, make必然退出
2) command错误,make结束本规则执行,但是如果用命令行参数-i, 或伪目标.IGNORE或命令前加'-'(减号)忽略它
4. 如何书写makefile
1) 作出工程的依赖树( 可借用gcc -M/-MM 提取依赖, 特别是头文件的依赖 )
2) 有上到下书写规则; 可以借用一些自动工具( automake, autoconf, autoheader )或者‘通用的makefile'(仅仅适用小程序)
2. 高级
make可以嵌入变量函数和判断语句,甚至可以include其它makefile
2.1 变量
1)用户定义( =, := 定义,后者不做向后扫描 )
2)系统定义( 如$(CC)= cc; make -p | grep '/$(CC) )
3)shell传入(如 HOME )
优先级是 用户定义 > shell >系统定义
4) 特殊变量
$@ 目标集
$< 规则中第一个依赖
$? 比目标新的依赖
$^ 全部依赖
5) 常用内部变量及定义
CC=cc
CFLAGS=-O
CXXFLAGS=-O # c++ option
LD=ld
2.2 函数和判断语句
1) GNU make提供一些函数,主要是字符串操作,比如:
source = a.c b.cpp c.h
csrc = $(filter %c %cpp, $(source) )
提出source中源文件
2) 判断ifreq 允许执行不同分支的命令或者定义:
ifreq( $(CC), gcc )
libs = $( libs_for_gcc )
else
libs = $( normal_libs )
endif
2.3 特殊符号与常用选项
#: comment
/: line contiune
@: to silent command
-: ignore error of command
-f: file
-n: 假执行,可用于调试
-i: ignore error of all commands
-p: 显示内部规则等
-s: silent
2.4 目标
1) 实目标 (有对应文件)
2)为目标 ( 无对应文件,也没有依赖,所以总是会有动作 ),比如clean
clean:
@echo 'doing clean objects'
-rm *.o
2.5 内部规则及改写
1) 对一些常见的简单规则,make有内部规则,用户只需要些依赖,make会自动依序寻找合适的文件来生成目标
如下面的规则定义.c-->.o的规则:
.c.o:
$(COMPILE.c) $(OUTPUT_OPTION) $<
只需要这样些规则, 已经是自动规则了:
main.o : defs.h
甚至整个makefile可以写成,因为make有一条.o推出无后缀的规则:
main : main.o
main.o : defs.h
2) 后缀式规则 VS. 模式规则
.c.o是老式的写法,模式规则这样重新.c.o:
%.o :%.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
3) 可以改写内部规则
2.6 多个makefile
大项目,/src下面放一个主控makefile, 各个模块的子目录各放一个makefile,主控makefile可以这样写:
all: ...
cd sub_1: make -f a1.mk
cd sub_2: make -f a2.mk
也可以用include语句加入其它makefile
3. example
依赖树:
main
+------------+---------------+
main.o sub.o myclass.o
+---+------+-----+--------+ +-----+-------+
main.cpp defs.h sub.cpp sub.h myclass.cpp myclass.h
CC=g++
CXXFLAGS= -g -Wall
objs=main.o sub.o myclass.o
1)
all : main
main : $( objs )
$(CC) -o $@ $^
main.o : main.cpp defs.h
$(CC) $(CXXFLAGS) -c main.cpp
sub.o : sub.cpp sub.h defs.h
$(CC) $(CXXFLAGS) -c sub.cpp
myclass.o : myclass.cpp myclass.h
$(CC) $(CXXFLAGS) -c myclass.cpp
.PHONY : clean
clean :
@echo 'doing clean objects'
-rm *.o
2)
#利用目标规则
all: main
main: $(objs)
$(CC) -o $@ $^
main.o: defs.h
sub.o: sub.h defs.h
myclass: myclass.h
.PHONY : clean
clean :
@echo 'doing clean objects'
-rm *.o
1.1 规则: obj.o: x.c y.h
<tab>command
obj.o 依赖x.c和y.h,一旦make发现前提(x.c y.h)比目标(obj.o)新或者obj.o根本不存在,则执行command
2. make 只处理“第一个”目标和与之相关的目标,对由此建立的依赖树做后序处理, 如上例中,如果x.c有其他依赖,则先处理x.c,再处理y.h, 最后是obj.o
3. make 错误有两类
1) 依赖文件找不到或者无法推出, make必然退出
2) command错误,make结束本规则执行,但是如果用命令行参数-i, 或伪目标.IGNORE或命令前加'-'(减号)忽略它
4. 如何书写makefile
1) 作出工程的依赖树( 可借用gcc -M/-MM 提取依赖, 特别是头文件的依赖 )
2) 有上到下书写规则; 可以借用一些自动工具( automake, autoconf, autoheader )或者‘通用的makefile'(仅仅适用小程序)
2. 高级
make可以嵌入变量函数和判断语句,甚至可以include其它makefile
2.1 变量
1)用户定义( =, := 定义,后者不做向后扫描 )
2)系统定义( 如$(CC)= cc; make -p | grep '/$(CC) )
3)shell传入(如 HOME )
优先级是 用户定义 > shell >系统定义
4) 特殊变量
$@ 目标集
$< 规则中第一个依赖
$? 比目标新的依赖
$^ 全部依赖
5) 常用内部变量及定义
CC=cc
CFLAGS=-O
CXXFLAGS=-O # c++ option
LD=ld
2.2 函数和判断语句
1) GNU make提供一些函数,主要是字符串操作,比如:
source = a.c b.cpp c.h
csrc = $(filter %c %cpp, $(source) )
提出source中源文件
2) 判断ifreq 允许执行不同分支的命令或者定义:
ifreq( $(CC), gcc )
libs = $( libs_for_gcc )
else
libs = $( normal_libs )
endif
2.3 特殊符号与常用选项
#: comment
/: line contiune
@: to silent command
-: ignore error of command
-f: file
-n: 假执行,可用于调试
-i: ignore error of all commands
-p: 显示内部规则等
-s: silent
2.4 目标
1) 实目标 (有对应文件)
2)为目标 ( 无对应文件,也没有依赖,所以总是会有动作 ),比如clean
clean:
@echo 'doing clean objects'
-rm *.o
2.5 内部规则及改写
1) 对一些常见的简单规则,make有内部规则,用户只需要些依赖,make会自动依序寻找合适的文件来生成目标
如下面的规则定义.c-->.o的规则:
.c.o:
$(COMPILE.c) $(OUTPUT_OPTION) $<
只需要这样些规则, 已经是自动规则了:
main.o : defs.h
甚至整个makefile可以写成,因为make有一条.o推出无后缀的规则:
main : main.o
main.o : defs.h
2) 后缀式规则 VS. 模式规则
.c.o是老式的写法,模式规则这样重新.c.o:
%.o :%.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
3) 可以改写内部规则
2.6 多个makefile
大项目,/src下面放一个主控makefile, 各个模块的子目录各放一个makefile,主控makefile可以这样写:
all: ...
cd sub_1: make -f a1.mk
cd sub_2: make -f a2.mk
也可以用include语句加入其它makefile
3. example
依赖树:
main
+------------+---------------+
main.o sub.o myclass.o
+---+------+-----+--------+ +-----+-------+
main.cpp defs.h sub.cpp sub.h myclass.cpp myclass.h
CC=g++
CXXFLAGS= -g -Wall
objs=main.o sub.o myclass.o
1)
all : main
main : $( objs )
$(CC) -o $@ $^
main.o : main.cpp defs.h
$(CC) $(CXXFLAGS) -c main.cpp
sub.o : sub.cpp sub.h defs.h
$(CC) $(CXXFLAGS) -c sub.cpp
myclass.o : myclass.cpp myclass.h
$(CC) $(CXXFLAGS) -c myclass.cpp
.PHONY : clean
clean :
@echo 'doing clean objects'
-rm *.o
2)
#利用目标规则
all: main
main: $(objs)
$(CC) -o $@ $^
main.o: defs.h
sub.o: sub.h defs.h
myclass: myclass.h
.PHONY : clean
clean :
@echo 'doing clean objects'
-rm *.o