makefile的语法规则 通用模版
没有makefile可以直接make
![](http://images0.cnblogs.com/blog/660888/201409/032310298609274.png)
如果文件是a.c可以直接make a 生成 a 可执行文件
![](http://images0.cnblogs.com/blog/660888/201409/032310309535074.png)
@符号是不显示执行的命令信息
test:
@echo "liuwei"
不加@符号
echo "liuwei"liuwei
加上显示
liuwei
-遇到错误也往下执行命令
test:
-rm aaa;
@echo "liuwei"
目录下没有aaa文件
如果没有-,结果就不会输出 liuwei
加上-, 虽然报错,也输出 liuwei
make clean:
make clean 一般都把除了源文件外的文件删除
如果makefile同级目录有clean文件,就会报错
![](http://images0.cnblogs.com/blog/660888/201409/032310319227145.png)
解决之道:
.PHONY:clean 在原来的基础上加上这句话即可解决
.PHONY:clean
clean:
make -C src clean
rm -rf app
make -C 的使用:
libcalc.a:
make -C src libcalc.a
gcc main.c -Iinclude lib/libcalc.a -o app
libcalc.so:
make -C src libcalc.so
gcc main.c -Iinclude -L./lib -lcalc -o app
.PHONY:clean
clean:
make -C src clean
rm -rf app
make后面的 C 选项 表示 进入到 src 的 文件夹内 执行 src 目录里的 指令
![](http://images0.cnblogs.com/blog/660888/201409/032310332826929.png)
Makefile 高级运用 :
通过四个 .c文件 和 makefile 生成一个静态库
![](http://images0.cnblogs.com/blog/660888/201409/032310339225800.jpg)
makefile里写法如下:
test:add.c sub.c dive.c mul.c
gcc -c $^
执行如下:
liuwei@liuwei-virtual-machine:~/calc/src$ make test
gcc -c add.c sub.c dive.c mul.c
test : add.c sub.c dive.c mul.c
test代表目标 后面的四个文件代表这个目标的条件(依赖)
$@ 代表目标
$^ 代表所有条件
$< 代表第一个条件
%.o : %.c 系统的默认行为 // 是指从.c转换成.o,%是通配符,名字需要一样
test.a : add.o sub.o dive.o mul.o
//直接通过.o文件生成静态库ar rcs $@ $^ //注意 %@表示目标文件 %^表示所有的条件(依赖)
生成test.a这个库文件,需要后面四个.o文件
不过现在目录里没有四个o文件,系统只能找到四个c文件
这时候就会想办法从.c生成.o
makefile默认有这种机制生成,
最后再创建静态库
![](http://images0.cnblogs.com/blog/660888/201409/032310347823671.png)
如何查看系统默认这种行为:
make -p > file
通过查看file文件可以得到
![](http://images0.cnblogs.com/blog/660888/201409/032310352192071.png)
然后
![](http://images0.cnblogs.com/blog/660888/201409/032310371724741.png)
可以看到
![](http://images0.cnblogs.com/blog/660888/201409/032310376726655.png)
如何改变这种默认行为:
在makefile里增加
%.o:%.c
gcc -c $<
test.a:add.o sub.o dive.o mul.o
ar rcs $@ $^
%.o:%.c
gcc -c $<
![](http://images0.cnblogs.com/blog/660888/201409/032310385477754.png)
这时候系统从 .c文件到 .o文件 就会 走 这个流程
于是 cc全部 变成了gcc
makefile变量信息:
在makefile里可以定义变量,输出的时候需要 $(变量名)
NAME = liuwei
test:
echo $(NAME)
![](http://images0.cnblogs.com/blog/660888/201409/032310391104181.png)
makefile里有几个默认的参数变量
通过下面图片,可以得出
![](http://images0.cnblogs.com/blog/660888/201409/032310371724741.png)
#编译器参数
CFLAGS 可以修改成 -g -Wall
#预处理参数
CPPFLAGS 可以修改成 -I../include -DDEBUG
#加载器参数 可以修改成 -L../lib
LDFLAGS
makefile 通用模版:
obj = add.o sub.o mul.o dive.o
target = libcalc.a
$(target):$(obj)
//变量在上面生成ar rcs $@ $^
//现在需要.o的时候 通过.c文件走下面的 gcc%.o:%.c
gcc -c $<
![](http://images0.cnblogs.com/blog/660888/201409/032310408447852.png)
makefile的函数使用:
$(wildcard *.c) : //寻找当前目录下的所有 .c 文件
src = $(wildcard *.c)
test:
@echo $(src)
[liuwei@ ~/calc/src]$>make test
add.c dive.c mul.c sub.c
$(patsubst %.c , %.o , %(src)) : //把src目标的所有 .c文件 置换成 .o文件
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))
test:
@echo $(src)
@echo $(obj)
[liuwei@ ~/calc/src]$>make test
add.c dive.c mul.c sub.c
add.o dive.o mul.o sub.o
于是 通用模版 可以 再次变化成 以下形式
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))
target = libcalc.a
$(target):$(obj)
ar rcs $@ $^
%.o:%.c
gcc -c $<
clean:
rm -rf *.o
rm -rf libcalc.a
rm -rf ../lib/libcalc.a
rm -rf ../lib/libcalc.so
![](http://images0.cnblogs.com/blog/660888/201409/032310413449766.png)
练习最终版本:
生成静态库的makefile版本:
pos = ../lib
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))
target = libcalc.a
$(target):$(obj)
ar rcs $@ $^
mv $@ $(pos)
%.o:%.c
gcc -c $<
clean:
rm -rf $(obj)
rm -rf $(pos)/$(target)
![](http://images0.cnblogs.com/blog/660888/201409/032310419695409.png)
生成动态库的makefile版本:
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))
target = libcalc.so
pos = ../lib
$(target):$(obj)
gcc -shared -W -o $@ $(obj) // 此时 $obj 为 四个.o文件 但是目录缺少.o文件,于是走下面的 %.o:%.c
mv $@ $(pos)
%.o:%.c
gcc -fPIC -c $<
clean:
rm -rf *.o
rm -rf $(pos)/$(target)
![](http://images0.cnblogs.com/blog/660888/201409/032310423756351.png)