使用CMake打包和安装python绑定

时间:2018-02-07 18:23:32

标签: python c++ cmake swig distutils

我有一个C ++项目,我已经为使用SWIG生成了Python绑定。我现在正尝试通过添加安装操作来完成项目的CMake文件。但是每当我完成安装并尝试调用我的函数时,我都会收到一条错误,指出foo has no attribute bar()

这与Python不知道绑定所依赖的.so文件的位置有关。如果foo.py_foo.so都在同一目录中,我可以完美地使用绑定。我正在努力弄清楚我应该如何安装"所有Python绑定和它们所依赖的.so都是以可移植的方式。

显然,我可以将.so的安装路径导出到LD_LIBRARY_PATH,但这对于必须有适当解决方案的解决方案来说似乎是个蠢事。

我的CMakeLists.txt。我已经删除了与编译我的C ++ lib RTK相关的位:

# Project
##

# TODO this actually needs 3.3+
cmake_minimum_required(VERSION 2.6)
project(RTKLIB)

FIND_PACKAGE(SWIG REQUIRED)
INCLUDE(${SWIG_USE_FILE})

FIND_PACKAGE(PythonLibs 3 REQUIRED)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})

find_program(PYTHON "python3" REQUIRED)
include(GNUInstallDirs)


# Variable declarations
##
# Define this directory 
set(RTKLIB_ROOT ${CMAKE_CURRENT_SOURCE_DIR})

# Define the build dir
set(RTKLIB_BIN_DIR "${RTKLIB_ROOT}/build")

list(APPEND CMAKE_MODULE_PATH "${RTKLIB_ROOT}/cmake")

# Setup python vars
set(SETUP_PY_IN "${RTKLIB_ROOT}/setup.py.in")  # initial version of setup.py
set(SETUP_PY    "${RTKLIB_BIN_DIR}/setup.py")     # cmake generated setup.py
set(OUTPUT      "${RTKLIB_BIN_DIR}/python_timestamp") # Timestamp used as dep
set(RTKLIB_PY  "rtk_lib")  # name of the python lib


# Set the output dir for SWIG
set(CMAKE_SWIG_OUTDIR ${RTKLIB_BIN_DIR}/${RTKLIB_PY})


# Generate Python bindings
##
# SWIG Config
SET_PROPERTY(SOURCE include/rtk_lib.i PROPERTY CPLUSPLUS ON)
SWIG_ADD_MODULE(${RTKLIB_PY} python include/rtk_lib.i)           # Generate C-Python bindings
SWIG_LINK_LIBRARIES(${RTKLIB_PY} RTK ${PYTHON_LIBRARIES})    # Link the bindings with python

# Generate the setup.py file
configure_file(${SETUP_PY_IN} ${SETUP_PY}) 

# Build command that depends on the SWIG output files and updates the timestamp
add_custom_command(OUTPUT ${OUTPUT}
                COMMAND ${PYTHON} ${SETUP_PY} build
                COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT}
                DEPENDS ${RTKLIB_BIN_DIR}\${SWIG_MODULE_${RTKLIB_PY}_REAL_NAME})

# Custom target that depends on the timestamp file generated by the custom command
add_custom_target(ALL DEPENDS ${OUTPUT})

# Install the shared library
install(TARGETS ${SWIG_MODULE_${RTKLIB_PY}_REAL_NAME}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

# Install to user's packages
install(CODE "execute_process(COMMAND ${PYTHON} ${SETUP_PY} install --user)")

如果有任何帮助,这是我的setup.py.in

from distutils.core import setup

setup(name='rtk_lib',
        version='${PACKAGE_VERSION}',
        description="""Python bindings for rtk_lib, allowing for serial and
                and file interfaces with RTK messages.""",
        packages=['${RTKLIB_PY}'])

代码的快速摘要:它为与Python兼容的C ++生成包装类,然后它编译并链接包装类与Python库和原始RTK C ++库。之后,您有一个名为rtk_lib的目录,其中包含您的包装类和rtk_lib.py模块。在rtk_lib目录之外是_rtk_lib.so依赖的输出rtk_lib.py共享库。因此,为了使绑定起作用,我将_rtk_lib.so复制到该rtk_lib目录并调用python3。然后我可以导入lib,一切都很棒。

我尝试安装共享库,但即便如此,我仍然得到相同的rtk_lib has no attribute blablabla()

1 个答案:

答案 0 :(得分:0)

看起来像一个老问题,但还是可以解决。

请参见此示例swig_examples_cpp,其中显示了由SWIG包装的简单C ++函数,并使用CMake和CLion对其进行了构建。 C版本是here

这是完整的Python Cmake文件:

project(python_example)

find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})

find_package(PythonLibs)
include_directories(${PYTHON_INCLUDE_PATH})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_SWIG_FLAGS "")

set_source_files_properties(../src/example.i PROPERTIES CPLUSPLUS ON)

swig_add_library(python_example
        TYPE MODULE
        LANGUAGE python
        OUTPUT_DIR ../../py_out   # move the .so to py_out
        OUTFILE_DIR .             # leave the .cpp in cmake-build-debug
        SOURCES ../src/example.i
        ../src/example.cpp ../src/example.h
        )

set_target_properties(python_example PROPERTIES
        LIBRARY_OUTPUT_DIRECTORY ../../py_out  # must match dir in OUTPUT_DIR
        )

构建完成后,运行python test.py进行查看。请注意,所有内容都在bash / Ubuntu中,因此MacO应该可以,但Windows可能会引起一些混乱。

有关详细信息,请参见自述文件。