目录
1.Make管理
(1)为什么要使用make管理
当进行大型项目开发的时候,文件会非常的多,几十到上百个源文件,所以每次手工输入GCC命令的话,会非常的麻烦,并且容易出错,所以使用make工具来对项目进行管理;
(2)make的工作方式
make主要工作:
如果仅仅修改了某几个源文件的话,则只需要重新编译这几个源文件即可。
如果是某个头文件修改了,则只需要重新编译包含该头文件的源文件,编译不必要的重复。
如果修改了其中某个源文件,如果其他源文件依赖于该文件,则也要重新编译所有依赖该文件的源文件。
make工作机制:通过一个称为Makefile的文件来完成并自动维护编译工作,Makefile只需要按照相应的某种语法格式来编写,其中最主要的内容是定义了源文件之间的依赖关系,说明了如何编译这个源文件并链接生成可执行文件。
GNU Make当前工作目录下,以如下的方式进行搜索Makefile:
- GNUmakefile
- makefile
- Makefile
(3)make命令选项
命令格式 | 含义 |
-C dir | 读入指定目录下的Makefile |
-f file | 读入当前目录下的file文件为Makefile |
-i | 忽略所有的命令执行错误 |
-I dir | 指定被包含的Makefile所在目录 |
-n | 只打印要执行的命令,但不执行这些命令 |
-p | 显示make变量数据库和隐含规则 |
-s | 在执行命令时不显示命令 |
-w | 如果make在执行过程中改变目录,则打印当前目录名 |
2.Makefile文件
(1)什么是Makefile文件
make命令执行时,需要一个Makefile文件,告诉make命令应该怎么样去编译和链接程序。
一个工程的源文件数量很多,按其类型,功能和模块分别放在若干个目录中,Makefile文件定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,或者更加复杂的操作。
Makefile文件带来的好处是“自动化编译”——一旦写好之后,只需要一个make命令,即可自动编译整个工程。
(2)Makefile基本结构
①Makefile文件的操作规则
- 如果这个工程没有编译过,则所有的C文件都要编译并被链接;
- 如果这个工程的某几个C文件被修改,则只需要编译修改的C文件,并链接目标程序;
- 如果这个工程的头文件被改变了,则需要编译引用了这几个头文件的C文件,并链接目标程序。
②Makefile包含的内容
target:dependency_files
<Tab>command
- target:需要make工具创建的目标体,通常是目标文件或者执行文件;
- dependency_files:要创建的目标体所依赖的文件;
- command:创建每个目标体时需要运行的命令;
提示:在Makefile中的每一个command之前必须有Tab符号(只要在command之前按下tab即可),否则运行make命令时会出错。
(3)Makefile实例
例子1:输出a+b的结果!
新建一个add.c文件:sudo touch add.c
编辑文件:sudo gedit add.c
编写Makefile文件:
add:add.o
gcc add.c -o add(表示目标文件链接成为可执行文件)
add.o:add.c
gcc -c add.c -o add.o(表示源文件编译为目标文件)
clean:
rm *.o add(清除所有以.o结尾的文件)
使用make工具读入Makefile并执行target和command,生成目标文件和可执行文件:
sudo make
运行可执行文件:./add
清除可执行文件:make clean
例子2:稍微复杂一点的实现加,减,乘,除,最后将实现的功能全部放在一个头文件中,在面main.c主函数中调用。
头文件:
main.c文件
编写Makefile文件:
3.Makefile变量
GNU的make工具除了提供有建立目标的基本功能之外,还有很多便于表达式的依赖性关系以及建立目标命令的特点,比如定义变量或者宏定义(如果我们使用的C语言一样的定义)。对于编译几十个C源文件的话,为每一个目标的编译指定冗长的编译选项的话,将非常的不方便和乏味,所以采用变量的方式直接替换。
make中的变量格式为:$(VAR).
比如对其上面的pragram的Makefile文件使用变量替换如下:
提示:如果加入了新的.o文件的话,那么只需要修改objects变量。
注意:变量名不包含“:”,“#”,“=”和结尾空格的任何字符串(变量名中包含字符,数字已经下划线以外的情况应该尽量避免,因为在将来可能被赋予特殊的含义,并且变量名的大小写敏感),Makefile中推荐使用小写字母作为变量名,预留大写字母作为控制隐含规则参数或者用户重载命令选项参数的变量名。
(1)预定义变量
预定义变量就是通常在Makefile都会出现的变量,其中部分为默认值,也就是常见的设定值(用户也可以对其进行修改)。
预定义变量 命令格式 含义 AR 库文件维护程序的名称,默认为ar AS 汇编程序的名称,默认值为as CC C编译器的名称,默认值为cc CPP C预编译器的名称,默认为$(CC)-E CXX C++编译器的名称,默认值为g++ FC FORTRAN编译器的名称,默认值为f77 RM 文件删除程序的名称,默认值为rm -f ARFLAGS 库文件维护程序的选项 ASFLAGS 汇编程序的选项 CFLAGS C编译器的选项 CPPFLAGS C预编译的选项 CXXFLAGS C++编译器的选项 FFLAGS FORTRAN编译器的选项
(2)Makefile的自动变量
自动变量通常可以代表编译语句出现目标文件和依赖文件等,并且有具体的含义。
自动变量 命令格式 含义 $ * 不包含扩展名的目标文件名称 $ + 所有的依赖文件,以空格分开,并出现的先后有序,可能包含重复的依赖文件 $ < 第一个依赖文件的名称 $ ? 所有时间戳比目标文件晚的依赖文件,并以空格分开 $ @ 目标文件的完成名称 $ ^ 所有不重复的依赖文件,以空格分开 $ % 如果目标是归档成员,则该变量表示目标的归档成员名称
(3)Makefile的环境变量
Makefile中还可以使用环境变量。make在启动的时候会自动读取系统当前已经定义了的环境变量,并且会自动创建与之具有相同名称和数值的变量。如果在Makefile中用户自定义了相同的名称变量,那么用户自定义变量将将会覆盖同名的环境变量。
以上面的pragram为例,使用自动变量继续扩展:
这里的CC代表编译器GCC,CFLAGS是一个选项,-Wall表示GCC编译器报所有的警告信息,-g表示在可执行程序中包含标准调试信息。$@表示目标文件pragram,$^表示所有不重复的依赖文件objects。