# Windows XP下编译C++14/17程序手记 自己平时写程序不太讲究向前兼容性,有什么新的用什么,先爽了再说。 于是,当甲方提出他们想要在`Windows XP`上运行一个源码中使用了大量高版本`boost`/`CGAL`/`std::thread`/`lambda`的程序的时候,我就相当的思密达了…… 关键词:`mingw-64`,`boost`,`CGAL`,`libigl` 以下为折腾要点与结论。所有的叙述都是在`Windows XP SP3`32位的大前提下讨论的。 + CMake主程序至少到`3.10.1`都是可以运行在`XP`上的,但`3.8.2`之前才可以生成`VC 2003 (vc编号7.1, msvc编号10.0)`工程; + 但是不建议折腾`VC 2003`这条线,因为`c++11`特性无解; + 然而开始时我没想到这一点,还是折腾了,附加结论:兼容于`VC 2003`的最高`boost`版本是`1.44.0`; + 接下来开始搞`mingw`,建议用`mingw-w64`(不要被名字迷惑,人家有32位版),截至目前(2018年01月18日)最新版搭配`gcc 7.2`,`c++11/14/17`兼容性上没有问题,可执行文件在`XP`上面也没有问题; + `Win-builds`与`Msys2`版本,截至目前的最新版都已经不支持在`XP`下运行了,我也没兴趣研究老到什么版本可以运行;`Cygwin`虽然也有相对比较新的版本支持XP,但`Cygwin`库中的`gcc`版本才到5.4(2019年06月25日),所以不符合要求; + 安装`mingw-w64`时,线程库记得选`POSIX`,否则**据说**不支持`std::thread`; + 装完`mingw-w64`的32位版本之后,需要将其下的`bin`目录加入`Path`,否则`CMake`不会自动找到它(这是小事),且运行起来会报找不到`DLL`的错误(这是大事); + `mingw-w64`下的`make`命令叫`mingw32-make`; + 编译`boost`: > `bootstrap.bat gcc` > `b2 ... toolset=gcc`,`...`处的命令跟其他平台一样 > 为啥写`gcc`呢?因为不写的话默认就用`msvc`了;同时,`Known toolsets are: acc, borland, cc, como, clang, darwin, gcc, gcc-nocygwin, intel-darwin, intel-linux, intel-win32, kcc, kylix, metrowerks, mipspro, msvc, qcc, pathscale, pgi, sun, sunpro, tru64cxx, vacpp, xlcpp, vc7, vc8, vc9, vc10, vc11, vc12, vc14, vc141, vmsdecc`,人家不认`mingw`这个东西,[某些教程](https://stackoverflow.com/questions/20265879/how-to-build-boost-1-55-with-mingw/)在这个问题上有错 + `Windows`下编译`CGAL`时,`gmp`和`mpfr`的问题很烦,即使用`CGAL`安装器也未必能成功下载预编译的库;可以[手动下载](https://cgal.geometryfactory.com/CGAL/precompiled_libs/auxiliary/win32/)之后手动解压到`auxiliary/gmp`目录;目前最新版的预编译库分别是[gmp-all-CGAL-3.9](https://cgal.geometryfactory.com/CGAL/precompiled_libs/auxiliary/win32/GMP/5.0.1/gmp-all-CGAL-3.9.zip)和[mpfr-all-CGAL-3.9](https://cgal.geometryfactory.com/CGAL/precompiled_libs/auxiliary/win32/MPFR/3.0.0/mpfr-all-CGAL-3.9.zip),解压后目录应该是这种结构: C:\DOCUMENTS\DEV\LIB\CGAL-4.10.2\AUXILIARY ├─gdb │ └─python │ │ └─CGAL └─gmp │ ├─include │ └─lib | | └─ libgmp-10.dll | | └─ libmprf-4.dll | | └─ …… 如果是64位,自己把上面链接地址中的`win32`改成`x64`。 + `gcc`编译速度确实比`msvc`慢,但占用的磁盘空间也小多了; + 最终的`boost`编译命令:`b2 install --prefix=C:\dev\lib\boost_1_65_1\install\mingw --build-dir=C:\dev\lib\boost_1_65_1\build toolset=gcc` + 编译出来`boost`没问题,但`CGAL`只能编译成静态库,一旦选择`BuildSharedLibrary`选项,链接`CGAL-Core`的时候就出错,说找不到`Boost`里面一个跟线程相关的函数;到最后也没找到原因,先拿静态库凑合用了,反正目前为止没有报错; + `libigl`,在`mingw-w64`下有一个小bug:`include/igl/writeOFF.cpp`中由一个名叫`RGB`的变量跟某个名叫`RGB`的宏冲突,报错`macro "RGB" requires 3 arguments, but only 2 given`;[修正方法是把这个变量随便重命名一下……](https://github.com/metorm/libigl/commit/d1cc25b7e1e09b22782581e5694f4f63f37bc4b4) --- 2018年05月26日更新: 最近又有某个项目要做这个事情了,这次更夸张,要编译`C++17`和`Qt 5.9`。手记如下: 1. `Git`,[最后一个支持XP的版本](https://superuser.com/questions/1153883/git-for-windows-xp): >TortoiseGit 1.8.16.0 (https://download.tortoisegit.org/tgit/1.8.16.0/) >Git 2.10.0 (https://github.com/git-for-windows/git/releases/tag/v2.10.0.windows.1) 2. `Python`至少到[2.7.6版本](https://legacy.python.org/download/releases/2.7.6/)还能用; 2. Qt源码:`git`下来的方式貌似挺先进,但是感觉缺文件还是怎么的,执行不下去,最后从[官网这里](http://download.qt.io/official_releases/qt/5.9/5.9.5/single/)下载了源码包。尤其诡异的是,`git`仓库里面有5.9.6这个分支,但这个链接中只有5.9.5. 3. `Ruby 1.9.3`或更早版本兼容于XP,2.0以后的就需要自己想办法编译了。 4. `Qt 5.9`的`configure.bat`脚本有点问题,参见[本博客“Windows批处理中SET对errorlevel的影响”一文](http://www.tiger2doudou.com/blog/post/metorm/Windows%E6%89%B9%E5%A4%84%E7%90%86%E4%B8%ADSET%E5%AF%B9errorlevel%E7%9A%84%E5%BD%B1%E5%93%8D)。 5. 编译`Qt`时跳过的模块:`-skip qtwebview -skip qtwebengine -skip qtactiveqt -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtfeedback -skip qtgamepad -skip qtlocation -skip qtquick1 -skip qtquickcontrols -skip qtquickcontrols2 -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtwebchannel`——做个`widget`程序而已,这些模块跳过去可以节省空间,也降低了出错概率。 4. `Qt 5.5`以后用了一些`XP`下不支持的`Win API`,我遇到的第一个是`SHGetKnownFolderPath`,查看对比代码后,虽然直觉上感觉可以把`Qt 5.5`(官方最后一个支持XP的版本)的代码挪过来,但心里发怵,决定还是把我要编译的工程降级一下试试…… 5. `Qt 5.5`少了一些模块,所以要跳过的模块改成了`-skip qtwebkit -skip qtwebkit-examples -skip qtwebengine -skip qtactiveqt -skip qtandroidextras -skip qtcanvas3d -skip qtlocation -skip qtquick1 -skip qtquickcontrols -skip qtsensors -skip qtserialport -skip qtwebchannel` 6. 最终的`configure`命令:`configure.bat -static -debug-and-release -confirm-license -opensource -opengl desktop -platform win32-g++ -prefix "C:\Documents\dev\lib\qt-builds\qt-5.5.1-mingw-7.2.0-posix-static" -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -make libs -make tools -nomake examples -nomake tests -skip qtwebkit -skip qtwebkit-examples -skip qtwebengine -skip qtactiveqt -skip qtandroidextras -skip qtcanvas3d -skip qtlocation -skip qtquick1 -skip qtquickcontrols -skip qtsensors -skip qtserialport -skip qtwebchannel` 6. `Qt 5.5`的源代码占用约4G。`static`版本模式下,编译的临时文件加源码占用,安装后的文件占用不到3G。注意,`install`过程是**复制**文件,所以整个过程实际所需空间要乘二。愿诸君好自为之…… 7. `install`之后,`Qt creator`还需要单独安装。从源码来看,[[https://download.qt.io/archive/qtcreator/4.1/4.1.0/|Qt Creator 4.1.0]]是最后一个可以在`Qt 5.5`下编译出来的版本。可以自己编译,也可以随便下载个`5.5`的官方包,安装时选择仅安装`Qt creator`就行了。 8. 然后在`Qt creator`选项中`Qt version`项目下手动加入你安装的目录中的`qmake.exe`,后面的检测版本什么的会自动进行。然后设置好编译器什么的,就可以开始写程序了。 9. 知道`static`版本出来的文件大,没想打他有这么大:一个带空窗体的`Hello world`程序,`Debug`版本居然有351M,`Release`版也有15M. 6. 编译`libxml2`:下载源码,进入`win32`子目录,按`ReadMe`和`help`操作。 --- 2019年06月25日更新: 安装打包程序`Inno Setup`应该是自6.0版本取消了对XP的支持。最新能用的5.5.9,官网旧版本处有下载。 --- 2019年07月04日更新 今天编译[[https://github.com/Dav1dde/glad|glad库]],但编译这玩意儿时非要从gayhub下载一个东西。但XP下的根证书可能已经与gayhub现在在用的证书对不上了。于是就反复的报url错误。 最终从[[https://stackoverflow.com/questions/36600583/python-3-urllib-ignore-ssl-certificate-verification|这里]]找到了解决办法。这个网页上面的添加ctx参数的方法: import urllib2 import ssl ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE urllib2.urlopen("https://your-test-server.local", context=ctx) 可能能用,但`glad`库中用的是`urllib.request.open()`函数,不接受`context`参数。最终使用了下面的方案,即: > You can just change default context: ssl._create_default_https_context = ssl._create_unverified_context and you don't need ctx at all. --- 2020年10月2日更新: 支持WinXP的最新的Qt Creator版本是`qt-creator-opensource-windows-x86-3.4.2.exe`