gcc编译单个文件,makefile可按照编程的规则编译单个,或多个文件。参考网络上的视频和大神的帖子整理出自己会用到的如下。
makefile基本语法:
一.语法格式:
目标:依赖
(tab)命令
例1:
all:
gcc test1.c -o test1
例2: (clean:删除编译产生的.o文件以及test1可执行文件)
all:test1.o
gcc test1.o -o test1
test1.o:test1.c
gcc -c test1.c
clean:
rm -rf *.o test1
二.声明“伪目标”
如果make目标与路径下文件名重复,编译会出错,如下:
这时候需要声明伪目标
格式:
.PHONY:目标
all:
gcc test1.c -o test1
.PHONY:clean
clean:
rm -rf *.o test1
三.赋值:
1.'=':赋值最后被指定的值
2.'?=':前面有赋值,赋前面的值,没有赋值,赋当前值
3.':=':直接赋值,赋当前值
4.'+=':追加赋值(注意,输出的变量中间有空格)
例:'='
var1=aaa
var2=$(var1)bbb
var1=ccc
all:
echo $(var2)
输出 cccbbb
例:'?='
var1=aaa
var2=$(var1)bbb
var1?=ccc
all:
echo $(var2)
输出 aaabbb,因为前面已经对var1赋值了,所以var1=ccc不会赋值
例:':='
var1:=aaa
var2=$(var1)bbb
var1:=ccc
all:
echo $(var2)
输出 aaabbb,因为在执行var2=$(var1)bbb前,执行了var1:=aaa,在此刻立即赋值。
例:'+='
var1:=aaa
var2=$(var1)bbb
var1+=ccc
all:
echo ${var2}
输出‘aaa cccbbb’
四.预定义变量&通配符
'$<':第一个依赖文件名
'$@':目标的完整名称
'$^':目标所对应的所有依赖
'%':通配符
例:
var:=hello.o main.o
hello.o:$(var)
gcc -o $(var) hello # 这里的$(var)可以替换为'$^',代表依赖文件的列表,也就是上面的hello.o main.o
# gcc -o $^ hello
%.o:%.c # %.o代表所有的.o,hello.o,main.o
# %.c代表所有的.c,hello.c,main.c
gcc -c $^ -o $@ # $^ 代表第一个依赖,hello.c,main.c
# $@ 代表所有的目标
#######以上的makefile可以释义成以下#################################
var:=hello.o main.o
hello.o:hello.o main.o
gcc -o hello.o main.o hello
hello.o:hello.c
gcc -c hello.c -o hello.o
main.o:main.c
gcc -c main.c -o main.o
~
五.函数
1.wildcard函数
功能:展开指定的目录,如果有多个目录,用空格隔开
格式:$(wildcard PATTENR)
test目录下有a.c,test/test1目录下有b.c,现在要将目录展开得到.c文件
var=$(wildcard ./*.c ./test1/*.c)
all:
echo $(var)
执行make得到
root@ubuntu:/home/alon/test# make
echo ./a.c ./test1/b.c
./a.c ./test1/b.c
2.notdir函数
功能:去掉路径
格式:$(notdir $(var))
在1.wildcard函数例子中,我们得到的是./a.c 和./test1/b.c这两个文件的路径,那我们现在要获得这两个文件的文件名,就需要用到该命令
var=$(wildcard ./*.c ./test1/*.c)
var1=$(notdir $(var))
all:
@echo $(var1)
执行make我们得到
root@ubuntu:/home/alon/test# make
a.c b.c
3.dir命令
功能:打印目录
格式:$(dir $(var))
var=$(wildcard ./*.c ./test1/*.c)
var1=$(notdir $(var))
var2=$(dir $(var))
all:
@echo $(var2)
执行make得到
root@ubuntu:/home/alon/test# make
./ ./test1/
4.patsubst命令
功能:替换文件后缀名(不替换源文件后缀名)
格式:$(patsubst 源文件,目标文件,源文件列表)
var=$(wildcard ./*.c ./test1/*.c)
var1=$(notdir $(var))
var2=$(dir $(var))
var3=$(patsubst %.c,%.s,$(var))
all:
@echo $(var3)
执行make得到
root@ubuntu:/home/alon/test# make
./a.s ./test1/b.s
ls命令看一下原.c文件并没有被改变
root@ubuntu:/home/alon/test# ls ./*.c ./test1/*.c
./a.c
./test1/b.c:
5.foreach函数
格式:$(foreach <var>,<list>,<text>)
功能:把参数<list>中的单词逐一取出放到参数<var>所指定的变量中,然后再执行<text>中包含的表达式。
var=$(wildcard ./*.c ./test1/*.c)
var1=$(notdir $(var))
var2=$(dir $(var))
var3=$(patsubst %.c,%.s,$(var))
var4=$(foreach n,$(var2),$(wildcard $(n)*.c)) # $(var2)的值给n,是a.c与b.c的路径,也就是./ ./test1/
# 然后执行wildcard命令,展开n路径下所有的.c文件
all:
@echo $(var4)
执行make看一下结果
root@ubuntu:/home/alon/test# make
./a.c ./test1/b.c