CMake输出/构建目录


115

我是CMake的新手,阅读了一些有关如何使用它的教程,并编写了一些复杂的50行CMake脚本,以便为3个不同的编译器编写程序。这可能总结了我在CMake中的全部知识。

现在我的问题是我有一些源代码,制作程序时我不想碰到/碰到它们的文件夹。我希望所有CMake以及make输出文件和文件夹都进入其中../Compile/,因此我为此在CMake脚本中更改了一些变量,并且在我在笔记本电脑上执行以下操作时它起作用了:

Compile$ cmake ../src
Compile$ make

在那里,我现在在的文件夹中有干净的输出,这正是我想要的。

现在,我移至另一台计算机,并重新编译了CMake 2.8.11.2,然后我几乎回到了原来的水平!它总是将东西编译到srcmy所在的文件夹中CMakeLists.txt

我在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

我想念什么吗?


4
几乎不需要设置所有要设置的变量。CMake将它们设置为合理的默认值。您绝对不应修改CMAKE_BINARY_DIRCMAKE_CACHEFILE_DIR。如果您删除所有这些set()电话而只做cd Compile; rm -rf *; cmake ../src呢?
Angew不再为2012年

5
基本上,只要您在运行CMake时位于源目录之外,它就不会修改源目录,除非您的CMakeList明确告诉它。
Angew不再为2012年

@Angew谢谢您的提示,这令人惊讶!我删除了所有这些行,只使用了cmake ../src,它就像一个魅力!这真是令人惊讶,因为我在第一次学习CMake之前就尝试过,但没有成功。请在正式答复中注明您的答案,以给您大的复选标记:)
The Quantum Physicist

1
救我的是@Adam Bowen的评论,即“您不能使用源代码构建为源目录创建源代码构建”
Aur Saraf

Answers:


60

几乎不需要设置所有要设置的变量。CMake将它们设置为合理的默认值。您绝对不应修改CMAKE_BINARY_DIRCMAKE_CACHEFILE_DIR。将它们视为只读。

首先,从src目录中删除现有的有问题的缓存文件:

cd src
rm CMakeCache.txt
cd ..

然后删除所有set()命令并执行以下操作:

cd Compile
rm -rf *
cmake ../src

只要您在运行CMake时不在源目录中,它就不会修改源目录,除非您的CMakeList明确告诉它。

完成这项工作后,您可以查看CMake默认将内容放置在何处,并且仅当您对默认位置(例如的默认值EXECUTABLE_OUTPUT_PATH)不满意时,才修改所需的位置。并尝试相对表达出来CMAKE_BINARY_DIRCMAKE_CURRENT_BINARY_DIRPROJECT_BINARY_DIR等。

如果您查看CMake文档,您会看到变量分为语义部分。除非常特殊的情况外,您应将“提供信息的变量”下列出的所有内容都视为CMakeList中的只读内容。


2
我开始将cmake与src目录中的构建一起使用...此技术最初失败了。一旦我删除了src目录中的所有cmake构建文件/缓存,该技术就起作用了。谢谢!
2014年

18
也许最好不要使用rm -rf *。如果cd Compile失败的话这还不是很漂亮……
罗马

2
@罗马我认为这样的命令行示例几乎是伪代码。它比键入“进入目录Compile,删除目录中的所有内容,然后运行带有源目录路径的CMake ”更为冗长和精确。我认为部分读者具有基本常识和判断力。
Angew不再为SO

@AviTevet:我认为这是正确的答案。如果源目录中以前的cmake调用中包含cmake缓存文件,则除非您从源目录中删除所有旧文件,否则您不会得到cmake为生成的文件选择另一个目录。在我看来,CMake的行为很糟糕。你为什么不写另一个答案?
乔苏

112

听起来好像您想要一个外源版本。您可以通过两种方法来创建源代码之外的版本。

  1. 做你正在做的事,跑步

    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:

    cmake /path/to/my/build/folder

    甚至

    cmake .

    如果当前目录已经是build文件夹。

  2. 对于CMake 3.13或更高版本,请使用以下选项设置源文件夹和构建文件夹

    cmake -B/path/to/my/build/folder -S/path/to/my/source/folder
  3. 对于较旧的CMake,请使用一些未记录的选项来设置源文件夹和构建文件夹

    cmake -B/path/to/my/build/folder -H/path/to/my/source/folder

    它将执行与(1)完全相同的操作,但不依赖当前的工作目录。

CMake 默认情况下将其所有输出放置在构建树中,因此,除非您大量使用cmake文件${CMAKE_SOURCE_DIR}或将其${CMAKE_CURRENT_SOURCE_DIR}放置在cmake文件中,否则CMake 不要触摸您的源树

可能出错的最大问题是,如果您先前在源代码树中生成了一个生成树(即,您有一个源代码内部生成)。完成此操作后,上面的(1)的第二部分就会启动,并且cmake不会对源或构建位置进行任何更改。因此,您无法使用in-source build来为源目录创建out-of-source构建。您可以通过(至少)CMakeCache.txt从源目录中删除(至少)来解决此问题。CMakeFilesCMake生成的其他一些文件(大部分在目录中)也应删除,但是这些不会导致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."
)

上面的宏来自一个称为的常用模块MacroOutOfSourceBuildMacroOutOfSourceBuild.cmakeGoogle上有许多来源,但我似乎找不到原始内容,而且足够简短,无法完整包含在此处。

不幸的是,cmake通常在调用宏时就已经写入了一些文件,因此尽管它会阻止您实际执行构建,但仍然需要删除CMakeCache.txtCMakeFiles

您可能会发现设置二进制文件,共享库和静态库的写入路径很有用-在这种情况下,如何将cmake输出设置为“ bin”目录?(免责声明,对于该问题,我拥有最高投票率的答案……但这就是我对此的了解)。


其实设置源文件夹选项-S,不-H
smac89

@ smac89谢谢!好像他们在3.13中记录了它们-我已经更新了答案以反映现代CMake。
亚当·鲍文

8

将我的评论变成答案:

万一有人做我做的事情,首先将所有构建文件放在源目录中:

cd src
cmake .

cmake的会放了一堆的编译文件和缓存文件(CMakeCache.txtCMakeFilescmake_install.cmake等)的src目录。

要更改为非源构建,我必须删除所有这些文件。然后我可以做@Angew在他的回答中建议的操作:

mkdir -p src/build
cd src/build
cmake ..

7

CMake Wiki以来:

CMAKE_BINARY_DIR(如果您正在构建源代码),则与CMAKE_SOURCE_DIR相同,否则,这是您的构建树的顶级目录

比较这两个变量,以确定是否开始了源外构建


6

您不应在脚本中依赖硬编码的构建目录名称,因此../Compile必须更改与的行。

这是因为它应该取决于用户在哪里进行编译。

而不是使用以下预定义的变量之一:http : //www.cmake.org/Wiki/CMake_Useful_Variables (查找CMAKE_BINARY_DIRCMAKE_CURRENT_BINARY_DIR


2
这是我一直在寻找的东西- CMAKE_CURRENT_BINARY_DIR,通常会告诉您当前的二进制构建路径。可能可以用于设置相关的库/ bin版本。
parasrish
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.