makefile文件编写
1.make命令调用格式:
make [-f makefile文件名][选项][宏定义][目标]
2.常用选项有:
-Idirname 指定被包含的makefile所在目录
-w 如果make在执行时改变目录,打印当前目录名
-d 打印调试信息
-k 用该选项,即使make程序遇到错误也会继续向下运行
3.makefile文件主要包含了6部分内容
1、显式规则:用于描述系统中模块之间的相互依赖关系,以及产生目标文件所要执行的命令(规则)。
编写规则通用形式:
target : dependency [depenency [...] ]
command
command
[...]
注:command前是tab键,而非空格
使用这些命令来根据依赖模块产生目标,这里的command既可以是gcc/g++编译命令,也可以是shell命令或是其他可执行文件。
main : main.o f1.o f2.o
gcc -o main main.o f1.o f2.o
main.o : main.c def1.h
gcc -c main.c
f1.o : f1.c def1.h def2.h
gcc -c f1.c
f2.o : f2.c def2.h def3.h
gcc -c f2.c
2、隐式规则:又称预定义规则。隐式规则简化了makefile的编写和维护。(make命令带-p选项),
比如:后缀规则,可以指定:.SUFFIXES: .o .cpp
.cpp.o:
$(CPP) –c $<
3、模式规则提供的一种扩展make隐式规则的方法,规则与普通规则一样,主要是目标必定含有%号,
比如:%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
4、变量定义(自动变量/预定义变量/自定义变量)
5、文件指示(include, make -I, #if include)。
6、特殊字符:注释# 转义/ 通配符* 宿主目录~ 模式字符“%”
“*.c”代表了当前工作目录下所有的以“.c”结尾的文件
“%”意思是匹配一个或者多个字符,例如,“%.h”表示所有以“.h”结尾的文件
4.变量(或者说宏)
1、定义方法: VARNAME=some_text [...]
如: OBJS := howdy.o helper.o
2、变量引用:$(VARNAME)或 ${VARNAME)
3、变量扩展:VARNAME += $(VARNAME) some_textn..
注:在使用变量时要注意库的连接左右问题
建议使用:VARNAME := some_textn $(VARNAME)
4、作用:用代表某些多处使用而又可能发生变化的内容,节省重复修改的工作,避免遗漏。一般用来代表一些文件名或选项。
5、自动变量
$@ 规则的目标所对应的文件名
$< 规则中的第一个相关文件名
$^ 规则中所有相关文件的列表,以空格为分隔符
$? 规则中日期新于目标的所有相关文件的列表
$(@D) 目标文件的目录部分
$(@F) 目标文件的文件名部分
$* 这个变量表示目标模式中“%”及其之前的部分。
6、预定义变量
CC C编译程序,默认值=cc
CFLAGS 传给C编译器的标志
CPP C++编译程序,默认值=cpp
CPPFLAGS
LDFLAGS 传给链接程序(ld)的标志,默认值=
AR 归档维护程序,默认值=ar
ARFLAGS 默认值=rv
AS 汇编程序,默认值=as
ASFLAGS
5.makefile实例
1、通过g++的MM选项显示各文件间依赖关系
gcc -MM main.c f1.c f2.c
main.o: main.c def1.h
f1.o: f1.c def1.h def2.h
f2.o: f2.c def2.h def3.h
2、多目标
$(OBJ_DIR)%.o:$(SRC_DIR)%.cpp
@echo "Compiling $< ==> $@..."
$(CXX) $(INC) $(C_FLAGS) -c $< -o $@
3、静态模式
objects = foo.o bar.o
all: $(objects)
%.o: %.c
$(gcc) -c $(CFLAGS) $< -o $@
4、大项目makefile的处理
Ø给源文件分类,并存放在不同的目录中,给各个目录定义变量。
Ø按层定义makefile.pub文件,该文件主要定义一些变量(如INC, SRC)、函数、本层会生成的lib文件。
Ø子层文件include上层及相关makefile.pub文件。并根据情况对变量进行扩展。
Ø生成库文件提供给下一级makefile进行链接。
Ø嵌套调用make
subsystem:
cd subdir && $(MAKE)
subsystem:
$(MAKE) –C subdir
Ø在makefile文件中定义VPATH = src:../headers
Ø使用环境变量
5、程序包(函数的定义)
•定义程序包:
define run-yacc
yacc $(firstword $^)
mv y.tab.c $@
endef
•程序包的使用
%.c : %.y
$(run-yacc)
6、函数使用
$(<function> <arguments>)
或是:
i := ${<function> <arguments>}
示例:
INC = $(patsubst %,-I%,$(ALLINC))
make支持的函数有:
$(subst <from>,<to>,<text>)
$(patsubst <pattern>,<replacement>,<text>)
$(filter <pattern...>,<text>) .....
7、分支语法
< conditional-directive>
< text-if-true>
endif
以及:
< conditional-directive>
<text-if-true>
else
<text-if-false>
endif
注:conditional-directive可以是:ifeq(), ifneq(), ifdef, ifndef
分支语法示例:
libs_for_gcc = -lgnu
normal_libs =
foo: $(objects)
ifeq ($(CC),gcc)
$(CC) -o foo $(objects) $(libs_for_gcc)
else
$(CC) -o foo $(objects) $(normal_libs)
endif
注:上面示例的这个规则中,目标foo可以根据变量$(CC)的值选取不同的函数库来编译程序
8.make的妙用
•同步文件至远端服务器:
cmdscp:
scp -P3600 exe user_00@172.25.32.162:/usr/local/..