网站首页 > 文章精选 正文
1. 前言
在上一篇基础篇中,我们主要探讨了VS的构造系统模型,了解了VS项目最基本的输入输出配置。输入输出是系统对外的功能接口,是系统最基础的部分。
在本章的进阶篇中,我们要探讨构造系统的内部参数。内部参数用于调整构造系统的行为,这些参数主要来自构造系统中的各个工具。其中,编译器和链接器作为构造系统中最核心的工具,是和我们打交道最多的,也是本文的主要研究对象。
2. 配置选项
在上一篇《掌握Visual Studio项目配置【基础篇】》中,我们主要讲解了构造系统的基本输入输出配置。基本输入输出配置包含了编译器、链接器的一小部分,剩下的部分主要是编译器链接器的运行参数配置。
如下图所示,VS编译器参数配置,集中在"C/C++"配置页:
VS链接器相关配置,集中在“链接器”配置页:
可见VS的项目配置中,包含了大量的编译、链接配置选项。这些选项大多数情况下保持默认值即可,不需要开发者参与。
但是,某些特殊的应用需求,只有通过配置编译器、链接器选项才能实现。所有在界面上进行的配置操作,最终都会转换为编译器和链接器的运行参数。点击上图中“命令行”标签页即可查看这些参数。
3. 官方释义
下方列出了微软对于以上两个配置节点逐项解释的文档地址:
- C/C++ 属性页:https://learn.microsoft.com/zh-cn/cpp/build/reference/c-cpp-prop-page?view=msvc-140
- “链接器”属性页:https://learn.microsoft.com/zh-cn/cpp/build/reference/linker-property-pages?view=msvc-140
虽然微软对每一项配置都做了解释,但总体看下来,能够看懂的寥寥无几。
例如,在“链接器”属性页中,对以下配置项
官方解释如下:
不管是配置项本身还是官方释义,都很难看懂。之所以很难看懂,是因为我们对编译器链接器的工作原理和系统底层细节不够了解。所以接下来,我们要研究一下编译器和链接器。
4. 编译器和链接器
4.1 基础
由源码生成可执行程序的过程分为四个阶段:预处理,编译,汇编,链接。
其中:
- 预处理器:用于处理源码中的预处理指令;
- 编译器:用于将源码转换成汇编代码。VS中的编译器程序为cl.exe;
- 汇编器:将汇编代码转换为机器码,机器码保存在目标文件中(*.obj),一个源文件(*.cpp)对应生成一个目标文件;
- 链接器:用于将多个包含机器码的目标文件合成为库(*.dll,*.lib)或可执行程序(*.exe)。VS中的链接器程序为link.exe。
这些知识十分基础,不作过多描述。
4.2 进阶
虽然在一般项目中,集成环境已经为我们做了大部分工作,修改编译器、链接器参数的应用场景比较少,但是学习编译器链接器的深入使用,对理解底层系统、拓展技能树、拓宽技术视野、增强技术储备有很大意义。
编译器、链接器参数较多,且涉及编译原理、操作系统等底层知识,有一定的难度。很多情况下,问题本身并不难,难的是如何掌握问题背后的知识体系。所以我们要做好阅读大量资料的准备。
微软官方文档中包含了VS编译器和链接器的参考手册:
- MSVC编译器参考:https://learn.microsoft.com/zh-cn/cpp/build/reference/compiling-a-c-cpp-program?view=msvc-140
- MSVC链接器参考:https://learn.microsoft.com/zh-cn/cpp/build/reference/linking?view=msvc-140
上面两个参考文档,虽然直接作为教程有些牵强,但总体看下来,有以下几点使用价值:
- 参考手册包括中文及英文原版内容,为一手文档,可以有效防止内容缺漏和误解。做技术要尽量看一手文档;
- 在项目中遇到看不懂的配置选项时,可以在参考手册中查阅说明;
- 从参考手册中,可以了解到编译器、链接器参数涉及到哪些对象、知识点,这是深入了解底层知识非常好的着手点。 例如,从编译器的警告级别控制参数: -/w、/W0、/W1、/W2、/W3、/W4、/w1、/w2、/w3、/w4、/Wall、/wd、/we、/wo、/Wv、/WX(警告级别):https://learn.microsoft.com/zh-cn/cpp/build/reference/compiler-option-warning-level?view=msvc-140 章节中可以进一步了解编译器有哪些警告、可以对警告进行哪些配置、#pragma warning指令的用法等等细化知识点。官方文档详尽程度有限,凡是遇到不懂的概念,都可以自行搜索相关资料,进一步了解其细节。
限于篇幅,这里仅提供了研究思路,具体配置的深入讲解将放在下一篇。
5. 在Qt中配置编译链接参数
我们知道,Qt可以配置不同的构建套件。在Windows上进行Qt开发时,我们通常选择VS的构建套件,即MSVC套件。VS中编译器链接器的运行参数同样可以在Qt中配置。
在Qt的.pro文件中,使用以下qmake变量可以向编译器和链接器传递参数(或叫标志flags):
C编译器:
- QMAKE_CC:用于指定C编译器名称或路径。
- QMAKE_CFLAGS:用于配置编译C源文件时的编译器参数,在所有构建模式下均生效。
- QMAKE_CFLAGS_DEBUG:设置编译C++源文件时的编译器参数,仅在Debug构建模式下生效。
- QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO:设置编译C++源文件时的编译器参数,仅在Profile构建模式下生效。
- QMAKE_CFLAGS_RELEASE:设置编译C++源文件时的编译器参数,仅在Release构建模式下生效。
- 其他编译器配置相关qmake变量见qmake文档。
C++编译器:
- QMAKE_CXX:用于指定C++编译器名称或路径。
- QMAKE_CXXFLAGS:用于配置编译C++源文件时的编译器参数,在所有构建模式下均生效。
- QMAKE_CXXFLAGS_DEBUG:设置编译C++源文件时的编译器参数,仅在Debug构建模式下生效。
- QMAKE_CXXFLAGS_RELEASE:设置编译C++源文件时的编译器参数,仅在Release构建模式下生效。
- QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO:设置编译C++源文件时的编译器参数,仅在Profile构建模式下生效。
- 其他编译器配置相关qmake变量见qmake文档。
链接器:
- QMAKE_LFLAGS:用于配置链接器参数。
- QMAKE_LFLAGS_DEBUG:用于配置链接器参数,仅在Debug构建模式下生效。
- QMAKE_LFLAGS_RELEASE:用于配置链接器参数,仅在Release构建模式下生效。
- QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO:用于配置链接器参数,仅在Profile构建模式下生效。
- LIBS:用于配置库搜索路径、链接程序库。
- 其他链接器配置相关qmake变量见qmake文档。
具体的使用细节,以Qt文档为准,参考 Variables | qmake Manual:https://doc.qt.io/qt-5/qmake-variable-reference.html。
修改以上变量以后,如何验证修改的编译器链接器参数是否生效呢?在Qt Creator中构建Qt项目时,要注意观察 编译输出窗口。此窗口中包含构建过程中详细的步骤和参数。如下图所示:
其中,
- 以cl 开头的命令,为编译命令, cl 为编译器,后面的部分为编译器参数;
- 以link开头的命令,为链接命令,link为链接器,后面的部分为链接器参数。
修改qmake变量后,通过对比编译器链接器参数的变化,即可验证配置的参数是否生效。注意,修改pro文件最好执行一次qmake,以确保修改生效,原理在《掌握Qt构造系统》文章中有对应解释。
下面举例说明。
5.1 示例1:添加编译参数
语法参考:
- 编译器命令行语法:https://learn.microsoft.com/zh-cn/cpp/build/reference/compiler-command-line-syntax?view=msvc-140
编译器选项参考:
- 按类别列出的编译器选项:https://learn.microsoft.com/zh-cn/cpp/build/reference/compiler-options-listed-by-category?view=msvc-140
- 按字母顺序列出的编译器选项:https://learn.microsoft.com/zh-cn/cpp/build/reference/compiler-options-listed-alphabetically?view=msvc-140
修改.pro文件:
禁用编译器优化:
QMAKE_CXXFLAGS += -Od
查看编译输出:
从编译输出可以看出,-Od禁用优化选项成功传递给了编译器,且编译成功。
5.2 示例2:添加链接参数
语法参考:
- 链接器命令行语法:https://learn.microsoft.com/zh-cn/cpp/build/reference/linking?view=msvc-140#linker-command-line-syntax
链接器选项参考:
- 链接器选项:https://learn.microsoft.com/zh-cn/cpp/build/reference/linker-options?view=msvc-140
修改.pro文件:
打开链接器详细信息输出开关:
QMAKE_LFLAGS += /VERBOSE
查看编译输出:
从编译输出可以看出,-Od禁用优化 选项成功传递给了链接器,且编译成功,同时打印了大量链接器详细日志,这些日志对于了解链接器工作过程有帮助。
看懂编译输出是深入Qt开发的必备技能,通过编译输出能够查看到底层构建系统的运行细节,也有助于排查一些难以定位的问题。
6. 结语
由于编译器链接器内容繁多,限于篇幅,本文只进行了逻辑梳理,很多细节没有涉及。读者可以自行新建项目进行测试,修改配置,对比观察。编程必须要亲自动手实践,只有这样才能避免浮于表面,才能举一反三,完善知识细节。
关于特定场景下的编译器链接器配置,我们会在后面的文章中细化讲解。
本文原创发布于 Qt未来工程师。
- 上一篇: Qt框架从入门到项目:安装方法
- 下一篇: Qt .pro和.qrc创建及介绍
猜你喜欢
- 2025-01-14 Qt界面——搭配QCustomPlot
- 2025-01-14 Qt支持RKMPP硬解的视频监控系统/录像存储和回放/云台控制
- 2025-01-14 东营交警实名曝光一批酒驾人员名单 88人受处罚
- 2025-01-14 Java的优势:跨平台只是一部分
- 2025-01-14 VS2017 C++ 程序报错“error C2065:“M_PI”: 未声明的标识符"
- 2025-01-14 Qt添加MSVC构建套件的方法
- 2025-01-14 Qt开发-基本工具的使用
- 2025-01-14 新型结构四旋翼无人机视觉导航中,半物理仿真平台是怎样设计的?
- 2025-01-14 qt for webassembly环境搭建图文教程
- 2025-01-14 Qt .pro和.qrc创建及介绍
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 稳压管的稳压区是工作在什么区 (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)