C++、Qt编译相关概念

问题描述

使用vs2022创建了一个静态库,欲在qt程序中使用,结果报 undefined reference to xxx 错误,这里的xxx就是静态库中定义的方法。可以保证:

  1. 已经正确配置依赖并添加头文件
  2. 在vs中创建一个示例程序并引入该lib发现可以正常使用

由于对c++生态不太熟,做此记录

问题原因

vs使用的是msvc编译器,而qtcreator中使用的却是mingw编译器。两者并不兼容。

解决方案

qtcreator切换到msvc编译器,并且需要在电脑上正确安装与该msvc编译器对应的visual studio IDE。

概念区分

VC 和 VS

VC相关的概念在下面有详细说明,需要注意的是:除了下面说的它是一个C++编译器之外,在不同的语境下它也有可能是其他东西,例如一个名为VC++的IDE或者C语言等

可以简单理解为:vs(即Visual Studio IDE)是一个ide,对应java中的eclipse等。vc(即MSVC)是vindows下c++的编译环境,对应java中jdk的javac。

用vs开发时可以选择不同的vc版本

参考:https://zhuanlan.zhihu.com/p/497033106

MSVC、MSVC++、VC、VC++、Visual C++、Microsoft Visual C++

它们都是同一个东西

GNU、MinGW、GCC、gcc、g++(都带一个g)

GNU 简单理解为一个开源软件集合,其中有很多开源软件,例如 GNU/Linux,GNU/GCC 等

实际上GNU是一个单独的操作系统,拥有自己的内核 Hurd 和一些列周边软件,但在生产环境中常常将其替换成更成熟的 linux内核。如此,这种替换了linux内核但同时拥有GNU周边软件的GNU系统就被称为 GNU/Linux,它和linux其实是两个不同的系统,只不过很多时候直接将其简称为linux。

上面说的那个开源软件集合,其实指的就是GNU系统下的一些周边软件。

GCC 全称 GNU Compiler Collection,顾名思义,它是GNU系统下编译器的集合,它下面有各种语言的编译器,例如java编译器、c/c++编译器(gcc和g++)、OC编译器等

gcc/g++ 全称 GNU C Compiler,就是上述GCC集合中的c/c++编译器。事实上,它们也并非真正的编译器,它们只是一个驱动,用于判断被编译文件类型或系统环境等,然后调用真正的c/c++编译器cc1或cc1plus。它们的区别是:g++不管遇到c或c++文件都当作c++文件,从而调用cc1plus编译器进行编译。而gcc则进行区分。再者g++在编译完成后会自动链接c++的标准库,gcc不会。

有些文章说g++会调用gcc或反过来都是错误的。

MinGW 全称 Minimalist GNU for Windows,它就是将GNU系统下的一些工具软件打包给windows用。其中就包含gcc。

详见:https://blog.csdn.net/lee_ham/article/details/81778581

MSVC 和 MinGW

可以简单认为两者都是c++的编译器(但上面说过MinGW是一个工具集,实际上编译器是gcc),区别在于:

MSVC是windows下独有的,全称:Microsoft Visual C++。它和VS是一一绑定的。可以简单认为,想用哪个版本的MSVC就需要下载安装对应版本的VS。

事实上,也可以单独安装MSVC编译器,叫做 Visual C++ Building Tools ,但后续使用据说相对麻烦。

官网有详细说明:https://visualstudio.microsoft.com/zh-hans/visual-cpp-build-tools/

官网也有详细教程:通过 vc++ building tools 使用命令行编译c++程序

两者的部分版本对应关系:

MSVC++ version_MSC_VER
14.11910 (Visual Studio 2017 15.0)
14.201920 (Visual Studio 2019 Version 16.0)
14.301930 (Visual Studio 2022 Version 17.0)

注:_MSC_VER 介绍见下文

MinGW 全称:Minimalist GNU on Windows,可以跨平台,兼容性强,但速度慢。

MSVC2019、MSVC14、microsoft visual c++ compiler 17.2.3、VS17.2.5、_MSC_VER=1930、Visual C++ 2022 都是什么意思

MSVC2019:qt套件名称。全称是 Desktop Qt %{Qt:Version} MSVC2019 64bit,其中的MSVC2019只是名称中的一部分。该名称只是该套件开发者自定义的,他想怎么叫都行,甚至还提供了修改选项,你想修改成什么都行。具体使用的编译器从Qt套件的详情信息中可以看到。

但我认为这个2019可能对应的是该套件使用编译器所寄生的vs的版本(MSVC和VS版本基本有一一对应的关系),但其并不是绝对的(例如这里Qt显示的是2019,而我本地的是VS2022,编译运行也没问题)。

microsoft visual c++ compiler 17.2.32616.157:就是VS2022,即VS17.2.5。这里应该指的是该版本VS本身编译的版本

https://docs.microsoft.com/en-us/visualstudio/install/visual-studio-build-numbers-and-release-dates?view=vs-2022

MSVC14:编译器版本

_MSC_VER=1930:_MSC_VER并不是Visual Studio 的版本号,也不是Visual C++的版本号。它用来表示编译器版本。它是定义在编译器中的一个宏,例如,若使用 MSVC14.30编译代码,代码中获取_MSC_VER值则为1930。

Visual C++ 2022:查看vs版本时能看到该信息,推测2022指的应该是vs的版本,因为visual c++和vs可以看作寄生关系,故应该也能用vs版本表示vc版本。我查看vs2017的版本也相应变成了visual c++2017。

Qt 和 QtCreator

可以简单理解为:QtCreator是一个IDE,用来开发Qt程序。Qt是一个桌面程序开发运行环境,可以使用C++、java、python等进行开发。可以简单理解为类似jdk。

Make、nmake、CMake、qMake

对于单个c++源文件,可以手动编译它。但是一个项目可能有成百上千个源文件,一个个去编译不太现实,且它们之间还有一些依赖关系造成手动编译愈加困难。

此时就可以使用make工具进行批处理(linux系统下)。使用该工具时需创建一个makefile文件,然后在该文件中指定源文件的编译顺序、依赖等,然后调用make指令,它就能自动根据该文件的配置对源码进行编译。

上面说创建makefile需写明一些编译的配置规则,但有时项目中源代码很多很杂,依赖关系也很复杂,此时编写makefile文件就很困难,且make只用于unix系统下。

于是就有了CMake工具。在unix系统下,该工具能根据配置文件 CmakeList.txt 自动生成 makefile。在windows系统下,该工具能自动生成vs项目,vs内置了一个nmake的工具用于编译源码,相当于unix下的make工具。

Qt对C++做了进一步的封装,丰富了很多C++不具备的特性,所以你可以将它们理解为两种不同的语言。

故不能直接使用make或nmake工具编译Qt源码。此时QMake应运而生,它将依赖 xxx.pro 文件将源文件转换成C++(这样简单理解),然后生成makefile(unix下)或对应平台的项目。

故可以简单认为QMake是qt环境下的Cmake。别人画了个图,觉得还行:

事实上,Cmake也是支持Qt的,只不过相对QMake较为麻烦。

这部分参考:https://www.zhihu.com/question/27455963https://www.zhihu.com/question/333560253

configure、CMake

linux下安装软件步骤一般都是:

./configure --prefix=/opt/xxx
make
make install

这里的 configure 就是一个shell脚本,是软件开发人员写的,是一个约定俗成的东西。一般该脚本会检测系统环境然后生成 makefile 文件,所以使用该脚本后就能使用make命令进行编译了,编译完成后使用make install进行安装。

看起来很像CMake,事实上CMake就有取代它的趋势,近些年越来越多的项目从configure转向了CMake

Qt中的 jom.exe

用过linux都知道,很多时候,编译代码要手动去执行make指令,它会根据makefile进行编译. 一般make可以加一个参数-j 表示使用多少个线程来编译,-j4就表示使用4个线程编译. linux下使用make,而在windows上面使用nmake,是vs提供的一个东西, 但是有很个坑的事,就是nmake不支持-j这个参数,,也是就是说它是单线程编译. Qt为了解决这样子的一个问题,弄出一个jom.exe,这和make的功能基本是一样的,但是他比nmake多出来的就是,-j这个参数.也就是说它支持多线程编译. 至于和make的其他区别我也不清楚,如果你不特别追究的话,简单理解为 jom==make==nmake*x

https://bbs.csdn.net/topics/392205042

qt中的 Kits,Qt versions,Compilers

1.1 先说Compilers,即编译器。在windows平台一般用MSVC和MinGW这两种。MSVC是指微软的MicroSoft Visual C++ 编译器,MinGW即Minimalist GNU on Windows,是GNU组织提供的编译器。
1.2 再说Qt version:,即Qt 版本。不严格来说,Qt是一个编译好的各种工具的库,每次发布这个库都会有一个版本号(比如你安装的5.9.1),并且用MinGW和MSVC各编译一份。如果你安装了MinGW的库,之后开发程序就用MinGW的编译器编译,发布的时候使用MinGW的库。如果安装的MSVC的库,就用MSVC的。同时都安装也是可以的,一般不交叉使用。
库中有一个很重要的可执行程序叫qmake.exe(它自然也分MinGW和MSVC两种),是用来构建Qt项目的。在Qt version界面,就是以qmake作为qt版本的依据。
1.3 Kits,中文翻译叫构建套件。如果点击你那个Qt 5.9.1 MinGW,就会看到,里面包含了套件名字,设备,C/C++编译器,调试器,Qt 版本等信息。这些东西搭配在一起,成为一个套件。常见的情况是以MSVC编译 + CDB调试,作为一个套件,MinGW编译+
GDB调试作为另一个套件。当你开发/导入一个Qt项目的时候,就需要选择相应的套件。
2、qt-opensource-windows-x86-msvc2013_64-5.5.1.exe 是一个综合的安装包,下载后安装的时候可以选择装哪个编译器对应的库。一般选MinGW 或者MSVC,也可以选Android开发用的arm编译器。安装完成时,如果系统里已经有MSVC编译器、或者安装了Qt提供的MinGW编译器,一般是会自动给你配置好kit的,不需要再配置。
QCAD项目不了解。我大概看了一下,需要命令行编译。这个也简单的,你只要安装好Qt,在开始菜单里找Qt 对应的一个开发者命令提示符,类似于Qt 5.9 64-bit for Desktop (MSVC 2015)这样的。这个命令提示符已经为你配置好了qmake nmake/mingw32-make 等工具。只需要打开这个命令提示符,cd到你的QCAD项目路径下,使用相应的命令进行编译。

https://bbs.csdn.net/topics/392261056?list=lz

总结

一圈看下来我觉得还是名称和版本很混乱,一个vc就有很多叫法,也有很多版本表示方式。甚至在不同语义下,vc的含义是不一样的,有时它可以指C语言,有时指编译器,有时指一个名为vc++的IDE等,之前看到一篇文章有介绍,但是找不到了

C++有两种编译器,MinGW和MSVC。MinGW可以跨平台且兼容性好,MSVC只能用于windows但速度快。MSVC和visual studio IDE可以理解为寄生关系,要用某个指定版本的MSVC就需要下载其对应的VS。

Qt中的Kits中的MSVC并没有对应编译器的实现。想要使用对应的编译器就需要电脑上本身就有该编译器。例如Qt项目指定使用MSVC作为编译器,电脑上就需要安装对应的VS

MinGW和MSVC并不兼容,故一般来说不能混用,否则会造成undefined reference to xxx错误,例如开头举的例子。

Leave a Comment