分享

C/C++(10)C/C++ 关于Makefile的编写

 星光闪亮图书馆 2020-02-05

1. 源代码

第一部分整个项目源代码的目录树如下,

├── 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); 
}


2. 手动编译

编译有两个阶段:先编译(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


3. Makefile(基础版)自动编译

通常,Makefile由 target:dependenciesrule 两个部分组成。注意,rule前面空白区域必须用Tab键,不能用空格键。

target: first.dependency second dependency third.dependency
<replace with a Tab> 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


4. Makefile(简化版)自动编译

通常,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


5. 编译后删除中间文件

另外,当要删除编译之后的**.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./view/666.html
[2. gcc -o 参数] http://c./view/700.html
[3. Makefile的生成及其简化方法] https://blog.csdn.net/dongzhongshu/article/details/5628459


备注

[感谢一] 感谢dongzhongshu和他的博文makefile .c.o的说明,谢谢。
[备注一] 初稿,2019年07月04号。
[备注二] 二稿,2019年07月05号。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多