【问题标题】:Build a python package with setup.py in CMake在 CMake 中使用 setup.py 构建 python 包
【发布时间】: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__)),然后使所有包都与该目录相关,以便从源代码构建。

标签: python build cmake package setup.py


【解决方案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 sysconfigf'libs/YourLib{sysconfig.get_config_var("EXT_SUFFIX")}'获取。
      猜你喜欢
      • 2020-10-04
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多