CMake đầu ra / thư mục xây dựng


115

Tôi còn khá mới đối với CMake và đã đọc một vài hướng dẫn về cách sử dụng nó và đã viết một số đoạn mã CMake 50 dòng phức tạp để tạo một chương trình cho 3 trình biên dịch khác nhau. Điều này có thể kết luận tất cả kiến ​​thức của tôi trong CMake.

Bây giờ vấn đề của tôi là tôi có một số mã nguồn, có thư mục mà tôi không muốn chạm vào / gây rối khi tạo chương trình. Tôi muốn tất cả makecác tệp và thư mục CMake và đầu ra đều được chuyển vào ../Compile/, vì vậy tôi đã thay đổi một vài biến trong tập lệnh CMake của mình cho điều đó và nó hoạt động đôi khi tôi làm điều gì đó như thế này trên máy tính xách tay của mình:

Compile$ cmake ../src
Compile$ make

Với điều đó, tôi đã có một đầu ra sạch sẽ trong thư mục tôi đang ở ngay bây giờ, đó chính là thứ tôi đang tìm kiếm.

Bây giờ tôi đã chuyển sang một máy tính khác và biên dịch lại CMake 2.8.11.2, và tôi gần như trở lại hình vuông! Nó luôn luôn biên dịch thứ vào srcthư mục nơi chứa của tôi CMakeLists.txt.

Phần mà tôi chọn thư mục trong tập lệnh CMake của mình là:

set(dir ${CMAKE_CURRENT_SOURCE_DIR}/../Compile/)
set(EXECUTABLE_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(LIBRARY_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dir})
set(CMAKE_BUILD_FILES_DIRECTORY ${dir})
set(CMAKE_BUILD_DIRECTORY ${dir})
set(CMAKE_BINARY_DIR  ${dir})
SET(EXECUTABLE_OUTPUT_PATH ${dir})
SET(LIBRARY_OUTPUT_PATH ${dir}lib)
SET(CMAKE_CACHEFILE_DIR ${dir})

Và bây giờ nó luôn kết thúc bằng:

-- Build files have been written to: /.../src

Tui bỏ lỡ điều gì vậy?


4
Không cần thiết phải đặt tất cả các biến mà bạn đang cài đặt. CMake đặt chúng thành giá trị mặc định hợp lý. Bạn chắc chắn không nên sửa đổi CMAKE_BINARY_DIRhoặc CMAKE_CACHEFILE_DIR. Điều gì xảy ra nếu bạn xóa tất cả các set()cuộc gọi này và chỉ làm cd Compile; rm -rf *; cmake ../src?
Angew không còn tự hào về SO

5
Về cơ bản, miễn là bạn đang ở ngoài thư mục nguồn khi chạy CMake, nó sẽ không sửa đổi thư mục nguồn trừ khi CMakeList của bạn yêu cầu rõ ràng.
Angew không còn tự hào về SO

@Angew Cảm ơn bạn vì mẹo, thật bất ngờ! Tôi đã xóa tất cả những dòng đó và chỉ sử dụng cmake ../src và nó hoạt động như một sự quyến rũ! Điều này thật đáng ngạc nhiên vì tôi đã thử nó trước đây khi tôi lần đầu tiên học CMake và nó không hoạt động. Xin vui lòng đặt câu trả lời của bạn trong một trả lời chính thức cung cấp cho bạn các chất béo lớn dấu kiểm :)
Các Quantum Nhà vật lý học

1
Có gì cứu tôi đã nhận xét @ Adam Bowen rằng "bạn không thể tạo một out-of-nguồn xây dựng cho một thư mục nguồn với một trong nguồn xây dựng"
Aur Saraf

Câu trả lời:


60

Không cần thiết phải đặt tất cả các biến mà bạn đang cài đặt. CMake đặt chúng thành giá trị mặc định hợp lý. Bạn chắc chắn không nên sửa đổi CMAKE_BINARY_DIRhoặc CMAKE_CACHEFILE_DIR. Coi những thứ này là chỉ đọc.

Trước tiên, hãy xóa tệp bộ đệm ẩn có vấn đề hiện có khỏi thư mục src:

cd src
rm CMakeCache.txt
cd ..

Sau đó, loại bỏ tất cả các set()lệnh và thực hiện:

cd Compile
rm -rf *
cmake ../src

Miễn là bạn đang ở bên ngoài thư mục nguồn khi chạy CMake, nó sẽ không sửa đổi thư mục nguồn trừ khi CMakeList của bạn yêu cầu rõ ràng.

Khi bạn đã làm việc này, bạn có thể xem nơi CMake đặt mọi thứ theo mặc định và chỉ khi bạn không hài lòng với các vị trí mặc định (chẳng hạn như giá trị mặc định của EXECUTABLE_OUTPUT_PATH), chỉ sửa đổi những vị trí bạn cần. Và cố gắng thể hiện chúng tương đối so với CMAKE_BINARY_DIR, CMAKE_CURRENT_BINARY_DIR, PROJECT_BINARY_DIR, vv

Nếu bạn xem tài liệu CMake, bạn sẽ thấy các biến được phân chia thành các phần ngữ nghĩa. Ngoại trừ những trường hợp rất đặc biệt, bạn nên coi tất cả những gì được liệt kê trong "Biến cung cấp thông tin" là chỉ đọc trong CMakeLists.


2
Tôi bắt đầu sử dụng cmake với các bản dựng trong thư mục src ... kỹ thuật này ban đầu không thành công. Khi tôi đã xóa tất cả các tệp / bộ nhớ đệm cmake trong thư mục src, kỹ thuật này đã hoạt động. Cảm ơn!
Avi Tevet

18
Có lẽ tốt hơn là không nên khuyên sử dụng rm -rf *. Nó không đẹp nếu cd Compilethất bại ...
Roman

2
@Roman Tôi coi các ví dụ dòng lệnh như vậy khá nhiều mã giả. Nó ít dài dòng hơn và chính xác hơn là gõ "nhập thư mục Compile, xóa mọi thứ ở đó, sau đó chạy CMake với đường dẫn đến mã nguồn." Tôi giả định nhận thức và nhận định chung cơ bản của một phần người đọc.
Angew không còn tự hào về SO

@AviTevet: Tôi nghĩ đây là câu trả lời chính xác. Nếu có các tệp bộ đệm cmake từ một lệnh gọi cmake trước đó bên trong thư mục nguồn, bạn sẽ không yêu cầu cmake chọn một thư mục khác cho các tệp đã tạo, trừ khi bạn xóa tất cả các tệp cũ khỏi thư mục nguồn. Theo ý kiến ​​của tôi, hành vi khá hỏng của CMake. Tại sao bạn không viết câu trả lời khác?
Jo So

112

Có vẻ như bạn muốn một bản dựng ngoài nguồn . Có một số cách bạn có thể tạo bản dựng ngoài nguồn.

  1. Làm những gì bạn đang làm, chạy

    cd /path/to/my/build/folder
    cmake /path/to/my/source/folder

    mà sẽ gây cmake để tạo ra một cây xây dựng trong /path/to/my/build/foldercho cây nguồn trong /path/to/my/source/folder.

    Khi bạn đã tạo xong, cmake sẽ nhớ thư mục nguồn nằm ở đâu - vì vậy bạn có thể chạy lại cmake trên cây xây dựng với

    cmake /path/to/my/build/folder

    hoặc thậm chí

    cmake .

    nếu thư mục hiện tại của bạn đã là thư mục xây dựng.

  2. Đối với CMake 3.13 trở lên, hãy sử dụng các tùy chọn này để đặt nguồn và tạo thư mục

    cmake -B/path/to/my/build/folder -S/path/to/my/source/folder
  3. Đối với CMake cũ hơn, hãy sử dụng một số tùy chọn không có tài liệu để đặt nguồn và tạo thư mục :

    cmake -B/path/to/my/build/folder -H/path/to/my/source/folder

    sẽ thực hiện chính xác điều tương tự như (1), nhưng không phụ thuộc vào thư mục làm việc hiện tại.

CMake đặt tất cả các đầu ra của nó trong cây xây dựng theo mặc định, vì vậy trừ khi bạn đang sử dụng tự do ${CMAKE_SOURCE_DIR}hoặc ${CMAKE_CURRENT_SOURCE_DIR}trong các tệp cmake của mình, nó sẽ không chạm vào cây nguồn của bạn .

Điều lớn nhất có thể xảy ra là nếu trước đó bạn đã tạo một cây xây dựng trong cây nguồn của mình (tức là bạn có một bản dựng trong nguồn ). Khi bạn đã hoàn thành việc này, phần thứ hai của (1) ở trên sẽ bắt đầu và cmake không thực hiện bất kỳ thay đổi nào đối với nguồn hoặc vị trí xây dựng. Do đó, bạn không thể tạo một bản dựng ngoài nguồn cho một thư mục nguồn với một bản dựng trong nguồn . Bạn có thể sửa lỗi này khá dễ dàng bằng cách xóa (tối thiểu) CMakeCache.txtkhỏi thư mục nguồn. Có một số tệp khác (chủ yếu trong CMakeFilesthư mục) mà CMake tạo ra mà bạn cũng nên xóa, nhưng những tệp này sẽ không khiến cmake coi cây nguồn là cây xây dựng.

Vì các bản dựng ngoài nguồn thường được mong muốn hơn các bản dựng trong nguồn, bạn có thể muốn sửa đổi bản dựng của mình để yêu cầu các bản dựng ngoài nguồn:

# Ensures that we do an out of source build

MACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD MSG)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${CMAKE_BINARY_DIR}" insource)
     GET_FILENAME_COMPONENT(PARENTDIR ${CMAKE_SOURCE_DIR} PATH)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${PARENTDIR}" insourcesubdir)
    IF(insource OR insourcesubdir)
        MESSAGE(FATAL_ERROR "${MSG}")
    ENDIF(insource OR insourcesubdir)
ENDMACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD)

MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
    "${CMAKE_PROJECT_NAME} requires an out of source build."
)

Macro trên đến từ một mô-đun thường được sử dụng có tên MacroOutOfSourceBuild. Có rất nhiều nguồn MacroOutOfSourceBuild.cmaketrên google nhưng tôi dường như không thể tìm thấy tài liệu gốc và nó đủ ngắn để đưa vào đây đầy đủ.

Thật không may, cmake thường ghi một vài tệp vào thời điểm macro được gọi, vì vậy mặc dù nó sẽ ngăn bạn thực sự thực hiện xây dựng, bạn vẫn sẽ cần phải xóa CMakeCache.txtCMakeFiles.

Bạn có thể thấy hữu ích khi đặt các đường dẫn mà tệp nhị phân, thư viện được chia sẻ và thư viện tĩnh được ghi vào - trong trường hợp đó, hãy xem cách tôi tạo đầu ra cmake thành dir 'bin'? (tuyên bố từ chối trách nhiệm, tôi có câu trả lời được bình chọn nhiều nhất cho câu hỏi đó ... nhưng đó là cách tôi biết về nó).


Trên thực tế các tùy chọn để thiết lập các thư mục nguồn là -S, không-H
smac89

@ smac89 Cảm ơn! Có vẻ như họ đã ghi lại chúng trong 3.13 - Tôi đã cập nhật câu trả lời để phản ánh CMake hiện đại.
Adam Bowen

8

Chuyển nhận xét của tôi thành câu trả lời:

Trong trường hợp có ai đó đã làm những gì tôi đã làm, bắt đầu bằng cách đặt tất cả các tệp xây dựng trong thư mục nguồn:

cd src
cmake .

cmake sẽ đặt một bó xây dựng các file và các file cache ( CMakeCache.txt, CMakeFiles, cmake_install.cmake, vv) trong srcdir.

Để chuyển sang bản dựng ngoài nguồn, tôi phải xóa tất cả các tệp đó. Sau đó, tôi có thể làm những gì @Angew đề xuất trong câu trả lời của anh ấy:

mkdir -p src/build
cd src/build
cmake ..

7

Kể từ CMake Wiki :

CMAKE_BINARY_DIR nếu bạn đang xây dựng trong nguồn, đây giống như CMAKE_SOURCE_DIR, nếu không thì đây là thư mục cấp cao nhất của cây xây dựng của bạn

So sánh hai biến này để xác định xem bản dựng ngoài nguồn có được bắt đầu hay không


6

Bạn không nên dựa vào tên dir xây dựng được mã hóa cứng trong tập lệnh của mình, vì vậy dòng với ../Compilephải được thay đổi.

Đó là bởi vì nó sẽ tùy thuộc vào người dùng nơi biên dịch.

Thay vì điều đó, hãy sử dụng một trong các biến xác định trước: http://www.cmake.org/Wiki/CMake_Useful_Variables (tìm kiếm CMAKE_BINARY_DIRCMAKE_CURRENT_BINARY_DIR)


2
đây chính là những gì tôi đang tìm kiếm - CMAKE_CURRENT_BINARY_DIR, thường sẽ cho biết về đường dẫn xây dựng nhị phân hiện tại. Có thể được sử dụng để thiết lập các bản dựng libs / bin phụ thuộc.
ký sinh trùng
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.