Подтвердить что ты не робот

С cmake, как бы отключить встроенные сборки?

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

Я пропустил лучший способ сделать это?

4b9b3361

Ответ 1

Думаю, мне нравится ваш путь. Список рассылки cmake хорошо справляется с ответом на эти типы вопросов.

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

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

Ответ 2

У 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)

-

[email protected]:~/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;
}

Ответ 3

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

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

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
    include(PreventInSourceBuilds)
    
  • Он использует 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()

Ответ 4

У меня есть функция оболочки 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 build из этого, они могут просто вызвать /usr/bin/cmake напрямую (или вообще не использовать функцию обертки). И это глупо просто.

Ответ 5

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

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

Ответ 6

Для пользователей 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 ..

Ответ 7

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