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,在此进行记录。
PyMesh安装指南中涉及到一些系统依赖,这些依赖需要单独安装:
- Python
- NumPy
- SciPy
- GMP
- MPFR
- Boost
本次编译在MSYS2环境下进行。开发软件包选择mingw-w64-x86_64-*
,因此编译产品可以直接在Windows原生环境中运行。
运行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
克隆PyMesh仓库。此处建议使用FastGit代理来加速完整仓库和子模块的克隆。
git clone https://github.com/PyMesh/PyMesh.git
cd PyMesh
git submodule update --init
前往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
前往pymesh/
以外的文件夹,下载GMP
和MPFR
的源码。也可以使用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
建立临时的库目录来构建GMP和MPFR,也可以使用/usr
作为安装目录。
mkdir ~/Projects/c
至此,环境配置完成。
第三方依赖库需编译为静态链接库(.lib)。编译过程分为系统依赖库和PyMesh/third-party
中的第三方依赖库。
在全部编译的过程中,我们尽量很少地使用setup.py
提供的代码,否则会带来一些麻烦。
cd /path/to/your/gmp
./configure --prefix=~/Projects/c --enable-cxx
make
make check # 可选,该过程非常耗时
make install
注意,编译MPFR需要指定GMP的安装路径。
cd /path/to/your/mpfr
./configure --prefix=~/Projects/c --with-gmp=~/Projects/c --disable-shared
make && make install
根据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
修改setup.py
,由于第3步已经完成了第三方依赖的编译安装,因此不需要再次编译了。
# Line 102
# 注释掉编译第三方的代码
# self.build_third_party()
修改后执行:
./setup.py build
此时命令会报错。
编辑build_3.x/build.ninja
文件进行排错。这里可以使用记事本的替换功能进行。
将所有/wd4251
字符串删除;
检查libgmp
和libmpfr
的路径是否有错;
查找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。
MPIR是Windows平台兼容GMP的库。一些第三方依赖库在预定义头中判断了当前系统,如果为WIN32则使用mpir.h
头文件。GMP可以在Windows平台成功编译安装,因此本文选择使用GMP,并对第三方依赖库的源代码进行部分修改。
不能,或者很难,所以另请高明(MSYS)。
许多使用make
进行编译源码,需要执行./configure
进行配置,而CMD/Powershell不能像Shell一样执行这些脚本,因此无法进行。
import pymesh
时提示DLL加载错误?请不要脱离msys
环境来运行PyMesh。并且记得在$PATH
中或$PYTHONPATH
里添加python/pymesh/lib
路径。PyMesh需要加载PyMesh-cpython-xxx.pyd
这个库。
pymesh.test()
一共跑了0个测试?至少在我的机器上是这样,但不影响正常使用。