CMAKE_CURRENT_BINARY_DIR返回错误目录:CMake配置问题排查
嘿,我来帮你理清楚这个问题——你遇到的核心点是混淆了CMake中两个关键变量的差异,以及外部构建和内部构建的工作机制。
先回顾下你的场景:
你的文件夹结构
- SomeApp
- CMakeLists.txt
- source.cpp
- cmake-build-debug
- protobuf
- CMakeLists.txt
- file.proto
根目录 CMakeLists.txt 内容
cmake_minimum_required(VERSION 3.9) project(SomeApp) message("Root Dir: ${CMAKE_CURRENT_BINARY_DIR}") ADD_SUBDIRECTORY(protobuf)
protobuf 目录下的 CMakeLists.txt 内容
message("Protobuf Dir: ${CMAKE_CURRENT_BINARY_DIR}")
实际编译输出
Root Dir: /home/<...>/SomeApp/cmake-build-debug Protobuf Dir: /home/<...>/SomeApp/cmake-build-debug
你预期的输出
Root Dir: /home/<...>/SomeApp/ Protobuf Dir: /home/<...>/SomeApp/protobuf/
问题出在哪?
你看到的差异,本质是**外部构建(out-of-source build)和官方文档示例中内部构建(in-source build)**的区别,加上对CMAKE_CURRENT_BINARY_DIR变量的误解:
变量含义搞混了
CMAKE_CURRENT_SOURCE_DIR:永远指向当前正在处理的CMakeLists.txt所在的源码目录,不受构建方式影响,这才是你想要获取源码路径时该用的变量。CMAKE_CURRENT_BINARY_DIR:指向当前CMakeLists.txt对应的构建输出目录——如果是外部构建(比如你在cmake-build-debug目录下运行cmake ..),这个路径就是构建目录里的对应位置;如果是内部构建(直接在源码目录运行cmake .),它才会和源码目录路径一致。
外部构建的默认行为
你是在cmake-build-debug目录执行的CMake配置,这属于外部构建:- 根
CMakeLists.txt的CMAKE_CURRENT_BINARY_DIR自然就是cmake-build-debug路径。 - 至于protobuf子目录的
CMAKE_CURRENT_BINARY_DIR也指向根构建目录,大概率是因为你没有让CMake为子项目创建单独的构建子文件夹——默认情况下,ADD_SUBDIRECTORY(protobuf)会在根构建目录下生成protobuf文件夹作为子项目的构建目录,但如果你的IDE(比如CLion)有特殊配置,或者你在命令行里做了额外设置,可能会导致子项目直接复用根构建目录。
- 根
怎么解决?
根据你的需求,有三种方案可选:
方案1:改用内部构建(不推荐)
直接在SomeApp目录下运行cmake .,这时候CMAKE_CURRENT_BINARY_DIR会和源码目录完全一致,就能得到你预期的输出。但这种方式会把构建文件和源码混在一起,不利于项目维护,不推荐。
方案2:用正确的变量获取源码路径
如果你只是想获取源码目录的路径,不管构建方式是什么,把CMAKE_CURRENT_BINARY_DIR换成CMAKE_CURRENT_SOURCE_DIR即可。修改后的代码如下:
根目录CMakeLists.txt:
cmake_minimum_required(VERSION 3.9) project(SomeApp) message("Root Dir: ${CMAKE_CURRENT_SOURCE_DIR}") ADD_SUBDIRECTORY(protobuf)
protobuf目录CMakeLists.txt:
message("Protobuf Dir: ${CMAKE_CURRENT_SOURCE_DIR}")
这样不管你用内部还是外部构建,输出都会和你预期的一致。
方案3:让子项目使用独立的构建目录
如果你希望子项目的构建输出放在cmake-build-debug/protobuf下(而不是根构建目录),确保ADD_SUBDIRECTORY没有指定第二个参数,或者显式指定子构建目录:
ADD_SUBDIRECTORY(protobuf protobuf)
这样protobuf子项目的CMAKE_CURRENT_BINARY_DIR就会变成/home/<...>/SomeApp/cmake-build-debug/protobuf。
内容的提问来源于stack exchange,提问作者ju.

