【问题标题】:CMake output/build directoryCMake 输出/构建目录
【发布时间】:2013-09-20 12:43:52
【问题描述】:

我对 CMake 很陌生,阅读了一些关于如何使用它的教程,并编写了一些复杂的 50 行 CMake 脚本,以便为 3 种不同的编译器制作程序。这可能总结了我在 CMake 中的所有知识。

现在我的问题是我有一些源代码,当我制作程序时我不想碰/弄乱它的文件夹。我希望所有 CMake 和 make 输出文件和文件夹都进入 ../Compile/,因此我为此更改了 CMake 脚本中的一些变量,并且当我在笔记本电脑上执行类似操作时它工作了一段时间:

Compile$ cmake ../src
Compile$ make

我现在所在的文件夹中有一个干净的输出,这正是我正在寻找的。​​p>

现在我转移到另一台计算机,重新编译 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 将它们设置为合理的默认值。您绝对应该修改CMAKE_BINARY_DIRCMAKE_CACHEFILE_DIR。如果您删除所有这些 set() 调用并只执行 cd Compile; rm -rf *; cmake ../src 会发生什么?
  • 基本上,只要你在运行 CMake 时在源目录之外,除非你的 CMakeList 明确告诉它,否则它不会修改源目录。
  • @Angew 感谢您的提示,这令人惊讶!我删除了所有这些行,只使用了 cmake ../src ,它就像一个魅力!这太令人惊讶了,因为我之前在第一次学习 CMake 时尝试过,但没有成功。请把你的答案写在官方回复中,给你打个大大的打勾:)
  • 救了我的是@Adam Bowen 的评论,“你不能用源内构建为源目录创建一个外源构建”

标签: c++ build makefile cmake output


【解决方案1】:

听起来您想要out of source build。有几种方法可以创建非源代码构建。

  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 .
    

    如果你的当前目录已经是构建文件夹。

  2. 对于 CMake 3.13 或更高版本,请使用 these options to set the source and build folders

    cmake -B/path/to/my/build/folder -S/path/to/my/source/folder
    
  3. 对于较旧的 CMake,请使用一些 undocumented options to set the source and build folders:

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

    这将与 (1) 做完全相同的事情,但不依赖于当前工作目录。

默认情况下,CMake 会将其所有输出放在 构建树 中,因此除非您在 cmake 文件中大量使用 ${CMAKE_SOURCE_DIR}${CMAKE_CURRENT_SOURCE_DIR},否则它不应触及您的 源代码树.

最大的问题是如果您之前在源代码树中生成了一个构建树(即您有一个 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.txtCMakeFiles

您可能会发现设置二进制库、共享库和静态库的写入路径很有用 - 在这种情况下,请参阅 how do I make cmake output into a 'bin' dir?(免责声明,我在该问题上获得最高票数的答案......但这就是我所知道的关于它)。

【讨论】:

  • 其实设置源文件夹的选项是-S,不是-H
  • @smac89 谢谢!看起来他们在 3.13 中记录了它们 - 我已经更新了答案以反映现代 CMake。
【解决方案2】:

几乎不需要设置您要设置的所有变量。 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 文档,您会看到变量被划分为语义部分。除了非常特殊情况外,您应该将“提供信息的变量”下列出的所有内容视为 CMakeLists 中的只读变量。

【讨论】:

  • 我开始在 src 目录中使用带有构建的 cmake ......这种技术最初失败了。一旦我删除了 src 目录中的所有 cmake 构建文件/缓存,这种技术就起作用了。谢谢!
  • 最好不要建议使用rm -rf *。如果cd Compile 失败,那就不好看了……
  • @Roman 我认为这样的命令行示例几乎是伪代码。它比键入“输入目录Compile,删除那里的所有内容,然后使用源目录的路径运行CMake”更简洁,更准确。我假设部分读者有基本的常识和判断。
  • @AviTevet:我认为这是正确的答案。如果源目录中有来自先前 cmake 调用的 cmake 缓存文件,您将不会让 cmake 为生成的文件选择另一个目录,除非您从源目录中删除所有旧文件。在我看来,CMake 的行为非常糟糕。你为什么不写另一个答案?
【解决方案3】:

把我的评论变成答案:

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

cd src
cmake .

cmake 会将一堆构建文件和缓存文件(CMakeCache.txtCMakeFilescmake_install.cmake 等)放在src 目录中。

要更改为非源代码构建,我必须删除所有这些文件。然后我可以做@Angew 在他的回答中推荐的事情:

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

【讨论】:

    【解决方案4】:

    截至CMake Wiki

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

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

    【讨论】:

      【解决方案5】:

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

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

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

      【讨论】:

      • 这正是我想要的——CMAKE_CURRENT_BINARY_DIR,通常会告诉我当前的二进制构建路径。可能可用于设置依赖的 libs/bin 构建。
      【解决方案6】:

      从 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
      

      【讨论】:

        猜你喜欢
        • 2018-11-25
        • 1970-01-01
        • 1970-01-01
        • 2011-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-02
        相关资源
        最近更新 更多