编译那点事儿:从GCC/G++为例到make再到CMake

静态语言如C,C++,java都是需要提前编译好才能执行的,今天聊聊如何快速的编译一个工程,先从最简单的编译一个C代码文件工程(一个.c也能叫工程的没毛病 囧)开始吧!

编译一个C文件,一般都是使用GCC,那么以gcc编译器为例,将编译过程按照我个人的理解进行剖析一下吧,编译一般是分四步:1.预编译 2.编译为汇编代码 3.汇编 4.连接

以一个最简单的C代码为例子:

//mian.c文件

#define YUBIANYIPROCESSVALUE 8888
int main()
{
	int value = YUBIANYIPROCESSVALUE;
	printf("Hello World,my value = %d\n",value);
	getchar();
	return 0;
}

如何编译成一个可在执行程序呢?先假设程序员同志们已经安装了mingGw,并配置好了环境变量(具体怎么配置百度或参见其他文章吧)。现在我们用gcc命令在终端进行编译,如上所诉,分四步:

1.预编译

gcc指令:

//-E指定gcc将main.c进行预编译处理并将结果输出到main.i文件
gcc -E main.c -o main.i

我们来看看执行结束后main.i的结果是什么样的呢?

看到8888了吗?这就是预处理后的代码

可以看到和源代码main.c相比只是将#define的宏YUBIANYIPROCESSVALUE替换成了8888,这就是预处理做的工作(除了#define还是那些C语言代码需要预处理呢???),它会将C代码中所有需要预处理的地方都进行预处理,包括define、模版等等。

2.编译为汇编代码

现在我们已经得到了预处理后的结果文件main.i文件,接下来我们就要进行第二步,将预处理后的文件编译成汇编代码(汇编语言代码,还记得语法吗?我反正玩光了 囧…..),怎么做呢?还是上指令:

//-S指定gcc将文件mian.i编译成汇编代码并输出到main.s文件中
gcc -S main.i -o main.s

再来看看输出的文件main.s里面是啥呢?

main.s中的汇编内容代码(谁个好汗能全看懂吗?我反正全忘光了….)

肯定地,功能也是打印出一个“Hello World,my name = 8888”,只是汇编语言的写法了。我们继续。

3.汇编

现在我们又得到了一个写满了汇编语言代码的文件main.s,这一步进行汇编的意思实际就是对汇编语言.s文件生成一个可执行的.o文件,这种文件描述了对各个函数的入口标记,但不包括外部变量引用的标记(需要下一步”连接”才能获取到)。指令:

//-c指定gcc将文件mian.s生成可重定向的特殊可执行内容保存到mian.o中
gcc -c main.s -o mian.o

现在,再用nodepad看看呢?

ansi格式下已经是乱码了,更看不懂了(操作系统能懂就行 囧)

照样肯定的,功能也是打印出一个“Hello World,my name = 8888”,只是看不懂的写法了。我们继续。

4.连接

连接的意思就是通过链接器将多个.o文件(多个.c文件生成的,本列只有一个main.c文件,但是你写的应该更多吧?对吧 ???)进行链接起来,生成最终的我们对应系统下的可执行程序(windows下.exe文件)。gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。指令:

//(不带参数了)默认gcc会将文件main.o生成最后的可执行程序名字叫做main(不同平台后缀名不同,所以不给后缀了)
gcc main.o -o main

好了 我这里(平台是windows)就生成了main.exe

双击运行看看:

运行成功

就这样我终于不依赖任何的ide完成了我的C文件编译了!! 这还只是一个文件,文件多了怎么办?我意志力强大,我能坚持 我一个一个预编译,编译成汇编,汇编成.o,链接!我很强的 囧….. (如果我有200个.c 的话….来吧 干活 哈哈哈)

如何加速我们的编译呢?

A.加速编译1:还是通过GCC指令

以上我们通过4步指令完成了对main.c的编译,其实不用那么麻烦,这4不对编译来说其实可以对用户隐藏的,你可以直接跳过前3步直接执行第4步:

//直接生成可执行文件
gcc main.c -o main

这样直接就把main.c生成了一个可执行文件main.exe(windows下),嗯快多了。

B.加速编译2:通过mingGw自带的 make编译工具

大家在下载mingGw的时候其实里面有一个叫做mingGw32-make.exe(windows下)的可执行文件,它的作用就是针对很大的工程(肯定有许多许多的.c文件),可以自动化的为我们进行.c文件的编译,并且可以指定多线程(缩短编译时间),但是,这个工具需要你写一个它能看的懂的编译文件makefile(你要做的就是新建一个没有后缀格式的makefile文件,然后在这个文件里面写你要编译的.c文件,具体怎么写,就要学习一下make的书写语法了),准备好makefile文件后,在这个makefile所在的文件夹打开终端输入指令:

//告诉工具mingGw32-make以1个线程读取执行当前文件夹下的makefile文件,(实际就是进行.c文件的编译了,makefile可要写正确哦)
mingGw32-make -j1

毋庸置疑,想要多线程进行编译当然可以加速编译了,比如 -j3(3个线程),-j4(4个线程)…..这样就实现了多线程进行编译啦!速度杠杠的!!比你慢慢一个一个.c进行编译是不是更爽了,哈哈

然而,这还不是最爽的。继续…

C.加速编译3:教练,我想跨平台编译!!!

通过加速编译2我们知道了可以用make工具和配置编写makefile文件进行快速大型工程的编译,但makefile里面写的编译语法是不支持跨平台的,意思就是你在windows上要写一个makefile文件,然后如果你想到linux上再编译你的工程,那么你又得写一个makefile文件,mac在写一个…这我头很痛…..囧。怎么办?我又要写这么多makefile文件,能不能只写一个makefile文件就全平台编译搞定了呢?答案是 CMake工具 (可能还有其他的如qt的qmake工具,也是跨平台的哦):

实际上cmake就是更抽象了一层而已,它也有一个make类似的makefile文件,叫做CMakeLists.txt,需要你在里面来写它能看的懂的语法代码,具体怎么写,查资料咯,然而和make工具不同的是,它实际不会执行对源代码(如本例的main.c文件)进行编译,它只是生成对应平台的工程文件(windows下一般是vs工程,linux是makefile).直接在CMakeLists.txt所处的文件夹下打开终端执行:

//通知cmake在当前文件夹下读取执行CMakeLists.txt文件,并生成默认的当前平台下的工程文件(windows下如果你安装了vs那么默认会生成一个sln工程,linux一般会生成一个makefile文件,哈哈)
cmake           
//如果CMakeLists.txt在build文件夹下 当前终端在CMakeLists.txt所在的上一级
目录打开
//根据build目录内的文件树结构(入口文件是CMakeLists.txt(类似C的入口函数main 名字不可改!!注意)) 将会在platProject生成sln等工程文件

cmake -S build -B build/platProject   

//(应该看懂了-S 和-B 的意思吧 前者指定CMakeLists.txt所在的目录,后者指定输出目录)
//如果CMakeLists.txt在build文件夹下 当前终端在CMakeLists.txt所在的上一级
目录打开
//根据build目录内的文件树结构(入口文件是CMakeLists.txt(类似C的入口函数main 名字不可改!!注意)) 将会在platProject生成makefile等文件(使用“make”指令即可生成exe)

cmake -G"MinGW Makefiles" -S build -B build/platProject

//(应该看懂了-S 和-B 的意思吧 前者指定CMakeLists.txt所在的目录,后者指定输出目录)

如上注释,可知会生成一个makefile文件,然后我们就可以用make工具(mingGw32-make.exe)执行该makefile文件编译了。

可见cmake其实只是一个辅助工具,最终的编译实际还是make工具在执行,然而make它其实也只是调用gcc命令进行编译,所以,大概的编译就是这样了。

最后:赶紧去学习CMakeLists.txt的写法去吧!!! (makefile的写法也了解一下????)

(个人理解 仅供参考哈 原文地址https://www.jdeverything.com/index.php/2020/05/10/%e7%bc%96%e8%af%91%e9%82%a3%e7%82%b9%e4%ba%8b%e5%84%bf%e4%bb%8egcc-g%e4%b8%ba%e4%be%8b%e5%88%b0make%e5%86%8d%e5%88%b0cmake/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值