Makefile学习

sdjasj

使用

1
make

makefile的规则

1
2
3
4
target ... : prerequisites ...
command
...
...
  • 例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o

main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
  • command前以tab开头

  • target

    • 可以是一个object file(目标文件),也可以是一个执行文件,还可以是一个标签(label)。
  • prerequisites

    • 生成该target所依赖的文件和/或target
  • command

    • 该target要执行的命令(任意的shell命令)

target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中

prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行

  • 利用"\"换行

变量

定义

1.“=”(前面定义的变量可以使用后面定义的变量,不推荐)

1
2
3
foo = $(bar)
bar = $(ugh)
ugh = Huh?

2.“:="(前面定义的变量无法使用后面定义的变量,推荐)

1
2
3
x := foo
y := $(x) bar
x := later

3.“?=”(其含义是,如果左边变量没有被定义过,那么变量的值就是右值,如果左边变量先前被定义过,那么这条语句将什么也不做)

1
FOO ?= bar
追加变量值

可以使用 += 操作符给变量追加值

1
2
3
objects := main.o foo.o bar.o utils.o
objects += another.o
##$(objects) 值变成:“main.o foo.o bar.o utils.o another.o”
例子
1
2
3
4
5
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o

edit : $(objects)
cc -o edit $(objects)

1.Makefile中的变量其实就是C/C++中的宏

2.变量在声明时需要给予初值,而在使用时,需要给在变量名前加上 $ 符号,但最好用小括号 () 或是大括号 {} 把变量给包括起来。如果要使用真实的 $ 字符,那么需要用 $$ 来表示。

清空目标文件的规则

1
2
3
.PHONY : clean
clean :
-rm edit $(objects)

.PHONY 表示 clean 是一个“伪目标”。而在 rm 命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事

书写规则

Makefile中只应该有一个最终目标,其它的目标都是被这个目标所连带出来的,第一条规则中的目标将被确立为最终的目标,如果第一条规则中的目标有很多个,那么,第一个目标会成为最终的目标。make所完成的也就是这个目标

伪目标

1
2
3
.PHONY : clean
clean :
rm *.o temp

当遇到目标体clean时,make先查看其是否有依赖体(prerequisites),因为clean没有依赖体,所以make认为目标体是最新的而不执行任何操作.为了编译这个目标体,必须输入make clean.

命令执行

当依赖目标新于目标时,也就是当规则的目标需要被更新时,make会一条一条的执行其后的命令。需要注意的是,如果要让上一条命令的结果应用在下一条命令时,应该使用分号分隔这两条命令

因为每行命令在一个单独的shell中执行。这些Shell之间没有继承关系,两行命令在两个不同的进程执行

1
2
var-kept:
export foo=bar; echo "foo=[$$foo]"

或者加上"\"

1
2
3
var-kept:
export foo=bar; \
echo "foo=[$$foo]"

通配符使用

make支持三个通配符: *?~

  • ”/“是根目录,”~“是家目录。Linux存储是以挂载的方式,相当于是树状的,源头就是”/“,也就是根目录。而每个用户都有”家“目录,也就是用户的个人目录,比如root用户的”家“目录就是/root,普通用户a的家目录就是/home/a
    • ~hchen/test 则表示用户hchen的宿主目录下的test 目录
  • * 匹配任意长度的任意字符,可以是0个
    • *.c 表示所有后缀为c的文件
  • ? 匹配任意单个字符,必须是1个

变量中通配符展开

1
2
objects := $(wildcard *.o) #objects的值是所有 .o 的文件名的集合
objects = *.o #object只是*.o
  • 標題: Makefile学习
  • 作者: sdjasj
  • 撰寫于: 2022-03-05 10:14:50
  • 更新于: 2022-03-06 11:51:45
  • 連結: https://redefine.ohevan.com/2022/03/05/Makefile学习/
  • 版權宣告: 本作品采用 CC BY-NC-SA 4.0 进行许可。
 留言