CMake子目录find_package生成的目标未传递至同级子目录问题咨询
一、子目录依赖编译正常是设计行为,并非巧合
CMake中通过add_library/add_executable创建的目标属于全局作用域:只要根目录的CMakeLists.txt通过add_subdirectory引入了子目录,子目录内生成的目标就会对整个项目可见。你的场景里:
- 根目录先引入
first child生成lib1目标,后续引入second child时,lib2可以直接依赖lib1; - 主程序依赖lib2时,也能间接识别到lib1,这完全符合CMake的设计逻辑,绝非巧合。
二、find_package生成目标无法传递的原因与解决
你遇到的torch_cpu is not a target报错,核心是外部包生成的目标需要保证在所有用到它的CMakeLists.txt中可见,具体分析和解决如下:
1. 问题根源
当你在lib1的CMakeLists.txt中调用find_package(Torch)时,torch_cpu这类目标仅在当前及后续处理的CMakeLists.txt中可见。如果lib2的CMakeLists.txt未执行find_package(Torch),它就不知道torch_cpu的存在——即便你用target_link_libraries(lib1 PUBLIC ${TORCH_LIBRARIES})传递了接口属性,生成器表达式$<TARGET_PROPERTY:torch_cpu,...>也会因找不到目标而报错。
2. 解决方法
方案一:在依赖链所有层级显式调用find_package
在lib2的CMakeLists.txt开头添加find_package(Torch REQUIRED),确保torch_cpu目标在lib2的处理流程中被定义,直接解决目标找不到的问题,这是最直接的工程做法。方案二:通过EXPORT接口自动传递依赖(规范工程用法)
若希望lib1能自动传递Torch依赖,无需下游手动执行find_package,可在lib1的CMakeLists.txt中配置导出逻辑:# 安装lib1并导出目标配置 install(TARGETS lib1 EXPORT lib1Targets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin INCLUDES DESTINATION include) install(EXPORT lib1Targets FILE lib1Targets.cmake DESTINATION lib/cmake/lib1) # 生成配置文件,自动引入Torch依赖 include(CMakePackageConfigHelpers) configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/lib1Config.cmake INSTALL_DESTINATION lib/cmake/lib1 ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib1Config.cmake DESTINATION lib/cmake/lib1)同时在
Config.cmake.in中添加find_dependency(Torch REQUIRED),这样下游通过find_package(lib1)时会自动加载Torch,确保torch_cpu目标可见。
补充:CMake目标与变量的作用域差异
- 变量:默认局部作用域,子目录不会自动继承父目录变量,需通过
PARENT_SCOPE或缓存变量传递; - 目标:全局作用域,一旦创建全项目可见,但外部包生成的目标(如
torch_cpu)依赖find_package触发定义,必须保证每个用到它的CMakeLists.txt都执行了对应的find_package。
内容的提问来源于stack exchange,提问作者Mohammed Li

