同时编译多个xxx.c文件
参考文章
make
make是一个命令工具,是一个解释makefile中指令的命令工具,当执行 make 时,make 会在当前的目录下搜寻 Makefile (or makefile) 这个文本文件,执行对应的操作。make 会自动的判别原始码是否经过变动了,而自动更新执行档。
为什么要使用make?
假设,现在一个项目里面包含了100个程序文件,如果要对这个项目进行编译,那么光是编译指令就有100条。如果要重新进行编译,那么就又得像之前一样重新来一遍。所以,用make来进行操作,间接调用gcc比较方便。如果我们更动过某些原始码档案,则make 也可以主动的判断哪一个原始码与相关的目标文件档案有更新过, 并仅更新该档案。这样可以减少重新编译所需要的时间,提高效率。
makefile
makefile其实就是一个文档,里面定义了一系列的规则指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,它记录了原始码如何编译的详细信息! makefile一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
语法规则
[Target/目标文件]:[Dependeds/依赖文件] [Dependeds/依赖文件] [Dependeds/依赖文件]...
[Command/命令] (命令前面需要按一下tab键)
//注意:命令前面不是空格,而是一个TAB键
//在Makefile文件中,注释符号为"#"
假设有几个程序:
Demo:main.o add.o sub.o ## 目标文件为:Demo 依赖文件为:main.o add.o sub.o
gcc main.o add.o sub.o -o Demo ## 使用gcc编译main.o add.o sub.o并生成名为Demo的可执行文件
add.o:add.c add.h ## 目标文件为:add.o 依赖文件为:add.c add.h
gcc -c add.c ##使用gcc编译add.c并生成add.o文件(默认)
sub.o:sub.c sub.h ## 目标文件为:sub.o 依赖文件为:sub.c sub.h
gcc -c sub.c ## 使用gcc编译sub.c并生成sub.o文件(默认)
main.o:main.c add.h sub.h ## 目标文件为:main.o 依赖文件为:main.c add.h sub.h
gcc -c main.c ## 使用gcc编译main.c并生成main.o文件(默认)
创建一个名字为Makefile的文件夹编辑如下图内容 然后使用make去执行(同时会生成xxx.o文件)
如果我们自己写的头文件刚好和xxx.c文件在同一目录,可以在Makefile中省略头文件。
例如,我们所有的文件. h和. c都在同一目录下,我们可以省略掉头文件:
如何删除不需要的.o文件
注意:
make指令是默认执行再最前面的语句。所以我们输入make的时候,相当于默认执行make Demo,当我们需要清楚除.o文件的时候就需要执行 make clean
makefile其实可以更加简洁的—自动推导
自动推导 make会自动推导目标文件后面的依赖文件。例如: 目标文件add.o,make将会自动推导出它有源文件add.c。
用户自定义变量 我们可以自定义一个OBJS变量和RM变量来分别替换 “main.o add.o sub.o ”和“ rm -f *.o”
OBJS = main.o add.o sub.o
RM = rm -f *.o
当我们需要使用变量的时候就可以用$来引用
$(OBJS)
$(RM)
我理解成就是字符串替换的意思 makefile中已经定义的变量(默认)
————————————————————————————————————————————————————————————————————————————————————
变量名 | 含义 | 默认值
————————————————————————————————————————————————————————————————————————————————————
AR | 生成静态库库文件程序的指令 | ar
————————————————————————————————————————————————————————————————————————————————————
AS | 汇编编译器的名称 | as
————————————————————————————————————————————————————————————————————————————————————
CC | C语言编译器的名称 | cc
————————————————————————————————————————————————————————————————————————————————————
CPP | C语言编译器的名称 | $(CC)-E
————————————————————————————————————————————————————————————————————————————————————
CXX | C++语言编译器的名称 | g++
————————————————————————————————————————————————————————————————————————————————————
FC | FORTRAM语言编译器的名称 | f77
————————————————————————————————————————————————————————————————————————————————————
RM | 删除文件程序的名称 | rm -f
————————————————————————————————————————————————————————————————————————————————————
ARFLAGS | 生成静态库库文件程序的选项 | 无默认值
————————————————————————————————————————————————————————————————————————————————————
ASFLAGS | 汇编语言编译器的编译选择 | 无默认值
————————————————————————————————————————————————————————————————————————————————————
CFLAGS | C语言编译器的编译选项 | 无默认值
————————————————————————————————————————————————————————————————————————————————————
CPPFLAGS | C语言预编译的编译选项 | 无默认值
————————————————————————————————————————————————————————————————————————————————————
CXXFLAGS | C++语言编译器的编译选项 | 无默认值
————————————————————————————————————————————————————————————————————————————————————
FFLAGS | FORTRAN语言编译器的编译选项 | 无默认值
————————————————————————————————————————————————————————————————————————————————————
自动变量
Makefile中的变量除了用户自定义变量和预定义变量外,还有一类自动变量。
Makefile中的编译语句经常会出现目标文件和依赖文件,自动变量可以去代替目标文件和依赖文件。
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
变量 | 含义
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
$* | 表示目标文件的名称,不包含目标文件的扩展名
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
$+ | 表示所有的依赖文件,这些依赖文件之间以空格分开,按照出现的先后顺序,其中可能包含重复的文件
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
$< | 表示依赖项中第一个依赖文件的名称
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
$? | 依赖文件中,所有目标文件时间戳晚的依赖文件,依赖文件之间以空格分开
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
$@ | 目标项中目标文件的名称
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
$^ | 依赖项中,所有不重复的依赖文件,这些文件之间空格分开
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
示例
Demo:main.o add.o sub.o
gcc $^ -o $@
## gcc main.o add.o sub.o -o Demo
add.o:add.c add.h
gcc -c $<
## gcc -c add.c
sub.o:sub.c sub.h
gcc -c $<
## gcc -c sub.c
main.o:main.c add.h sub.h
gcc -c $<
## gcc -c main.c
模式匹配
例如:对于模式规则 “%. o : %. c ”,它表示的含义是:所有的 . o 文件依赖于对应的 . c文件。我们可以使用模式规则来定义隐含规则。
%.o: %.c
上面一句等同于下面两句
add.o: add.c
sub.o: sub.c
当文件路径不同的情况,如何编译?
VPATH 可以在Makefile文件中指定VPATH变量,指定make从指定文件目录中去找文件
VPATH = [第一个路径]:[第二个路径]:[第三个路径]:....
但是make的时候会提示找不到头文件的错误
CFLAGS指定头文件的位置
如果makefile在路径~TEXT下,还可以简化写法
这里的VPATH,和CFLAGS可以这样简写是因为当前的路径就是~/TEXT。而且需要在VPATH中多指明 demo这个文件夹,因为主函数main.c是在这个目录里面的。
|