С cmake, как бы вы отключили сборку в исходном коде? - PullRequest
39 голосов
/ 30 июля 2009

Я хочу запретить людям загромождать наше исходное дерево созданными файлами CMake ... и, что более важно, запретить им наступать на существующие Makefiles, которые не являются частью того же процесса сборки, для которого мы используем CMake. (лучше не спрашивать)

Я придумал для этого несколько строк в верхней части моего 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 в дереве исходного кода до появления ошибки.

Мне не хватает лучшего способа сделать это?

Ответы [ 7 ]

49 голосов
/ 25 апреля 2012

CMake имеет две недокументированные опции: 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.

/ дом / Селиванов / CMake-2.8.8 / Источник / 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;
}
7 голосов
/ 25 марта 2014

Включите такую ​​функцию, как эта . Это похоже на то, что вы делаете с этими различиями:

  1. Он инкапсулирован в функцию, которая вызывается при включении модуля PreventInSourceBuilds.cmake. Ваш основной CMakeLists.txt должен включать его:

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
    include(PreventInSourceBuilds)
    
  2. Используется get_filename_component () с параметром REALPATH, который разрешает символические ссылки перед сравнением путей.

В случае изменения ссылки на github, вот исходный код модуля (который должен быть помещен в PreventInSouceBuilds.cmake, в каталог с именем 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()
5 голосов
/ 13 октября 2013

У меня есть cmake() функция оболочки в моем .bashrc / .zshrc, похожая на эту:

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, но это не мешает людям, которые действительно хотят сделать сборку in-source / top-of-tree - они могут просто вызовите /usr/bin/cmake напрямую (или вообще не используйте функцию обертки). И это глупо просто.

4 голосов
/ 30 июля 2009

Я думаю, мне нравится твой путь. Список рассылки cmake хорошо отвечает на вопросы такого типа.

В качестве примечания: вы можете создать исполняемый файл "cmake" в каталоге, который завершится неудачно. В зависимости от того, "или нет". находится на их пути (на Linux). Вы могли бы даже символическую ссылку /bin/false.

В Windows я не уверен, что файл в вашем текущем каталоге найден первым или нет.

1 голос
/ 17 ноября 2014

Для тех, кто в 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 ..
1 голос
/ 19 декабря 2011

Вы можете настроить свой файл .bashrc как этот

Посмотрите на функции cmakekde и kdebuild . Установите BUILD и SRC env. переменные и редактируйте эти функции в соответствии с вашими потребностями. Это будет построено только в buildDir , а не srcDir

0 голосов
/ 30 июля 2009

Просто сделайте каталог доступным только для чтения людьми / процессами, выполняющими сборку. Создайте отдельный процесс, который проверяет каталог из системы контроля версий (вы используете систему контроля версий, верно?), А затем делает ее доступной только для чтения

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...