Python 同名的库和 CMake 目标
Python library and CMake target with the same name
我正在构建一个库“mylib”,它是 C++ header-only 并且有一个 Python API 使用 pybind11。
我想将“mylib”用作包含编译指令的 CMake 目标和 Python API 的名称。 然而,这会导致 名称冲突.
问题描述
考虑以下文件结构:
CMakeLists.txt
include/mylib.hpp
python_api.cpp
实际上也有测试和示例,每个都有自己的 CMakeLists.txt
,但对于本示例而言,唯一重要的是:
在(主)CMakeLists.txt
中,我正在定义一个 CMake 目标“mylib”,它具有 header(s) 的包含路径,而且 'links' 的目标依赖项。这样用户(或 Python API 的测试、示例或构建)只需 'link' 目标就可以了。 (最后,当我安装 header 时,我还在 mylibTargets.cmake
中安装了目标,这样最终用户就可以支持 CMake)。
现在问题:我的Python 包应该有相同的名称,“mylib”。但是,如果我用“mylib”调用 pybind11_add_module
,CMake 会抱怨
CMake Error at .../share/cmake/pybind11/pybind11Tools.cmake:166 (add_library):
add_library cannot create target "mylib" because another target with the
same name already exists. The existing target is an interface library
created in source directory "..".
See documentation for policy CMP0002 for more details.
有权投诉。同时,我不能为 CMake 目标(因为我想使用唯一的逻辑名称“mylib”安装和使用它)或 pybind11 目标(因为它必须编码“mylib”)使用不同的名称。
所以:我该如何解决这个问题?
(我发现的 only solution 是重命名其中一个目标,但如上所述我不想这样做)
详细示例
考虑简化,单一,CMakeLists.txt
:
cmake_minimum_required(VERSION 3.1..3.19)
# configure target
project(mylib)
find_package(xtensor REQUIRED)
add_library(${PROJECT_NAME} INTERFACE)
target_include_directories(${PROJECT_NAME} INTERFACE
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries(${PROJECT_NAME} INTERFACE xtensor)
# installation of headers and of CMake target
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include)
install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets)
install(
EXPORT ${PROJECT_NAME}-targets
FILE "${PROJECT_NAME}Targets.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
# Build Python module
find_package(pybind11 CONFIG REQUIRED)
pybind11_add_module(${PROJECT_NAME} python_api.cpp) # <- target name conflict
target_link_libraries(example PUBLIC pybind11::module)
解决方法太有限
我可以将 Python API 的构建(并稍后安装)完全拆分为一个独立的 CMakeLists.txt
。但是,我想使用目标“mylib”,我已经配备了它需要的一切,来构建 Python API。由于我想在不强制安装库的情况下执行此操作,所以我不知道如何在 'single' CMakeLists.txt
中执行此操作
pybind11_add_module
只是 add_library
的包装器,这是明确写在 documentation 中的那个函数。因此,大多数适用于公共库的“技巧”也适用于 python 模块。
也就是说,如果您希望将结果文件命名为 mylib.so
但不能负担得起使用 mylib
作为目标名称,那么您可以使用任何其他名称作为 target 但为该目标调整 OUTPUT_NAME 属性。例如:
# Python library target has suffix '_python'
pybind11_add_module(mylib_python ...)
# But name of the library file doesn't have this suffix
set_target_properties(mylib_python PROPERTIES OUTPUT_NAME mylib)
我正在构建一个库“mylib”,它是 C++ header-only 并且有一个 Python API 使用 pybind11。 我想将“mylib”用作包含编译指令的 CMake 目标和 Python API 的名称。 然而,这会导致 名称冲突.
问题描述
考虑以下文件结构:
CMakeLists.txt
include/mylib.hpp
python_api.cpp
实际上也有测试和示例,每个都有自己的 CMakeLists.txt
,但对于本示例而言,唯一重要的是:
在(主)CMakeLists.txt
中,我正在定义一个 CMake 目标“mylib”,它具有 header(s) 的包含路径,而且 'links' 的目标依赖项。这样用户(或 Python API 的测试、示例或构建)只需 'link' 目标就可以了。 (最后,当我安装 header 时,我还在 mylibTargets.cmake
中安装了目标,这样最终用户就可以支持 CMake)。
现在问题:我的Python 包应该有相同的名称,“mylib”。但是,如果我用“mylib”调用 pybind11_add_module
,CMake 会抱怨
CMake Error at .../share/cmake/pybind11/pybind11Tools.cmake:166 (add_library):
add_library cannot create target "mylib" because another target with the
same name already exists. The existing target is an interface library
created in source directory "..".
See documentation for policy CMP0002 for more details.
有权投诉。同时,我不能为 CMake 目标(因为我想使用唯一的逻辑名称“mylib”安装和使用它)或 pybind11 目标(因为它必须编码“mylib”)使用不同的名称。
所以:我该如何解决这个问题?
(我发现的 only solution 是重命名其中一个目标,但如上所述我不想这样做)
详细示例
考虑简化,单一,CMakeLists.txt
:
cmake_minimum_required(VERSION 3.1..3.19)
# configure target
project(mylib)
find_package(xtensor REQUIRED)
add_library(${PROJECT_NAME} INTERFACE)
target_include_directories(${PROJECT_NAME} INTERFACE
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries(${PROJECT_NAME} INTERFACE xtensor)
# installation of headers and of CMake target
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include)
install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets)
install(
EXPORT ${PROJECT_NAME}-targets
FILE "${PROJECT_NAME}Targets.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
# Build Python module
find_package(pybind11 CONFIG REQUIRED)
pybind11_add_module(${PROJECT_NAME} python_api.cpp) # <- target name conflict
target_link_libraries(example PUBLIC pybind11::module)
解决方法太有限
我可以将 Python API 的构建(并稍后安装)完全拆分为一个独立的 CMakeLists.txt
。但是,我想使用目标“mylib”,我已经配备了它需要的一切,来构建 Python API。由于我想在不强制安装库的情况下执行此操作,所以我不知道如何在 'single' CMakeLists.txt
pybind11_add_module
只是 add_library
的包装器,这是明确写在 documentation 中的那个函数。因此,大多数适用于公共库的“技巧”也适用于 python 模块。
也就是说,如果您希望将结果文件命名为 mylib.so
但不能负担得起使用 mylib
作为目标名称,那么您可以使用任何其他名称作为 target 但为该目标调整 OUTPUT_NAME 属性。例如:
# Python library target has suffix '_python'
pybind11_add_module(mylib_python ...)
# But name of the library file doesn't have this suffix
set_target_properties(mylib_python PROPERTIES OUTPUT_NAME mylib)