web-dev-qa-db-ja.com

cmakeを使用して、ソース内ビルドをどのように無効にしますか?

生成されたCMakeファイルでソースツリーを乱雑にすることを禁止したい...そしてさらに重要なことに、CMakeを使用しているのと同じビルドプロセスの一部ではない既存のMakefilesを踏むことを禁止したい。 (聞かないでください)

これを行うために私が思いついた方法は、次のように、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ファイルが作成されます。

これを行うためのより良い方法がありませんか?

42
mpontillo

私はあなたのやり方が好きだと思います。 cmakeメーリングリストは、これらのタイプの質問に答えるのに適しています。

補足として:失敗したディレクトリに「cmake」実行可能ファイルを作成することができます。 「。」かどうかによって異なります。それらのパスにあります(Linuxの場合)。/bin/falseをシンボリックリンクすることもできます。

Windowsでは、現在のディレクトリ内のファイルが最初に見つかるかどうかはわかりません。

4
Juan

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;
}
53

これ のような関数を含めます。これは、これらの違いで行うことと似ています。

  1. これは、PreventInSourceBuilds.cmakeモジュールを含めると呼び出される関数にカプセル化されます。メインのCMakeLists.txtには次のものを含める必要があります。

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
    include(PreventInSourceBuilds)
    
  2. パスを比較する前にシンボリックリンクを解決する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()
7
aled

_.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に切り替えたとき、同僚の最大の不満は解消されましたが、本当にインソース/トップオブツリービルドを実行したい人がそうすることを妨げることはありません。 _/usr/bin/cmake_を直接呼び出すことができます(またはラッパー関数をまったく使用しません)。そしてそれは愚かな単純です。

5
evadeflow

.bashrcファイルは これ のように構成できます。

関数cmakekdekdebuildを見てください。 BUILDおよびSRCenvを設定します。変数を作成し、必要に応じてこれらの関数を編集します。これは、srcDirではなくbuildDirでのみビルドされます

1
smitrp

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

今実行します:

. ./dotme

トップレベルのソースツリーでcmakeを実行しようとすると:

$ cmake .
CMAKE_DISABLE_IN_SOURCE_BUILD ON

CMakeFiles /またはCMakeCache.txtは生成されません。

ソース外のビルドを実行していて、初めてcmakeを実行する必要がある場合は、実際の実行可能ファイルを呼び出すだけです。

$ cd build
$ /usr/bin/cmake ..
0
androidin

ビルドを行う人/プロセスがディレクトリを読み取り専用にするだけです。ソース管理からディレクトリにチェックアウトし(ソース管理を使用していますよね?)、読み取り専用にする別のプロセスがあります。

0
Harper Shelby