没错,就是这么皮

原因还是很奇葩,电脑上装的是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命令进行编译。

编译过程中可能遇到的问题:

  1. 编译过程中可能遇到hypot命名空间未定义的问题,这是由于Python将C++的hypot重命名为_hypot导致的。 解决方案为在Python安装目录下include/pyconfig.h中引入#include <cmath>加入所缺失的定义。 必须要将该头文件作为第一个include,因为C++引入和顺序有一定的关系。

  2. 安装依赖库(如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++编译器来完成功能。

标签: none

仅有一条评论

  1. Esper的小号 Esper的小号

    挺骚的,还有吗.jpg

添加新评论