基于CMake构建XTensor Python包时无法链接xtensor::optimize等目标的问题
问题1:使用add_subdirectory/FetchContent时链接xtensor::optimize和xtensor::use_xsimd
这两个目标是xtensor提供的INTERFACE类型目标,只要确保依赖被正确引入且编译选项配置到位,就能正常链接到你的模块。具体步骤如下:
1. 用FetchContent引入完整依赖链
在你的CMakeLists.txt开头添加以下代码,确保引入兼容版本的xtl、xsimd和xtensor,同时启用xsimd支持:
cmake_minimum_required(VERSION 3.18) project(mymodule) include(FetchContent) # 先设置编译选项,确保xtensor启用xsimd和优化 set(XTENSOR_ENABLE_XSIMD ON CACHE BOOL "Enable XSIMD optimization for xtensor") set(XTENSOR_OPTIMIZE ON CACHE BOOL "Enable compiler optimizations for xtensor") # 引入依赖,指定兼容的版本号 FetchContent_Declare( xtl GIT_REPOSITORY https://github.com/xtensor-stack/xtl.git GIT_TAG 0.7.5 ) FetchContent_Declare( xsimd GIT_REPOSITORY https://github.com/xtensor-stack/xsimd.git GIT_TAG 11.0.0 ) FetchContent_Declare( xtensor GIT_REPOSITORY https://github.com/xtensor-stack/xtensor.git GIT_TAG 0.25.0 ) FetchContent_Declare( xtensor_python GIT_REPOSITORY https://github.com/xtensor-stack/xtensor-python.git GIT_TAG 0.26.0 ) # 初始化所有依赖 FetchContent_MakeAvailable(xtl xsimd xtensor xtensor_python)
2. 链接目标到你的Python模块
定义完你的Python模块目标后,直接将两个优化目标添加到链接列表中:
# 假设你的模块是用xtensor-python创建的 add_library(mymodule MODULE mymodule.cpp) target_link_libraries(mymodule PRIVATE xtensor::xtensor xtensor::xtensor-python xtensor::optimize xtensor::use_xsimd ) # 设置Python模块属性,确保能被pip正确识别 set_target_properties(mymodule PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}" SUFFIX "${PYTHON_MODULE_EXTENSION}" )
如果用add_subdirectory代替FetchContent,只需将依赖的源码放在项目子目录中,添加add_subdirectory(xtl)、add_subdirectory(xsimd)等语句,再按上述方式链接即可。注意要确保子目录中的依赖版本兼容,且提前设置XTENSOR_ENABLE_XSIMD等选项。
问题2:若方案1不可行,通过pip安装自动配置依赖(仅作备选)
由于xtl、xtensor、xsimd是C++库,pip本身不直接管理这类系统级依赖,所以这种方案局限性较大,仅作参考:
1. 借助conda作为依赖补充
如果你的用户可以接受conda环境,可在pyproject.toml中添加conda依赖声明,或者在安装说明中提示用户先通过conda安装C++依赖:
# pyproject.toml示例 [project.optional-dependencies] conda = ["conda-lock"]
然后在安装脚本中自动调用conda安装xtensor、xsimd、xtl包,这样find_package(xtensor)就能正常找到依赖。
2. 预编译依赖并打包进wheel
将xtl、xtensor、xsimd的预编译库打包进你的Python包,在CMakeLists.txt中指定CMAKE_PREFIX_PATH指向包内的依赖目录,让find_package能定位到本地依赖。这种方式需要你针对不同平台预编译对应版本的库,维护成本较高。
内容的提问来源于stack exchange,提问作者Der Fänger im Roggen

