使用FetchContent处理依赖库时出现“构建目录路径前缀”错误
我有一个依赖libwebsockets的项目,而libwebsockets本身依赖mbedtls。我使用FetchContent从GitHub拉取所有依赖,它们会被存放在构建目录的_deps文件夹中。为了实现静态构建,我设置了CMAKE_PREFIX_PATH,让libwebsockets的find_path()调用能找到mbedtls的头文件;同时设置了libwebsockets在find_library()调用中使用的缓存变量,指向mbedtls的目标,确保配置阶段就能找到这些库。
libwebsockets相关查找代码如下:
find_path(LWS_MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) find_library(MBEDTLS_LIBRARY mbedtls) find_library(MBEDX509_LIBRARY mbedx509) find_library(MBEDCRYPTO_LIBRARY mbedcrypto)
虽然libwebsockets已在构建目录中找到mbedtls,但配置阶段仍出现错误:
CMake Error in build/_deps/libwebsockets-src/lib/CMakeLists.txt: Target "websockets" INTERFACE_INCLUDE_DIRECTORIES property contains path: "C:/dev/realtime-cpp/build/_deps/mbedtls-build/include" which is prefixed in the build directory.
其他目标也存在类似错误。我理解头文件位于构建目录中,但不清楚这为何会成为问题,以及该如何解决?
问题原因
CMake禁止目标的INTERFACE_INCLUDE_DIRECTORIES包含构建目录内的路径,核心原因是构建目录属于临时产物,安装或导出目标时,其他项目无法访问这个路径,会导致依赖失效。当你通过find_path直接指向mbedtls的构建目录头文件时,libwebsockets会把这个临时路径写入自身目标的接口属性中,触发CMake的安全检查。
解决步骤
改用mbedtls的安装路径而非构建路径
不要直接让libwebsockets找构建目录里的mbedtls,而是先让mbedtls完成安装(哪怕是本地安装到构建目录内的子文件夹),再让libwebsockets从安装路径查找。
在mbedtls的FetchContent配置后,添加安装指令:FetchContent_MakeAvailable(mbedtls) # 让mbedtls安装到构建目录内的install子目录 install( TARGETS mbedtls mbedx509 mbedcrypto EXPORT mbedtls-targets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib INCLUDES DESTINATION include ) install(EXPORT mbedtls-targets FILE mbedtls-config.cmake DESTINATION lib/cmake/mbedtls)调整libwebsockets的依赖查找逻辑
跳过手动设置CMAKE_PREFIX_PATH和缓存变量,改用CMake的find_package来导入mbedtls的导出目标,这样libwebsockets会自动使用正确的接口路径:# 在libwebsockets的FetchContent配置前,先找到已安装的mbedtls find_package(mbedtls REQUIRED PATHS ${CMAKE_BINARY_DIR}/lib/cmake/mbedtls) # 告诉libwebsockets直接使用已找到的mbedtls目标,而非自己查找 set(LWS_WITH_MBEDTLS ON CACHE BOOL "") set(LWS_MBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIRS} CACHE PATH "") set(MBEDTLS_LIBRARY mbedtls::mbedtls CACHE STRING "") set(MBEDX509_LIBRARY mbedtls::mbedx509 CACHE STRING "") set(MBEDCRYPTO_LIBRARY mbedtls::mbedcrypto CACHE STRING "")禁用CMake的构建路径检查(临时应急方案)
如果上述方案无法快速落地,可以临时关闭CMake的路径检查(不推荐长期使用,会埋下路径依赖隐患):set(CMAKE_INTERFACE_INCLUDE_DIRECTORIES_NO_BUILD_PATH OFF CACHE BOOL "")
关键原理
使用CMake的导出目标(mbedtls::mbedtls这类命名空间目标)时,CMake会自动管理接口路径为安装路径而非临时构建路径,从根源避免触发构建目录路径的检查错误。
内容的提问来源于stack exchange,提问作者glades

