首先我们创建两个文本文档实验,第一个文本文档我们名为a.c,第二个文件名为b.c,在第一个文件中调用文件b的函数。
简单的代码如下
a.c文件:
#include <stdio.h>
int main()
{
func_b();
return 0;
}
b.c文件:
#include <stdio.h>
void func_b()
{
printf(“this is b\n”);
}
将两个文就上传到服务器,执行编译指令 gcc -o test a.c b.c对两个文件进行编译,编译可能会有警告,但是问题不大,编译完成之后使用指令 :./test运行文件可以得到b.c文件中的函数运行结果。
gcc -o test a.c b.c这句指令中分为四个步骤:1.预处理,2.编译,3.汇编,4连接。
预处理后a.c变为xxx.S文件再变为xxx.o的文件后与处理好后的b.c连接在一起。
但是这句指令也有其缺点,他会把所有文件都重新编译一边(不管这个文件是否有过修改),当文件较多时一般不使用这一句编译指令。
但是也有可以解决的方法,例如用下面这几条语句
1.gcc -c -o a.o a.c//把a.c编译为a.o
2.gcc -c -o b.o b.c//把b.c编译为b.o
3.gcc -o test a.o b.o//把a.o与b.o连接在一起
那么问题又来了,如何判断那些文件被修改,
比较xxx.o与xxx.c的修改时间,如果xxx.c的时间比xxx.o的时间更新的话,那就是被修改过的。
下面来说一下Makefile最基本的规则:
目标文件:依赖文件(当依赖比目标新就执行命令)
TAB键后面跟命令
简单的Makefile逻辑
例如test依赖于a.o与b.o
test:a.o b.o
(如果a.o与b.o比test新那就执行gcc -o test a.o b.o生成新的test)
a.o:a.c
(如果a.c比a.o新那就执行gcc -c -o a.o a.c)
b.o:b.c
(如果b.c比b.o新那就执行gcc -c -o b.o b.c)
接下来我们写一个简单的Makeflie:
test:a.o b.o
gcc -o test a.o b.o
a.o:a.c
gcc -c -o a.o a.c
b.o:b.c
gcc -c -o b.o b.c
保存后上传到服务器,使用make命令会自动寻找当前文档下的Makefile并且执行;
到此第一个实验基本完成
接下来我们开始第二个实验:
先大概了解一下Makefile的语法知识
首先是通配符: %.o
$@:表示目标
$<: 表示第一个依赖文件
$^: 表示所有依赖文件
上个实验中修改后的代码如下:(再增加一个空文件c.c)
test:a.o b.o c.o
gcc -o test $^
%.o:%.c
gcc -c -o $@ $<
接下来我们加入一个clean
代码如下:
test:a.o b.o c.o
gcc -o test $^
%.o:%.c
gcc -c -o $@ $<
clean:
rm *.o
.PHONY: clean
(.PHONY:)为假想目标
我们进行下个实验 即时变量:
简单变量(即时变量)
A := xxx #A的值即刻确定,在定义时即确定
B = xxx #B的值在使用到时才确定
:= # 即时变量
= # 延时变量
?= # 延时变量,如果是第一次定义才起效,如果在前面该变量已定义则忽略这句
+= # 附加,他是即时变量还是延时变量取决于前面的定义
执行如下代码:
A := $©
B = $©
C= abc
D = 100ask
D ?=SUNNN
all:
@echo A= $(A)
@echo B= $(B)
@echo D= $(D)
C +=123
执行结果:
A=
B= abc 123
D= 100ask
第三个实验到这里结束
接下来我们进行第四个实验=====Makefile一些函数
1.$(foreach var,list,text)
实验代码如下:
A = a b c
B =
(
f
o
r
e
a
c
h
f
,
(foreach f,
(foreachf,(A), $(f).o)
all:
@echo B = $(B)
输出结果:
B = a.o b.o c.o
2.$(filter pattern…,text) # 在text中取出符合patten格式的值
$(filter-out pattern…,text) #在text中取出不符合patten格式的值
实验代码如下:
A = a b c
B =
(
f
o
r
e
a
c
h
f
,
(foreach f,
(foreachf,(A), $(f).o)
C= a b c d/
D =
(
f
i
l
t
e
r
(filter %/,
(filter©)
E =
(
f
i
l
t
e
r
−
o
u
t
(filter-out %/,
(filter−out©)
all:
@echo B = $(B)
@echo D = $(D)
@echo E = $(D)
3. $(wildcard pattern) #pattern定义了文件名的格式
#wildacard取出其中存在的文件
实验代码如下:
A = a b c
B =
(
f
o
r
e
a
c
h
f
,
(foreach f,
(foreachf,(A), $(f).o)
C= a b c d/
D =
(
f
i
l
t
e
r
(filter %/,
(filter©)
E =
(
f
i
l
t
e
r
−
o
u
t
(filter-out %/,
(filter−out©)
files = $(wildcard *.c)
files2 = a.c b.c c.c d.c e.c
files3 = $(wildcard $(files2))
all:
@echo B = $(B)
@echo D = $(D)
@echo E = $(D)
@echo files = $(files)
@echo files2 = $(files3)
实验结果:
B = a.o b.o c.o
D = d/
E = d/
files = a.c b.c
files2 = a.c b.c
4.
(
p
a
t
s
u
b
s
t
p
a
t
t
e
r
n
,
r
e
p
l
a
c
e
m
e
n
t
,
(patsubst pattern,replacement,
(patsubstpattern,replacement,(var)) #从列表取出每一个值,如果符合pattern,则替换为replacement
实验代码如下:
A = a b c
B =
(
f
o
r
e
a
c
h
f
,
(foreach f,
(foreachf,(A), $(f).o)
C= a b c d/
D =
(
f
i
l
t
e
r
(filter %/,
(filter©)
E =
(
f
i
l
t
e
r
−
o
u
t
(filter-out %/,
(filter−out©)
files = $(wildcard *.c)
files2 = a.c b.c c.c d.c e.c
files3 = $(wildcard $(files2))
dep_files =
(
p
a
t
s
u
b
s
t
(patsubst %.c,%.d,
(patsubst(files2))
all:
@echo B = $(B)
@echo D = $(D)
@echo E = $(D)
@echo files = $(files)
@echo files3 = $(files3)
@echo dep_files = $(dep_files)
实验结果:
B = a.o b.o c.o
D = d/
E = d/
files = a.c b.c
files3 = a.c b.c
dep_files = a.d b.d c.d d.d e.d