#System:centos
我们知道在vs中开发一个项目可以建立很多的文件包括各种头文件和.c 文件,编译的时候程序会自动编译链接。然而在linux下开发程序,当项目较大,文件又多时,我们需要将这些文件组织起来进行编译链接,这就需要用到make工具和makefile文件了;
make:
make是linux中的一个常用命令,在当前目录下,输入make,系统会自动在当前目录中寻找名为Makefile或makefile的文件,并对之进行解释处理,完成其指定功能;
Makefile文件
其实这里最重要的就是写好Makefile,Makefile写好了直接make就可以得到可执行文件,Makefile简单点理解就是各程序文件的组织结构;
语法规则:
targets :prerequisites
command
。。。
targets是目标名,一般来说是一个文件名;
prerequisites是目标所依赖的文件;多个文件中空格隔开,太长以\换行
command为命令行,tab开头(makefile中tab开头的视为命令)
这个规则告诉make文件的依赖关系和如何生成目标文件
文件的基本层级为从上往下一一细分
# 为注释符
举个例子就懂了,有下个几个文件:main.c ; add.c ; cout.c ; hello.c main.h 共5个文件。之间的关系为每个.c文件中都include main.h文件
在main.c文件中调用了其他3个.c文件;
makefile如下:
all:test
test: main.o add.o hello.o cout.o
gcc main.o add.o hello.o cout.o -o test
main.o: main.c main.h
gcc -c main.c
add.o: add.c main.h
gcc -c add.c
hello.o: hello.c main.h
gcc -c hello.c
cout.o: cout.c main.h
gcc -c cout.c
clearn:
rm cout.o
执行make之后,文件目录下就有main.o ;add.o ;hello.o ;cout.o ;test
test就是可执行文件,./test 就能输出结果。
这里前几行也可以这样写:
all:main.o add.o hello.o cout.o
gcc main.o add.o hello.o cout.o -o all
最终目标是all文件而不是test文件,makefile文件中第一行显示的目标一般视为文件需要实现的最终目标;
test通过链接几个.o 文件来生成
.o 文件通过编译相应的.c 文件来生成,加上相应的.h 文件,完整的命令应该是:gcc -c .c -o *.o 因为gcc -c会自动生成相应的.o文件,因此这里不需要-o;整个文件就说明了文件的依赖关系和目标文件的生成方式;当文件中任意文件发生更改,make会根据文件修改时间找到修改后的文件并对该文件及相关的内容重新编译,再更新目标文件;
目标名称的指定有以下惯例:
上面的clean被称为伪目标,makefile不生成这个文件,它一般也没有依赖文件,因此make无法生成它的依赖关系和决定它是否要执行。只有通过显示地指明这个目标才能让其生效。即:make clean 就能执行clean下的命令;注意的是伪目标的取名不能和文件名重名;也可以用.PHONY来声明伪目标;
自动生成依赖关系
对于头文件来说,可以通过makefile命令来自动生成其与源程序文件的依赖关系,
gcc -MM main.c ,它会自动添加main.c 依赖的头文件
Makefile中的变量
在makefile中也是可以定义变量的,makefile中的变量类似于C/C++中的宏,代表一个文本字符串,在程序执行的时候自动展开,区别是它是可以改变的;
变量的声明和定义:
变量声明时需要赋予初值,使用时需要在前面加上$,习惯用()括起来;
几种定义的方式:
1、object = main.c add.c hello.c cout .c
2、object := $(object1)
3、
define object
main.c
hello.c
endef
object为变量名,后面跟的为变量值;第一种为常见的=赋值,第二种和第一种相似,但规定前面的变量不能使用后面的变量,只能使用前面已经定义好的变量(变量的递归应用),最后一种和C中类似;
支持嵌套,支持+=赋值等等;
函数调用
在makefile中可以进行函数的调用,里面有一些常用的基本函数: subst; findstring; filter; sort; dir; notdir; 等等,这里不一一介绍;