CMake: add_subdirectory()

本文探讨了在CMake环境下如何有效地管理多个项目的依赖关系,包括独立编译、使用脚本辅助以及通过ADD_SUBDIRECTORY方法整合子项目的不同策略。特别关注了解决重复依赖和跨项目依赖的具体实现。

一个开发场景: 工程A输出一个库文件, 工程B输出可执行文件,但依赖于A的输出,利用CMake组织二者


方案1:

两个工程独立编译,把A的输出install到固定目录,工程B到该目录中解决依赖,可以使用find_library()


方案2:

利用脚本,本质上和方案1一样,但是通过脚本可以大量减少键盘操作


上述两个方案都是假设在configure工程B的时候,工程A的输出库文件已经存在,否则find_library()会提示错误,有没有办法

在工程A编译之前就成功编译工程B,即在CMake中指定工程B依赖于工程A?

方案3:

在工程B的CMakeLists.txt中使用ADD_SUBDIRECTORY()

如果A工程不在B工程目录结构下,需要指定binary_dir,即A工程输出路径

此时依赖关系不要用find_library(),否则一样错误,而要在target_link_libraries()中指定 (linux下,target_link_libraries()中此时不需要填写

lib的全名,而应该填写工程A的${PROJECT_NAME}即可)



方案3的补充:

工程A依赖于B和C, 而B和C同时依赖于D,如果在B和C中都使用ADD_SUBDIRECTORY()增加D,则最终编译A时会提示错误

cannot create target "D" because another target with the same name already exists

解决方法是在 B和C中使用target属性

if (NOT TARGET D)
    add_subdirectory( DRoot D)
endif() 

避免D被重复包含



<think>嗯,用户遇到了CMakeadd_subdirectory错误,提示指定的子目录不存在。我需要先理解这个问题的具体情况。用户提到的三个子目录:redfox_mpu_sdk/ProtobufFile、redfox_mpu_sdk/Middleware和redfox_mpu_sdk/Business,可能这些目录在项目结构中实际不存在,或者路径有误。首先,我应该考虑用户的项目结构是否正确。可能用户将子目录名称拼写错误,或者路径层级不对。比如,是否这些目录真的位于redfox_mpu_sdk下?或者是否应该直接放在项目根目录下,而不是嵌套在redfox_mpu_sdk里?这时候需要检查CMakeLists.txt中add_subdirectory的路径参数是否正确。另外,用户可能使用了相对路径,但当前的工作目录(binary目录)不同,导致路径解析错误。这时候需要确认CMake的执行路径和源目录的关系。例如,如果CMakeLists.txt在项目根目录,而子目录确实存在于根目录下,那么正确的路径应该是ProtobufFile而不是redfox_mpu_sdk/ProtobufFile。用户可能错误地添加了父目录名称作为路径的一部分。还有一种可能是这些子目录是动态生成的,或者需要从外部仓库克隆,但用户尚未执行获取这些目录的操作。这时候需要检查是否存在.gitmodules或类似的配置,并确保子模块已经初始化并更新。此外,用户是否在add_subdirectory中使用了EXCLUDE_FROM_ALL选项?根据之前的引用,这个选项会影响目标的生成,但不会直接导致目录不存在的错误。不过,如果子目录本身不存在,无论是否使用该选项,CMake都会报错。所以问题的核心还是路径是否正确。 接下来,我应该分步骤给出解决方案。首先检查路径是否正确,确认子目录的实际位置。然后建议使用绝对路径或正确的相对路径。另外,检查是否需要生成这些目录,或者是否存在拼写错误。还可以建议使用CMake的message命令输出路径信息,帮助调试。 用户可能不太清楚相对路径在CMake中的处理方式,所以需要解释相对路径是相对于当前CMakeLists.txt的位置。例如,如果主CMakeLists.txt在project_root,而子目录在project_root/redfox_mpu_sdk/ProtobufFile,那么正确的相对路径应该是redfox_mpu_sdk/ProtobufFile。但如果用户的主CMakeLists.txt在redfox_mpu_sdk的同级目录,而子目录位于其内部,那么路径应该是正确的。需要用户确认实际结构。 另外,考虑用户是否在Windows上遇到大小写问题,虽然CMake通常区分大小写,但Windows文件系统不区分,但路径仍然需要正确匹配。不过这种情况较少见,可能更多是路径拼写错误。 最后,总结解决方案,帮助用户逐步排查路径问题,确保子目录存在且路径正确,必要时使用绝对路径或生成目录的步骤。</think>### CMake add_subdirectory子目录不存在问题解决方案 当出现`add_subdirectory`指定的子目录不存在时,需按以下步骤排查: #### 1. 验证物理路径是否存在 确认子目录`redfox_mpu_sdk/ProtobufFile`等是否实际存在于项目根目录中。可通过以下命令验证: ```bash ls -l redfox_mpu_sdk/ProtobufFile redfox_mpu_sdk/Middleware redfox_mpu_sdk/Business ``` #### 2. 检查相对路径写法 在CMake中,相对路径是相对于当前`CMakeLists.txt`所在目录的。若主`CMakeLists.txt`位于项目根目录,子目录的正确写法应为: ```cmake add_subdirectory(redfox_mpu_sdk/ProtobufFile) ``` #### 3. 使用绝对路径(推荐) 通过`CMAKE_SOURCE_DIR`宏定义绝对路径: ```cmake add_subdirectory(${CMAKE_SOURCE_DIR}/redfox_mpu_sdk/ProtobufFile) ``` #### 4. 特殊目录处理建议 若子目录是动态生成的: ```cmake # 先创建目录再添加 file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/redfox_mpu_sdk/ProtobufFile) add_subdirectory(${CMAKE_SOURCE_DIR}/redfox_mpu_sdk/ProtobufFile) ``` #### 5. 路径调试技巧 在CMake中添加调试信息: ```cmake message(STATUS "当前路径: ${CMAKE_CURRENT_SOURCE_DIR}") message(STATUS "目标路径: ${CMAKE_SOURCE_DIR}/redfox_mpu_sdk/ProtobufFile") ``` #### 6. 子模块处理 若子目录是git子模块: ```bash # 先初始化子模块 git submodule update --init --recursive ``` ### 典型错误场景对比 | 错误类型 | 错误示例 | 正确写法 | |---------|---------|---------| | 路径层级错误 | `add_subdirectory(ProtobufFile)` | `add_subdirectory(redfox_mpu_sdk/ProtobufFile)` | | 大小写错误 | `add_subdirectory(RedFox_MPU_SDK)` | `add_subdirectory(redfox_mpu_sdk)` | | 缺少父目录 | `add_subdirectory(ProtobufFile)` | `add_subdirectory(redfox_mpu_sdk/ProtobufFile)` | ### 引用说明 当使用`EXCLUDE_FROM_ALL`时,需特别注意子目录的物理存在性,该选项仅控制是否构建目标,不会自动创建目录[^1]。路径解析规则遵循CMake的目录作用域机制[^2],建议始终使用绝对路径进行跨目录操作[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值