我对 CMake 很陌生,阅读了一些关于如何使用它的教程,并编写了一些复杂的 50 行 CMake 脚本,以便为 3 个不同的编译器制作程序。这可能总结了我在 CMake 中的所有知识。
现在我的问题是我有一些源代码,当我制作程序时我不想触摸/弄乱它的文件夹。我希望所有 CMake 和 make
输出文件和文件夹都进入 ../Compile/
,因此我为此更改了 CMake 脚本中的一些变量,并且当我在笔记本电脑上执行类似操作时它工作了一段时间:
Compile$ cmake ../src
Compile$ make
我现在所在的文件夹中有一个干净的输出,这正是我正在寻找的。
现在我搬到另一台电脑上,重新编译 CMake 2.8.11.2,我几乎回到了原点!它总是将事物编译到我的 CMakeLists.txt
所在的 src
文件夹中。
我在 CMake 脚本中选择目录的部分是:
set(dir ${CMAKE_CURRENT_SOURCE_DIR}/../Compile/)
set(EXECUTABLE_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(LIBRARY_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dir})
set(CMAKE_BUILD_FILES_DIRECTORY ${dir})
set(CMAKE_BUILD_DIRECTORY ${dir})
set(CMAKE_BINARY_DIR ${dir})
SET(EXECUTABLE_OUTPUT_PATH ${dir})
SET(LIBRARY_OUTPUT_PATH ${dir}lib)
SET(CMAKE_CACHEFILE_DIR ${dir})
现在它总是以:
-- Build files have been written to: /.../src
我错过了什么吗?
CMAKE_BINARY_DIR
或 CMAKE_CACHEFILE_DIR
。如果您删除所有这些 set()
调用并只执行 cd Compile; rm -rf *; cmake ../src
会发生什么?
听起来您想要一个 out of source build。有几种方法可以创建源外构建。
做你正在做的事情,运行 cd /path/to/my/build/folder cmake /path/to/my/source/folder 这将导致 cmake 在 /path/to/my/build/folder 中生成一个构建树/path/to/my/source/folder 中的源代码树。创建它后,cmake 会记住源文件夹的位置 - 因此您可以使用 cmake /path/to/my/build/folder 甚至 cmake 在构建树上重新运行 cmake。如果您的当前目录已经是构建文件夹。对于 CMake 3.13 或更高版本,使用这些选项设置源和构建文件夹 cmake -B/path/to/my/build/folder -S/path/to/my/source/folder 对于较旧的 CMake,使用一些未记录的选项设置源和构建文件夹: cmake -B/path/to/my/build/folder -H/path/to/my/source/folder 这将与(1)完全相同,但不依赖于当前工作目录。
默认情况下,CMake 会将其所有输出放在 build tree 中,因此除非您在 cmake 文件中大量使用 ${CMAKE_SOURCE_DIR}
或 ${CMAKE_CURRENT_SOURCE_DIR}
,否则它不应触及您的 源代码树< /em>。
最大的问题是如果您之前在源代码树中生成了构建树(即您有一个 in source 构建)。完成此操作后,上面 (1) 的第二部分就会启动,并且 cmake 不会对源代码或构建位置进行任何更改。因此,您不能为具有源内构建的源目录创建源外构建。您可以通过从源目录中删除(至少)CMakeCache.txt
来轻松解决此问题。 CMake 生成的还有一些其他文件(主要在 CMakeFiles
目录中)您也应该删除,但这些文件不会导致 cmake 将源代码树视为构建树。
由于源外构建通常比源内构建更可取,因此您可能需要修改 cmake 以要求源外构建:
# Ensures that we do an out of source build
MACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD MSG)
STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
"${CMAKE_BINARY_DIR}" insource)
GET_FILENAME_COMPONENT(PARENTDIR ${CMAKE_SOURCE_DIR} PATH)
STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
"${PARENTDIR}" insourcesubdir)
IF(insource OR insourcesubdir)
MESSAGE(FATAL_ERROR "${MSG}")
ENDIF(insource OR insourcesubdir)
ENDMACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD)
MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
"${CMAKE_PROJECT_NAME} requires an out of source build."
)
上面的宏来自一个叫做MacroOutOfSourceBuild
的常用模块。 google 上有很多关于 MacroOutOfSourceBuild.cmake
的来源,但我似乎找不到原件,而且它足够短,可以完整包含在此处。
不幸的是,cmake 通常在调用宏时已经写入了一些文件,因此尽管它会阻止您实际执行构建,但您仍然需要删除 CMakeCache.txt
和 CMakeFiles
。
您可能会发现设置二进制库、共享库和静态库的写入路径很有用 - 在这种情况下,请参阅 how do I make cmake output into a 'bin' dir?(免责声明,我在该问题上获得了最高投票的答案......但这就是我所知道的) .
几乎不需要设置您要设置的所有变量。 CMake 将它们设置为合理的默认值。您绝对应该不修改 CMAKE_BINARY_DIR
或 CMAKE_CACHEFILE_DIR
。将这些视为只读。
首先从 src 目录中删除现有的有问题的缓存文件:
cd src
rm CMakeCache.txt
cd ..
然后删除所有 set()
命令并执行以下操作:
cd Compile && rm -rf *
cmake ../src
只要您在运行 CMake 时位于源目录之外,它就不会修改源目录,除非您的 CMakeList 明确告诉它这样做。
完成这项工作后,您可以查看 CMake 默认放置的位置,只有当您对默认位置不满意(例如 EXECUTABLE_OUTPUT_PATH
的默认值)时,才只修改您需要的位置。并尝试相对于 CMAKE_BINARY_DIR
、CMAKE_CURRENT_BINARY_DIR
、PROJECT_BINARY_DIR
等来表达它们。
如果您查看 CMake 文档,您会看到变量被划分为语义部分。除了非常特殊的情况,您应该将“提供信息的变量”下列出的所有内容视为 CMakeLists 中的只读。
rm -rf *
。如果 cd Compile
失败,那就不好看了……
Compile
,删除那里的所有内容,然后使用源目录的路径运行 CMake”更简洁、更准确。我假设基本常识&部分读者的判断。
将我的评论变成答案:
万一有人做了我所做的,首先将所有构建文件放在源目录中:
cd src
cmake .
cmake 会将一堆构建文件和缓存文件(CMakeCache.txt
、CMakeFiles
、cmake_install.cmake
等)放在 src
目录中。
要更改为源外构建,我必须删除所有这些文件。然后我可以做@Angew 在他的回答中推荐的事情:
mkdir -p src/build
cd src/build
cmake ..
从 CMake Wiki 开始:
CMAKE_BINARY_DIR 如果您在源代码中构建,这与 CMAKE_SOURCE_DIR 相同,否则这是构建树的顶级目录
比较这两个变量以确定是否启动了源外构建
您不应依赖脚本中硬编码的构建目录名称,因此必须更改带有 ../Compile
的行。
这是因为它应该取决于用户在哪里编译。
而不是使用预定义变量之一:http://www.cmake.org/Wiki/CMake_Useful_Variables(查找 CMAKE_BINARY_DIR
和 CMAKE_CURRENT_BINARY_DIR
)
CMAKE_CURRENT_BINARY_DIR
,通常会说明当前的二进制构建路径。可能可用于设置依赖的 libs/bin 构建。
从 cmake 3.19 开始,您还可以使用 preset files,您可以在其中指定输出二进制目录以及其他有用的内容:
{
"version": 2,
"cmakeMinimumRequired": {
"major": 3,
"minor": 19,
"patch": 0
},
"configurePresets": [
{
"name": "default",
"displayName": "Default",
"description": "Default build cfg",
"generator": "Unix Makefiles",
"binaryDir": "${sourceDir}/Compile",
"cacheVariables": {
},
"environment": {
}
}
]
}
然后只需使用 --preset
arg 运行 cmake:
cmake --preset=default
然后只需 cd
到您的构建目录并运行 make
,在您的情况下:
cd ./Compile
make
-S
,而不是-H