C/C++编译链接

一、编译过程

1 编译过程

  1. 预处理:根据预处理指令重新生成一个C/C++程序。读取C/C++源程序,对其中的伪指令(以#开头的指令)进行处理。
  2. 编译:将预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后,产生相应的汇编代码文件。
  3. 汇编:将编译完的汇编代码文件翻译成机器指令,并生成可重定位目标程序的.o文件,该文件为二进制文件,字节编码是机器指令。
  4. 链接:通过链接器将一个个目标文件库文件链接在一起生成一个完整的可执行程序。

2 名词解释

  • 编译:一般的编译如果没有特指就是指的上面四个步骤的总和。
  • 库文件:供外部调用的函数和变量。(资源类型。其本质是将资源存为变量)
    1. 静态库:在程序链接的时候,会将程序中使用到函数的代码从库文件中拷贝到应用程序中。(windows下以.lib结尾,linux下以.a结尾。)每运行一个程序就会在内存中拷贝多拷贝一份静态库。
    2. 动态库:在程序的链接时候,会将程序中使用到函数作上标记,只有在程序开始启动运行的时候,才会动态地加载所需模块。(windows下叫DLL,linux下叫共享库以.so结尾so ==share object)不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
  • 目标文件:编译过程中链接起来的生成可执行文件。

二、交叉编译

1 什么是交叉编译

  • 交叉编译是指在一个平台生成另一个平台上的可执行代码

  • 比如我们在 x86 平台上,编写程序并编译成能运行在 ARM 平台的程序,编译得到的程序在 x86 平台上是不能运行的,必须放到 ARM 平台上才能运行。

2 为什么需要交叉编译

  • 不同体系架构拥有不同的机器特性(例如: 是64位还是32位系统、是大端还是小端系统、是否必修按照4字节对齐方式进行访问、默认数据类型是有符号还是无符号、是否支持MMU),所以我们要针对这些平台单独编译出该环境能够执行的机器指令。
  • 这是因为有时目标平台上不允许或不能够安装我们所需要的编译器,而我们又需要这个编译器的某些特征。

三、工具介绍

  • gcc:用于编译c语言源文件。gcc是GNU编译器子集,GNU工具链保护很多工具,例如:C ++(g++),Objective-C,Objective-C ++,Java(gcj),Fortran(gfortran),Ada(gnat),Go(gccgo),OpenMP,Cilk Plus和OpenAcc。

    实例

    /*hello.c*/
    #include <stdio.h>
    int main(){
        printf("Hello world!\n");
        return 0;
    }
    

    编译并执行

    $ gcc hello.c -o hello 
    $ ./hello 
    # 执行
    Hello world!
    
  • make和Makefile:当工程存在多个源文件时,每次需要编译时都键入编译命令,这非常麻烦。make工具(GNU Make)是简化此任务的解决方案.

    Makefile:用于帮助我们自动构建和管理项目。可以看作提前写好如何编译工程中各个源文件的指令。

    make:智能的批处理工具,它本身并没有编译和链接的功能,而是用类似于批处理的方式—通过调用makefile文件中用户指定的命令来进行编译和链接的

    实例

    /*hello.c*/
    #include <stdio.h>
    int main(){
        printf("Hello world!\n");
        return 0;
    }
    
    # Makefile
    all:hello
    
    hello.out: hello.o
            gcc -o hello hello.o
    
    hello.o: hello.c
            gcc -c hello.c
    
    clean:
            rm hello.o hello
    

    执行make

    $ make
    gcc -c hello.c
    gcc -o hello hello.o
    
    $ ./hello 
    Hello world!
    
    $ make clean
    rm hello.o hello
    
  • cmake和CMakeLists组态档:cmake会按照CMakeLists去生成Makefile。Makefile在一些简单的工程完全可以人工编写,但是当工程非常大的时候,手写Makefile也非常麻烦。如果源代码想在不同平台编译,还必须注意不同平台的差异。且如果使用不同的 make 工具,也得为每一种标准写一次 Makefile。

    官网:https://cmake.org/

    实例

    /*hello.c*/
    #include <stdio.h>
    int main(){
        printf("Hello world!\n");
        return 0;
    }
    
    # CMakeLists.txt
    # CMake 最低版本号要求
    cmake_minimum_required (VERSION 3.13.0)
    
    # 项目信息
    project (Hello)
    
    # 指定生成目标hello
    add_executable(hello hello.c)
    

    执行cmake和make

    $ cmake .
    
    $ make
    gcc -c hello.c
    gcc -o hello hello.o
    
    $ ./hello 
    Hello world!
    
    $ make clean
    rm hello.o hello
    
  • qmake:基本功能和cmake是差不多的,可以自动生成对应平台的Makefile。且无论是否用Qt编写,它可以用于任何软件项目。但是qmake主要包含了自动包括moc和uic的构建规则。

    官网:https://doc.qt.io/archives/qt-4.8/qmake-manual.html

  • qmake和cmake区别:cmake也是同样支持Qt程序的,cmake也能生成针对qt 程序的那种特殊makefile, 只是cmake的CMakeLists.txt写起来相对与qmake的.pro文件复杂点。但是cmake功能比qmake强大。 一般的Qt工程直接使用qmake就可以了,但是QT6之后官方的构建工具换成了cmake,足以见得cmake的强大。

posted @ 2023-02-03 09:33  09w09  阅读(149)  评论(0)    收藏  举报