我试图让cmake的建立到一个目录“建设”,在project/build
,其中的CMakeLists.txt在project/
。
我知道我可以这样做:
mkdir build
cd build
cmake ../
但毕竟是累赘。 我可以把它放在一个脚本,并调用它,但后来它的不愉快向CMake提供不同的参数(如-G“MSYS Makefile文件”),或者我需要编辑每个平台上的文件。
最好我会做的主要的CMakeLists.txt像SET(CMAKE_OUTPUT_DIR版本)。 请告诉我,这是可能的,如果是这样,怎么样? 或其他一些出来的源码编译的方法,可以很容易指定不同的参数?
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"
需要注意的是必须不存在的选项和目录路径之间的空格字符。
我最近发现一个解决办法是乱源构建概念,一个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变量make
。 make -C
变化做任何事情之前的目录。 因此,使用$(MAKE) -C build
相当于做cd build; make
cd build; make
。
总之,调用与这个Makefile的包装make all
或make
相当于做:
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 ++的应用项目模板 。
这个答案最初发布在这里 。 我认为它适用于您的情况也是如此。
根据前面的答案,我写了下面的模块可以包括执行乱源的构建。
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
不会被传递到“乱源构建呼叫”。
建议,以改善该模块的欢迎。