Windows MSYS2 构建安装 PyMesh

1. 前言

关于PyMesh

PyMesh is a code base developed by Qingnan Zhou for his PhD research at New York University. It is a rapid prototyping platform focused on geometry processing. PyMesh is written with both C++ and Python, where computational intensive functionalities are realized in C++, and Python is used for creating minimalistic and easy to use interfaces.

PyMesh GitHub仓库:GitHub - PyMesh/PyMesh: Geometry Processing Library for Python

在Linux和MacOS中,PyMesh可以使用setup.py完成一键安装,但由于依赖库及编译环境所限,在Windows中使用该脚本会导致许多错误,而无法完成编译和安装。

经过多次踩坑,我成功地在Windows中安装运行了PyMesh,在此进行记录。

系统环境

  • Windows 10 20H2
  • MSYS2

2. 环境配置

PyMesh安装指南中涉及到一些系统依赖,这些依赖需要单独安装:

  • Python
  • NumPy
  • SciPy
  • GMP
  • MPFR
  • Boost

本次编译在MSYS2环境下进行。开发软件包选择mingw-w64-x86_64-*,因此编译产品可以直接在Windows原生环境中运行。

  1. 运行MSYS2 MinGW x64终端,并运行以下命令安装所需工具:

    # 安装必需的dev库和工具
    pacman -S base-devel msys2-devel
    # 安装MinGW工具链
    pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja
    # 安装Python和依赖库
    pacman -S mingw-w64-x86_64-python3 mingw-w64-x86_64-python-pip mingw-w64-x86_64-python-numpy mingw-w64-x86_64-python-scipy
    # 安装GMP和MPFR所需的m4依赖
    pacman -S m4
    
    # 我的环境配置如下
    $ which make gcc g++ gfortran cmake ninja
    /mingw64/bin/make
    /mingw64/bin/gcc
    /mingw64/bin/g++
    /mingw64/bin/gfortran
    /mingw64/bin/cmake
    /mingw64/bin/ninja
    
  2. 克隆PyMesh仓库。此处建议使用FastGit代理来加速完整仓库和子模块的克隆。

    git clone https://github.com/PyMesh/PyMesh.git
    cd PyMesh
    git submodule update --init
    
  3. 前往pymesh/以外的文件夹,在Boost网站下载、解压、安装Boost。本案例使用boost_1_78_0演示。

    # 根据自己路径确定
    cd ~/Projects
    wget https://boostorg.jfrog.io/artifactory/main/release/1.78.0/source/boost_1_78_0.zip
    unzip boost_1_78_0.zip
    # 初始化
    cd boost_1_78_0
    ./bootstrap.bat  # 双击运行即可
    # 安装至/usr
    ./b2 --build-dir=./tmp --build-type=complete threading=multi link=static toolset=gcc stage install --prefix=/usr
    
  4. 前往pymesh/以外的文件夹,下载GMPMPFR的源码。也可以使用CGAL提供的Windows预编译库文件。

    wget https://gmplib.org/download/gmp/gmp-6.2.1.tar.xz
    tar xvf gmp-6.2.1.tar.xz
    wget https://www.mpfr.org/mpfr-current/mpfr-4.1.0.tar.xz
    tar xvf mpfr-4.1.0.tar.xz
    

    (可选)安装MPFR补丁文件:

    cd mpfr-4.1.0/
    wget https://www.mpfr.org/mpfr-current/allpatches
    pacman -S patch
    patch -N -Z -p1 < allpatches
    
  5. 建立临时的库目录来构建GMP和MPFR,也可以使用/usr作为安装目录。

    mkdir ~/Projects/c
    

至此,环境配置完成。

3. 编译依赖库

第三方依赖库需编译为静态链接库(.lib)。编译过程分为系统依赖库和PyMesh/third-party中的第三方依赖库。

在全部编译的过程中,我们尽量很少地使用setup.py提供的代码,否则会带来一些麻烦。

编译GMP

cd /path/to/your/gmp
./configure --prefix=~/Projects/c --enable-cxx
make
make check   # 可选,该过程非常耗时
make install

编译MPFR

注意,编译MPFR需要指定GMP的安装路径。

cd /path/to/your/mpfr
./configure --prefix=~/Projects/c --with-gmp=~/Projects/c --disable-shared
make && make install

编译third_party依赖

根据setup.py中设置的编译命令,咱们需要编译以下的库:cgal eigen triangle clipper qhull cork draco tetgen tbb mmg json。这些库使用third_party/build.py进行编译。

在此之前,部分代码文件需要进行修改。以下代码内容中的行号提示,均以完全没有修改过的最最最原始的文件为准。

修改build.py
# Line 35
# 在build_generic方法中修改build_flags变量,添加一个选项。路径改为自己的
# 环境变量缺啥加啥就行
    build_flags = build_flags + " -DBoost_INCLUDE_DIR=X:/path/to/boost_1_78_0/"

# Line 43
# 为cmake cmd添加一个生成MinGW Makefiles的选项。这个选项不能直接加到字符串里,否则会被split()分开。
    cmdsplit = cmd.split()
    cmdsplit.append('-G "MinGW Makefiles"')
    # subprocess.check_call(cmd.split(), cwd=build_dir);
    subprocess.check_call(cmdsplit, cwd=build_dir);
修改third_party/cork/src/util/prelude.h
// Line 33
// 添加M_PI的定义
#define M_PI 3.14159265358979323846
修改third_party/cork/src/isct/fixint.h
// Line 50
// 使用gmp.h代替mpir.h

#ifdef _WIN32
// #include <mpir.h>
#include <gmp.h>
修改third_party/cork/src/isct/gmpext4.h
// Line 31
// 使用gmp.h代替mpir.h

//#include <mpirxx.h>
#include <gmpxx.h>
修改third_party/cork/src/mesh/mesh.isct.tpp
// Line 636

// Vec3d raw = mesh->verts[v->ref].pos;
Vec3d raw = TopoCache::mesh->verts[v->ref].pos;
修改third_party/draco/src/draco/io/parser_utils.cc
// Line 21
// 添加两个头文件

#include <stdexcept>
#include <limits>
修改third_party/draco/src/draco/core/cycle_timer.h
// Line 22
// 更改timeval结构体定义头

// #include <windows.h>
// typedef LARGE_INTEGER timeval;
#include <sys/time.h>
修改third_party/draco/src/draco/core/cycle_timer.cc
// Line 19 27 35
// 删除所有 #ifdef _WIN32的宏定义

#ifdef _WIN32
  QueryPerformanceCounter(&tv_end);
  ......
#else
  gettimeofday(&tv_end, NULL);
  ......
#endif

  |
  V

  gettimeofday(&tv_end, NULL);
  ......
修改third_party/mmg/CMakeLists.txt
# Line 24
# 添加 -fcommon 的CMAKE_C_FLAGS

SET(CMAKE_C_FLAGS " -fcommon ${CMAKE_C_FLAGS}")

完成修改后,执行./build.py <libname>进行编译。

./build.py cgal
./build.py eigen
./build.py triangle
./build.py clipper
./build.py qhull
./build.py cork
./build.py draco
./build.py tetgen
./build.py tbb
./build.py mmg
./build.py json

4. 编译安装PyMesh

修改setup.py,由于第3步已经完成了第三方依赖的编译安装,因此不需要再次编译了。

# Line 102
# 注释掉编译第三方的代码

#        self.build_third_party()

修改后执行:

./setup.py build

此时命令会报错。

编辑build_3.x/build.ninja文件进行排错。这里可以使用记事本的替换功能进行。

  • 将所有/wd4251字符串删除;

  • 检查libgmplibmpfr的路径是否有错;

  • 查找Link the shared library ..\python\pymesh\lib\libPyMesh-CGAL.dll字符串,在LINK_LIBRARIES后添加链接-lgmp -lmpfr

      LINK_LIBRARIES = ../python/pymesh/lib/libPyMesh-Mesh.dll.a  ../python/pymesh/third_party/lib/libtbb.dll.a  ../python/pymesh/third_party/lib/libtbbmalloc.dll.a  D:/msys64/usr/lib/libboost_atomic-mgw11-mt-x64-1_78.a  .....  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -lgmp -lmpfr
    
  • 查找Link the shared library ..\python\pymesh\lib\libPyMesh-Boolean.dll字符串,在LINK_LIBRARIES后添加链接-lgmp -lmpfr,并删除LINK_LIBRARIES后的GMP与MPFR路径。

编辑完毕后,执行如下命令进行编译:

cd build_3.x
cmake --build . -j <Jobs> --config Release --

修改setup.py,由于已经完成了PyMesh的编译,因此不需要再次编译了。

# Line 103
# 注释掉编译PyMesh的代码

#        self.build_pymesh()

修改后执行:

./setup.py install

即完成PyMesh的安装。

遇到其他问题,参考第5部分Notes。

5. Notes

选择GMP还是MPIR?

MPIR是Windows平台兼容GMP的库。一些第三方依赖库在预定义头中判断了当前系统,如果为WIN32则使用mpir.h头文件。GMP可以在Windows平台成功编译安装,因此本文选择使用GMP,并对第三方依赖库的源代码进行部分修改。

Cygwin/CMD/Powershell能否完成这些工作?

不能,或者很难,所以另请高明(MSYS)。

许多使用make进行编译源码,需要执行./configure进行配置,而CMD/Powershell不能像Shell一样执行这些脚本,因此无法进行。

import pymesh时提示DLL加载错误?

请不要脱离msys环境来运行PyMesh。并且记得在$PATH中或$PYTHONPATH里添加python/pymesh/lib路径。PyMesh需要加载PyMesh-cpython-xxx.pyd这个库。

pymesh.test()一共跑了0个测试?

至少在我的机器上是这样,但不影响正常使用。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nullptrjzz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值