make clean
がmakefileが生成したすべてのファイルを削除するように、私はCMakeでも同じことをしたいと思います。多くの場合、私は手動でディレクトリをcmake_install.cmake
やCMakeCache.txt
のようなファイルを削除したり、CMakeFiles
フォルダを手動で調べたりします。
これらすべてのファイルを自動的に削除するcmake clean
のようなコマンドはありますか?理想的には、これは現在のディレクトリのCMakeLists.txt
ファイル内で定義された再帰的構造に従うべきです。
cmake clean
はありません。
私は通常 "build"のような単一のフォルダにプロジェクトをビルドします。 make clean
にしたいのなら、rm -rf build
だけにできます。
ルートの "CMakeLists.txt"と同じディレクトリにある "build"フォルダは、通常は良い選択です。あなたのプロジェクトを構築するためには、単に引数としてCMakeLists.txtの場所をcmakeに渡します。例えば、cd <location-of-cmakelists>/build && cmake ..
です。 (@ComicSansMSから)
CMakeの公式FAQ /:
GNU autotoolsで作成されたビルドツリーの中には、ビルドをクリーンにし、生成されたビルドシステムのMakefileやその他の部分を削除する "make distclean"ターゲットを持つものがあります。 CMakeLists.txtファイルはスクリプトや任意のコマンドを実行できるため、CMakeは "make distclean"ターゲットを生成しません。 CMakeは、CMakeの実行の一部としてどのファイルが生成されたのかを正確に追跡する方法はありません。悪質なターゲットを提供すると、ユーザーは期待どおりに機能するという誤った印象を与えます。 (CMakeは、コンパイラとリンカによって生成されたファイルを削除するための "make clean"ターゲットを生成します。)
"make distclean"ターゲットは、ユーザーがソース内ビルドを実行する場合にのみ必要です。 CMakeはインソースビルドをサポートしていますが、ユーザはアウトオブソースビルドの概念を採用することを強く推奨します。ソースツリーとは別のビルドツリーを使用すると、CMakeはソースツリーにファイルを生成しなくなります。 CMakeはソースツリーを変更しないので、厄介なターゲットは必要ありません。ビルドツリーを削除するか、別のビルドツリーを作成することで、新しいビルドを始めることができます。
私はそれを30分くらいグーグルしました、そして私が思いついた唯一の有用なことはfind
ユーティリティを呼び出すことでした:
# Find and then delete all files under current directory (.) that:
# 1. contains "cmake" (case-&insensitive) in its path (wholename)
# 2. name is not CMakeLists.txt
find . -iwholename '*cmake*' -not -name CMakeLists.txt -delete
また、make clean
(あるいはあなたが使っているCMakeジェネレータ)を の前に - 呼び出してください。
:)
どこにいてもGitが使用されている今日では、CMakeを忘れてgit clean -d -f -x
を使用すると、ソース管理下にないすべてのファイルが削除されます。
次のようなものを使うことができます。
add_custom_target(clean-cmake-files
COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)
// clean-all.cmake
set(cmake_generated ${CMAKE_BINARY_DIR}/CMakeCache.txt
${CMAKE_BINARY_DIR}/cmake_install.cmake
${CMAKE_BINARY_DIR}/Makefile
${CMAKE_BINARY_DIR}/CMakeFiles
)
foreach(file ${cmake_generated})
if (EXISTS ${file})
file(REMOVE_RECURSE ${file})
endif()
endforeach(file)
私は通常、前の例に "make clean"の呼び出しを追加する "make clean-all"コマンドを作成します。
add_custom_target(clean-all
COMMAND ${CMAKE_BUILD_TOOL} clean
COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)
依存関係として "clean"ターゲットを追加しようとしないでください。
add_custom_target(clean-all
COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
DEPENDS clean
)
「きれい」はCMakeの本当の目標ではなく、これはうまくいきません。
さらに、この「clean-cmake-files」を何かの依存関係として使用しないでください。
add_custom_target(clean-all
COMMAND ${CMAKE_BUILD_TOOL} clean
DEPENDS clean-cmake-files
)
これを行うと、clean-allが完了する前にすべてのCMakeファイルが消去され、makeは "CMakeFiles/clean-all.dir/build.make"の検索中にエラーをスローします。そのため、どのようなコンテキストでも、 "everything"の前にclean-allコマンドを使用することはできません。
add_custom_target(clean-all
COMMAND ${CMAKE_BUILD_TOOL} clean
COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)
それもうまくいきません。
単にrm CMakeCache.txt
を発行するだけでも私にはうまくいきます。
私は、ソース外ビルドが最善の解決策であることに同意します。しかし、あなたがインソースビルドをしなければならない時のために、私は here で利用可能なPythonスクリプトを書きました。
私が最近見つけた解決策は、ソース外ビルドの概念と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)
を使用してbuild
ディレクトリを作成することです。これはmkdir -p
の変数です。ディレクトリbuild
は、ソース外ビルドを実行する場所です。 mkdir
がすでに存在している可能性があるディレクトリを作成しようとしていることに対して私たちに叫んでいないことを保証するために、引数-p
を提供します。
ターゲット./build/Makefile
が行う2番目のことは、ディレクトリをbuild
ディレクトリに変更してcmake
を呼び出すことです。
all
ターゲットに戻り、$(MAKE) -C build
を呼び出します。ここで、$(MAKE)
はmake
に対して自動的に生成されるMakefile変数です。 make -C
は何かをする前にディレクトリを変更します。したがって、$(MAKE) -C build
を使用することはcd build; make
を実行することと同等です。
まとめると、このMakefileラッパーをmake all
または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ラッパーは必須のOut-of-SourceビルドCMake設定と組み合わせて、ユーザーがコマンドcmake
と対話する必要がないようにします。このソリューションはまた、build
ディレクトリからすべてのCMake出力ファイルを削除するための洗練された方法を提供します。
P.S Makefileでは、シェルコマンドからの出力を抑制するために接頭辞@
を使用し、シェルコマンドからのエラーを無視するために接頭辞@-
を使用します。 rm
をdistclean
ターゲットの一部として使用するとき、ファイルが存在しない場合、コマンドはエラーを返します(rm -rf build
のコマンドラインを使用して既に削除されているか、最初から生成されたことはありません)。このリターンエラーはMakefileを強制的に終了させます。これを防ぐために接頭辞@-
を使用します。ファイルが既に削除されている場合は問題ありません。私たちは自分のMakefileに続けて残りを削除してもらいたいのです。
注意すべきもう1つのこと:プロジェクトをビルドするために可変数のCMake変数、例えばcmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar"
を使用する場合、このMakefileは機能しないかもしれません。このMakefileはcmake ..
をタイプするか、cmake
に一貫した数の引数(Makefileに含めることができる)を提供することによって、CMakeを一貫した方法で呼び出すことを想定しています。
最後に、クレジットが支払われるべきクレジット。このMakefileラッパーは、 C++アプリケーションプロジェクトテンプレート によって提供されるMakefileを基にしています。
多分それは少し時代遅れです、しかし、あなたがcmake clean
をグーグルするとき、これが最初のヒットであるので、私はこれを加えます:
次のように指定したターゲットを使用してbuild dirでビルドを開始できます。
cmake --build . --target xyz
もちろん走れます
cmake --build . --target clean
生成されたビルドファイルでclean
ターゲットを実行します。
ビルドファイルを生成するときに-D
パラメータをCMakeに渡し、build /ディレクトリ全体を削除したくない場合は、次のようにします。
ビルドディレクトリ内のCMakeFiles /ディレクトリを削除するだけです。
rm -rf CMakeFiles/
cmake --build .
これによりCMakeが再実行され、ビルドシステムファイルが再生成されます。あなたのビルドも最初から始まります。
もちろん、ソース外ビルドはUnixのMakefileには最適な方法ですが、Eclipse CDTなどの他のジェネレータを使用している場合は、ソース内でビルドすることをお勧めします。その場合は、手動でCMakeファイルを削除する必要があります。これを試して:
find . -name 'CMakeCache.txt' -o -name '*.cmake' -o -name 'Makefile' -o -name 'CMakeFiles' -exec rm -rf {} +
Globstarをshopt -s globstar
で有効にしているのであれば、代わりに次のより嫌な方法を試してください。
rm -rf **/CMakeCache.txt **/*.cmake **/Makefile **/CMakeFiles
走れば
cmake .
それはCMakeファイルを再生成します。たとえば、*。ccで選択されているソースフォルダに新しいファイルを追加する場合に必要です。
これはそれ自体「クリーン」ではありませんが、キャッシュを再生成することによってCMakeファイルを「クリーンアップ」します。
"out of source"ビルド(つまりbuild
ディレクトリにビルドする)を使うときのクリーニングを簡単にするために、私は以下のスクリプトを使います:
$ cat ~/bin/cmake-clean-build
#!/bin/bash
if [ -d ../build ]; then
cd ..
rm -rf build
mkdir build
cd build
else
echo "build directory DOES NOT exist"
fi
クリーンアップする必要があるたびに、build
ディレクトリからこのスクリプトを入手する必要があります。
. cmake-clean-build
使用してみてください:cmake --clean-firstのCMakeLists.txt-fileのパス-B output-dir
--clean-first:最初にターゲットをビルドし、次にビルドします。
(クリーニングのみを行うには、-target cleanを使用します。)
カスタム定義があり、それらをクリーンアップの前に保存したい場合は、ビルドディレクトリで次のコマンドを実行します。
sed -ne '/variable specified on the command line/{n;s/.*/-D \0 \\/;p}' CMakeCache.txt
それから新しいビルドディレクトリを作成し(または古いビルドディレクトリを削除して再作成し)、最後に上記のスクリプトで取得した引数を付けてcmake
を実行します。
私はそのような目的のために次のシェルスクリプトを使います。
#!/bin/bash
for fld in $(find -name "CMakeLists.txt" -printf '%h ')
do
for cmakefile in CMakeCache.txt cmake_install.cmake CTestTestfile.cmake CMakeFiles Makefile
do
rm -rfv $fld/$cmakefile
done
done
Windowsを使用している場合は、このスクリプトにCygwinを使用してください。