makefile

Posted tujw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了makefile相关的知识,希望对你有一定的参考价值。

https://blog.csdn.net/weixin_38391755/article/details/80380786#commentBox

makefile 的命令是以tab开头的

主要内容:
显式规则、隐晦规则、变量定义、文件指示、注释
隐晦规则:自动推导功能
可以引用另外的makefile

include
不能是[tab]开头 如果有多个用空格分开
-include 如果没找到也不报错
-rm 也是

执行过程:
1.读入所有makefile
2.读入被include 的makefile
3.初始化变量
4.推导隐晦规则,分析所有规则
5.为所有的目标文件创建关系链
6.根据依赖关系,决定哪些目标要重新生成
7.执行生成命令

命令格式:
生成目标:依赖文件
[tab] 命令
也可以写成这样
target:prerequistites;command

多个路径之间用:分割
VPATH=[path]:[path]

vpath
为符合模式的文件指定搜寻目录

vpath
为符合模式的文件清除搜寻目录

vpath 清除所有

需要包含%,表示匹配0个到多个

.PHONY:clean 伪目标
不管是否有clean这个文件

使用伪目标生成多个目标文件
.PHONY:all
all:prog1 prog2
prog1: test.c main.c
cc -o prog1 prog1.o utils.o
prog2: test.c main.c
cc -o prog2 prog2.o utils.o

利用伪目标清除以来
.PHONY:cleanall cleanobj cleandiff
cleanal:cleanobj cleandiff
rm program
cleanobj:
rm .o
cleandiff:
rm
.diff
<targets...>::<prereq-patterns...>

$< 单个依赖文件
$@ 目标文件
$^ 所有依赖文件
$+ 所有依赖文件,不去重
$? 所有比目标新的依赖目标的集合
$% 规则中的目标成员名
$* 目标模式中%及其之前的部分

$(@D) 目录部分
$(@F) 文件部分
$(D)
$(
F) 同上
$(<D)
$(<F) 依赖文件的目录和文件
$(^D)
$(^F) 所有依赖文件(无重复)
$(+D)
$(^F) 所有依赖文件(有重复)
$(?D) 跟新部分
$(?F)

$(subf, output, $@) 执行一个makefile 函数,函数名为subf, 后面的为参数
$@ 自动化变量,所有目标的集合
wildcard Makefile关键字

$(filter%.o,$(files))
调用Makefile的filter函数,过滤.o结尾的文件

gcc -M main.c 自动生成依赖文件, 如果时GNU 需要用 -MM

3.8节 有点看不懂
%d:%c
为每个依赖文件$<生成依赖文件
@set -e:rm -rf @a:$(CC) -M S(CFLAGS) $<>$@.;sed ‘s,
.0[:}*,1.o $@:,g‘<$@.>$a; rm -rf @a.

不显示命令
@echo 正在编译xxx模块

make -n --just-print 显示命令,不执行
make -s 或 make --slient 全面禁止命令显示

切换目录后不能换行,用;
命令前加 -可以忽略错误
或者make -i 忽略错误
--k keep-going 如果出错就跳过这条命令

等价
subsystem:
cd subdir && $(MAKE)

subsystem:
$(MAKE) -C subdir

export <variable..>传递变量
unexport <variable..> 取消传递
export 传递所有变量

make -w || make --print-directory 显示工作目录

定义命令后 run-yacc为名字
中间的是命令
define run-yacc
yacc $(firstword $^)
mv y.tab.c $@
endef

-Wall 生成警告
变量
另一种定义变量的方式 a:=b
做了改进不会去看后面的变量

$(shell cmd) 执行shell命令,返回值为结果
要定义一个空格 需要用到注释

变量替换
所有.o结尾的替换成.c结尾
foo = a.o b.o
bar = $(foo:.o=.c)

定义一个空格
需要注意在写路径的时候不要在后面带注释
否则可能会出错
不,是一定..
space =
space = $(space) #

?=
如果没有定义过,就用后面的字符
否则还是用原来的

ifneq 不相等
ifeq($(val1), $(val2))
endif

ifdef val
else
endif

调用函数
参数用,隔开 这里 a b c d是一个字符串
$(func a b c d)

a=abc
a+=bcd 字符串加,中间一定会带空格

对与命令行参数,一般不能赋值
如果想给它赋值,可以用override

override define foo
bar
endef 定义多行变量

define two-lines
echo foo
echo $(bar)
endef 命令包,定义多行命令,需要[tab]开头

make -e 系统变量或带入的变量覆盖定义的变量

<target...>: 只在目标处有用
<target...>:override 覆盖系统变量

与目标变量一样
模式变量 %.o:CFLAGS=-O

-o0~3 表示优化等级0没有 3最高

ifndef

endif

判断a是不是空
ifeq($(strip $(a)),)
endif

$(subst ,,)
patsubst 模式字符串替换 可以用 %

字符串替换,前面的变后面的
$(var:=)

strip 去空格函数

$(findstring ,)
在in中查找find

$(filter <pattern..>,)

$(filter %.c,%.s,$(source))
反过滤,与上面相反
返回不符合的单词
$(filter-out %.c,%.s,$(source))

sort 升序排序 会去重
$(sort )

$(word ,) 取第n个单词
$(wordlist ,,) 从s到e的单词,s,e为数字
$(words ) 单词个数统计
$(firstword ) 取第一个单词

文件名操作
取目录
$(dir )
取文件名
$(notdir )
取后缀名
$(suffix <filename..>)
取前缀
$(basename )
加后缀
$(addsuffix ,)
加前缀
$(addprefix ,)
连接 分别连接,多出来的原样不动
$(join ,)

foreach 函数
$(foreach ,,)
var 相当于中间变量,其实随便取
list中去一个给var 然后在text 里转 text中写$(var).abc

$(if ,)
或 $(if ,,)

$(call ,,...)
reverse = $(1) $(2)
foo = $(call reverse,a,b) ==> foo = a b
reverse = $(2) $(1)
foo = $(call reverse,a,b) ==> foo = b a

$(origin $(val)) 变量的情况
有如下取值:
undefined
default
environment 环境变量
file makefile 文件中定义的
command line 命令行参数
override 被override 指示符重新定义的
automatic 自动化变量

$(shell commond)

生成错误和警告
$(error <text...>)
$(warning <text...>)

退出码
0 成功执行
1 错误
2 没有更新

make -f filename 指定 makefile 文件

make clean 完成 clean 目标
MAKECMDGOALS 终极目标列表
如果命令行没有指定,则为空

一般伪目标 规范,不强制
all 编译所有目标
clean 删除所有 make 出来的文件
install
安装已经编译好的程序(把目标执行文件拷贝到指定的目标中去)
print 列出改变过的源文件
tar 打包备份
dist 创建一个压缩文件(把tar文件压缩成z文件或gz文件)
TAGS 更新所有目标,以备完整重新编译
check test 测试makefile

-t 更新目标时间不更新文件,假装已经编译过了
-q 找目标,不存在报错
-W file 源文件, 根据规则推导来运行以来于这个文件的命令
-b -m 忽略和其他版本make的兼容性
-B 重编译
-C


make -C ~tujiawei/ -C code ===> make -C ~tujiawei/code
-debug[=options]
a 输出所有
b 基础,简单信息
v 比b稍微多一点
i 所有的隐含规则
j 详细信息
m 更新makefile

-d 相当于 -debug=a
-e 指定环境变量
-f 指定makefile
-i 忽略错误
-I 指定搜寻目标
-j 最大同时运行命令的个数
-k 出错也不停止
-l make运行命令的负载
-n 只是输出
-o 不重新生成指定file
-p 输出所有数据 -p -f /dev/null 更详细
-q 检查是否要更新 0 需要 2 有错
-r 禁止使用隐含规则
-R 禁止变量上的隐含规则
-s 不输出
-S 取消-k
-t 更新目标事件,加编译
-w 打印运行前后的信息
--no-print-directory 禁止 -w
-W 和 -n 一起输出更新动作
--warn-undefined-variable 有变量未定义就警告

隐含规则

以上是关于makefile的主要内容,如果未能解决你的问题,请参考以下文章

Makefile文件语法

使用带有 NMake 样式 Makefile 的 clang-cl 无法回显

如何使用 makefile 使用 Visual Studio 编译代码

重建后的Makefile重新编译代码需要很多时间

Makefile

Makefile步步为营