私が最近見つけた解決策は、ソース外のビルドコンセプトを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
が最初に行うことは、mkdir -p
の変数である$(MKDIR)
を使用してbuild
ディレクトリを作成することです。ディレクトリbuild
は、アウトソースビルドを実行する場所です。既に存在する可能性があるディレクトリを作成しようとした場合、mkdir
が私たちに悲鳴を上げないように、引数-p
を提供します。
ターゲット./build/Makefile
の2番目のことは、ディレクトリをbuild
ディレクトリに変更し、cmake
を呼び出すことです。
ターゲットに戻って、$(MAKE) -C build
を呼び出します。は、make
に対して自動的に生成されるMakefile変数です。 make -C
は何もする前にディレクトリを変更します。したがって、$(MAKE) -C build
を使用することは、cd build; make
を実行することと同じです。make all
かmake
で、このMakefileのラッパーを呼び出して、要約する
がやっと同等です:
mkdir build
cd build
cmake ..
make
ターゲットdistclean
はmake -C build clean
そして、cmake ..
を呼び出し、そして最後に、build
ディレクトリからすべての内容を削除します。私はこれがまさにあなたがあなたの質問で要求したものだと信じています。
メイクファイルの最後の部分は、ユーザー指定のターゲットがdistclean
であるかどうかを評価します。そうでなければ、呼び出す前にディレクトリをbuild
に変更します。これは非常に強力です。たとえば、ユーザーがmake clean
と入力すると、Makefileはこれをcd build; make clean
に相当するものに変換します。
結論として、このMakefileラッパーは、必須のアウトソースビルドCMake構成と組み合わせて、ユーザーがコマンドcmake
と対話する必要がないようにします。この解決法はまた、すべてのCMake出力ファイルをbuild
ディレクトリから削除する洗練された方法を提供します。
P.S. Makefileでは、接頭辞@
を使用してシェルコマンドの出力を抑制し、接頭辞@-
を使用してシェルコマンドのエラーを無視します。 distclean
ターゲットの一部としてrm
を使用すると、ファイルが存在しない場合(すでにコマンドラインを使用してrm -rf build
で削除されているか、最初に生成されたことがない場合)、エラーが返されます。このリターンエラーは、Makefileを強制的に終了させます。これを防ぐためにプレフィックス@-
を使用します。すでにファイルが削除されていてもかまいません。私たちはMakefileが残り続けていくことを望んでいます。
メモ:プロジェクトのビルドに可変数のCMake変数を使用すると、このMakefileは機能しないことがあります。たとえば、cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar"
です。このMakefileは、cmake ..
を入力するか、(Makefileに含めることができる)一貫した数の引数をcmake
で提供することによって、一貫した方法でCMakeを呼び出すことを前提としています。
最後に、クレジットが支払期限であるクレジット。このMakefileラッパーは、C++ Application Project Templateによって提供されるMakefileから適合されました。
この回答は当初の投稿hereです。私はそれもあなたの状況に適用されたと思った。
私はあなたと同じプロジェクトアーキテクチャを持っています。私の "ビルド"ディレクトリは常にここにあります。私は人格的に、_cmake .._と入力するのはそれほど大したことではないことに気づいています。 – Offirmo