获取CMake的打造出了源没有包装脚本?获取CMake的打造出了源没有包装脚本?(Getting c

2019-06-02 16:23发布

我试图让cmake的建立到一个目录“建设”,在project/build ,其中的CMakeLists.txt在project/

我知道我可以这样做:

mkdir build
cd build
cmake ../

但毕竟是累赘。 我可以把它放在一个脚本,并调用它,但后来它的不愉快向CMake提供不同的参数(如-G“MSYS Makefile文件”),或者我需要编辑每个平台上的文件。

最好我会做的主要的CMakeLists.txt像SET(CMAKE_OUTPUT_DIR版本)。 请告诉我,这是可能的,如果是这样,怎么样? 或其他一些出来的源码编译的方法,可以很容易指定不同的参数?

Answer 1:

CMake的3.13或较新的支持的命令行选项 -S-B来指定源和二进制目录,分别。

cmake -S . -B build -G "MSYS Makefiles"

这将寻找CMakeLists.txt在当前文件夹,并创建一个build在它的文件夹(如果它还不存在)。

对于旧版本的CMake,你可以使用无证CMake的选项-H-B指定在调用源代码和二进制目录cmake

cmake -H. -Bbuild -G "MSYS Makefiles"

需要注意的是必须不存在的选项和目录路径之间的空格字符。



Answer 2:

我最近发现一个解决办法是乱源构建概念,一个Makefile的包装结合起来。

在我的顶层的CMakeLists.txt文件,我包括以下内容,以防止源建立:

if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} )
    message( FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt." )
endif()

然后,我创建了一个顶级的Makefile,并包括以下内容:

# -----------------------------------------------------------------------------
# CMake project wrapper Makefile ----------------------------------------------
# -----------------------------------------------------------------------------

SHELL := /bin/bash
RM    := rm -rf
MKDIR := mkdir -p

all: ./build/Makefile
    @ $(MAKE) -C build

./build/Makefile:
    @  ($(MKDIR) build > /dev/null)
    @  (cd build > /dev/null 2>&1 && cmake ..)

distclean:
    @  ($(MKDIR) build > /dev/null)
    @  (cd build > /dev/null 2>&1 && cmake .. > /dev/null 2>&1)
    @- $(MAKE) --silent -C build clean || true
    @- $(RM) ./build/Makefile
    @- $(RM) ./build/src
    @- $(RM) ./build/test
    @- $(RM) ./build/CMake*
    @- $(RM) ./build/cmake.*
    @- $(RM) ./build/*.cmake
    @- $(RM) ./build/*.txt

ifeq ($(findstring distclean,$(MAKECMDGOALS)),)
    $(MAKECMDGOALS): ./build/Makefile
    @ $(MAKE) -C build $(MAKECMDGOALS)
endif

默认的目标all被敲打叫make ,并调用目标./build/Makefile

目标的第一件事./build/Makefile确实是创建build使用目录$(MKDIR)这是一个可变mkdir -p 。 该目录build是我们将履行我们的乱源建设。 我们所提供的参数-p ,确保mkdir不向我们喊着要努力创造可能已存在的目录。

目标第二件事./build/Makefile确实是更改目录到build目录并调用cmake

回到all目标,我们调用$(MAKE) -C build ,其中$(MAKE)是自动生成的Makefile变量makemake -C变化做任何事情之前的目录。 因此,使用$(MAKE) -C build相当于做cd build; make cd build; make

总之,调用与这个Makefile的包装make allmake相当于做:

mkdir build
cd build
cmake ..
make 

目标distclean调用cmake .. ,然后make -C build clean ,最后,将删除所有内容build目录。 我相信,这正是你在你的问题提出要求。

如果用户提供的目标是或不是生成文件的最后一块评估distclean 。 如果不是,它会改变目录到build调用它。 这是非常强大的,因为用户可以输入,例如, make clean和Makefile文件将变换成的等效cd build; make clean cd build; make clean

总之,这个Makefile包装,结合强制性外的源代码编译CMake的配置,让这个用户从来没有使用命令交互cmake 。 该解决方案还提供了一个巧妙的方法,从删除所有CMake的输出文件build目录。

PS在Makefile中,我们使用前缀@来抑制从shell命令的输出,并且前缀@-忽略从shell命令的错误。 当使用rm作为的一部分distclean的目标,如果不存在的文件的命令将返回一个错误(使用命令行使用它们可能已被删除已经rm -rf build ,或他们从来没有在第一时间产生的)。 这回的错误将迫使我们的Makefile中退出。 我们使用前缀@-防止。 这是可以接受的,如果一个文件已被删除; 我们希望我们的Makefile继续下去,并删除其余部分。

还有一点要注意:如果你使用可变数量的CMake变量来建立你的项目,这个Makefile可能无法正常工作,例如, cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar" 。 这个Makefile假设你调用CMake的以一致的方式,通过输入cmake ..或通过提供cmake的参数一致的号码(您可以在您的Makefile)。

最后,信贷,信贷到期。 此生成的文件包装器改编自通过所提供的生成文件C ++的应用项目模板 。

这个答案最初发布在这里 。 我认为它适用于您的情况也是如此。



Answer 3:

根据前面的答案,我写了下面的模块可以包括执行乱源的构建。

set(DEFAULT_OUT_OF_SOURCE_FOLDER "cmake_output")

if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
    message(WARNING "In-source builds not allowed. CMake will now be run with arguments:
        cmake -H. -B${DEFAULT_OUT_OF_SOURCE_FOLDER}
")

    # Run CMake with out of source flag
    execute_process(
            COMMAND ${CMAKE_COMMAND} -H. -B${DEFAULT_OUT_OF_SOURCE_FOLDER}
            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})

    # Cause fatal error to stop the script from further execution
    message(FATAL_ERROR "CMake has been ran to create an out of source build.
This error prevents CMake from running an in-source build.")
endif ()

这工作,但我已经注意到2个缺点:

  • 当用户是懒惰和简单的运行cmake . ,他们总会看到一个FATAL_ERROR 。 我找不到其他办法来防止CMake的从早期做任何其他操作和退出。
  • 传递给原调用的任何命令行参数cmake不会被传递到“乱源构建呼叫”。

建议,以改善该模块的欢迎。



文章来源: Getting cmake to build out of source without wrapping scripts?