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文件中加入下面的内容:

  1. LIBS += -lQt5AxServer -lQt5AxBase -lole32 -loleaut32 -luser32 -lgdi32 -ladvapi32 -luuid

错误竟然依旧!继续观察qmake出来的MakeFile,发现-lQt5Ax* 都被放到了最后。一拍脑袋,怎么忘记了, qmake 在产生Makefile对相同名称的库进行合并,会改变其原有的顺序这个坑~!于是,把需要使用 QAxServer 模块的工程改成这样:

  1. win32-g++{
  2. CONFIG += no_lflags_merge
  3. LIBS += -lQt5AxServer -lQt5AxBase -lole32 -loleaut32 -luser32 -lgdi32 -ladvapi32 -luuid
  4. }

把需要使用 QAxContainer 模块的工程改成这样:

  1. win32-g++{
  2. CONFIG += no_lflags_merge
  3. LIBS += -lQt5AxContainer -lQt5AxBase -lole32 -loleaut32 -luser32 -lgdi32 -ladvapi32 -luuid
  4. }

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 里。这个文件的内容如下:

  1. ...
  2. !qaxserver_no_postlink {
  3. !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_NEWLINE)
  4. QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} /idl $ ${ACTIVEQT_OUTPUT}.idl -version $ ${ACTIVEQT_VERSION}$ ${ACTIVEQT_NEWLINE})
  5. !isEmpty(RC_FILE) {
  6. QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDL "$ ${ACTIVEQT_OUTPUT}.idl" /nologo /tlb "$ ${ACTIVEQT_OUTPUT}.tlb"$ $ACTIVEQT_NEWLINE)
  7. QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} -tlb $ ${ACTIVEQT_OUTPUT}.tlb$ $ACTIVEQT_NEWLINE)
  8. } else {
  9. QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDL "$ ${ACTIVEQT_OUTPUT}.idl" /nologo /tlb "$ ${ACTIVEQT_TLBOUT}"$ $ACTIVEQT_NEWLINE)
  10. message("No rc-file linked into project; type library will be a separate file.")
  11. }
  12. !qaxserver_no_register: \
  13. QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} /regserver)
  14. QMAKE_CLEAN += $ ${ACTIVEQT_OUTPUT}.idl $ ${ACTIVEQT_OUTPUT}.tlb
  15. }

二话不说,全部改为"-"

  1. !qaxserver_no_postlink {
  2. !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_NEWLINE)
  3. QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} -idl $ ${ACTIVEQT_OUTPUT}.idl -version $ ${ACTIVEQT_VERSION}$ ${ACTIVEQT_NEWLINE})
  4. !isEmpty(RC_FILE) {
  5. QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDL "$ ${ACTIVEQT_OUTPUT}.idl" -nologo -tlb "$ ${ACTIVEQT_OUTPUT}.tlb"$ $ACTIVEQT_NEWLINE)
  6. QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} -tlb $ ${ACTIVEQT_OUTPUT}.tlb$ $ACTIVEQT_NEWLINE)
  7. } else {
  8. QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDL "$ ${ACTIVEQT_OUTPUT}.idl" -nologo -tlb "$ ${ACTIVEQT_TLBOUT}"$ $ACTIVEQT_NEWLINE)
  9. message("No rc-file linked into project; type library will be a separate file.")
  10. }
  11. !qaxserver_no_register: \
  12. QMAKE_POST_LINK += $ $quote($ $ACTIVEQT_IDC $ ${ACTIVEQT_TARGET} -regserver)
  13. QMAKE_CLEAN += $ ${ACTIVEQT_OUTPUT}.idl $ ${ACTIVEQT_OUTPUT}.tlb
  14. }

修改后,再次重新编译(要重新编译才能触发编译后事件),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应用:

  1. QT += core
  2. QT -= gui
  3. CONFIG += c++11
  4. TARGET = midl
  5. CONFIG += console
  6. CONFIG -= app_bundle
  7. TEMPLATE = app
  8. SOURCES += main.cpp

唯一的代码文件,main.cpp:

  1. #include <QCoreApplication>
  2. #include <QString>
  3. #include <QSettings>
  4. #include <QDir>
  5. #include <QProcess>
  6. #include <QStringList>
  7. #include <QDebug>
  8. #include <stdlib.h>
  9. int main(int argc, char *argv[])
  10. {
  11. QCoreApplication a(argc, argv);
  12. QString exeName = a.applicationName();
  13. //0. the exe name and ini filename should be  stored together.
  14. QString iniFile = a.applicationFilePath() + ".ini";
  15. QSettings settings(iniFile,QSettings::IniFormat);
  16. //1.get the current directory
  17. QString strCurrentDir = QDir::current().absolutePath();
  18. //2.get the visual studio vcvars32 path and raw EXE path
  19. QString vcvarsPath = settings.value("SETTINGS/VCVARS","D:\\Microsoft Visual Studio 10.0\\VC\\bin\\vcvars32.bat")
  20. .toString();
  21. QString exeDir = settings.value("SETTINGS/EXEDIR","C:\\Program Files (x86)\\Windows Kits\\8.1\\bin\\x86")
  22. .toString();
  23. //3.Make the cmd target
  24. QString cmd ;
  25. //3.1. call vc vars to
  26. //  cmd += " && ";
  27. cmd += "CALL ";
  28. cmd += "\"" + vcvarsPath + "\"";
  29. //3.2. chdir back to current
  30. cmd += " && ";
  31. cmd += "CD /D \"" + strCurrentDir.replace("/","\\") + "\"";
  32. //3.3. call exeName with args
  33. cmd += " && ";
  34. cmd += "\"" + exeDir + "\\" + exeName + "\" ";
  35. for(int i=1;i<argc;++i)
  36. cmd += argv[i] + QString(" ");
  37. settings.setValue("SETTINGS/VCVARS",vcvarsPath);
  38. settings.setValue("SETTINGS/EXEDIR",exeDir);
  39. //4. display and exe the cmd
  40. puts(cmd.toStdString().c_str());
  41. int ret = system(cmd.toStdString().c_str());
  42. a.exit(0);
  43. return ret;
  44. }

默认的VC配置可能和实际的不符合,不要紧,只要在 midl.exe (壳子)同文件夹下设置midl.exe.ini即可:

  1. [SETTINGS]
  2. VCVARS=D:\\Microsoft Visual Studio 10.0\\VC\\bin\\vcvars32.bat
  3. EXEDIR=C:\\Program Files (x86)\\Windows Kits\\8.1\\bin\\x86

修改这个参数即可。VCVARS即是vc编译器批处理文件的位置,EXEDIR是真的midl.exe的文件夹。

4. 试试看!

二话不说,开始编译,OK!

  1. 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
  2. /D/msys64/mingw32/bin/idc.exe ../bin/qtaxviewer_planetosm.dll -idl release//qtaxviewer_planetosm.idl -version 1.0
  3. release\\qtaxviewer_planetosm.idl
  4. midl release//qtaxviewer_planetosm.idl -nologo -tlb release//qtaxviewer_planetosm.tlb
  5. Setting environment for using Microsoft Visual Studio 2010 x86 tools.
  6. Processing release\\qtaxviewer_planetosm.idl
  7. qtaxviewer_planetosm.idl
  8. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\ocidl.idl
  9. ocidl.idl
  10. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\oleidl.idl
  11. oleidl.idl
  12. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\objidl.idl
  13. objidl.idl
  14. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\unknwn.idl
  15. unknwn.idl
  16. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\wtypes.idl
  17. wtypes.idl
  18. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\basetsd.h
  19. basetsd.h
  20. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\guiddef.h
  21. guiddef.h
  22. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\oaidl.idl
  23. oaidl.idl
  24. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\servprov.idl
  25. servprov.idl
  26. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\urlmon.idl
  27. urlmon.idl
  28. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\msxml.idl
  29. msxml.idl
  30. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\oaidl.acf
  31. oaidl.acf
  32. Processing C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\ocidl.acf
  33. ocidl.acf
  34. 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
  35. /D/msys64/mingw32/bin/idc.exe ../bin/qtaxviewer_planetosm.dll -tlb release//qtaxviewer_planetosm.tlb
  36. Type library attached to D:\documents\Qt\build-qplanetosm-Desktop_Qt_MinGW_w64_32bit_MSYS2-Release\bin\qtaxviewer_planetosm.dll.
  37. /D/msys64/mingw32/bin/idc.exe ../bin/qtaxviewer_planetosm.dll -regserver
  38. Server registered successfully!
  39. mingw32-make[2]: Leaving directory 'D:/documents/Qt/build-qplanetosm-Desktop_Qt_MinGW_w64_32bit_MSYS2-Release/qtviewer_planetosm'
  40. mingw32-make[1]: Leaving directory 'D:/documents/Qt/build-qplanetosm-Desktop_Qt_MinGW_w64_32bit_MSYS2-Release/qtviewer_planetosm'
  41. 09:57:52: 进程"D:\msys64\mingw32\bin\mingw32-make.exe"正常退出。
  42. 09:57:52: Elapsed time: 01:26.

http://blog.csdn.net/goldenhawking/article/details/51125604#comments

迁移到MSYS2 与 Qt 工具链注意的几个事情(g++在链接时,符号依赖项查找遵循从左至右的顺序,但qmake会自动合并造成错误。使用脚本给Mingw32-make创造出一个局部的VC编译环境)的更多相关文章

  1. 迁移到MSYS2 与 Qt 工具链注意的几个事情(注意链接顺序,并且人造mingw工具链所没有的局部midl.exe命令)

    Microsoft Visual Studio 2015社区版提供了强大的开发体验,且 Qt 提供了预编译版本.然而,由于客户提出兼容Windows XP ~ Windows 8.1 这样宽泛的环境要 ...

  2. Ubuntu安装软件时提示依赖项配置错误

    在终端中使用dpkg安装软件时有时会出现依赖项配置错误的情况, 解决方法是使用指令 sudo apt-get install -f 安装Ubuntu 16.04新系统不再配有的缺失依赖项,之后再次输入 ...

  3. ABI与编译器:ABI是由内核和工具链定义和实现的

    http://book.51cto.com/art/201412/460857.htm <Linux系统编程(第2版)>第1章入门和基本概念,这一章着眼于Linux系统编程的基础概念并从程 ...

  4. VS Code 安装与配置(使用MSYS2环境与mingw-w64 编译环境)

     更正了顺序,之前不知道怎么回事,内容顺序乱了 力求完美.详细,所以希望懂的人留言指点一下. 目前已经开始添加原理解释,希望大家能分享一些gcc gdb C语言等方面优秀链接 后续会慢慢增添内容,修正 ...

  5. 【嵌入式开发】 嵌入式开发工具简介 (裸板调试示例 | 交叉工具链 | Makefile | 链接器脚本 | eclipse JLink 调试环境)

    作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42239705  参考博客 : [嵌入式开发]嵌入式 开发环境 (远 ...

  6. 【原创】基于ZYNQ7000的交叉编译工具链Qt+OpenCV+ffmpeg等库支持总结(二)

    承接上文http://www.cnblogs.com/bombe1013/p/3294301.html,我们接下来说说Qt的移植与安装. 很喜欢Qt这个库以及Qt creater这个IDE,其实个人觉 ...

  7. 从大厂DevOps工具链部署,看现代产品的生命周期管理

    目录 1. 认识DevOps 1.1. DevOps工具链 1.2. CI 持续集成(Continuous Integration) 1.3. CD(持续交付 & 持续部署) 1.4. Agi ...

  8. xmake v2.3.7 发布, 新增 tinyc 和 emscripten 工具链支持

    xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能 ...

  9. X86上搭建交叉工具链,来给龙芯笔记本编译本地工具链(未完待续)

    故事的背景是,我买了一台龙芯2F的笔记本来装B. 为什么说是装B呢?因为不但操作系统是Linux,而且CPU还是龙芯的. 一般人有这么酷的装备吗?简直是装B大圣啊. 这里一定要申明一点,本人不是IT技 ...

随机推荐

  1. NOIP2016 天天爱跑步 - 树上差分

    传送门 题目分析: 一年前还是个傻子的时候居然直接放弃了这题. 首先列出两个方程:如果i节点的观察员能够观察到由s->t的那个人,那么: \[dep[s] - dep[i] = w[i], de ...

  2. URLDecoder和URLEncoder的使用总结

    其实,这两个类的使用并不复杂,URLDecoder和URLEncoder它的作用主要是用于普通字符串和application/x-www-form-rulencoded MIME字符串之间的转换,一般 ...

  3. POJ 1418 基本操作和圆 离散弧

    Viva Confetti Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 761   Accepted: 319 Descr ...

  4. html head标签的内容跑到body标签中 , 并且body中多了个空格

    今天遇到一个奇怪的问题 , 就是在head标签中写的内容跑到body标签中 , 第一种也是经常遇到的情况就是编码 UTF-8 格式带BOM的 , 这种情况是会多一个空格 , 这个基本都知道 , 按ut ...

  5. android 创建一个新的每次project什么时候 请问自己主动 参加 V7依赖?

    android 创建一个新的每次project什么时候 请问自己主动 参加 V7依赖? 分析原因: 主要是由于.我之前的 SDK 的版本号 更新的有点高了.低版本号是不会有这样的问题g的,新版本号中g ...

  6. JavaScript严谨模式(Strict Mode)提升开发效率和质量

    http://flandycheng.blog.51cto.com/855176/982719 http://my.oschina.net/Jsiwa/blog/272761

  7. c语言学习笔记(13)——链表

    链表 算法: 1.通俗定义: 解题的方法和步骤 2.狭义定义: 对存储数据的操作 3.广义定义: 广义的算法也叫泛型 无论数据是如何存储的,对数据的操作都是一样的 我们至少可以通过两种结构来存储数据 ...

  8. 在webapi中使用swagger

    1 在webapi项目下安装swagger,包名 Swashbuckle.AspNetCore 2 在webapi的startup.cs文件中添加swagger服务 /// <summary&g ...

  9. 漫步Unity3D(三)

    八.预制(Prefab) 仅此一点提出,由于它使用过于频繁. 还Unity 一中的核心要素.原本Unity你拖放模型到场景中的一个对象,或者,创建一个几何.或浅的地形.个物体的偏移.旋转和缩放.然后绑 ...

  10. Analysis of variance(ANOVA)

    方差分析,也称为"变异数分析",用于两个及两个以上样本均值(group means)差别的显著性检验.在 ANOVA 的环境下,一个观测得到的方差视为是由不同方差的源组合而成.