Domanda

Voglio impedire alle persone di ingombrare il nostro albero dei sorgenti con i file CMake generati ... e, cosa più importante, impedire loro di calpestare i Makefile esistenti che non fanno parte dello stesso processo di compilazione che abbiamo ' stai usando CMake per. (meglio non chiedere)

Il modo in cui mi sono inventato di fare questo è di avere alcune righe in cima al mio CMakeLists.txt , come segue:

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}")

Tuttavia, farlo in questo modo sembra troppo prolisso. Inoltre, se provo una build in-source, crea ancora la directory CMakeFiles / e il file CMakeCache.txt nella struttura di origine prima che l'errore venga generato.

Mi sto perdendo un modo migliore per farlo?

È stato utile?

Soluzione

Penso che mi piaccia la tua strada. La mailing list di cmake fa un buon lavoro nel rispondere a questo tipo di domande.

Come nota a margine: puoi creare un " cmake " file eseguibile nella directory che non riesce. A seconda che sia ". & Quot; è nel loro percorso (su Linux). Potresti anche symlink / bin / false.

In Windows, non sono sicuro che sia stato trovato prima un file nella directory corrente.

Altri suggerimenti

CMake ha due opzioni non documentate: CMAKE_DISABLE_SOURCE_CHANGES e 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;
}

Includi una funzione come questa . È simile a quello che fai con queste differenze:

  1. È incapsulato in una funzione, che viene chiamata quando si include il modulo PreventInSourceBuilds.cmake . Il tuo CMakeLists.txt principale deve includerlo:

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
    include(PreventInSourceBuilds)
    
  2. Utilizza get_filename_component () con il parametro REALPATH che risolve i collegamenti simbolici prima di confrontare i percorsi.

Nel caso in cui il link github cambi, ecco il codice sorgente del modulo (che dovrebbe essere inserito in un PreventInSouceBuilds.cmake , in una directory chiamata CMake , nell'esempio precedente ):

#
# 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()

Ho una funzione di shell cmake () nel mio .bashrc / .zshrc simile a questo:

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
}

Preferisco questa soluzione per cerimonie basse. Si è sbarazzato della più grande lamentela dei miei colleghi quando siamo passati a CMake, ma non impedisce alle persone che veramente vogliono fare una build in-source / top-of-tree dal farlo & # 8212 ; possono semplicemente invocare / usr / bin / cmake direttamente (o non usare affatto la funzione wrapper). Ed è stupido semplice.

Puoi configurare il tuo file .bashrc come questo

Guarda le funzioni cmakekde e kdebuild . Imposta BUILD e SRC env. variabili e modificare queste funzioni in base alle proprie esigenze. Questo verrà creato solo in buildDir anziché in srcDir

Per quelli su Linux:

aggiungi a CMakeLists.txt di livello superiore:

set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)

crea un file 'dotme' nel tuo livello principale o aggiungi al tuo .bashrc (a livello globale):

#!/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

ora esegui:

. ./dotme

quando si tenta di eseguire cmake nell'albero dei sorgenti di livello superiore:

$ cmake .
CMAKE_DISABLE_IN_SOURCE_BUILD ON

Nessun CMakeFiles / o CMakeCache.txt viene generato.

Quando esegui build out-of-source e devi eseguire cmake per la prima volta, chiama semplicemente l'eseguibile effettivo:

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

Rendi la directory di sola lettura da parte delle persone / dei processi che eseguono le build. Avere un processo separato che verifichi nella directory dal controllo del codice sorgente (si sta utilizzando il controllo del codice sorgente, giusto?), Quindi lo rende di sola lettura.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top