写在前面
今天学习了$gcc$的基本指令,之前总是望而却步,今天一口气。
前置知识
我们知道,$gcc$在编译$C$语言或者$C++$时,分为四个步骤。
- 预处理 替换头文件和宏,移除注释(.i文件)
- 编译,生成汇编代码 (.s文件)
- 汇编 生成目标文件(机器码 .o文件)
- 链接 生成可执行文件
编译命令
1 2 3 4 5 6 7 8 9 10 11 12 13
| //以下均以test.c为例 gcc test.c //此行代码会直接生成可执行文件,并默认保存为a.out gcc test.c -o test.o //-0指令表示生成文件命名为-o后的名字,若无其他指令则与后缀无关,都是可执行文件 //关于-o,以下几种需要-o重定向输出文件 gcc -S test.c//只处理预处理和编译 生成汇编代码 gcc -E test.c //只预处理 gcc -c test.c //只有预处理、编译、汇编三步,生成obj(.o)文件 gcc -I 路径 test.c //所调用的头文件所涉及的路径 gcc -Dmarco test.c //宏定义 gcc -Dmarc=def test.c//宏定义 gcc -g test.c//编译时,生成调试信息,常常与gdb配合使用 gcc -std=c9//指定语言标准 gcc -On(0-3) //开启编译优化选项,一般使用-O2
|
大明星:$makelist$
怎么样?看了上面的编译命令,是不是觉得原来也不过如此?
但是想一下,如果我们需要编译链接许多文件呢?有没有什么简便的方式呢?
这个时候,$makefile$就要闪耀登场了!
什么是$makefile$?之前用$windows$我从来没见过,因为强大的/一般的$IDE$已经为我们做好了一切事情。
$makefile$其实可以简单理解为指令的集合,是对指定的一些文件进行编译的指令,如果我们一个个写出来会很耗费时间,但是$makelist$可以让我们通过简单的$make$,实现相同的功能。
格式
1 2 3 4 5 6 7 8 9 10 11 12
| 目标文件:[依赖文件集合] 指令
main:test.o delete.o add.o gcc $^ -o $@ test.o:test.c gcc -c test.c -o test.o add.o:add.c gcc -c add.c -o add.o delete.o:delete.c gcc -c delete.c -o delete.o
|
上面只是3个文件,需要一行一行写出来,如果有1000个需要处理的文件呢?还要一行一行写出来未免效率也太低了。这个时候,$makefile$的扩展用法就要登场了。
变量定义
预定义变量
1 2 3 4 5
| $< 代表第一个依赖文件的名称
$@ 代表目标文件的名称
$^ 代表所有依赖文件的名称
|
此外还可以自己定义一些变量。
自定义变量
1 2 3
| CC = gcc CFLAGS = -I ../include
|
举个例子,上面代码可改为
1 2 3
| CC = gcc main:test.o delete.o add.o $(CC) $^ -o $@
|
隐含规则
模式规则
将一个带有某种后缀的文件转换为另一种后缀的文件
1 2
| .c.o: $(CC) $(CCFLAGS) -c -o $@ $<
|
后缀规则
冒号后为依赖文件,冒号前为目标文件
个人感受
1 2
| %.o:%.c(若有多个依赖文件则多写几个%) $(CC) $(CCFLAGS) -c -o $@ $<
|
综合以上规则,$makefile$文件可写为
1 2 3 4 5
| CC = gcc main:test.o delete.o add.o $(CC) $^ -o $@ .c.o: $(CC) -c $< -o $@
|