C/C++ Build 过程简介

作者: 白痴毛 | 来源:发表于2017-09-26 07:21 被阅读162次

    Build是将源代码转换为可执行文件的过程,在C/C++中,Build过程大体上分为三步:

    1. 预处理(Preprocessing)
    2. 编译(Compiling)
    3. 链接(Linking)

    在build过程中,只有cpp文件会build,h文件会在预处理(第一步)中整合到cpp里,就是直接把h的文本内容嵌入到cpp的上方,所以编译的时候是只有cpp没有h 的。

    整个build过程示意图如下

    build.jpg

    1. 预处理

    cpp文件首先预处理变为translation unit,translation unit仍然是文本代码文件,它是传入编译器的基本单元,把cpp和h整合到了一起,并且去掉不必要的空格 / 换行之类的。

    官方定义如下:

    1. A translation unit is the basic unit of compilation in C++. It consists of the contents of a single source file, plus the contents of any header files directly or indirectly included by it, minus those lines that were ignored using conditional preprocessing statements.
    2. A single translation unit can be compiled into an object file, library, or executable program.
    3. The notion of a translation unit is most often mentioned in the contexts of the One Definition Rule, and templates.

    2. 编译

    translation unit传入编译器(compiler)之后会被编译成obj文件(二进制)。
    即:高级语言->汇编语言->机器语言(二进制)
    一般而言,生成的都是obj,但如果你想写一个第三方库文件,那么编译器会对应的生成lib(静态链接库)或者dll(动态链接库)文件。

    每一个cpp生成一个translation unit,然后编译生成一个obj,所以cpp与obj是一一对应的,每一个cpp都会独立编译出来一个obj文件。

    3.链接

    如果不依赖动态链接库或静态链接库,链接就是把所有obj链接;如果还依赖外部库,链接还包括lib文件。
    注意:这里不包括dll文件,因为dll文件是在运行时才链接进来(其实也不应该叫链接,总之就是运行时才会加载进来,不会在链接生成exe的时候进来)

    动态链接库一般是游戏驱动之类的,比如openGL.dll,d3d9.dll,d3d11.dll等。
    大家玩游戏的时候可能会遇到无法运行,报错:缺少xxx.dll文件,就说明你游戏驱动没有安装,一般安装上驱动就会解决这个问题,原因就是在这里。
    看到这大家可能会有疑问:为什么要使用动态链接库DLL?

    1. 减小可执行文件exe的大小
    DLL技术的产生有很大一部分原因是为了减小可执行文件的大小。当操作系统进入Windows时代后,其大小已经达到几十兆乃至几百兆。试想如果还是使用DOS时代的单执行文件体系的话一个可执行文件的大小可能将达到数十兆,这是大家都不能接受的。解决的方法就是采用动态链接技术将一个大的可执行文件分割成许多小的可执行程序。
    2. 实现资源共享
    这里指的资源共享包括很多方面,最多的是内存共享、代码共享等等。早期的程序员经常碰到这样的事情,在不同的编程任务中编写同样的代码。这种方法显然浪费了很多时间,为了解决这个问题人们编写了各种各样的库。但由于编程语言和环境的不同这些库一般都不能通用,而且用户在运行程序时还需要这些库才行,极不方便。DLL的出现就像制定了一个标准一样,使这些库有了统一的规范。这样一来,用不同编程语言的程序员可以方便的使用用别的编程语言编写的DLL。另外,DLL还有一个突出的特点就是在内存中只装载一次,这一点可以节省有限的内存,而且可以同时为多个进程服务。
    3. 便于维护和升级
    细心的朋友可能发现有一些DLL文件是有版本说明的。(查看DLL文件的属性可以看到,但不是每一个DLL文件都有)这是为了便于维护和升级。举个例子吧,早期的Win95中有一个BUG那就是在闰年不能正确显示2月29日这一天。后来,Microsoft发布了一个补丁程序纠正了这个BUG。值得一提的是,我们并没有重装Win95,而是用新版本的DLL代替了旧版本的DLL。另一个常见的例子是驱动程序的升级。例如,著名的DirectX就多次升级,现在已经发展到了6.0版了。更妙的是,当我们试图安装较低版本的DLL时,系统会给我们提示,避免人为的操作错误。例如我们升级某硬件的驱动程序时,经常碰到Windows提示我们当前安装的驱动程序比原来的驱动程序旧。
    4. 比较安全
    这里说的安全也包括很多方面。比如,DLL文件遭受病毒的侵害机率要比普通的EXE文件低很多。另外,由于是动态链接的,这给一些从事破坏工作的“高手”们多少带来了一些反汇编的困难。

    关于链接的顺序,obj的不清楚(好像是顺序无关的,那就是按照排列顺序);外部库的连接顺序取决于VS项目链接配置里的项目属性-->链接器--> 输入-->附加依赖项里的顺序。

    相关文章

      网友评论

        本文标题:C/C++ Build 过程简介

        本文链接:https://www.haomeiwen.com/subject/ejbjextx.html