2009-07-30 19 views
35

Tôi muốn không cho phép mọi người làm lộn xộn cây nguồn của chúng tôi với các tệp CMake được tạo ... và quan trọng hơn, không cho phép họ bước trên Makefiles hiện có không thuộc cùng một quá trình xây dựng mà chúng tôi đang sử dụng CMake. (Tốt nhất là không hỏi)Với cmake, bạn sẽ tắt các bản dựng trong nguồn như thế nào?

Con đường tôi đã đưa ra để làm điều này là để có một vài dòng ở đầu CMakeLists.txt tôi, như sau:

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

Tuy nhiên, làm nó theo cách này có vẻ quá dài dòng. Ngoài ra, nếu tôi thử một bản dựng trong nguồn, nó vẫn tạo thư mục CMakeFiles/ và tệp CMakeCache.txt trong cây nguồn trước khi lỗi được ném.

Tôi có thiếu cách nào tốt hơn để thực hiện việc này không?

+0

Chúng tôi làm điều đó một cách chính xác như thế này. – JesperE

+2

Đây là giải pháp tốt nhất mà tôi đã tìm thấy cho đến nay. Bạn có thể làm cho thông điệp có nhiều thông tin hơn, mặc dù: thông báo (FATAL_ERROR "Xây dựng nguồn trong không được phép. Tạo một thư mục riêng biệt để xây dựng: \ nmkdir build; cd build; cmake .. \ nTrước đó, xóa các tệp đã được tạo: \ nrm -rf CMakeCache.txt CMakeFiles ") – Tronic

Trả lời

3

Tôi nghĩ tôi thích cách của bạn. Danh sách gửi thư của cmake thực hiện tốt công việc trả lời các loại câu hỏi này.

Lưu ý: bạn có thể tạo tệp thực thi "cmake" trong thư mục không thành công. Tùy thuộc vào việc có hay không "." nằm trong đường dẫn của họ (trên Linux). Bạn thậm chí có thể symlink/bin/false.

Trong cửa sổ, tôi không chắc liệu tệp trong thư mục hiện tại của bạn có được tìm thấy đầu tiên hay không.

+0

Ý tưởng hay; Tôi sẽ giải thích rằng như đặt một cái gì đó vào $ PATH sẽ chặn cuộc gọi để gọi lệnh - hoặc chỉ đơn giản là một kịch bản riêng biệt mà sẽ quấn nó. Hoặc có thể là bí danh chuẩn. Trừ khi có một cách 'bản xứ' để làm điều này trong cmake tôi nghĩ đó là con đường để đi. Và vâng, tôi tin vào Windows '.' là hoàn toàn trên $ PATH; trên UNIX nó không phải là, nhưng chúng tôi luôn có thể đặt một wrapper cmake ở một nơi khác trong $ PATH. – mpontillo

+20

Loại nutter nào có. trên con đường của họ? – Draemon

+1

Ý tưởng "cmake" giả sẽ không hoạt động theo mặc định, như thường lệ "." sẽ không ở trong con đường của họ. –

0

Chỉ cần làm cho thư mục chỉ đọc bởi những người/quy trình thực hiện các bản dựng. Có một quá trình riêng biệt kiểm tra thư mục từ kiểm soát nguồn (bạn đang sử dụng điều khiển nguồn, phải không?), Sau đó làm cho nó chỉ đọc.

+0

Cảm ơn câu trả lời. Thật không may, vì cách thức kiểm soát và hệ thống nguồn của chúng tôi hoạt động, sẽ không thực tế nếu thực hiện theo cách này. Tôi đang tìm một giải pháp tổng quát hơn. – mpontillo

1

Bạn có thể cấu hình file .bashrc của bạn như this one

Nhìn vào các chức năng cmakekdekdebuild. Đặt BUILD và SRC env. biến và chỉnh sửa các chức năng này theo nhu cầu của bạn. Điều này sẽ xây dựng chỉ trong buildDir hơn srcDir

46

CMake có hai lựa chọn không có giấy tờ: CMAKE_DISABLE_SOURCE_CHANGESCMAKE_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/Nguồn/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

Tuyệt vời! Đây sẽ là câu trả lời được chấp nhận. – Nav

+4

Thật không may điều này không ngăn cản CMake tạo CMakeCache.txt và CMakeFiles/và do đó nó không tốt hơn là báo hiệu lỗi (và tệ hơn là nó đưa ra một thông điệp khó hiểu). – Tronic

+1

Chỉ cần tạo một thư mục có tên "CMakeCache.txt" để tránh tạo tệp bộ nhớ cache. –

5

Tôi có một chức năng cmake() vỏ trong của tôi .bashrc/.zshrc tương tự như thế này:

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 
} 

Tôi thích giải pháp lễ thấp này. Nó đã loại bỏ khiếu nại lớn nhất của đồng nghiệp khi chúng tôi chuyển sang CMake, nhưng nó không ngăn cản những người thực hiện thực sự muốn thực hiện việc xây dựng nguồn/top-tree từ việc làm như vậy — họ chỉ có thể gọi trực tiếp /usr/bin/cmake (hoặc không sử dụng hàm bao bọc). Và nó là ngu ngốc đơn giản.

+0

Vấn đề với điều đó là không di động và không rõ ràng trong các nguồn. –

+0

Tôi thích giải pháp của bạn. Nó đơn giản và giải quyết vấn đề. – aaragon

7

Bao gồm một chức năng như this one.Điều này tương tự như những gì bạn làm với những khác biệt này:

  1. Được đóng gói trong một hàm, được gọi khi bạn bao gồm mô-đun PreventInSourceBuilds.cmake. CMakeLists.txt chính của bạn phải bao gồm nó:

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/CMake) 
    include(PreventInSourceBuilds) 
    
  2. Nó sử dụng get_filename_component() với tham số realpath mà giải quyết symlink trước khi so sánh những con đường.

Trong trường hợp những thay đổi liên kết github, đây là mã nguồn mô-đun (mà phải được đặt trong một PreventInSouceBuilds.cmake, trong một thư mục gọi là CMake, trong ví dụ trên):

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

Cảm ơn. Tôi đã chỉnh sửa câu trả lời này để bao gồm mã nguồn. Tôi thích cách tiếp cận này. – mpontillo

1

Đối với những người trên Linux:

thêm vào top-level CMakeLists.txt:

set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) 

c reate một file 'dotme' ở cấp cao nhất của bạn hoặc thêm vào .bashrc của bạn (toàn cầu):

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

bây giờ chạy:

. ./dotme 

khi bạn cố gắng chạy cmake trong nguồn cấp cao nhất cây:

$ cmake . 
CMAKE_DISABLE_IN_SOURCE_BUILD ON 

Không có CMakeFiles/hoặc CMakeCache.txt được tạo.

Khi làm out-of-nguồn xây dựng và bạn cần phải chạy cmake lần đầu tiên chỉ cần gọi thực thi thực tế:

$ cd build 
$ /usr/bin/cmake .. 
Các vấn đề liên quan