cmakeを使用して、ソース内ビルドをどのように無効にしますか?
質問
生成されたCMakeファイルでソースツリーを乱雑にすることを禁止します...さらに重要なことは、同じビルドプロセスの一部ではない既存の Makefiles
をステップ実行することを禁止します」 CMakeを使用して再。 (聞いてはいけない)
これを実現する方法は、次のように、 CMakeLists.txt
の先頭に数行を追加することです。
if("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
message(SEND_ERROR "In-source builds are not allowed.")
endif("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
ただし、この方法で行うのは冗長すぎるようです。さらに、インソースビルドを試みると、エラーがスローされる前に、ソースツリーに CMakeFiles /
ディレクトリと CMakeCache.txt
ファイルが作成されます。
これを行うためのより良い方法がありませんか?
解決
私はあなたのやり方が好きだと思います。 cmakeメーリングリストは、これらのタイプの質問に答えるのに適しています。
補足として:" cmake"を作成できます。失敗したディレクトリ内の実行可能ファイル。 "。"の有無によって(Linux上で)それらのパスにあります。 / bin / falseにシンボリックリンクすることもできます。
Windowsでは、現在のディレクトリ内のファイルが最初に見つかったかどうかわかりません。
他のヒント
CMakeには、文書化されていない2つのオプションがあります。
CMAKE_DISABLE_SOURCE_CHANGES
および CMAKE_DISABLE_IN_SOURCE_BUILD
cmake_minimum_required (VERSION 2.8)
# add this options before PROJECT keyword
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
project (HELLO)
add_executable (hello hello.cxx)
-
andrew@manchester:~/src% cmake .
CMake Error at /usr/local/share/cmake-2.8/Modules/CMakeDetermineSystem.cmake:160 (FILE):
file attempted to write a file: /home/andrew/src/CMakeFiles/CMakeOutput.log
into a source directory.
/home/selivanov/cmake-2.8.8/Source/cmMakefile.cxx
bool cmMakefile::CanIWriteThisFile(const char* fileName)
{
if ( !this->IsOn("CMAKE_DISABLE_SOURCE_CHANGES") )
{
return true;
}
// If we are doing an in-source build, than the test will always fail
if ( cmSystemTools::SameFile(this->GetHomeDirectory(),
this->GetHomeOutputDirectory()) )
{
if ( this->IsOn("CMAKE_DISABLE_IN_SOURCE_BUILD") )
{
return false;
}
return true;
}
// Check if this is subdirectory of the source tree but not a
// subdirectory of a build tree
if ( cmSystemTools::IsSubDirectory(fileName,
this->GetHomeDirectory()) &&
!cmSystemTools::IsSubDirectory(fileName,
this->GetHomeOutputDirectory()) )
{
return false;
}
return true;
}
こののような関数を含めます。これらの違いを利用して行うことと似ています:
-
これは関数にカプセル化され、
PreventInSourceBuilds.cmake
モジュールを含めると呼び出されます。メインのCMakeLists.txtに含める必要があります:set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake) include(PreventInSourceBuilds)
-
REALPATHパラメーターで get_filename_component()を使用しますパスを比較する前にシンボリックリンクを解決します。
githubリンクが変更された場合のモジュールソースコードは、上記の例の CMake
というディレクトリの PreventInSouceBuilds.cmake
に配置する必要があります。 ):
#
# This function will prevent in-source builds
function(AssureOutOfSourceBuilds)
# make sure the user doesn't play dirty with symlinks
get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)
# disallow in-source builds
if("${srcdir}" STREQUAL "${bindir}")
message("######################################################")
message("# ITK should not be configured & built in the ITK source directory")
message("# You must run cmake in a build directory.")
message("# For example:")
message("# mkdir ITK-Sandbox ; cd ITK-sandbox")
message("# git clone http://itk.org/ITK.git # or download & unpack the source tarball")
message("# mkdir ITK-build")
message("# this will create the following directory structure")
message("#")
message("# ITK-Sandbox")
message("# +--ITK")
message("# +--ITK-build")
message("#")
message("# Then you can proceed to configure and build")
message("# by using the following commands")
message("#")
message("# cd ITK-build")
message("# cmake ../ITK # or ccmake, or cmake-gui ")
message("# make")
message("#")
message("# NOTE: Given that you already tried to make an in-source build")
message("# CMake have already created several files & directories")
message("# in your source tree. run 'git status' to find them and")
message("# remove them by doing:")
message("#")
message("# cd ITK-Sandbox/ITK")
message("# git clean -n -d")
message("# git clean -f -d")
message("# git checkout --")
message("#")
message("######################################################")
message(FATAL_ERROR "Quitting configuration")
endif()
endfunction()
AssureOutOfSourceBuilds()
.bashrc
/ .zshrc
に次のような cmake()
シェル関数があります:
function cmake() {
# Don't invoke cmake from the top-of-tree
if [ -e "CMakeLists.txt" ]
then
echo "CMakeLists.txt file present, cowardly refusing to invoke cmake..."
else
/usr/bin/cmake $*
fi
}
この低セレモニーのソリューションが好きです。 CMakeに切り替えたときの同僚からの最大の不満は解消しましたが、インソース/トップオブツリービルドを行うことを本当にしたい人がそうするのを防ぐことはできません&#8212 ; / usr / bin / cmake
を直接呼び出すことができます(またはラッパー関数をまったく使用しません)。そして、それは愚か簡単です。
.bashrcファイルを this
のように構成できます。cmakekde および kdebuild 関数をご覧ください。 BUILDおよびSRC envを設定します。変数を作成し、必要に応じてこれらの関数を編集します。これは、 srcDir
ではなく、 buildDir でのみビルドされますLinuxの場合:
トップレベルのCMakeLists.txtに追加:
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
トップレベルで「dotme」ファイルを作成するか、.bashrcに追加します(グローバル):
#!/bin/bash
cmk() { if [ ! -e $1/CMakeLists.txt ] || ! grep -q "set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)" $1/CMakeLists.txt;then /usr/bin/cmake $*;else echo "CMAKE_DISABLE_IN_SOURCE_BUILD ON";fi }
alias cmake=cmk
now run:
. ./dotme
トップレベルのソースツリーでcmakeを実行しようとすると:
$ cmake .
CMAKE_DISABLE_IN_SOURCE_BUILD ON
CMakeFiles /またはCMakeCache.txtは生成されません。
アウトオブソースビルドを実行していて、最初に実際の実行可能ファイルを呼び出すだけでcmakeを実行する必要がある場合:
$ cd build
$ /usr/bin/cmake ..
ビルドを行う人/プロセスがディレクトリを読み取り専用にするだけです。ソース管理からディレクトリにチェックアウトする別のプロセスがあり(ソース管理を使用しているのですか?)、それを読み取り専用にします。