Pregunta

Quiero evitar que las personas saturen nuestro árbol de origen con los archivos CMake generados ... y, lo que es más importante, no permitirles que pisen los Makefiles existentes que no forman parte del mismo proceso de compilación que nosotros re utilizando CMake para. (mejor no preguntar)

La forma en que se me ha ocurrido para hacer esto es tener algunas líneas en la parte superior de mi CMakeLists.txt , de la siguiente manera:

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

Sin embargo, hacerlo de esta manera parece demasiado detallado. Además, si intento una compilación en origen, se creará el directorio CMakeFiles / y el archivo CMakeCache.txt en el árbol de origen antes de que se genere el error.

¿Me estoy perdiendo una mejor manera de hacer esto?

¿Fue útil?

Solución

Creo que me gusta tu camino. La lista de correo de cmake hace un buen trabajo al responder este tipo de preguntas.

Como nota al margen: puedes crear un " cmake " Archivo ejecutable en el directorio que falla. Dependiendo de si o no ". & Quot; Está en su camino (en linux). Incluso podrías hacer un enlace simbólico / bin / falso.

En Windows, no estoy seguro de si se encuentra primero un archivo en su directorio actual o no.

Otros consejos

CMake tiene dos opciones no documentadas: CMAKE_DISABLE_SOURCE_CHANGES y 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;
}

Incluya una función como esta . Es similar a lo que haces con estas diferencias:

  1. Está encapsulado en una función, a la que se llama cuando se incluye el módulo PreventInSourceBuilds.cmake . Su CMakeLists.txt principal debe incluirlo:

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
    include(PreventInSourceBuilds)
    
  2. Utiliza get_filename_component () con el parámetro REALPATH eso resuelve los enlaces simbólicos antes de comparar las rutas.

En caso de que cambie el enlace de github, aquí está el código fuente del módulo (que debe colocarse en un PreventInSouceBuilds.cmake , en un directorio llamado CMake , en el ejemplo anterior) ):

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

Tengo una función de shell cmake () en mi .bashrc / .zshrc similar 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
}

Prefiero esta solución de ceremonia baja. Se deshizo de la queja más grande de mis colegas cuando cambiamos a CMake, pero no impide que las personas que realmente quieran hacer una compilación en la fuente / parte superior del árbol lo hagan. solo puede invocar / usr / bin / cmake directamente (o no usar la función de envoltura). Y es estúpido simple.

Puedes configurar tu archivo .bashrc como this

Mira las funciones cmakekde y kdebuild . Set BUILD y SRC env. Variables y edita estas funciones de acuerdo a tus necesidades. Esto se construirá solo en buildDir en lugar de srcDir

Para aquellos en Linux:

agregar a CMakeLists.txt de nivel superior:

set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)

cree un archivo 'dotme' en su nivel superior o añádalo a su .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

ahora ejecuta:

. ./dotme

cuando intenta ejecutar cmake en el árbol de fuentes de nivel superior:

$ cmake .
CMAKE_DISABLE_IN_SOURCE_BUILD ON

No se generan CMakeFiles / o CMakeCache.txt.

Cuando realice una compilación fuera de la fuente y necesita ejecutar cmake la primera vez, simplemente llame al ejecutable real:

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

Simplemente haga que el directorio sea de solo lectura para las personas / procesos que realizan las compilaciones. Tenga un proceso separado que compruebe el directorio desde el control de origen (está usando el control de origen, ¿verdad?), Luego lo hace de solo lectura.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top