makefile 笔记(上)

0. Makefile是一个指示make命令如何为我们工作的命令文件

1. make 不带命令,则以Makefile文件中定义的第一个目标为运行目标(默认目标)

2. @echo "Hello" 与 echo "Hello",区别是多了个@,这一符号告诉make,在运行时不要将这一行的命令显示出来

3. 生成目标的命令行前必须至少有一个TAB

4. 目标如果有先决条件,则先依次执行该先决条件

5. make构建目标有判断准则,这个准则是先决条件中相关的文件是否比目标更新(通过文件的时间戳)

6. 如果目标名跟当前目录下一文件名重名,比如clean,那么make clean会将clean当作文件来处理,认为当前目录找到了clean文件,如果再加上clean目标没有任何先决条件,它就会认为clean是最新的

Makefile
--------
simple: main.o foo.o
    gcc -o simple main.o foo.o
main.o: main.c
    gcc -o main.o -c main.c
foo.o: foo.c
    gcc -o foo.o -c foo.c
clean:
    rm simple main.o foo.o


7. 针对6要采用假目标(phony target)来解决问题,关键字是.PHONY,它告诉make要把clean当作概念上的目标,不要当作文件来处理
Makefile
--------
.PHONY: clean
simple: main.o foo.o
    gcc -o simple main.o foo.o
main.o: main.c
    gcc -o main.o -c main.c
foo.o: foo.c
    gcc -o foo.o -c foo.c
clean:
    rm simple main.o foo.o


8. 引入变量,方便以后维护和利用,变量有定义和引用,引用用$(变量名)或${变量名},可以存放多个值,用空格分开
Makefile
--------
.PHONY: clean
CC = gcc
RM = rm
EXE = simple
OBJS = main.o foo.o
$(EXE): $(OBJS)
    $(CC) -o $(EXE) $(OBJS)
main.o: main.c
    $(CC) -o main.o -c main.c
foo.o: foo.c
    $(CC) -o foo.o -c foo.c
clean:
    $(RM) $(EXE) $(OBJS)



9. 自动变量
$@用于表示一个规则中的目标
$^表示的是规则中的所有先决条件
$<表示的是规则中的第一个先决条件

Makefile
--------
.PHONY: clean
CC = gcc
RM = rm
EXE = simple
OBJS = main.o foo.o
$(EXE): $(OBJS)
    $(CC) -o $@ $^
main.o: main.c
    $(CC) -o $@ -c $^
foo.o: foo.c
    $(CC) -o $@ -c $^
clean:
    $(RM) $(EXE) $(OBJS)



10.特殊变量
MAKE表示的是make命令名是什么,当我们要在Makefile中调用另一个Makefile时需要用到,采用这种方式有利于写一个容易移植的Makefile
MAKECMDGOALS表示的是当前用户所输入的make目标是什么

Makefile
--------
.PHONY: all
all:
    @echo "MAKE = $(MAKE)"
//screen content begin
$make
MAKE = make
//screen content end


Makefile
--------
.PHONY: all clean
all clean:
    @echo "\$$@ = $@"
    @echo "MAKECMDGOALS = $(MAKECMDGOALS)"
//screen content begin
$make all
$@ = all
MAKECMDGOALS = all
$make
$@ = all
MAKECMDGOALS = // 这里需要注意,虽然第一目标为缺省,但MAKECMDGOALS仍然是空
//screen content end


11. =符号和:=符号区别:=符号是递归扩展的,:=符号是简单扩展的即只赋值一次
Makefile
--------
.PHONY: all
x = foo
y = $(x) b
x = later
xx := foo
yy := $(xx) b
xx := later
all:
    @echo "y = $(y), xx = $(yy)"
// screen content begin
$make
y = later b, xx = foo b
// screen content begin

还有一种条件赋值操作符?=,其用法是当变量以前没有定义时,就定义它并且将左边的值赋值给它,如果已经定义了那么就不再改变其值
Makefile
--------
.PHONY: all
foo = x
foo ?= y
bar ?= y
all:
    @echo "foo = $(foo), bar = $(bar)"
// screen content begin
$make
foo = x, bar = y
// screen content end

另外还有+=操作符,跟C中功能类似

12. Makefile中的变量不仅可以在Makefile中赋值,还可以通过Shell和运行make命令时进行赋值
// screen content begin
$make bar=x
foo =x, bar = x
// screen content end
// screen content begin
$make
foo = x, bar = y
$export bar=x
$make
foo = x, bar = x
// screen content end


13. 在给变量赋值的同时完成后缀的替换,以此变得更简洁
Makefile
--------
.PHONY: all
foo = a.o b.o c.o
bar := $(foo:.o=.c)
all:
    @echo "bar = $(bar)"
// screen content begin
$make
bar = a.c b.c c.c
// screen content end


14. 如果要防止变量被Makefile之外的途径覆盖掉,那么需要通过override关键字
Makefile
--------
.PHONY: all
overrride foo = x
all:

    @echo "foo = $(foo)"

// screen content begin

$make foo=haha
foo = x
// screen content end


15. 通配符%提供的模式可大大简化Makefile,不用每个源文件都需要去构建一条规则
Makefile
--------
.PHONY: clean
CC = gcc
RM = rm
EXE = simple
OBJS = main.o foo.o
$(EXE): $(OBJS)
    $(CC) -o $@ $^
%.o: %.c
    $(CC) -o $@ -c $^
clean:
    $(RM) $(EXE) $(OBJS)


16. 使用函数wildcard和patsubst,将会使15的Makefile变得更简洁,通过wildcard可以得到我们所需的文件,其形式是$(wildcard pattern),而patsubst是用来进行字符串替换
的,其形式是$(patsubst pattern, replacement, text)

Makefile
--------
.PHONY: clean
CC = gcc
RM = rm
EXE = simple
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
$(EXE): $(OBJS)
    $(CC) -o $@ $^
%.o: %.c
    $(CC) -o $@ -c $^
clean:
    $(RM) $(EXE) $(OBJS)

还有addprefix函数,是用来给字符串中的每个子串加上一个前缀,形式是$(addprefix prefix, names...)
Makefile
--------
.PHONY: all
without_dir = foo.c bar.c main.o
with_dir := $(addprefix objs/, $(without_dir))
all:

    @echo $(with_dir)

// screen content begin

$make
objs/foo.c objs/bar.c objs/main.o
// screen content end

还有filter函数,是用于从一个字符串中,根据模式得到满足模式的字符串,其形式是$(filter patten..., text)
Makefile
--------
.PHONY: all
sources = foo.c bar.c baz.s ugh.h
sources := $(filter %.c %.s, $(sources))
all:

@echo $(sources)

// screen content begin

$make
foo.c bar.c baz.s
// screen content end

还有filter-out函数,是用于从一个字符串中根据模式滤除一部分字符串,其形式是$(filter-out pattern..., text)
Makefile
--------
.PHONY: all
objects = main1.o foo.o main2.o bar.o
result = $(filter-out main%.o, $(objects))
all:

    @echo $(result)

// screen content begin

$make
foo.o bar.o
// screen content end 

还有strip函数,是用于去除变量中的多余的空格,其形式是$(strip string)
Makefile
--------
.PHONY: all
original = foo.c       bar.c
stripped := $(strip $(original))
all:
    @echo "original = $(original)"

    @echo "stripped = $(stripped)"

// screen content begin

$make
original = foo.c        bar.c
stripped = foo.c bar.c 

// screen content end


参考:《驾驭Makefile》 李云著

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值