1`构建阶段、构建目标和使用
构建
构建阶段
构建:将高级语言源码转换为可执行程序
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 进行授权