Question

Je veux empêcher les personnes d'encombrer notre arborescence de sources avec des fichiers CMake générés ... et, plus important encore, de ne pas les empêcher de marcher sur des Makefiles existants qui ne font pas partie du même processus de construction que nous ' re utiliser CMake pour. (mieux vaut ne pas demander)

Pour ce faire, voici quelques lignes en haut de mon CMakeLists.txt , comme suit:

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

Cependant, le faire de cette manière semble trop prolixe. En outre, si j'essaie une génération in-source, le répertoire CMakeFiles / et le fichier CMakeCache.txt sont toujours créés dans l'arborescence source avant que l'erreur ne soit renvoyée. / p>

Me manque-t-il d'une meilleure façon de faire cela?

Était-ce utile?

La solution

Je pense que j'aime votre façon de faire. La liste de diffusion cmake fait un bon travail pour répondre à ce type de questions.

Remarque: vous pouvez créer un "cmake". fichier exécutable dans le répertoire qui échoue. Selon que vous l'utilisiez ou pas. est sur leur chemin (sur linux). Vous pouvez même créer un lien symbolique / bin / false.

Sous Windows, je ne sais pas si un fichier de votre répertoire actuel est trouvé en premier ou non.

Autres conseils

CMake a deux options non documentées: CMAKE_DISABLE_SOURCE_CHANGES et 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;
}

Incluez une fonction comme celle-ci . Cela ressemble à ce que vous faites avec ces différences:

  1. Il est encapsulé dans une fonction appelée lorsque vous incluez le module PreventInSourceBuilds.cmake . Votre CMakeLists.txt principal doit l’inclure:

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
    include(PreventInSourceBuilds)
    
  2. Il utilise get_filename_component () avec le paramètre REALPATH qui résout les liens symboliques avant de comparer les chemins.

Si le lien github change, voici le code source du module (qui doit être placé dans un PreventInSouceBuilds.cmake , dans un répertoire appelé CMake , dans l'exemple ci-dessus. ):

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

J'ai une fonction shell cmake () dans mon .bashrc / .zshrc similaire à celui-ci:

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
}

Je préfère cette solution de cérémonie basse. Nous nous sommes débarrassés de la plainte majeure de mes collègues lorsque nous sommes passés à CMake, mais cela n'empêche pas les personnes qui veulent vraiment de créer une construction in-source / top-of-tree - elles pouvez simplement appeler / usr / bin / cmake directement (ou ne pas utiliser la fonction wrapper du tout). Et c'est stupide simple.

Vous pouvez configurer votre fichier .bashrc comme celui-ci

Regardez les fonctions cmakekde et kdebuild . Réglez BUILD et SRC env. variables et éditez ces fonctions selon vos besoins. Cela générera uniquement dans buildDir plutôt que srcDir

Pour les utilisateurs de Linux:

ajouter au niveau supérieur CMakeLists.txt:

set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)

créez un fichier 'dotme' dans votre niveau supérieur ou ajoutez-le à votre fichier .bashrc (globalement):

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

exécutez maintenant:

. ./dotme

lorsque vous essayez d'exécuter cmake dans l'arborescence source de niveau supérieur:

$ cmake .
CMAKE_DISABLE_IN_SOURCE_BUILD ON

Aucun fichier CMakeFiles / ou CMakeCache.txt n'est généré.

Lorsque vous effectuez une compilation hors source et que vous devez exécuter cmake pour la première fois, appelez simplement l'exécutable actuel:

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

Assurez-vous que le répertoire est en lecture seule pour les personnes / processus effectuant les constructions. Avoir un processus distinct qui extrait le répertoire à partir du contrôle de source (vous utilisez le contrôle de source, n'est-ce pas?), Puis le rend en lecture seule.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top