Makefile笔记

Makefile笔记

Makefile为make工具提供一系列规则,是Linux下变成的有效生产力工具。make在后面不加参数时,会自动寻找Makefile,后面不加目标文件,默认生成第一条规则定义的文件。

参考链接

文件格式

Makefile的每一条规则的形式如下:

<target> : <prerequisities>
[tab] <command>

每条规则说明:构建(build)目标的前置条件是什么,如何构建。其中,“目标”是必需的,“前置条件”和“命令”至少有一个。

target

target通常是文件名,指明要构建的对象。

还有一种用法,使用“伪目标”来执行操作

.PHONY: clean #声明clean是伪目标
clean:
	rm *.o #清除.o文件的操作

prerequisites

前置条件通常是一组文件名,之间用空格分割。

指定了“目标”是否重建的判别标准:前置文件有过更新(前置文件的last-modification时间戳比目标文件的时间戳新),目标文件就需要重建。

如果前置文件没有,会报错停止。

result.txt: source.txt
	cp source.txt result.txt

commands

命令表示如何更新目标文件,由一行或多行的shell命令组成,它是构建“目标”的具体指令,运行结果通常是生成目标文件。

基本语法

注释

和shell一样,注释是用#号

回声

正常情况下,make会打印每条命令,然后执行,可以在命令之前加上@可以关闭回声(echoing)

.PHONY: test
test:
	@echo "hello" #@号关闭了回声

只输出hello

通配符

Makefile中的通配符与bash一致,主要是?和*

模式匹配

使用%方便处理大量同类文件

%.o : %.c
#等价于
#f1.o:f1.c
#f2.o:f2.c
#......

变量

Makefile允许自定义变量

v1 = Hello World
v2 = $(v1)
test:
	@echo $(v2) #变量要被包裹在$()中
	@echo $$HOME #调用shell变量时,要多加一个$进行转义

赋值方式有多种

VARIABLE = value
# 在执行时扩展,允许递归扩展。

VARIABLE := value
# 在定义时扩展。

VARIABLE ?= value
# 只有在该变量为空时才设置值。

VARIABLE += value
# 将值追加到变量的尾端。

Makefile还有内置变量

比如,$(CC) 指向当前使用的编译器,$(MAKE) 指向当前使用的Make工具。这主要是为了跨平台的兼容性。

自动变量

(1)$@指代当前正在构建的目标

a.txt:
	@touch $@ #指代正在构建的a.txt
#等价于
#a.txt:
#	@touch a.txt

(2) $<指代第一个前置条件

a.txt: b.txt c.txt
    cp $< $@ #这里$<指代b.txt
#等价于
#a.txt: b.txt c.txt
#    cp b.txt a.txt

(3) $?指代比目标更新的所有前置条件,中间用空格隔开。比如,规则为t: p1 p2,其中p2的时间戳比t新,$?就指代p2

(4) $^ 指代所有前置条件,之间以空格分隔。比如,规则为t: p1 p2,那么$^就指代p1 p2

(5) $* 指代匹配符%匹配的部分,比如%匹配f1.txt中的f1,$*就表示 f1

(6) $(@D) 和 $(@F) 分别指向 $@ 的目录名和文件名。

(7)$(<D) 和$(<F) 分别指向 $< 的目录名和文件名。

例子

dest/%.txt: src/%.txt
    @[ -d dest ] || mkdir dest
    cp $< $@

上面代码将src目录下的txt文件,拷贝到 dest 目录下。首先判断dest目录是否存在,如果不存在就新建,然后,$<指代前置文件(src/%.txt),$@指代目标文件(dest/%.txt)。

判断和循环

判断训话的语法和bash一致

#if语句
ifeq ($(CC),gcc)
  libs="gcc"
else
  libs="not gcc"
endif
testIf:
	@echo $(libs)

#循环
LIST = one two three
#不同行makefile中的shell属于不同进程,在同一行用;分隔可以在同一个shell内执行,
#"\"可以连接多行
all:
	@for i in $(LIST); \ 
	do \
		echo $$i; \
	done

Makefile函数

函数调用格式

$(function arguments)

常用函数举例

(1) shell

可以执行shell命令

test:
	@echo $(shell pwd)

(2)wildcard

可以使用bash的通配符

test:
	@echo $(wildcard dir/*.txt)

(3) subst

文本替换函数

#格式
$(subst from,to,text)

comma = ","
#空变量
empty =
#空格需要用空变量作为标识符
space = $(empty) $(empty)
foo = "a b c"
#不能有多余空格
bar = $(subst $(space),$(comma),$(foo))

test:
	@echo $(bar)

(4) patsubst

用于模式匹配的替换

#格式
$(patsubst pattern,replacement,text)

#将文件名"x.c.c bar.c",替换成"x.c.o bar.o"
$(patsubst %.c,%.o,x.c.c bar.c)

(5) OUTPUT

替换后缀名

min: $(OUTPUT:.js=.min.js)

编译C语言项目例子

edit : main.o kbd.o command.o display.o 
    cc -o edit main.o kbd.o command.o display.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
    cc -c display.c

clean :
     rm edit main.o kbd.o command.o display.o

.PHONY: edit clean
posted @ 2017-10-08 12:15  潇雨危栏  阅读(452)  评论(0编辑  收藏  举报