C++ CMake输出/生成目录

C++ CMake输出/生成目录,c++,build,makefile,cmake,output,C++,Build,Makefile,Cmake,Output,我对CMake很陌生,读了一些关于如何使用它的教程,并编写了一些复杂的50行CMake脚本,以便为3个不同的编译器编写一个程序。这可能是我对CMake的全部知识的总结 现在我的问题是,我有一些源代码,当我制作程序时,我不想接触/弄乱它们的文件夹。我想让所有的CMake和生成输出文件和文件夹进入。/Compile/,因此我在CMake脚本中为此更改了一些变量,并且在我的笔记本电脑上执行类似操作时,它一直有效: Compile$ cmake ../src Compile$ make 我现在所在的文

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

现在我的问题是,我有一些源代码,当我制作程序时,我不想接触/弄乱它们的文件夹。我想让所有的CMake和
生成
输出文件和文件夹进入
。/Compile/
,因此我在CMake脚本中为此更改了一些变量,并且在我的笔记本电脑上执行类似操作时,它一直有效:

Compile$ cmake ../src
Compile$ make
我现在所在的文件夹中有一个干净的输出,这正是我想要的

现在我转移到另一台计算机上,重新编译了CMake 2.8.11.2,我几乎回到了原点!它总是将内容编译到my
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

我遗漏了什么吗?

您不应该在脚本中依赖硬编码的build dir名称,因此必须更改带有
。/Compile
的行

这是因为它应该由用户决定在哪里编译

而不是使用一个预定义的变量:
(查找
CMAKE\u BINARY\u DIR
CMAKE\u CURRENT\u BINARY\u DIR

几乎不需要设置所有正在设置的变量。CMake将它们设置为合理的默认值。您绝对不应该修改
CMAKE\u BINARY\u DIR
CMAKE\u CACHEFILE\u DIR
。将这些视为只读

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

cd src
rm CMakeCache.txt
cd ..
cd src
cmake .
然后删除所有
set()
命令并执行以下操作:

cd Compile && rm -rf *
cmake ../src
只要运行CMake时您在源目录之外,它就不会修改源目录,除非您的CMakeList明确告诉它这样做

一旦您完成了这项工作,您就可以查看CMake在默认情况下放置东西的位置,并且只有当您对默认位置(例如
可执行文件输出路径的默认值
)不满意时,才可以只修改您需要的位置。并尝试相对于
CMAKE\u BINARY\u DIR
CMAKE\u CURRENT\u BINARY\u DIR
PROJECT\u BINARY\u DIR
等表达它们


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

听起来您需要一个。有几种方法可以创建源代码外构建

  • 做你正在做的,快跑

    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 3.13或更高版本,请使用

  • 对于较旧的CMake,请使用一些:

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

  • 默认情况下,CMake将其所有输出放在构建树中,因此,除非您在CMake文件中大量使用
    ${CMake\u SOURCE\u DIR}
    ${CMake\u CURRENT\u SOURCE\u DIR}
    ,否则它不应该接触您的源代码树

    可能出错的最大问题是,如果您以前在源代码树中生成了生成树(即,您有一个源代码内生成)。完成此操作后,上面(1)的第二部分将开始,cmake不会对源位置或构建位置进行任何更改。因此,您无法为具有源内版本的源目录创建源外版本。您可以通过(至少)从源目录中删除
    cmakcache.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

    您可能会发现设置二进制文件、共享库和静态库写入的路径很有用—在这种情况下,请参见(免责声明,我对这个问题的答案是最有投票权的……但我就是这样知道的)。

    截至:

    CMAKE_二进制目录 如果您是在源代码中构建,这与CMAKE_source_DIR相同,否则这是您的 建树


    比较这两个变量以确定是否启动了源代码外构建

    将我的评论转化为答案:

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

    cd src
    rm CMakeCache.txt
    cd ..
    
    cd src
    cmake .
    
    cmake将在
    src
    目录中放置一组构建文件和缓存文件(
    CMakeCache.txt
    CMakeFiles
    cmake\u install.cmake
    ,等等)

    要更改为源代码外版本,我必须删除所有这些文件。然后我可以按照@Angew在回答中的建议做:

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

    几乎不需要设置所有正在设置的变量。CMake将它们设置为合理的默认值。你绝对不应该修改