文章

1`构建阶段、构建目标和使用

构建

构建阶段

构建:将高级语言源码转换为可执行程序

1742209654531

c++: .cpp .h -> .ii -> .s -> .obj -> .exe

分别由 预处理器、编译器 / 解释器、汇编器、链接器 执行

构建流程:

  • 预处理(Preprocessing)根据预处理指令 对源代码进行 插入 / 替换 / 判断条件……
    • 包含:替换为文件
      • #include “” / <>
    • 宏:替换为实际内容
      • #define
      • __ FUNTION __ 获取当前函数名
      • __ LINE __ 获取当前代码行号
      • __ FILE __ 获取当前文件名
      • __ DATE __ 获取当前日期
      • __ TIME __ 获取当前时间
      • __ STDC_VERSION __ 获取当前编译器的版本
    • 条件: 根据条件决定那部分需要编译,可以使目标程序变小,运行时间变短
      • #ifdef //某个宏是否已经定义(if define)
      • #ifndef //某个宏是否没有定义(if not define)
      • #else
      • #endif
      • #if //常量表达式是否为真(非0)
      • #elif
      • #else
  • 编译(Compilation)会进行语法分析,检查错误,翻译成汇编语言代码,会产生符号表(标识符(变量/函数名)), 和为符号表分配相对地址(相对每个文件)
  • 汇编(Assembly)汇编代码翻译成机器码(二进制),会根据各个段分配更精确的相对地址
  • 链接(Linking)将多个二进制文件链接在一起,生成可执行文件,合并并给符号分配绝对地址并替换,从而使得代码可以通过符号地址执行相应操作

运行阶段

执行机器码指令,比如int a = 4;,这时会将4存入到a映射的绝对内存地址

IDE中对应的按键

下面以vs为例

解决方案 == 一个/多个项目的容器

build构建 == 执行完整的构建流程

clear清理 == 清理所有构建期间生成的文件

rebuild重构 == clear + build

run运行 == build + 运行可执行文件

Parser解析器

解析器 / 语法分析器 是编译器的核心组件之一,它会对输入的字符序列 利用扫描器词法分析 输出切割后的单词流,对单词流 根据语法分析器 构建出相应的 语法树 / 精简过的抽象语法树

抽象语法树(AST)是一种 树形数据结构,它以一种更抽象、更易于处理的方式表示输入数据的语法结构

构建目标

静态库:

  • 预处理 -> 编译 -> 汇编 -> 归档器打包
  • 不涉及链接阶段,归档器打包也不会分配符号绝对地址
  • 静态库(.lib)
  • 不可单独执行,但可以复用
  • 在生成可执行文件的链接阶段,从静态库拷贝所有数据到可执行文件,并分配绝对地址,最终我们只需要可执行文件,就像加入到项目的一段代码一样
  • 会造成可执行文件显著增大,但调用速度较快
  • 不能再包含其他的动态链接库或者静态库

动态库:

  • 预处理 -> 编译 -> 汇编 -> 链接
  • 涉及链接阶段,仅对对库本身符号解析,分配库的绝对地址
  • 动态库:(.lib文件(导入库)和.dll文件).lib包含分配地址后的符号表, dll包含实际的函数和数据
  • 不可单独执行,但可以复用
  • 在生成可执行文件的链接阶段,需要包含lib和dll文件,它并不会拷贝到可执行文件,而是在运行时通过lib访问dll导出的数据
  • 不会造成可执行文件显著增大,但调用速度较慢
  • 可以再包含其他的动态或静态链接 库

可执行文件

  • 预处理 -> 编译 -> 汇编 -> 链接
  • 对所有文件和链接到项目的库 中符号进行解析,如果是静态库,会静态链接,如果是动态库,会动态链接
  • 可执行文件(.exe)
  • 可以单独执行

使用库

下面以vs为例

构建目标:

  • vs -> project -> properties -> confuguration properties -> general -> confuguration type 选择构建类型

构建输出目录:

  • -> general -> output directory 设置输出目录

构建中间件输出目录:

  • -> general -> intermediate directory 设置输出目录

静态库:

  • 头文件
    • #include 直接通过预处理指令包含,可以为绝对路径/拷贝到和项目同一目录后的相对目录
    • -> VC++directories -> include directories
    • -> c/c++(要创建首个源文件才可以看到) -> general -> Additional include directories 添加头文件目录
  • lib
    • 项目右击 -> add -> existing item 添加库目录,拷贝到和项目同一目录
    • -> VC++directories -> library directories
    • -> linker -> input -> Additional dependencies 添加库名字,-> linker -> general -> Additional library directories 添加库目录

动态库:

  • 头文件
    • 和上面一样
  • lib
    • 和上面一样
  • dll
    • 拷贝到项目的exe目录下
    • -> VC++directories -> executable directories

DLL库导入导出

1
2
__declspec(dllexport) double myFunc(double a, double b);
__declspec(dllimport) double myFunc(double a, double b);

展开

__declspec关键字可以用来修饰函数/变量/类

1
2
3
4
5
6
#ifdef DLLEXPORT
#define _DLL_DECLARE_ declspec(dllexport)
#else
#define _DLL_DECLARE_ declspec(dllimport)
_DLL_DECLARE_ double myFunc(double a, double b);
_DLL_DECLARE_ double myFunc(double a, double b);

展开

我们通常会用宏代替

本文由作者按照 CC BY 4.0 进行授权
本页总访问量