Windows下使用MinGW编译dlib(失败)
没错,就是这么皮
原因还是很奇葩,电脑上装的是VS2013,不支持C++11标准,而dlib要求编译器支持C++11标准。但是由于宇宙第一IDE体态太大,重新安装费时费力,且不打算花时间处理可能存在的卸载残留,便打起了GCC的主意。在网上查阅资料,发现GCC4.7之后就支持C++11标准了,于是打算使用配置的MinGW-W64 GCC 6.4.0进行配置。
首先修改setup.py
:
第148-157行,替换:
if platform.system() == "Windows":
cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)]
if sys.maxsize > 2**32:
cmake_args += ['-A', 'x64']
# Do a parallel build
build_args += ['--', '/m']
else:
cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
# Do a parallel build
build_args += ['--', '-j'+str(num_available_cpu_cores(2))]
为
cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
# Do a parallel build
build_args += ['--', '-j4']
将MSVC的编译选项换为GCC的,MinGW-W64默认编译64位程序。
其中最后一行的-j4
指的是make的线程数目,如何自由修改想必不必多说。
由于可以随时使用源码包的源文件重新替换,可以直接修改文件而不做注释。
若需修改所使用的数学包,修改dlib/cmake_utils/find_blas.cmake
:
第67-68, 74行
pkg_check_modules(BLAS_REFERENCE openblas)
pkg_check_modules(LAPACK_REFERENCE lapack)
...
set(REQUIRES_LIBS "${REQUIRES_LIBS} openblas lapack")
这里使用的是pkg-config
作为依赖管理器,在Windows中可以通过使用环境变量PKG_CONFIG_PATH
来配置其搜索路径。简单地来说,就是通过使用pkg-config
工具,可以快速地获得在编译时引入该库时所需要的选项。
比如OpenBLAS库,假设安装位置在X:\openblas\
,库文件位于X:\openblas\lib\
,则在该目录下应有一个pkgconfig
文件夹,里面有openblas.pc
文件,为pkg-config
所需要的库描述文件,在make时自动生成。(按理说所有的.pc
文件应该放在统一的目录下,方便查找和缩短查找路径)
则此时配置PKG_CONFIG_PATH
为:set %PKG_CONFIG_PATH%=X:\openblas\lib\pkgconfig;%PKG_CONFIG_PATH%
.pc
文件为文本文件,里面的路径空格需要特殊处理,可以使用\
来转义连接,也可以用直接把路径用双引号括起来。
编译时需要指定cmake参数:
setup.py build -G "MinGW Makefiles" --set "CMAKE_C_COMPILER"="C:/Program Files/mingw-w64/bin/gcc.exe" --set "CMAKE_CXX_COMPILER"="C:/Program Files/mingw-w64/bin/g++.exe" --set "CMAKE_MAKE_PROGRAM"="C:/Program Files/mingw-w64/bin/make.exe"
分别指定使用MinGW(而不是MSVC)、C编译器、C++编译器和make命令进行编译。
编译过程中可能遇到的问题:
-
编译过程中可能遇到
hypot
命名空间未定义的问题,这是由于Python将C++的hypot
重命名为_hypot
导致的。 解决方案为在Python安装目录下include/pyconfig.h
中引入#include <cmath>
加入所缺失的定义。 必须要将该头文件作为第一个include,因为C++引入和顺序有一定的关系。 - 安装依赖库(如BLAS库)的时候,路径带有空格,在最后的生成pyd的时候,可能会导致路径错误。
推荐解决办法是重新安装依赖库之不含空格等特殊符号的路径下。
但是如果实在是懒,不想重新编译安装(
指自己)的话,在此提供一种骚操作: cmake将链接时所使用的库作为命令行,以文本的形式存储起来。在本例中,存储位置为build\temp.win-amd64-3.6\Release\CMakeFiles\dlib_python.dir\linklibs.rsp
。 思想是通过修改纠正其中生成错误的地方,达到目标效果。-lgfortran
也要手动加入,如果使用了gcc编译的BLAS库的话 想法是美好的,但是现实是残酷的:在每次运行setup.py build
时,为了确保代码的完整性,会将这些中间文件重新生成一遍。 也就是说,即使修改了该文件,再重新时,该文件的内容又会被重新以原方式生成一遍。 好在Windows 10对于cmd做了一些对图形界面更加友好的修改,使得我们可以不用再去先右键再选中文字了。在经过多次试验后,发现当选中文字时,不但不会继续刷信息,而且运行的程序似乎也会暂停运行(类似断点的效果?)。 也就是说,可以通过在运行到链接.pyd
库之前的每一行输出时,暂停检查linklibs.rsp
文件,直到出现该消息为止。 通过这种方式可以顺利通过编译,链接完以后,就基本完成dlib的编译了。 至于升级pkg-config
是否能解决问题,在下并不知道。
===================================================== 后续更新
在使用的时候,报了 系统找不到指定文件 的错误。也就是说,最终整个过程还是失败的。
猜测可能的原因是,编译时生成的是libdlib.a
文件,属于linux操作系统下的静态库,而加载dlib库时,应该要动态加载dll文件,因而产生了该问题。同样,也不能排除文件格式和后缀不同所导致的问题。其原因有待后续深入探究。当然,最好的办法还是按照官方教程来,使用合适版本的VC++编译器来完成功能。
挺骚的,还有吗.jpg