如何解决如何使用 cmake、swig setuptools 项目从复杂的安装文件夹创建包
我正在编写一个非常复杂的库,它使用 C++ 代码和用 swig 生成的 Python 绑定。该代码旨在用于纯 C++ 或 Python 接口。 当前的部署过程运行良好,但非常基础:cmake -> Visual Studio -> 安装。然后在使用库的 python 脚本中,我必须用正确的路径“附加 sys.path”到已安装的库和 python 模块,例如:
sys.path.insert(0,os.path.abspath(os.path.join('..','install','install_msvc17_python38_64bits','lib','python3.8','site-packages','fms')))
cmake 过程本身非常复杂,有许多子文件夹和一个用于 python 包装的特定文件夹。我不想修改它。
我想为用户简化安装过程。理想情况下,他会运行“python setup.py install”以避免打开 cmake、visual studio,尤其是在路径中添加内容。
所以,我最近调查了 setuptool,但老实说,我不明白它到底想要它做什么以及如何做。我找到了几个很好的教程和示例,我创建了一个 setup.py 文件(见下文),但它并不完全是我想要的。
首先我想向您展示使用 cmake 构建过程创建的文件夹:
install_folder
当我使用 setup.py install 安装东西时,我得到了正确的 cmake 配置、生成、构建、安装,但包会导致问题。这个完整组织的副本在 C:\Anaconda3\Lib\site-packages\FMS-0.6.0-py3.8-win-amd64.egg 中完成。当然,当我在 python 中导入我的库时,我得到了(如预期的......):
>>> import FMS
Traceback (most recent call last):
File "<stdin>",line 1,in <module>
ModuleNotFoundError: No module named 'FMS'
一个好的组织应该是:
-
FMS-0.6.0-py3.8-win-amd64.egg
- 文档
- FMS
- FMS_core.dll
- FMS_core.py
- FMS_core.pyd
如何通过 build_ext 掌握anaconda site-package文件夹中的文件夹组织?
非常感谢!
我已经看过的东西:
- Place pre-compiled extensions in root folder of non-pure Python Wheel package
- https://martinopilia.com/posts/2018/09/15/building-python-extension.html
- Extending setuptools extension to use CMake in setup.py?
- https://docs.python.org/fr/3/install/index.html
# -*- coding: utf-8 -*-
import os
import sys
import subprocess
from subprocess import Popen,PIPE
from sysconfig import get_paths
from pprint import pprint
from setuptools import setup,Extension
from setuptools.command.build_ext import build_ext
# Convert distutils Windows platform specifiers to CMake -A arguments
PLAT_TO_CMAKE = {
"win32": "Win32","win-amd64": "x64","win-arm32": "ARM","win-arm64": "ARM64",}
CMAKE_INSTALL_DIR = "C://Program Files//CMake//bin//cmake.exe"
class CMakeExtension(Extension):
def __init__(self,name,sourcedir=""):
Extension.__init__(self,sources=[])
self.sourcedir = os.path.abspath(sourcedir)
class CMakeBuild_FMS(build_ext):
def build_extension(self,ext):
extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
#extdir = os.path.join(extdir,'fms')
# Python
python_main_paths = get_paths() # a dictionary of key-paths
version_python = str(sys.version_info[0]) + str(sys.version_info[1])
PYTHON_DIR_EXE = sys.executable
PYTHON_DIR_INC = python_main_paths['include']
PYTHON_DIR_LIBS = os.path.join(python_main_paths['data'],'libs',"python" + version_python + ".lib")
# Utilities (default repositories)
SWIG_EXE = os.path.abspath(os.path.join('..','..',"utilities","swigwin-4.0.2","swig.exe"))
Eigen3_DIR = os.path.abspath(os.path.join('..',"eigen-3.3.9","install","share","eigen3","cmake"))
Boost_INCLUDE_DIR = os.path.abspath(os.path.join('..',"boost_1_74_0"))
FMT_DIR = os.path.abspath(os.path.join('..',"FMT_V4","install"))
# RGINE
RGINE_DIR = os.path.abspath(os.path.join('..',"rgine","cmake"))
# required for auto-detection of auxiliary "native" libs
if not extdir.endswith(os.path.sep):
extdir += os.path.sep
cfg = "Debug" if self.debug else "Release"
# CMake lets you override the generator - we need to check this.
# Can be set with Conda-Build,for example.
cmake_generator = os.environ.get("CMAKE_GENERATOR","Visual Studio 15 2017 Win64")
cmake_args = [
"-DFMS_VERSION_INFO={}".format(self.distribution.get_version()),"-DCMAKE_BUILD_TYPE={}".format(cfg),# not used on MSVC,but no harm
"-DSWIG_EXECUTABLE={}".format(SWIG_EXE),"-DCMAKE_INSTALL_PREFIX={}".format(extdir),"-DRGINE_DIR={}".format(RGINE_DIR),"-DEigen3_DIR={}".format(Eigen3_DIR),"-DBoost_INCLUDE_DIR={}".format(Boost_INCLUDE_DIR),"-DFMT_AUTO_DOCUMENTATION={}".format("OFF"),"-DFMT_DIR={}".format(FMT_DIR),"-DFMT_V4_Mode={}".format("Binaries"),"-DPYTHON_EXECUTABLE={}".format(sys.executable),"-DPYTHON_INCLUDE_DIR={}".format(PYTHON_DIR_INC),"-DPYTHON_LIBRARY={}".format(PYTHON_DIR_LIBS),"-DFMS_INSTALL_EXTERNAL_DEPENDENCIES={}".format("TRUE"),"-DFMS_AUTO_DOCUMENTATION={}".format("FALSE"),"-DFMS_Sphinx_AUTO_DOCUMENTATION={}".format("FALSE"),"-DDOXYGEN_SHOW_WARNINGS={}".format("FALSE"),]
build_args = []
# Multi-config generators have a different way to specify configs
cmake_args += [
"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(),extdir)
]
build_args += ["--config",cfg]
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)
print("CONfigURE / GENERATE PROJET ------------------------------------")
subprocess.check_call([CMAKE_INSTALL_DIR,"-G",cmake_generator,"-S",ext.sourcedir] + cmake_args,cwd=self.build_temp)
print("BUILD PROJET ---------------------------------------------------")
subprocess.check_call([CMAKE_INSTALL_DIR,"--build","."] + build_args,cwd=self.build_temp)
print("INSTALL PROJET -------------------------------------------------")
subprocess.check_call([CMAKE_INSTALL_DIR,"--install","."],cwd=self.build_temp)
# The information here can also be placed in setup.cfg - better separation of
# logic and declaration,and simpler if you include description/version in a file.
setup(
name="FMS",version="0.6.0",author="me",author_email="me@somwhere.mars",description="FMS",long_description="",ext_modules=[CMakeExtension("FMS","")],cmdclass={"build_ext": CMakeBuild_FMS},zip_safe=False,)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。