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原生环境中运行。
-
运行
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
至此,环境配置完成。
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
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
third_party/cork/src/util/prelude.h
// Line 33
// 添加M_PI的定义
#define M_PI 3.14159265358979323846
修改
third_party/cork/src/isct/fixint.h
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
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
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
third_party/draco/src/draco/io/parser_utils.cc
// Line 21
// 添加两个头文件
#include <stdexcept>
#include <limits>
修改
third_party/draco/src/draco/core/cycle_timer.h
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
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
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
字符串删除; -
检查
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。
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加载错误?
import pymesh
请不要脱离
msys
环境来运行PyMesh。并且记得在
$PATH
中或
$PYTHONPATH
里添加
python/pymesh/lib
路径。PyMesh需要加载
PyMesh-cpython-xxx.pyd
这个库。
pymesh.test()
一共跑了0个测试?
pymesh.test()
至少在我的机器上是这样,但不影响正常使用。