2009-07-30 11 views
35

Chcę uniemożliwić ludziom zaśmiecanie naszego drzewa źródłowego wygenerowanymi plikami CMake ... i, co ważniejsze, zabronić im wchodzenia na istniejące Makefiles, które nie są częścią tego samego procesu kompilacji, dla którego używamy CMake. (Najlepiej nie pytać)Z cmake, w jaki sposób wyłączyć kompilacje w źródle?

sposób mam wymyślić, aby to zrobić, aby mieć kilka linii na szczycie mojej CMakeLists.txt, co następuje:

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

jednak robi to w ten sposób wydaje zbyt szczegółowe. Ponadto, jeśli spróbuję kompilacji w źródle, nadal tworzy ona katalog CMakeFiles/ i plik CMakeCache.txt w drzewie źródłowym, zanim zostanie zgłoszony błąd.

Czy brakuje mi lepszego sposobu na zrobienie tego?

+0

robimy to dokładnie w ten sposób. – JesperE

+2

To najlepsze rozwiązanie, jakie dotychczas znalazłem. Możesz jednak uczynić wiadomość bardziej informatywną: message (FATAL_ERROR "Kompilacje In-source są niedozwolone. Utwórz osobny folder do budowania: \ nmkdir kompilacja; cd kompilacja; cmake .. \ nPrzed tym usuń pliki już utworzone: \ nrm -rf CMakeCache.txt CMakeFiles ") – Tronic

Odpowiedz

3

Myślę, że podoba mi się sposób. Lista mailingowa cmake sprawdza się dobrze w odpowiadaniu na tego typu pytania.

Na marginesie: można utworzyć plik wykonywalny "cmake" w katalogu, który się nie powiedzie. W zależności od tego, czy ".", Czy nie. jest na ich drodze (na Linuksie). Możesz nawet użyć dowiązania symbolicznego/bin/false.

W systemie Windows nie jestem pewien, czy plik w bieżącym katalogu zostanie znaleziony jako pierwszy.

+0

Dobry pomysł; Zinterpretuję to jako umieszczenie czegoś na ścieżce $ PATH, która przechwyci wywołanie cmake - lub po prostu osobny skrypt, który go zawinie. A może standardowy alias. O ile nie ma "natywnego" sposobu na zrobienie tego w cmake, myślę, że to jest droga. I tak, wierzę w Windows ". jest domyślnie w zmiennej $ PATH; w systemie UNIX nie jest, ale zawsze możemy umieścić wrapper cmake gdzieś indziej w $ PATH. – mpontillo

+20

Co to za nutter. na ich drodze? – Draemon

+1

Fałszywy pomysł "cmake" nie będzie działał domyślnie, jak zwykle "." nie będzie na ich drodze. –

0

Po prostu utwórz katalog tylko do odczytu przez ludzi/procesy tworzące kompilacje. Czy masz oddzielny proces, który sprawdza w katalogu z poziomu kontroli źródła (korzystasz z kontroli źródła, prawda?), A następnie czyni go tylko do odczytu.

+0

Dzięki za odpowiedź. Niestety, ze względu na sposób, w jaki działa nasza kontrola i system źródłowy, niepraktyczne byłoby robienie tego w ten sposób. Szukałem bardziej ogólnego rozwiązania. – mpontillo

1

Można skonfigurować plik .bashrc jak this one

spojrzeć na funkcje cmakekde i kdebuild. Ustaw BUILD i SRC env. zmienne i edytuj te funkcje zgodnie z Twoimi potrzebami. Pozwoli to budować tylko w buildDir zamiast SRCDIR

46

CUpewnij ma dwa nieudokumentowane opcje: CMAKE_DISABLE_SOURCE_CHANGES i 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/Źródło/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; 
} 
+1

Awesome! To powinna być zaakceptowana odpowiedź. – Nav

+4

Niestety nie uniemożliwia to CMake tworzenia CMakeCache.txt i CMakeFiles/i dlatego nie jest to lepsze niż sygnalizowanie błędu (i jest gorsze w tym, że daje tajemniczy komunikat). – Tronic

+1

Wystarczy utworzyć katalog o nazwie "CMakeCache.txt", aby uniknąć tworzenia pliku pamięci podręcznej. –

5

Mam funkcji cmake() powłoki w moim .bashrc/.zshrc podobny do tego:

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 
} 

Wolę tę niską rozwiązanie ceremonii. Pozbyłem się największej skargi moich kolegów, kiedy przełączyliśmy się na CMake, ale nie przeszkadza to, że ludzie, którzy chcą chcieć zrobić kompilację wewnątrz-źródłową/szczytową drzewa, robią to - mogą po prostu wywołać /usr/bin/cmake bezpośrednio (lub w ogóle nie korzystać z funkcji opakowania). I jest to proste: głupiutki.

+0

Problem polega na tym, że nie jest przenośny i nie jest jawny w źródłach. –

+0

Podoba mi się twoje rozwiązanie. To proste i rozwiązuje problem. – aaragon

7

Dołącz funkcję podobną do this one.Jest ona podobna do tego, co zrobić z tymi różnicami:

  1. Jest zamknięty w funkcji, która jest wywoływana, kiedy to moduł PreventInSourceBuilds.cmake. Twoim głównym CMakeLists.txt musi obejmować go:

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake) 
    include(PreventInSourceBuilds) 
    
  2. Wykorzystuje get_filename_component() parametrem realpath która rozwiązuje dowiązania przed porównaniem ścieżki.

W przypadku zmiany Link GitHub, oto kod źródłowy modułu (który powinien być umieszczony w PreventInSouceBuilds.cmake, w katalogu o nazwie CMake, w powyższym przykładzie):

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

Dzięki. Edytowałem tę odpowiedź, aby dołączyć kod źródłowy. Podoba mi się to podejście. – mpontillo

1

Dla tych na Linux:

dodać do najwyższego poziomu CMakeLists.txt:

set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) 

c Reate plik „dotme” w górnym poziomie lub dodać do swojego .bashrc (globalnie):

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

teraz uruchomić:

. ./dotme 

podczas próby uruchomienia cmake w źródle najwyższego poziomu drzewo:

$ cmake . 
CMAKE_DISABLE_IN_SOURCE_BUILD ON 

Nie jest generowany plik CMakeFiles/lub CMakeCache.txt.

Podczas out-of-źródła budować i trzeba uruchomić cmake raz pierwszy po prostu zadzwoń rzeczywisty wykonywalny:

$ cd build 
$ /usr/bin/cmake .. 
Powiązane problemy