程序的编译链接
前言
源文件 – 中间目标文件 – 执行文件
编译:检查程序语法、函数、变量声明(函数未声明编译器给警告,可生成ObjectFile)
链接:在所有Object File中找函数的实现。否则报错Link 2001
一、MakeFile 规则
1、如果这个工程没编译过,所有c文件编译并被链接
2、某几个C文件被修改,只编译被修改的C文件,并链接目标
3、如果工程头文件被改变了。编译引用了这几个头文件的C文件
target... : prerequisites ..
command
...
...
target: 目标文件 || 执行文件 || 标签,以空格分开,可以使用通配符
prerequisites:生成target所需要的目标或目标
comman: make 需要执行的命令(任意的shell命令),不和target:prerequisites,以[tab]开头,和prerequisites可用分号做分隔
如果命令太长可用 "\" 做换行符
二、MakeFile主要内容:
显示规则
如何生成一个或多个文件
隐晦规则
变量定义
文件指示
注释
***Makefile命令中,以[Tab]键开始
MakeFIie引用其他的Makefile
include <filename> 不能以[Tab]开始
make开始时找寻 include指的其他MakeFile。
make -I 或--include-dir 的参数
/usr/local/bin 以及/usr/include
Make工作方式
读入所有的Makefile
读入被include的其他MakeFile
初始化文件中的变量
推导隐晦规则,并分析所有规则
为所有的目标文件创建依赖关系链
根据依赖关系,决定那些目标需要重新生成
执行生成命令
MakeFile 书写规则
MakeFile中的变量就是宏
objects = *.o # 表示objects就是*.o,并不会展开
文件搜索
VPATH 指定依赖文件的目录,目录由:分开
VPATH = src:../headers #指定src 和 ../headers
使用make 的 vpath的关键字
vpath <pattern> <directories> 为符合模式<pattern>的文件指定搜索目录<directories>
vpath <pattern> 清除符合模式<pattern>的文件搜索目录
vpath 清除所有已被设置好的文件搜索目录
伪目标
.PHONY : clean
伪目标总是被执行
静态模式
objects = foo.o bar.o
all:$(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@ #$<表示所有依赖目标集, $@表示所有目标集
等同于:
foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o
自动生成依赖性
CC -M main.c (自动找寻源文件中包含的头文件,并生成一个依赖关系)
书写命令:
显示命令
@命令 #隐藏命令
make执行时,make -n或--just-print #只是显示命令,不会执行命令
make -s或 --slient #全面禁止命令显示
命令执行
如果上一条的命令用于下一条,写在一行并用;分隔
命令出错
在命令前[Tab]后加-,标记不管命令出不出错都认为是成功的
或给make加上-i 或 --ignore-errors MakeFile所有命令都会忽略错误
make参数-k 或 --keep-going 如果规则中命令出错,终止该规则执行,但继续执行其他规则
嵌套make
总控MakeFile
传递变量到下级MakeFile export<variable ...>
不传递变量到下级MakeFile unexport<variable ...>
传递所有变量 export
SHELL、MAKEFLAGS(上层make参数) #总能传到下级Makefile
-w或--print-directory #-C时-w自动打开, -S(-slient)-w失效
定义命令包
以define,endef结束定义命令序列、
define run-yacc yacc $(firstword $^) mv y.tab.c $@ endef
使用变量
变量用法
= (右侧的变量值可以是后面定义的值)
:= 前面的变量不能使用后面的变量,只能使用前面已经定义好了的变量
?= 如果F00没被定义过,定义,如果之前定义过,什么也不干
+= 追加变量值
变量值替换
foo := a.o b.o c.o
bar := $(foo:.o=.c)
把$(foo)所有.o字串全部替换为.c
x = variable1 variable2 := Hello y => $(subst 1,2,$(x)) #把$(x)所有1替换为2
z = y a := $($($(Z)))
条件判断
<conditional-directive>
<text-if-true>
else
<text-if-false>
endif
<conditional-directive>包括
ifeq ifeq (<arg1>, <arg2>) 判断arg1==arg2则为真
ifneq ifneq (<arg1>, <arg2>) 判断arg1!=argv2则为真
ifdef ifdef <variable-name> 判断<variable-name>值为非空,则为真
ifndef ifndef <variable-name> 判断<variable-name>值为空,则为真
在<conditional-directive>中,不能以[Tab]键作为开始
********make是在读取MakeFile计算条件表达式,并根据条件表达式来选择语句,不要把自动变量($@)加入条件表达式中,自动变量在运行时才有