makefile教程1
扫描二维码
随时随地手机看文章
一 初识Makefile
make是一种用于项目编译的应用程序,本质是一种脚本。而Makefile则是对make脚本的规则描述。仅仅是写脚本编译项目的话shell脚本也是可以做的,用make的原因在于,make可以解析源文件之间的依赖,根据依赖关系自动维护编译工作。执行宿主操作系统中的各种命令。
Makefile是一个描述文件,定义一系列的规则来指定源文件之间的调用先后顺序。有自己特定的语法规则,可以定义函数及函数调用。可以集成各种系统命令。Makefile用于指导make程序如何完成工作。
echo "hello world!"
-
1
-
2
对于文件名,可以叫Makefile或makefile,也可以自定义名称。对于是否自定义Makefile文件名的区别在于使用方式不同。
-
1
-
1
-
1
-
1
makefile建立
通过实现一个加减乘除方法作为例子,文件结构如图所示
最简单的makefile
-
app:add.c jian.c cheng.c chu.c main.c
-
gcc add.c jian.c cheng.c chu.c main.c -I../include -o app
makefile进阶
-
app:add.o jian.o cheng.o chu.o main.o
-
gcc add.o jian.o cheng.o chu.o main.o -o app
-
add.o:add.c
-
gcc -c add.c -I../include
-
jian.o:jian.c
-
gcc -c jian.c -I../include
-
cheng.o:cheng.c
-
gcc -c cheng.c -I../include
-
chu.o:chu.c
-
gcc -c chu.c -I../include
-
main.o:main.c
-
gcc -c main.c -I../include
makefile优化
(1)常用的变量名(约定俗成的):
CC:表示c编译器版本
(2)一些特殊字符
$(变量):对变量取值
(3)特殊变量
用于当前目标:
(4)makefile内置函数
wildcard:按照指定格式获取当前目录下的所有文件名
代码
-
.PHONY:clean #伪目标
-
CC=gcc
-
INCLUDE=-I../include
-
CFLAGS=-c -g -Wall $(INCLUDE) #-g增加调试信息 -Wall严格编译
-
CPPFLAGS=-E -D #-E头文件展开 -D编译时定义宏
-
CXX=g
-
LDFLAGS=-L../lib -lpthread #这只是个例子,并没用到该库。-l库名
-
TARGET=app
-
RM=rm -rf
-
-
SRCFILE=$(wildcard *.c)
-
DEFFILE=$(patsubst %.c,%.o,$(SRCFILE))
-
-
$(TARGET):$(DEFFILE)
-
$(CC) $^ -o $(TARGET)
-
%.o:%.c
-
$(CC) $(CFLAGS) $<
-
-
clean:
-
-$(RM) $(TARGET) $(DEFFILE)
-
install:
-
sudo cp $(TARGET) /usr/bin
-
uninstall:
-
sudo $(RM) /usr/bin/$(TARGET)
二、Makefile基本结构与依赖
Makefile由一个个规则组成,一个规则的结构大致如下:
commands
#include
void func()
{
printf("hello world!\n");
}
-
main.c文件
extern void func();
int main()
{
func();
return 0;
}
Makefile文件:
gcc main.o func.o -o main
gcc -o main.o -c main.c
func.o : func.c
gcc -o func.o -c func.c
目标依赖规则:
-
当目标不存在时,执行对应命令。
-
当依赖在时间上比目标更新时,执行对应命令。
-
当依赖关系连续存在时,要依次向上回溯每个目标。
如果目标存在,但依赖项比目标时间要新,则也要向上检查,生成目标。
三 伪目标的引入
Makefile中的目标指什么?
-
Makefile中目标一般对应着一个文件
-
make比较目标文件和依赖之间的新旧关系,如果依赖新则执行命令
-
make以文件处理作为第一优先级
-
CC := gcc
-
TAGRET := hello.out
-
-
$(TARGET): func.o main.o
-
$(CC) -o $(TARGET) func.O
上述Makefile中第一二行依次定义了变量CC、TARGET,第四五行引用了这两个变量,引用变量采用"变量名或者{变量名}"的形式。
Makefile中的变量只能是字符串类型。
Makefile中变量有四种赋值方式:
1,简单赋值( := ) 编程语言中常规理解的赋值方式,只对当前语句的变量有效
2,递归赋值( = )赋值语句可能影响多个变量,所有目标变量相关的其他变量都受影响
3,条件赋值( ?= )如果变量未定义,则使用符号中的值定义变量。如果该变量已经赋值,则该赋值语句无效。
4,追加赋值( = )原变量用空格隔开的方式追加一个新值
用例子来了解一下各个赋值的差别:
简单赋值
-
x := foo
-
y := $(x)b
-
x := new
-
-
.PHONY : test
-
test:
-
@echo "y => $(y)"
-
@echo "x => $(x)"
输出值:
x => new
y => foob
递归赋值
-
x = foo
-
y = $(x)b
-
x = new
-
-
.PHONY : test
-
test:
-
@echo "y => $(y)"
-
@echo "x => $(x)"
输出值:
y = > newb
x => new
条件赋值
-
x := foo
-
y := $(x)b
-
x ?= new
-
-
.PHONY : test
-
test:
-
@echo "y => $(y)"
-
@echo "x => $(x)"
输出值:
y => foob
x = foo
追加赋值
-
x := foo
-
y := $(x)b
-
x = $(y)
-
-
.PHONY : test
-
test:
-
@echo "y => $(y)"
-
@echo "x => $(x)"
输出结果:
y => foob
x => foo foob
递归赋值就是一个连锁反应,只要之前与该变量直接产生过关联的变量都会有影响。
条件赋值,第一次为变量赋值的时候推荐条件赋值。
五 Makefile中的变量值的替换
1.使用指定字符串替换变量中的后缀字符(串)
格式:或{var:a=b}
注意:替换表达式中不能有空格】
例:
-
src := acc bcc ccc
-
obj := $(src:cc=o)
-
test:
-
@echo "obj => $(obj)"
make test输出结果:
ao bo co
2.变量的模式替换
使用%保留变量值中的指定字符串,替换替他字符
格式:{var:a%b=x%y}
注意:替换表达式中不能有空格
例:
-
src := a123b.c a234b.c ajkhb.c
-
obj := $(src:a%b.c=x%y)
-
test:
-
@echo "obj => $(obj)"
分析:原串 a123b.c按照a%b.c进行模式匹配的时候a与b.c中间的123就会被%匹配到,后边就会被保留下来,a和b.c就会被x和y取代。其他的类似。
make test执行结果:
x123y x234y xjkhy
3.规则中的模式替换
targets:target-pattern:prereq-pattern
command1
command2
意义:通过target-pattern从targets中匹配子目标,再通过prereq-pattern从子目标生成依赖,进而构成完整规则。
例:
-
objs := func.o main.o
-
$(objs): %.o : %.c
-
gcc -o $@ -c $^
分析:
上述第二行,通过%.o匹配objs中的func.o,通过func.c生成依赖,再匹配main.o生成main.c依赖。
上述第二行会被make程序解析成
-
func.o: func.c
-
gcc -o $@ -c $^
-
main.o: main.c
-
gcc -o $@ -c $^
-
4.变量的嵌套引用
一个变量名中可以包含对其他变量的引用
嵌套引用的本质是使用一个变量表示另外一个变量
例:
-
x := y
-
y := z
-
a := $($(x))
分析: 这个很好理解,上述第三行可以解析为
a := $(y) ==> a := z
5.命令行变量
在shell中运行make的时候,在命令行中定义变量
命令行变量可以默认覆盖Makefile中定义的变量。
例:
-
hm := hello makefile
-
test:
-
@echo "hm => $(hm)"
shell中执行 make hm = cmd
执行结果: hm => cmd
6.override关键字
override关键字用于保护Makefile中的变量不被覆盖。
-
override var := dest
-
test:
-
@echo "var => $(var)"
shell中执行 make hm = cmd
执行结果: var =>dest
这个类似于C 中的const关键字
7.define关键字
define关键字用于在Makefile中定义多行变量
变量定义从变量名开始到endef结束
define定义的变量等价于使用 = 定义的变量(递归赋值)
例:
-
define ade
-
Jack!
-
Tom!
-
endef
可以加上override 修饰
-
over define cmd
-
@echo "Run cmd ls..."
-
@ls
-
endif