迁移到MSYS2 与 Qt 工具链注意的几个事情(注意链接顺序,并且人造mingw工具链所没有的局部midl.exe命令)
Microsoft Visual Studio 2015社区版提供了强大的开发体验,且 Qt 提供了预编译版本。然而,由于客户提出兼容Windows XP ~ Windows 8.1 这样宽泛的环境要求,使得我们不得不考虑更换工具链。经过反复对比测试,在Mingw32, Cygwin, MSYS2, Visual Studio 2010几个工具链中,综合性能、未来的可持续性、中文支持以及第三方库支持(比如qwt),认为MSYS2较为合适。在后续复杂的迁移过程中,基本是平顺的,但也遇到了一些问题,这里做个记录。
1、ActiveQt COM/OLE 支持有问题,需要额外设置编译参数
我们有个子项目需要生成一个ActiveX控件,使用到了 QAxContainer模块。在编译时,报告了上百个编译错误,提示找不到 libole32.a, libuuid.a 等库中包含的符号。经过简单分析,特别是MakeFile中的编译器指令提示,MSYS2没有正确处理ActiveQt的链接选项。具体说来,由于g++在链接时,符号依赖项查找遵循从左至右的顺序,如果设置不当,会导致诡异的链接错误,请参考这篇文章。
知道了这个问题,我们手工在pro文件中加入下面的内容:
- LIBS += -lQt5AxServer -lQt5AxBase -lole32 -loleaut32 -luser32 -lgdi32 -ladvapi32 -luuid
错误竟然依旧!继续观察qmake出来的MakeFile,发现-lQt5Ax* 都被放到了最后。一拍脑袋,怎么忘记了, qmake 在产生Makefile对相同名称的库进行合并,会改变其原有的顺序这个坑~!于是,把需要使用 QAxServer 模块的工程改成这样:
- win32-g++{
- CONFIG += no_lflags_merge
- LIBS += -lQt5AxServer -lQt5AxBase -lole32 -loleaut32 -luser32 -lgdi32 -ladvapi32 -luuid
- }
把需要使用 QAxContainer 模块的工程改成这样:
- win32-g++{
- CONFIG += no_lflags_merge
- LIBS += -lQt5AxContainer -lQt5AxBase -lole32 -loleaut32 -luser32 -lgdi32 -ladvapi32 -luuid
- }
no_lflags_merge 表示不进行库合并和排序(排序是合并的副作用,估计内部合并时用了类似set 之类的类stl容器),这样,Makfile中,Qt5Ax*库就位于系统库之前了!这一点在Qt官方Mingw32安装版里是调整好了的。
修改后,链接通过,但是,Post Link 流程出错。
2. 解决参数转译符冲突
链接后,第一个问题是无法生成IDL文件。考察编译输出命令行,发现对 idc.exe 调用时,传参数使用的是 windows 参数转译符 "/"。然而,在msys2环境里,"/"不是unix命令行的合法参数转译符,应该用“-”(减号)才对。不要紧,这个编译后事件的命令全部存储在 mingw32(64)/share/qt5/mkspecs/features/win32/idcidl.prf 里。这个文件的内容如下:
- ...
- !qaxserver_no_postlink {
- !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_NEWLINE)
- QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} /idl $ ${ACTIVEQT_OUTPUT}.idl -version $ ${ACTIVEQT_VERSION}$ ${ACTIVEQT_NEWLINE})
- !isEmpty(RC_FILE) {
- QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDL "$ ${ACTIVEQT_OUTPUT}.idl" /nologo /tlb "$ ${ACTIVEQT_OUTPUT}.tlb"$ $ACTIVEQT_NEWLINE)
- QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} -tlb $ ${ACTIVEQT_OUTPUT}.tlb$ $ACTIVEQT_NEWLINE)
- } else {
- QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDL "$ ${ACTIVEQT_OUTPUT}.idl" /nologo /tlb "$ ${ACTIVEQT_TLBOUT}"$ $ACTIVEQT_NEWLINE)
- message("No rc-file linked into project; type library will be a separate file.")
- }
- !qaxserver_no_register: \
- QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} /regserver)
- QMAKE_CLEAN += $ ${ACTIVEQT_OUTPUT}.idl $ ${ACTIVEQT_OUTPUT}.tlb
- }
二话不说,全部改为"-"
- !qaxserver_no_postlink {
- !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_NEWLINE)
- QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} -idl $ ${ACTIVEQT_OUTPUT}.idl -version $ ${ACTIVEQT_VERSION}$ ${ACTIVEQT_NEWLINE})
- !isEmpty(RC_FILE) {
- QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDL "$ ${ACTIVEQT_OUTPUT}.idl" -nologo -tlb "$ ${ACTIVEQT_OUTPUT}.tlb"$ $ACTIVEQT_NEWLINE)
- QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} -tlb $ ${ACTIVEQT_OUTPUT}.tlb$ $ACTIVEQT_NEWLINE)
- } else {
- QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDL "$ ${ACTIVEQT_OUTPUT}.idl" -nologo -tlb "$ ${ACTIVEQT_TLBOUT}"$ $ACTIVEQT_NEWLINE)
- message("No rc-file linked into project; type library will be a separate file.")
- }
- !qaxserver_no_register: \
- QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} -regserver)
- QMAKE_CLEAN += $ ${ACTIVEQT_OUTPUT}.idl $ ${ACTIVEQT_OUTPUT}.tlb
- }
修改后,再次重新编译(要重新编译才能触发编译后事件),idl 顺利产生。
可是,接着问题又大了,msys2 的工具链里没有 midl.exe。这个工具是windows SDK 的一部分,且需要Visual C++的 cl.exe。先是尝试在PATH里加入路径,但没有成功。除非彻底加入vcvars32.bat的所有设置,否则无法通过。这个问题有办法:
3. 为Mingw32 环境提供midl.exe支持
前文书,midl.exe 是 windows SDK中的工具,这个工具依赖Visual C++编译器。然而,在MingW工具链中,默认是无法调用VC编译器的。为了给Mingw32-make创造出一个局部的VC编译环境,新建一个简单的控制台外壳,名字也叫“midl.exe”,在内部调用 vcvars32.bat并把命令行参数传给真正的 midl.exe即可:
pro文件,控制台Qt应用:
- QT += core
- QT -= gui
- CONFIG += c++11
- TARGET = midl
- CONFIG += console
- CONFIG -= app_bundle
- TEMPLATE = app
- SOURCES += main.cpp
唯一的代码文件,main.cpp:
- #include <QCoreApplication>
- #include <QString>
- #include <QSettings>
- #include <QDir>
- #include <QProcess>
- #include <QStringList>
- #include <QDebug>
- #include <stdlib.h>
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- QString exeName = a.applicationName();
- //0. the exe name and ini filename should be stored together.
- QString iniFile = a.applicationFilePath() + ".ini";
- QSettings settings(iniFile,QSettings::IniFormat);
- //1.get the current directory
- QString strCurrentDir = QDir::current().absolutePath();
- //2.get the visual studio vcvars32 path and raw EXE path
- QString vcvarsPath = settings.value("SETTINGS/VCVARS","D:\\Microsoft Visual Studio 10.0\\VC\\bin\\vcvars32.bat")
- .toString();
- QString exeDir = settings.value("SETTINGS/EXEDIR","C:\\Program Files (x86)\\Windows Kits\\8.1\\bin\\x86")
- .toString();
- //3.Make the cmd target
- QString cmd ;
- //3.1. call vc vars to
- // cmd += " && ";
- cmd += "CALL ";
- cmd += "\"" + vcvarsPath + "\"";
- //3.2. chdir back to current
- cmd += " && ";
- cmd += "CD /D \"" + strCurrentDir.replace("/","\\") + "\"";
- //3.3. call exeName with args
- cmd += " && ";
- cmd += "\"" + exeDir + "\\" + exeName + "\" ";
- for(int i=1;i<argc;++i)
- cmd += argv[i] + QString(" ");
- settings.setValue("SETTINGS/VCVARS",vcvarsPath);
- settings.setValue("SETTINGS/EXEDIR",exeDir);
- //4. display and exe the cmd
- puts(cmd.toStdString().c_str());
- int ret = system(cmd.toStdString().c_str());
- a.exit(0);
- return ret;
- }
默认的VC配置可能和实际的不符合,不要紧,只要在 midl.exe (壳子)同文件夹下设置midl.exe.ini即可:
- [SETTINGS]
- VCVARS=D:\\Microsoft Visual Studio 10.0\\VC\\bin\\vcvars32.bat
- EXEDIR=C:\\Program Files (x86)\\Windows Kits\\8.1\\bin\\x86
修改这个参数即可。VCVARS即是vc编译器批处理文件的位置,EXEDIR是真的midl.exe的文件夹。
4. 试试看!
二话不说,开始编译,OK!
- g++ -Wl,-s -shared -Wl,-subsystem,windows -mthreads -Wl,--out-implib,../bin/libqtaxviewer_planetosm.dll.a -Wl,../../qtv.planet/qtviewer_planetosm/qtaxviewer_planetosm.def -o ../bin/qtaxviewer_planetosm.dll object_script.qtaxviewer_planetosm.Release -lglu32 -lopengl32 -lgdi32 -luser32 -lQt5AxServer -lQt5AxBase -lole32 -loleaut32 -luser32 -lgdi32 -ladvapi32 -luuid -lQt5AxServer -lQt5AxBase -lQt5Widgets -lQt5Gui -lQt5Network -lQt5Core
- /D/msys64/mingw32/bin/idc.exe ../bin/qtaxviewer_planetosm.dll -idl release//qtaxviewer_planetosm.idl -version 1.0
- release\\qtaxviewer_planetosm.idl
- midl release//qtaxviewer_planetosm.idl -nologo -tlb release//qtaxviewer_planetosm.tlb
- Setting environment for using Microsoft Visual Studio 2010 x86 tools.
- Processing release\\qtaxviewer_planetosm.idl
- qtaxviewer_planetosm.idl
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\ocidl.idl
- ocidl.idl
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\oleidl.idl
- oleidl.idl
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\objidl.idl
- objidl.idl
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\unknwn.idl
- unknwn.idl
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\wtypes.idl
- wtypes.idl
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\basetsd.h
- basetsd.h
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\guiddef.h
- guiddef.h
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\oaidl.idl
- oaidl.idl
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\servprov.idl
- servprov.idl
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\urlmon.idl
- urlmon.idl
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\msxml.idl
- msxml.idl
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\oaidl.acf
- oaidl.acf
- Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\ocidl.acf
- ocidl.acf
- CALL "D:\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" && CD /D "D:\documents\Qt\build-qplanetosm-Desktop_Qt_MinGW_w64_32bit_MSYS2-Release\qtviewer_planetosm" && "C:\Program Files (x86)\Windows Kits\8.1\bin\x86\midl" release//qtaxviewer_planetosm.idl -nologo -tlb release//qtaxviewer_planetosm.tlb
- /D/msys64/mingw32/bin/idc.exe ../bin/qtaxviewer_planetosm.dll -tlb release//qtaxviewer_planetosm.tlb
- Type library attached to D:\documents\Qt\build-qplanetosm-Desktop_Qt_MinGW_w64_32bit_MSYS2-Release\bin\qtaxviewer_planetosm.dll.
- /D/msys64/mingw32/bin/idc.exe ../bin/qtaxviewer_planetosm.dll -regserver
- Server registered successfully!
- mingw32-make[2]: Leaving directory 'D:/documents/Qt/build-qplanetosm-Desktop_Qt_MinGW_w64_32bit_MSYS2-Release/qtviewer_planetosm'
- mingw32-make[1]: Leaving directory 'D:/documents/Qt/build-qplanetosm-Desktop_Qt_MinGW_w64_32bit_MSYS2-Release/qtviewer_planetosm'
- 09:57:52: 进程"D:\msys64\mingw32\bin\mingw32-make.exe"正常退出。
- 09:57:52: Elapsed time: 01:26.
http://blog.csdn.net/goldenhawking/article/details/51125604
迁移到MSYS2 与 Qt 工具链注意的几个事情(注意链接顺序,并且人造mingw工具链所没有的局部midl.exe命令)的更多相关文章
- 迁移到MSYS2 与 Qt 工具链注意的几个事情(g++在链接时,符号依赖项查找遵循从左至右的顺序,但qmake会自动合并造成错误。使用脚本给Mingw32-make创造出一个局部的VC编译环境)
Microsoft Visual Studio 2015社区版提供了强大的开发体验,且 Qt 提供了预编译版本.然而,由于客户提出兼容Windows XP ~ Windows 8.1 这样宽泛的环境要 ...
- 区块链学习(四)truffle部署编译智能合约以太坊私有链
前面我们介绍了以太坊私有链的搭建以及多节点私有链网络,这次我们介绍如何使用truffle框架来部署编译智能合约到我们之前搭建的私有链网络中. 搭建环境及需使用的工具:ubuntu18.04 Truf ...
- [js]js代码执行顺序/全局&私有变量/作用域链/闭包
js代码执行顺序/全局&私有变量/作用域链 <script> /* 浏览器提供全局作用域(js执行环境)(栈内存) --> 1,预解释(仅带var的可以): 声明+定义 1. ...
- win使用MSYS2安装Qt开发环境
原文链接 MSYS2 下载地址: pacman的具体用法 有pacman的具体使用方法.我们首先对系统升级 我们首先对系统升级 pacman -Syu 就会检测整个系统可以升级的组件,并自动下载安装, ...
- Win7下msys64安装mingw工具链
1. 安装msys64 安装到指定目录, 例如C:\msys64 2. 命令行更新 运行msys2.exe打开命令行窗口, 执行命令 pacman -Syuu 3. 修改安装源 进入msys64/et ...
- 小萝贝控机大师工具推荐(一款在PC就能控制手机界面的工具)
在一次写博客的过程中,要截取手机app上的几张图片,然后粘贴到博客里面去,不了解这个工具的时候,我就从手机上截图(使用其他的截图app或者使用手机自己的截图功能),然后再传送到电脑上,然后再放到博文中 ...
- 使用 xsd.exe 命令工具将 xsd 架构生成 类(CS) 文件
vs自带命令行工具 命令:xsd xml文件路径 C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC>xsd d:Scheme.xml ...
- 工具类:将其他编码类型转换成UTF-8或者其他类型的工具类
将其他编码类型转换成UTF-8或者其他类型的工具类 public static String changeUTF(String str) { String newStr = null; try { n ...
- iOS开发之工具篇-20个可以帮你简化移动app开发流程的工具
如果想进入移动app开发这个领域,你总能从别的开发者或者网上或者书上找到各种各样的方法和工具,对于新手来说,还没有摸清门路就已经陷入迷茫了.这里推荐20个可以帮你简化app开发流程的工具.很多开发者都 ...
随机推荐
- Git commit template 模板设定
多人协作开发一个项目时,版本控制工具是少不了的,git是linux 内核开发时引入的一个优秀代码管理工具,利用它能很好使团队协作完成一个项目.为了规范团队的代码提交,也方便出版本时的release n ...
- 03-树1. List Leaves (25)
Given a tree, you are supposed to list all the leaves in the order of top down, and left to right. I ...
- SQL Server 内存管理在64位时代的改变
64位机上 地址空间比以前大了去了.它引起的改变多了去了 1.MemToLeave这个词不存在了.因为SQL Server以不再做这种预留空间的事了,也就是说multiple page 想用多少就用 ...
- Oracle ORA-01555(快照过旧)
一.引言: [oracle@yft yft]$ oerr ora 01555 01555, 00000, "snapshot too old: rollback segment number ...
- Linux命令(持续更新ing)
*.命令语法: a.在进行参数设定时,通常为“-”号,若为完整参数名称,则输入“--”符号; b.指令太长的时候,可以使用“\”符号使指令连续到下一行; c.各种符号的意义: '' ...
- C++异常处理的编程方法(阿愚,整整29集)
相遇篇 <第1集 初次与异常处理编程相邂逅> <第2集 C++中异常处理的游戏规则> <第3集 C++中catch(…)如何使用> <第4集 C++的异常处理 ...
- VMware双网卡实现虚拟机连开发板和Internet
前面已经介绍过关于VMware产生的虚拟交换机和虚拟网卡,当宿主机拥有两个网卡时,可以让虚拟系统同时实现上网和连接开发板的功能. 首先,在设置中虚拟出两块虚拟机网卡,一块连接VMnet0交换机一块连接 ...
- Wordpress 音频播放器 Wordpress audio player with jQuery audioplayer.swf
原文地址:http://justcoding.iteye.com/blog/545978 Wordpress audio player with jQuery How to use Wordpress ...
- PDF转word文档
本文未对扫描版的PDF实验,但是可编辑PDF版本可以转换为word而且转换后的word是可编辑的. 1.从http://xiazai.zol.com.cn/detail/33/326858.shtml ...
- 【BZOJ 1088 扫雷Mine】模拟
http://www.lydsy.com/JudgeOnline/problem.php?id=1088 2*N的扫雷棋盘,第二列的值a[i]记录第 i 个格子和它8连通的格子里面雷的数目. 第一列的 ...