私が最近見つけた解決策は、アウト オブ ソース ビルドの概念を 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
ターゲットが行う 2 番目のことは、ディレクトリ./build/Makefile
をディレクトリに変更し、.build
cmake
ターゲットに戻りall
、 を呼び出します$(MAKE) -C build
。ここで、$(MAKE)
は に対して自動的に生成される Makefile 変数ですmake
。make -C
何かをする前にディレクトリを変更します。したがって、 を使用することは、 を使用$(MAKE) -C build
することと同じcd build; make
です。
要約すると、この Makefile ラッパーをmake all
orで呼び出すことは、次のことmake
と同等です。
mkdir build
cd build
cmake ..
make
ターゲットは をdistclean
呼び出しcmake ..
、次にを呼び出し、最後にディレクトリmake -C build clean
からすべてのコンテンツを削除します。build
これはまさにあなたが質問で要求したものだと思います。
Makefile の最後の部分は、ユーザーが指定したターゲットが であるかどうかを評価しますdistclean
。build
そうでない場合は、呼び出す前にディレクトリをに変更します。これは非常に強力です。たとえば、ユーザーが を入力するmake clean
と、Makefile がそれを に相当するものに変換するからcd build; make clean
です。
結論として、この Makefile ラッパーは、必須のアウトオブソース ビルド CMake 構成と組み合わせて、ユーザーがコマンドを操作する必要がないようにしますcmake
。build
このソリューションは、ディレクトリからすべての CMake 出力ファイルを削除する洗練された方法も提供します。
PS Makefile では、プレフィックスを使用し@
てシェル コマンドからの出力を抑制し、プレフィックスを使用してシェル コマンド@-
からのエラーを無視します。rm
ターゲットの一部として使用distclean
する場合、ファイルが存在しない場合、コマンドはエラーを返します (ファイルは、コマンド ラインを使用して既に削除されているrm -rf build
か、最初から生成されていない可能性があります)。この戻りエラーにより、Makefile は強制的に終了します。@-
それを防ぐためにプレフィックスを使用します。ファイルが既に削除されている場合は許容されます。Makefile を続行し、残りを削除する必要があります。
注意すべきもう 1 つの点: プロジェクトをビルドするために可変数の CMake 変数を使用する場合、この Makefile は機能しない可能性がありますcmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar"
。cmake ..
この Makefile は、入力するかcmake
、一貫した数の引数 (Makefile に含めることができます) を指定することによって、一貫した方法で CMake を呼び出すことを前提としています。
最後に、クレジットが必要なクレジット。この Makefile ラッパーは、C++ Application Project Templateによって提供される Makefile から適用されました。
この回答はもともとここに投稿されました。あなたの状況にも当てはまると思いました。