Pergunta

Eu quero impedir as pessoas de desordenar nossa árvore fonte com arquivos de CEfectue gerados ... e, mais importante, não permitir-los de pisar Makefiles existente que não fazem parte do mesmo processo de construção estamos usando CMake para. (Melhor não perguntar)

A maneira que eu tenho chegar a fazer isso é ter algumas linhas no topo da minha CMakeLists.txt, da seguinte forma:

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

No entanto, fazê-lo desta forma parece muito detalhado. Além disso, se eu tentar uma compilação in-source ainda cria o diretório CMakeFiles/ eo arquivo CMakeCache.txt na árvore de origem antes de o erro é lançado.

Am I faltando uma maneira melhor de fazer isso?

Foi útil?

Solução

Eu acho que como o seu caminho. A lista cmake discussão faz um bom trabalho de responder esses tipos de perguntas.

Como uma nota lateral: você pode criar um "cmake" arquivo executável no diretório que falha. Dependendo ou não "" está em seu caminho (no Linux). Você pode até mesmo ligar simbolicamente / bin / false.

No Windows, eu não tenho certeza se um arquivo em seu diretório atual é encontrado pela primeira vez ou não.

Outras dicas

CMake tem duas opções não documentadas: 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;
}

Incluir uma função como esta . É semelhante ao que você faz com estas diferenças:

  1. Ele é encapsulado em uma função, que é chamado quando você incluir o módulo PreventInSourceBuilds.cmake. Seu principal CMakeLists.txt deve incluí-lo:

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
    include(PreventInSourceBuilds)
    
  2. Ele usa get_filename_component () com realpath parâmetro que resolve links simbólicos antes de comparar os caminhos.

Em caso do link github mudanças, aqui está o código fonte do módulo (que deve ser colocado em um PreventInSouceBuilds.cmake, em um diretório chamado CMake, no exemplo acima):

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

Eu tenho uma função shell cmake() na minha .bashrc / .zshrc semelhante a esta:

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
}

Eu prefiro esta solução de baixo cerimônia. Ele se livrou de maior queixa dos meus colegas quando nós mudamos para CMake, mas não impede que as pessoas que realmente quer fazer um / build in-fonte top-of-árvore de fazê-lo, eles pode simplesmente invocar /usr/bin/cmake diretamente (ou não utilizar a função de mensagens publicitárias em todos). E é estúpida simples.

Você pode configurar seu arquivo .bashrc como esta

Olhe para as funções cmakekde e kdebuild . Set construir e SRC env. variáveis ??e editar essas funções de acordo com as suas necessidades. Isto irá construir apenas em builddir em vez de SRCDIR

Para aqueles em Linux:

Adicione aos de nível superior CMakeLists.txt:

set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)

criar um arquivo 'dotme' em seu de nível superior ou adicionar ao seu .bashrc (globalmente):

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

Agora execute:

. ./dotme

quando você tenta executar cmake na árvore de origem de nível superior:

$ cmake .
CMAKE_DISABLE_IN_SOURCE_BUILD ON

No CMakeFiles / ou CMakeCache.txt será gerado.

Ao fazer out-of-source de construção e você precisa executar cmake primeira vez apenas chamar o real executável:

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

Basta fazer o diretório somente leitura pelas pessoas / processos fazendo as compilações. Ter um processo separado que os controlos fora para o diretório do controle de origem (você estiver usando o controle de origem, certo?), Então torna somente leitura.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top