在 CMake 中使用 setup.py 构建 python 包
Posted
技术标签:
【中文标题】在 CMake 中使用 setup.py 构建 python 包【英文标题】:Build a python package with setup.py in CMake 【发布时间】:2015-05-27 18:18:59 【问题描述】:编辑:这个问题有点太长了。这是我真正的问题:如何在 CMake 中使用 setuptools (setup.py) 构建和安装 python 包?我的代码的详细信息如下所示(但使用源外构建方法,带有源的方法是有效的)。
我有一个项目需要分发我自己的 python 包。我制作了一个 setup.py 脚本,但我想用 CMake 构建和安装它。
我关注了Using CMake with setup.py,但它只适用于CMakeLists.txt
旁边的setup.py
和python 文件夹,并且没有从构建目录执行cmake。
使用这种布局:
Project/
--build/
--lib/
----python/
------folder1/
------folder2/
------data/
------...
------__init__.py
----setup.py
----CMakeLists.txt
--CMakeLists.txt
和CMakeLists.txt
:
cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)
add_subdirectory(lib)
(..)
和lib/CMakeLists.txt
:
find_program(PYTHON "python")
if (PYTHON)
set(SETUP_PY_IN "$CMAKE_CURRENT_SOURCE_DIR/setup.py")
set(SETUP_PY "$CMAKE_CURRENT_BINARY_DIR/setup.py")
set(DEPS "$CMAKE_CURRENT_SOURCE_DIR/python/__init__.py")
set(OUTPUT "$CMAKE_CURRENT_BINARY_DIR/build")
configure_file($SETUP_PY_IN $SETUP_PY)
add_custom_command(OUTPUT $OUTPUT
COMMAND $PYTHON
ARGS setup.py build
DEPENDS $DEPS)
add_custom_target(target ALL DEPENDS $OUTPUT)
install(CODE "execute_process(COMMAND $PYTHON $SETUP_PY install)")
endif()
和setup.py
:
from setuptools import setup, find_packages
setup(name="python",
version="xx",
author="xx",
packages = find_packages(),
package_data = '': ['*.txt'],
description="Python lib for xx")
当我从构建目录运行CMake
,然后运行make
时,目标已构建,但没有任何内容。就好像没有找到包裹一样。安装安装没有.py
文件的python包。
【问题讨论】:
你试过在 add_custom_command 中设置 WORKING_DIRECTORY 吗? 您应该使用相对于当前源目录的所有路径。放置一行,例如DIR = os.path.dirname(os.path.realpath(__file__))
,然后使所有包都与该目录相关,以便从源代码构建。
【参考方案1】:
setuptools 不知道源代码外构建,因此找不到任何 python 源文件(因为您没有将它们复制到二进制目录,所以那里似乎只存在 setup.py
文件)。为了解决这个问题,您必须将 python 源代码树复制到 CMAKE_CURRENT_BINARY_DIR
。
【讨论】:
【参考方案2】:https://bloerg.net/2012/11/10/cmake-and-distutils.html 建议在setup.py
中将package_dir
设置为$CMAKE_CURRENT_SOURCE_DIR
。
【讨论】:
【参考方案3】:如前所述,您可以将 python 文件复制到构建文件夹,例如像这样的
set(TARGET_NAME YourLib)
file(GLOB_RECURSE pyfiles python/*.py)
foreach (filename $pyfiles)
get_filename_component(target "$filename" NAME)
message(STATUS "Copying $filename to $TARGET_NAME/$target")
configure_file("$filename"
"$CMAKE_CURRENT_BINARY_DIR/$TARGET_NAME/$target" COPYONLY)
endforeach (filename)
然后有一个像这样的构建目标
add_custom_target(PyPackageBuild
COMMAND "$PYTHON_EXECUTABLE" -m pip wheel .
WORKING_DIRECTORY "$CMAKE_CURRENT_BINARY_DIR"
COMMENT "Building python wheel package"
)
add_dependencies(PyPackageBuild $TARGET_NAME)
如果您不想使用 pip,则必须调整 PyPackageBuld 目标。
如果你想包含一些共享库,例如用 C++ 编写,由 cmake 项目的其他部分构建,您必须将共享对象文件也复制到二进制文件夹中
set_target_properties($TARGET_NAME PROPERTIES
PREFIX "$PYTHON_MODULE_PREFIX"
SUFFIX "$PYTHON_MODULE_EXTENSION"
BUILD_DIRECTORY "$CMAKE_CURRENT_BINARY_DIR"
LIBRARY_OUTPUT_DIRECTORY "$CMAKE_CURRENT_BINARY_DIR/$TARGET_NAME/libs"
BUILD_WITH_INSTALL_RPATH TRUE)
set(TARGET_PYMODULE_NAME "$PYTHON_MODULE_PREFIX$TARGET_NAME$PYTHON_MODULE_EXTENSION")
并将其添加到setup.py
中的package_data
....
package_data=
'': ['libs/YourLib.cpython-39-x86_64-linux-gnu.so']
您可以在https://github.com/maximiliank/cmake_python_r_example 找到使用pybind11
进行“C++”绑定的工作示例
【讨论】:
cython版本,setup.py
中的共享库名archticture args可以通过import sysconfig
和f'libs/YourLibsysconfig.get_config_var("EXT_SUFFIX")'
获取。以上是关于在 CMake 中使用 setup.py 构建 python 包的主要内容,如果未能解决你的问题,请参考以下文章
Mac 上的 h5py setup.py:找不到 hdf5.h 文件