QGIS+QT5+VS2015(2017)的编译

QGIS+QT5+VS2015(2017)的编译

因学业的需要,接触到QGIS的有关知识,需要将其在VS环境下再开发。
这是我第一次学习开源的代码,很多地方磕磕绊绊,好几天才将代码编译完成。
以防日后遗忘,便于回顾。
特整理如下



准备工作

在整个工作开始之前,建议先做一些准备工作。


要求配置资源

  1. 操作系统:Win10 ×64
    (要注意自己的系统是64位还是32位,以下软件安装的位数版本均与系统一致;
    PS:一般安装包名仅含有×86为32位的版本)
  2. VS2015(2017) ×64;
  3. QT5.11.2 ×64;
  4. CMake3.10.2 ×64;(目前版本的QGIS要求3.1以上)
  5. Cygwin2.8 ×64;(用于下载flex及bison)
  6. osgeo4W ×64;(用于下载其他依赖库)
  7. GIS源码;(我下载的是3.2.2版本)

如果你可能用到Python,你还需要——
Python3.7 ×64;(目前版本的QGIS要求Python3以上)

如果你想要生成APIDoc,你可能还需要——
doxyden1.8.10 ×64;(要求1.8.8以上)


部分下载链接

  1. VS2015(2017) ×64;
    请前往官网下载
  2. QT5.11.2 ×64;
  3. CMake3.10.2 ×64;
    链接: cmake-3.10.2-win64-x64.
  4. Cygwin2.8 ×64;
    64链接: Cygwin-setup-x86_64.
    32链接: Cygwin-setup-x86.
  5. osgeo4W ×64;
    64链接: osgeo4w-setup-x86_64.
    32链接: osgeo4w-setup-x86.
  6. GIS源码;
    链接: 此链接自动更新QGIS到最新版本.

QGIS对各软件资源版本要求

(QGIS3.2.2版)
QGIS+QT5+VS2015(2017)的编译



配置步骤


库文件的准备

1. 安装VS2015 ×64以及5以上版本的QT,并将QT配置到VS上;安装CMake

(有需要的再额外安装Python37;安装doxyden;)

除VS默认加入环境路径,检查QT和CMake的bin文件已经加入环境路径
你可以右击“我的电脑”->“属性”->“高级系统设置”->“环境变量”->在系统变量中找到PATH,编辑查看
(如果此时不添加,也可在生成工程时一起配置环境)
QGIS+QT5+VS2015(2017)的编译

2. 安装Cygwin依赖库

在这之前,你可以新建一个文件夹QGIS,将下载的需要的文件都放到下面,便于整理,最后它将是这样。
QGIS+QT5+VS2015(2017)的编译

2.1 运行Cygwin setup-x86.exe,按以下步骤继续
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
随便选择一个网址,一般默认第一个;无需点击Add,直接下一步。
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
所需库均搜索完毕,点击下一步等候下载安装即可。

2.2 在这个过程中,注意以下几点
(1)View选择Category(若不是,点击View可更改)
(2)Search输入要下载的内容,本工具只用下载flex和bison
(3)选择Devel,展开,如果当前未下载则显示的是"Skip",点击会变成具体的版本,然后点击下一步即可下载(由于我这边都下过了,所以显示的是版本号和keep)。
没有下载的应该类似这样
QGIS+QT5+VS2015(2017)的编译
(4)Search一个库之后,点击"Skip"使其出现版本编号后,清除search框的内容,继续search下一个。全部搜索点击完成后,再点击下一步,所有搜索项将会一起下载。
(5)上述路径不要有中文或空格

3. 安装osgeo4W依赖库

(文件较多较大,建议在网速流畅的条件下进行)

3.1 运行osgeo4w-setup-x86_64.exe
如下
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
按个人需要修改路径
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
等待加载
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译

3.2 依赖库的搜索项
(1)操作同Cygwin的步骤类似,略去不提
(2)你需要依次search以下内容:
expat、fcgi、gdal、grass、gsl-devel、iconv、libspatialindex-devel、pyqt5、python3-devel、python3-qscintilla、python3-nose2、python3-future、python3-pyyaml、python3-mock、qca-qt5-devel、qca-qt5-libs、qscintilla-qt5、qt5-devel、qt5-libs-debug、qtwebkit-qt5-devel、qtwebkit-qt5-libs-debug、qwt-devel-qt5、sip-qt5、spatialite、qjson
(3)遵从“宁可多下,绝不少下”的原则
(4)仅仅下载Library的内容


用CMake生成工程

1. 配置环境

新建一个txt文件,命名path(具体什么命名无所谓)
将以下内容拷贝到里面。

@echo off 
set VS140COMNTOOLS = D:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\ 
call "D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 
set INCLUDE=%INCLUDE%;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include
set LIB=%LIB%;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib
set OSGEO4W_ROOT=D:\QGIS\OSGeo4W64
call "%OSGEO4W_ROOT%\bin\o4w_env.bat"
call "%OSGEO4W_ROOT%\bin\py3_env.bat"
call "%OSGEO4W_ROOT%\bin\qt5_env.bat"
set O4W_ROOT=%OSGEO4W_ROOT:\=/%
set LIB_DIR=%O4W_ROOT%
path %path%;D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin
path %PATH%;D:\Program Files\CMake\bin;D:\QGIS\cygwin64\bin
@set GRASS_PREFIX=D:/QGIS/OSGeo4W64/apps/grass/grass-7.4.1
@set INCLUDE=%INCLUDE%;%OSGEO4W_ROOT%\include
@set LIB=%LIB%;%OSGEO4W_ROOT%\lib;%OSGEO4W_ROOT%\lib
set LIB=%LIB%;%OSGEO4W_ROOT%\apps\Qt5\lib;%OSGEO4W_ROOT%\lib
set INCLUDE=%INCLUDE%;%OSGEO4W_ROOT%\apps\Qt5\include;%OSGEO4W_ROOT%\include
@cmd

注意说明:上面的路径以及grass的版本要根据自己的实际情况,做适当地改变
(1)VS140COMNTOOLS表示VS15,call后续跟的X64表示64位编译
(若是VS2017则用语句VS150COMNTOOLS表示)
(2)Include表示头文件,这里加了Win10系统的sdk;Lib表示编译的动态库
(3)Path表示环境变量(刚才在前面没有设置的路径,现在也可以在这里添加)
(4)特别注意:GRASS_PREFIX的路径地址必须是“/”,Path路径多个;之间不能有空格

保存txt的内容,将文件后缀名改为.bat
打开cmd命令窗口进入“path.bat”所在路径;(或在“path.bat”所在处shift加右键可直接看到打开命令窗口的选项)
输入以下命令:path.bat
(在win10新版本中语法规则改变,输入:/.path.bat)
出现类似“Microsoft Windows 版本 10.0.17134.345 2018 Microsoft Corporation。保留所有权利。”字样,表执行成功
接着输入cmake-gui
将会打开CMake编辑页
QGIS+QT5+VS2015(2017)的编译

2. 利用CMake构建项目

在上方文本框中分别输入QGIS源码路径;构建的VS工程的输出路径
QGIS+QT5+VS2015(2017)的编译
点击下方“Configure”,将弹出VS版本选择(若为VS2017选择Visual Studio 15 2017 Win64)
QGIS+QT5+VS2015(2017)的编译
随后,CMake将自动索引有关链接库,生成链接,对没有搜索到的库会报错显示没有找到路径。
(建议第一遍搜索后按我的配置手动增加路径)

增加步骤:
选择Add Entry
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
在这里,建议将QT与Python的有关路径全部改为OSGeo4W64/apps下的QT5和Python3文件夹下的路径。

因为CMake搜索机制是从硬盘文件夹逐步深入;所以主目录优先寻找到此主机安装上的QT与Python目录。
如果您的版本刚好是QT5.11.2与Python3+,可能不会影响结果,但如果版本有差异很可能造成后期编译出现链接错误。
而OSGeo4W64是QGIS方提供的最新库,将保证链接不出现问题(若后期有意更换最新版本的QGIS源码,仅在OSGeo4W64重新下载有关库到原保存文件夹下,更新生成VS工程即可)

以下附上我具体的路径配置
为避免其他情况,请保证以下图中路径均添加入其中。

勾选DISABLE_DEPRECATED表示禁用不推荐的功能为下一代做准备。建议勾选,不勾也可。
QGIS+QT5+VS2015(2017)的编译
ENABLE_QT5表示用QT5编译
ENABLE_TESTS表示生成测试文件,不勾选也可
(希望用Python编辑QGIS源码,则需要勾选ENABLE_PYTHON3)
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
WITH是对QGIS功能的插件添加项,一般与你的需求有关,如不需要在Python等其他软件下编辑,仅仅保留几项即可。若有其他需求,可再额外设置其依赖的第三方库
为避免其他问题,请保证以下WITH内容被勾选:
保证可以生成qgis.exe文件,需要勾选——
WITH_DESKTOP;WITH_INTERNAL_QEXTSERIALPORT;WITH_INTERNAL_QWTPOLAR
可选择性勾选基本的使用功能——
WITH_GUI;WITH_POSTGRESQL;WITH_STAGED_PLUGINS
QGIS+QT5+VS2015(2017)的编译
当“Configure”直到下方信息栏显示Configuring done;
点击“Generate”显示Generate done;
此时“Open Object”按钮变亮点击它,即可进入工程项目;
(下一次需要打开工程,可在新建项目文件夹下,寻找.sln后缀的工程文件,打开即可)
QGIS+QT5+VS2015(2017)的编译


在VS下编译

工程加载进入后,先将Debug格式改为Release或者RelWithDebInfo(在这两种版本下,编译不包含调试信息,容量上大大减小,运行速度大幅度提高;对于较大工程比较适用;在Rel版本下调试正确后换为Deg版本依旧正确,无须担心)

此处以RelWithDebInfo做例

1. 修改不识别的符号

先在资源管理器中找到qgis项目,右击该项目,选择“设为启动项目”
QGIS+QT5+VS2015(2017)的编译
接着,你可以先试着第一次生成解决方案,以排除所有页面不识别的错误

你应会遇到大量报错,请等待生成完毕。
在错误中会出现例如
“错误 C2143 语法错误: 缺少“)”(在“;”的前面) ”
“错误 C2001 常量中有换行符 ”
……
这些错误的原因是因为页面不支持("′")("″")的符号

在错误列表关闭错误,仅查看警告,并点击“说明”让其聚类。大体上将出现会三种警告类型。
对于以下这两种,我们忽视掉——
“警告 C4718 “QMapNode<int,QgsRasterIterator::RasterPartInfo>::doDestroySubTree”: 递归调用无副作用,正在删除 ”
“警告 C4702 无法访问的代码 ”
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译

而对于——
“警告 C4819 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 ”
QGIS+QT5+VS2015(2017)的编译
我们点双击其文件一栏的文件名,进入对应的.cpp或.h文件
QGIS+QT5+VS2015(2017)的编译
Ctrl+A 全选文件内容,点击上方“文件”,找到“高级保存设置”
QGIS+QT5+VS2015(2017)的编译
将其从无签名改为带签名
QGIS+QT5+VS2015(2017)的编译
修改后——
QGIS+QT5+VS2015(2017)的编译
修改所有出现此类警告的.cpp和.h文件,再次生成“qgis”项目,大部分报错将会消失。(也有可能直接编译通过)

2. 可能报错的其他问题

2.1与qtmain.lib有关的未初始化的定义
解决方法:
找到例如此的警告信息
LNK4099 未找到 PDB“qtmain.pdb”(使用“qtmain.lib(qtmain_win.obj)正在链接对象,如同没有调试信息一样
得到该警告来源的项目名,如“qgiscrashhandle”

右击“qgiscrashhandle项目”->“属性”->“连接器”->“输入”附加依赖项中修改添加
D:\QGIS\OSGeo4W64\apps\Qt5\lib\qtmain.lib QGIS+QT5+VS2015(2017)的编译

2.2 qgis_gui项目中出现未定义的标识符 "QWebElement"
解决方法:
“qgis_gui项目”->“属性”->“C/C++”->“常规”附加包含目录中修改添加
D:\QGIS\OSGeo4W64\apps\Qt5\include\QtWebKit
QGIS+QT5+VS2015(2017)的编译
注释掉报错函数关于QWebElemen类的内容,并在qgismaptip.cpp文件开头注释掉——
//#if WITH_QTWEBKIT
//#endif
(因为原代码中WITH_QTWEBKIT未定义,头文件 不可被识别;又因WITH_QTWEBKIT未定义,QWebElemen类中部分函数无法被调用,故也注释掉)
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译

2.3 qgis_gui项目中出现CORE_EXPORT显式实例化声明无效
解决方法:
对于报错的位置——qgsoptionalexpression.h文件中,在template后添加class
QGIS+QT5+VS2015(2017)的编译
重新生成解决方案。
如果完整的下载了链接库并正确引入路径,此时,不会再遇到其他问题。
QGIS+QT5+VS2015(2017)的编译
我们可以在输出路径下发现生成的qgis.exe文件
(路径:D:\QGIS\qgis-3.2.2-build\output\bin\RelWithDebInfo)

3. 其他可能的问题(来源于网络统计)

如果出现问题,优先选择从gis_core项目、qgis_analysis项目、qgis_gui项目依次调试(其他项目均依赖于他们)
此时仍然有可能出现:

3.1 找不到 <netinet/in.h>,注释掉即可

3.2 error MSB6006: “rc.exe”已退出,代码为 5
在C盘下直接搜索该应用,将其路径配置到项目中即可。

3.3 MSVCRT.lib(exe_winmain.obj) : error LNK2019: 无法解析的外部符号 WinMain
这是因为——
新建项目是控制台应用程序,而程序通过的是WinMian(及windows入口函数)
可以在“qgis_core项目”->“属性”->“连接器”->“输入”附加依赖项中修改添加
D:\QGIS\OSGeo4W64\apps\Qt5\lib\qtmain.lib
QGIS+QT5+VS2015(2017)的编译
重新生成即可。

3.4 链接错误或者缺少有关附加库问题
通常表现为——无法解析的外部符号;找不到、打不开.lib文件等
这与个人的主机环境有关,可以在“项目”->“属性”->“连接器”->“输入”附加依赖项中修改。
附上我的部分属性情况

Lib问题,检查附加依赖项
可以在“项目”->“属性”->“连接器”->“输入”附加依赖项中查看修改;

对于Release或者RelWithDebInfo版本,Lib路径基本如下图列举
对于Debug版本,部分Lib库名后有d标识
如下图的Qt5Cored即为Debug版本
(Debug版本与Release(RelWithDebInfo)版本的Lib名称不同,但路径一致。在工程修改版本环境时会自动更新链接,更改库名。无需手动更改。)
QGIS+QT5+VS2015(2017)的编译

附加依赖项——
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译

3.5 缺少可执行文件或者环境路径问题
Dll问题,检查可执行文件目录,即检查环境路径
可以在“项目”->“属性”->“VC++目录”->“可执行文件目录”中编辑查看
主要检查有无以下路径:
D:\QGIS\OSGeo4W64\apps\qt5\bin
D:\QGIS\OSGeo4W64\apps\Python37
D:\QGIS\OSGeo4W64\apps\Python37\Scripts
D:\QGIS\OSGeo4W64\bin
D:\Program Files\CMake\bin
D:\QGIS\cygwin64\bin
C:\WINDOWS\system32
C:\WINDOWS
C:\WINDOWS\system32\WBem



运行成果


配置运行环境

编译好的qgis.exe会在目录D:\QGIS\qgis-3.2.2-build\output\bin\RelWithDebInfo下

但打开qgis.exe时会出现报错
QGIS+QT5+VS2015(2017)的编译
此时,把OSGeo4W64\apps\Qt5\bin和OSGeo4W64\bin下的dll文件全部拷贝到exe文件同目录下即可

同时,把OSGeo4W64\apps\Qt5\plugins文件下的platforms文件夹也拷贝到exe文件同目录下
当程序运行时,找不到正确支持图标格式(svg)的库文件。这里需要把OSGeo4W64\apps\Qt5\plugins文件下的imageformats文件夹也拷贝到exe文件同目录下
QGIS+QT5+VS2015(2017)的编译
再次打开运行qgis.exe
如图所示——
QGIS+QT5+VS2015(2017)的编译


语言汉化

点击Settings->Options,选择国旗和语言(一定要选国旗),设置完成以后,重新启动即可。
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译



其他参考资料


二次开发

QGIS二次开发基础
这位博主的QGIS版本较老,但方法上并无影响。
可以参考。

C++_API_Documentation
QGIS的API信息


QGIS的构建CMAKE规则

粗略整理,可能有所遗漏,望见谅。
在qgis源码文件夹下,每一个CmakeList.txt文件都有对应当前目录文件的详细解释。
现仅对首层目录中的CmakeList.txt文件,整理其中的一部分定义,解释如下
(主要是对WITH项的解释)
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译
QGIS+QT5+VS2015(2017)的编译


感谢

考虑Python:QGIS2.18.18 + Qt5.8.0 + VS2015(X64) + Python3.6.
QGIS(2.18.15 源码)+Qt(5/5.9.3)+VS2015(X64)编译.