CMake库相对路径失效但绝对路径可用问题排查
为何CMake中使用相对路径引用库文件会失败?
问题背景
我有一个基础的CMake脚本,原始代码可正常运行:
# The object files of ds set(DS_LIB_FOLDER ../../build/) set(DS_LIB ds) get_filename_component(DS_LIB_FOLDER_ABS "${CMAKE_CURRENT_SOURCE_DIR}/${DS_LIB_FOLDER}" ABSOLUTE) set(DS_LIB_PATH ${DS_LIB_FOLDER_ABS}/lib${DS_LIB}.a)
修改最后一行使用相对路径后:
# The object files of ds set(DS_LIB_FOLDER ../../build/) set(DS_LIB ds) get_filename_component(DS_LIB_FOLDER_ABS "${CMAKE_CURRENT_SOURCE_DIR}/${DS_LIB_FOLDER}" ABSOLUTE) set(DS_LIB_PATH ${DS_LIB_FOLDER}/lib${DS_LIB}.a)
构建时出现报错:
ninja: error: '../../build/libds.a', needed by 'HostUnitTest', missing and no known rule to make it
改用GNU Makefiles构建时同样失败,但我已确认文件确实存在:
user@wsl:/mnt/c/work/project/product/tests/hosts$ ls -l ../../build/libds.a -rwxrwxrwx 1 user user 333466584 May 25 13:19 ../../build/libds.a user@wsl:/mnt/c/work/project/product/tests/hosts$ ls -l total 4 -rwxrwxrwx 1 user user 1471 May 25 14:13 CMakeLists.txt drwxrwxrwx 1 user user 4096 May 25 14:13 build -rwxrwxrwx 1 user user 272 May 25 11:54 main.cpp drwxrwxrwx 1 user user 4096 May 24 10:50 unit_tests
疑问:两种写法都涉及相对路径,绝对路径也是通过相对路径推导而来,为何改用相对路径会失败?
原因分析
核心问题出在CMake对相对路径的处理逻辑上,主要有两点:
相对路径的基准目录不是源码目录
CMake中,直接使用的相对路径(比如${DS_LIB_FOLDER}/lib${DS_LIB}.a),其解析基准是当前构建目录(CMAKE_CURRENT_BINARY_DIR),而非源码目录(CMAKE_CURRENT_SOURCE_DIR)。即使最终解析后的绝对路径和预期一致,CMake的处理逻辑也会不同。外部文件的识别规则差异
- 使用绝对路径时,CMake会直接确认文件存在,并将其视为外部依赖文件,不会尝试去生成它。
- 使用相对路径时,CMake默认认为该路径指向的文件是构建系统应该生成的产物。如果这个文件不在当前构建树内,且没有定义对应的构建规则,就会抛出“missing and no known rule to make it”的错误——哪怕文件实际存在,CMake也不会将其识别为预先生成的外部文件。
解决办法
如果想要用相对路径的写法,需要明确基于源码目录来拼接路径,让CMake正确识别这是外部文件:
set(DS_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${DS_LIB_FOLDER}/lib${DS_LIB}.a")
或者继续使用get_filename_component将相对路径转换为绝对路径,保持原始的正确逻辑。
内容的提问来源于stack exchange,提问作者Bob
相关产品推荐
相关产品推荐

