- makefile工程管理
1.1 makefile概述
linux 环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序员,至少不能称得上是unix程序员。在linux环境下使用GNU的make工具能够比较容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译,链接以至于最后的执行 ,不过这需要我们投入一些时间去完成一个或者多个称为makefile文件的编写,次文件正是make正常工作的基础。所要完成的makefile文件描述了整个工程的编译,链接等规则。
Make是一个命令工具,它解释makefile中的指令(应该说是规则)。在makefile文件中描述了整个工程所有文件的编译顺序、编译规则。Makfile有自己的书写格式。像c语言有自己的格式、关键字和函数一样。而且在makefile中可以使用系统shell所提供的任何命令来完成想要的工作。
首先我们需要明确一些基本概念:
编译:把高级语言书写的代码转换为机器语言可识别的机器码。编译高级语言后生成的指令虽然可被机器识别,但是还不能被执行。编译时,编译器检查高级语言的 语法,函数与变量的声明是否正确。只有所有的语法正确、相关变量定义正确编译器就可以编译出中间目标文件。通常,一个高级语言的源文件都可对应一个目标文件。目标文件在linux中默认后缀为“.o”(如“foo.c”的目标文件为“foo.o”)
链接:将多个.o 文件,或者.o文件和库文件链接成为可被操作系统执行的可执行程序(linux环境下,可执行文件的格式“ELF”格式),连接器不检查函数所在的源文件,只检查所有.o文件中定义的符号。将.o文件中使用的函数和其他.o或者库文件中的相关符号进行合并,对所有文件中符号进行重新安排(重定位),并连接系统相关文件(程序启动文件等)最终生成可执行文件。连接过程使用GNU的“ld”工具。
- makefile 规则的介绍:
make 需要开发者 自己构建 创建 。创建文件的名称: Makefile makefile 。
模型:
Target………. : prerequisites………..
(tab键) Command………….
目标文件 (a.out 可执行文件):依赖文件(xxx.c)
(以tab键开始)依赖文件生成目标文件的 指令
执行一个makfile文件需要 输入 make 指令 ,make指令能够寻找当前路径下面的makefile文件。
案例1:
a:main.c menu.c book.c
gcc -o a main.c menu.c book.c
通过版本1:得出版本2:
aa:main.o menu.o book.o
gcc -o a main.o menu.o book.o
main.o:main.c
gcc -c main.c
menu.o:menu.c
gcc -c menu.c
book.o:book.c
gcc -c book.c
.PHONLY:clean # 伪目标
clean:
rm -rf *.o
rm -rf aa
总结: 1. 整个makefile 文件 通过 在依赖关系上面做文章 。
2. 当在终端输入一个make 指令之后会寻找相应的makefile 文件,会将makefie当中第一个目标文件当作最终的可执行文件,如果目标文件不存在,会找相应的依赖文件。如果依赖文件不存在,会继续向下寻找以依赖文件为目标文件的依赖文件,如果依赖文件存在,则执行 将依赖文件转化成 目标文件。然后最终的目标文件的 依赖文件都产生,再将依赖文件转换成最终的 目标文件。
3. 依赖文件可以当作目标文件来对待。
4. clean : 不是真正的目标文件 是伪目标 文件: 简单 : 当作声明来理解.对应的指令是 make clean
展开后的写法:
.PHONLY:clean # 伪目标
clean:
rm -rf *.o
rm -rf aa
5. makefile 文件中的注释 用 #
- Makefile中使用变量
在makefile中 经常会使用变量,一般用obj object ……….等等 。
变量的赋值 = : 直接赋值
+= : 以追加的形式赋值
?= : 如果变量没有赋值,则将右值赋给变量,如果变量有赋值,以变量的赋值为标准。
:= : 覆盖之前的赋值。
案例:
@ : 取消提示指令符
all : 所有的目标文件 后面可以没有依赖文件
变量的取值: $( 变量名 )
obj=123
all:
@echo "$(obj)"
运行结果:
[root@localhost val]# make
echo "123" // 没有加@ 标志
123
[root@localhost val]# make
123
[root@localhost val]#
案例2 : 已追加的形式赋值
obj=123
obj+=456
all:
@echo "$(obj)"
运行结果:
[root@localhost val]# make
123 456
案例:?=
#obj=main.c
obj ?=obj.c
all:
@echo "$(obj)"
运行结果:
[root@localhost val]# make
obj.c
[root@localhost val]#
案例:
obj=main.c
obj :=obj.c
all:
@echo "$(obj)"
% : 在makefile当中 匹配任意的字符串
%.c : 匹配任意的xxxx.c 文件
%_config : 匹配的是任意的 xxxx_config 配置文件
案例:
val=main.c hello.c book.c kkkk.c
val2=$(val:%.c=%.s)
all:
@echo "$(val2)"
@echo "$(val)"
运行结果:
[root@localhost val]# make
main.s hello.s book.s kkkk.s
main.c hello.c book.c kkkk.c
[root@localhost val]#
练习: 将hello替换world
val=hello
val2=$(val:%hello=%world)
all:
@echo "$(val2)"
注意: 遇到.c 文件下面要写makefile 文件。
- Make的命令行选项如下:
-C (大写) dir 读入指定目录下的makefile (切换路径)
-f file 读入当前目录下的file文件作为makefile
-i 忽略所有的命令行错误
-I (大写i)指定被包含得makfile 所在目录 找头文件
-w 如果make在执行过程中改变目录,则打印当前目录名
-s 在执行命令时不显示命令
-p 显示make 变量数据库和隐含规则。
- Makflie常用的自动变量:
$@: 全部的目标文件
$^: 全部的依赖文件
$<: 第一个依赖文件
练习:
menu:
第二个makefile
obj=main.o
obj+=menu.o book.o
CC=gcc
DEST=ss
$(DEST):$(obj)
$(CC) -o $(DEST) $(obj)
main.o:main.c
$(CC) -c $^ -I include
menu.o:
make -C menu
book.o:book.c
$(CC) -c $^
clean:
rm -rf *.o
rm -rf aa
来源:CSDN
作者:Terry_fan
链接:https://blog.csdn.net/Running0000/article/details/103463796