简体   繁体   English

在 CMake 中使用 setup.py 构建 python 包

[英]Build a python package with setup.py in CMake

EDIT: The question is a bit too long.编辑:这个问题有点太长了。 Here is my real question: How can I build and install a python package with setuptools (setup.py) inside CMake?这是我真正的问题:如何在 CMake 中使用 setuptools (setup.py) 构建和安装 python 包? The detail of my code is shown below (but with an out-of-source build method, the method with the source is working).我的代码的详细信息如下所示(但使用源外构建方法,使用源代码的方法有效)。


I have a project where I need to distribute my own python package.我有一个项目需要分发我自己的 python 包。 I made a setup.py script but I would like to build & install it with CMake.我制作了一个 setup.py 脚本,但我想用 CMake 构建和安装它。

I followed Using CMake with setup.py but it only works with one CMakeLists.txt alongside the setup.py and the python folder and without executing cmake from a build directory.我遵循Using CMake with setup.py但它仅适用于setup.py和 python 文件夹旁边的一个CMakeLists.txt ,并且不从构建目录执行 cmake 。

With this layout :使用这种布局:

Project/
--build/
--lib/
----python/
------folder1/
------folder2/
------data/
------...
------__init__.py
----setup.py
----CMakeLists.txt
--CMakeLists.txt

and with CMakeLists.txt :并使用CMakeLists.txt

cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)
add_subdirectory(lib)
(..)

and with lib/CMakeLists.txt :并使用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()

and with setup.py :并使用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")

When I run CMake from build directory and then make , the target is built but with nothing.当我从 build 目录运行CMake然后make ,目标被构建但什么都没有。 It is as if no packages were found.就好像没有找到包裹一样。 The installation installs the python package without .py files.安装会安装没有.py文件的 python 包。

setuptools doesn't know about the out of source build and therefore doesn't find any python source files (because you do not copy them to the binary dir, only the setup.py file seems to exist there). setuptools 不知道源代码外构建,因此找不到任何 python 源文件(因为您没有将它们复制到二进制目录,所以那里似乎只存在setup.py文件)。 In order to fix this, you would have to copy the python source tree into the CMAKE_CURRENT_BINARY_DIR .为了解决这个问题,您必须将 python 源代码树复制到CMAKE_CURRENT_BINARY_DIR中。

https://bloerg.net/2012/11/10/cmake-and-distutils.html建议在setup.py中将package_dir设置为${CMAKE_CURRENT_SOURCE_DIR}

As pointed out previously you can copy your python files to the build folder, eg something like this如前所述,您可以将 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)

and then have a build target like this然后有一个像这样的构建目标

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})

In case you do not want to use pip you have to adjust the PyPackageBuld target.如果您不想使用 pip,则必须调整 PyPackageBuld 目标。

If you want to include some shared library, eg written in C++, which is build by other parts of your cmake project you have to copy the shared object file as well to the binary folder如果您想包含一些共享库,例如用 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}")

and add it to the package_data in setup.py并将其添加到setup.py中的package_data

....
package_data={
        '': ['libs/YourLib.cpython-39-x86_64-linux-gnu.so']
    }

You can find a working example using pybind11 for `C++´ bindings at https://github.com/maximiliank/cmake_python_r_example您可以在https://github.com/maximiliank/cmake_python_r_example找到使用pybind11进行“C++”绑定的工作示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM