第一部分整个项目源代码的目录树如下,
├── main.c
├── mytool1.c
├── mytool1.h
├── mytool2.c
├── mytool2.h
└── (makefile)
其中,main.c源代码 (依赖mytool1.h和mytool2.h两个头文件) 如下,
#include "mytool1.h"
#include "mytool2.h"
void main(int argc, char **argv) {
mytool1_print("hi");
mytool2_print("hi");
}
mytool1.h源代码如下,
#ifndef _MYTOOL_1_H
#define _MYTOOL_1_H
void mytool1_print(char *print_str);
#endif
mytool1.c源代码如下,
#include "mytool1.h"
void mytool1_print(char *print_str) {
printf("mytool1 prints: %s\n", print_str);
}
mytool2.h源代码如下,
#ifndef _MYTOOL_2_H
#define _MYTOOL_2_H
void mytool2_print(char *print_str);
#endif
mytool2.c源代码如下,
#include "mytool2.h"
void mytool2_print(char *print_str) {
printf("mytool2 prints: %s\n", print_str);
}
编译有两个阶段:先编译(gcc -c),后链接(gcc -o)。gcc -c表示编译器编译.c源文件,生成.o目标文件 [1]。
编译main.c源文件,生成main.o目标文件如下,
$ gcc -c main.c
编译mytool1.c源文件,生成mytool1.o目标文件如下,
$ gcc -c mytool1.c
编译mytool2.c源文件,生成mytool2.o目标文件如下,
$ gcc -c mytool2.c
gcc -o表示链接器链接.o目标文件,生成.out (可省略) 可执行文件 [2]。链接main.o, mytool1.o和mytool2.o目标文件,生成run可执行文件如下,
$ gcc -o run main.o mytool1.o mytool2.o
运行run可执行文件如下,
$ ./run
mytool1 prints: hi
mytool2 prints: hi
通常,Makefile由 target:dependencies 和 rule 两个部分组成。注意,rule前面空白区域必须用Tab键,不能用空格键。
target: first.dependency second dependency third.dependency
rule
其中,target表示目标生成文件,dependencies表示生成目标生成文件所需的输入文件/依赖文件,rule表示从dependencies到target所需的规则。
举个例子,一个Makefile文件如下,
run: main.o mytool1.o mytool2.o
gcc -o run main.o mytool1.o mytool2.o
main.o: main.c
gcc -c main.c
mytool1.o: mytool1.c
gcc -c mytool1.c
mytool2.o: mytool2.c
gcc -c mytool2.c
编译运行如下,
$ make
$ ./run
mytool1 prints: hi
mytool2 prints: hi
通常,Makefile提供一些含有特殊意义的字符/字符串可以用于简化Makefile代码。这些字符/字符串包括"$@", “$^”, 和"$<",分别表示"target目标文件", “dependencies所有的依赖文件”, 和"first.dependency第一个依赖文件"。
举个例子,一个简化后的Makefile如下,
run: main.o mytool1.o mytool2.o
gcc -o $@ $^
main.o: main.c
gcc -c $<
mytool1.o: mytool1.c
gcc -c $<
mytool2.o: mytool2.c
gcc -c $<
编译运行如下,
$ make
$ ./run
mytool1 prints: hi
mytool2 prints: hi
特殊地,当target:dependencies 中,目标文件使用依赖文件的默认文件名为前缀时,可以使用字符串 “.c.o:” 进一步简化。这里,字符串 “.c.o:” 可以表示 “main.o: main.c”,“mytool1.o: mytool1.c”,和 “mytool2.o: mytool2.c”。
举个例子,进一步简化后的Makefile如下,
run: main.o mytool1.o mytool2.o
gcc -o run main.o mytool1.o mytool2.o
.c o:
gcc -c $<
编译运行如下,
$ make
$ ./run
mytool1 prints: hi
mytool2 prints: hi
另外,当要删除编译之后的**.o**中间文件时,可以使用"clean"方法。
举个例子,删除中间文件的Makefile如下,
run: main.o mytool1.o mytool2.o
gcc -o run main.o mytool1.o mytool2.o
.c o:
gcc -c $<
clean:
rm -rf *.o
编译运行如下,
$ make; make clean
$ ls
main.c makefile makefileOLD mytool1.c mytool1.h mytool2.c mytool2.h run
[1. gcc -c 参数] http://c.biancheng.net/view/666.html
[2. gcc -o 参数] http://c.biancheng.net/view/700.html
[3. Makefile的生成及其简化方法] https://blog.csdn.net/dongzhongshu/article/details/5628459
[感谢一] 感谢dongzhongshu和他的博文makefile .c.o的说明,谢谢。
[备注一] 初稿,2019年07月04号。
[备注二] 二稿,2019年07月05号。