Tự động thêm tất cả các tệp trong một thư mục vào mục tiêu bằng CMake?


163

Tôi đang xem xét chuyển đổi một dự án đa nền tảng từ các hệ thống quản lý xây dựng riêng biệt trong Visual C ++, XCode và makefiles sang CMake.

Một tính năng thiết yếu tôi cần là tự động thêm tất cả các tệp trong một thư mục vào mục tiêu. Mặc dù điều này dễ thực hiện với make, nhưng nó không dễ thực hiện với Visual C ++ và XCode (sửa tôi nếu tôi sai). Có thể làm điều đó trực tiếp trong CMake không? Làm sao?


Btw. trong Visual Studio, ít nhất là trong các dự án C #, có một nút thanh công cụ trong trình thám hiểm dự án, được đặt tên hiển thị tất cả các tệp. Nó làm cho tất cả các thư mục con của một dự án hiển thị, bị mờ đi nếu chúng không chứa bất kỳ tệp nào được bao gồm một cách hợp lý trong dự án. Bạn có thể bao gồm các thư mục này thông qua menu ngữ cảnh, bao gồm tất cả các tệp nguồn bên trong chúng, theo cách đệ quy :)
yeoman

Câu trả lời:


228

Điều đó là có thể. Ví dụ file(GLOB:

cmake_minimum_required(VERSION 2.8)

file(GLOB helloworld_SRC
    "*.h"
    "*.cpp"
)

add_executable(helloworld ${helloworld_SRC})

Lưu ý rằng điều này đòi hỏi tay lại chạy về cmakenếu một tập tin nguồn được thêm vào hoặc gỡ bỏ, kể từ khi xây dựng hệ thống tạo ra không biết khi nào để hỏi CMake tái sinh, và làm nó ở mọi xây dựng sẽ tăng thời gian xây dựng.


11
Một cách khác để cmake chạy lại thủ công là chạm vào tệp CMakeLists.txt trước khi chạy make.
Seamus Connor


8
> "Chúng tôi không khuyên bạn nên sử dụng GLOB để thu thập danh sách các tệp nguồn từ cây nguồn của bạn. Nếu không có tệp CMakeLists.txt thay đổi khi một nguồn được thêm hoặc xóa thì hệ thống xây dựng được tạo không thể biết khi nào nên yêu cầu CMake tạo lại." Điều này không còn được khuyến nghị trong các tài liệu CMAKE3.7 được liên kết bởi Hand1Cloud
gấp ba

4
Thay thế cho GLOB là gì?
Shayne

13
Một cách tốt hơn kể từ v3.1 được đề xuất ở đây: target_source () crascit.com/2016/01/13/iêu
Sheen

34

Câu trả lời của Kleist chắc chắn có tác dụng, nhưng có một cảnh báo quan trọng:

Khi bạn viết Makefilethủ công, bạn có thể tạo một SRCSbiến bằng cách sử dụng hàm để chọn tất cả .cpp.htệp. Nếu một tệp nguồn sau đó được thêm vào, chạy lại makesẽ bao gồm nó.

Tuy nhiên, CMake (với một lệnh như file(GLOB ...)) sẽ tạo một danh sách tệp rõ ràng và đặt nó trong phần tự động tạo Makefile. Nếu bạn có một tệp nguồn mới, bạn sẽ cần phải tạo Makefilelại bằng cách chạy lại cmake.

chỉnh sửa: Không cần xóa Makefile.


4
Không thể đơn giản là chạy lại, mà nên xóa / sửa đổi Makefile lỗi thời?
Ethan

25
Đây không phải là một câu trả lời, đó là một nhận xét về câu trả lời của @ Kleist.
Neowizard

3
@Neowizard không theo thuật ngữ Stackoverflow.
kara deniz

1
Nhận xét này là tốt, nhưng nó là "tiêu chuẩn", phải không? Người hỏi đã sử dụng cmake rồi, vì vậy việc gợi ý làm cho có thể "thông minh hơn" không hữu ích.
frankliuao 30/03/2017

Vì vậy, có cách nào để thêm các tệp nguồn mới và sau đó xây dựng mà không chạy lại cmake?
artin

6

Gia hạn cho câu trả lời @Kleist :

Do CMake 3.12 tùy chọn bổ sung CONFIGURE_DEPENDS được hỗ trợ bởi các lệnh file(GLOB)file(GLOB_RECURSE). Với tùy chọn này, không cần phải chạy lại thủ công CMake sau khi thêm / xóa tệp nguồn trong thư mục - CMake sẽ tự động chạy lại trong quá trình xây dựng dự án tiếp theo.

Tuy nhiên, tùy chọn CONFIGURE_DEPENDS ngụ ý rằng thư mục tương ứng sẽ được kiểm tra lại mỗi khi yêu cầu xây dựng , vì vậy quá trình xây dựng sẽ tiêu tốn nhiều thời gian hơn so với không có CONFIGURE_DEPENDS .

Ngay cả với tùy chọn CONFIGURE_DEPENDS, tài liệu CMake có sẵn vẫn không khuyến nghị sử dụng file(GLOB)hoặc file(GLOB_RECURSE)để thu thập các nguồn.


"Tài liệu CMake vẫn không khuyến nghị sử dụng file(GLOB)hoặc file(GLOB_RECURSE)để thu thập các nguồn" Họ khuyên gì sau đó? Sử dụng cái gì khác để thu thập các nguồn hoặc liệt kê thủ công từng tệp nguồn duy nhất?
Thomas

1
@Thomas: Họ khuyên bạn nên liệt kê thủ công mọi tệp nguồn. Câu trả lời đó đưa ra một lời giải thích tuyệt vời về khuyến nghị.
Tsyvarev

-2

Vậy tại sao không sử dụng powershell để tạo danh sách các tệp nguồn cho bạn. Hãy xem kịch bản này

param (
    [Parameter(Mandatory=$True)]
    [string]$root 
)

if (-not (Test-Path  -Path $root)) {    
throw "Error directory does not exist"
}

#get the full path of the root
$rootDir = get-item -Path $root
$fp=$rootDir.FullName;


$files = Get-ChildItem -Path $root -Recurse -File | 
         Where-Object { ".cpp",".cxx",".cc",".h" -contains $_.Extension} | 
         Foreach {$_.FullName.replace("${fp}\","").replace("\","/")}

$CMakeExpr = "set(SOURCES "

foreach($file in $files){

    $CMakeExpr+= """$file"" " ;
}
$CMakeExpr+=")"
return $CMakeExpr;

Giả sử bạn có một thư mục có cấu trúc này

C:\Workspace\A
--a.cpp
C:\Workspace\B 
--b.cpp

Bây giờ hãy lưu tệp này dưới dạng "createdSourceList.ps1" và chạy tập lệnh dưới dạng

~>./generateSourceList.ps1 -root "C:\Workspace" > out.txt

tập tin out.txt sẽ chứa

set(SOURCE "A/a.cpp" "B/b.cpp")

Câu hỏi được gắn thẻ đa nền tảng - powershell không phải là đa nền tảng.
reichhart

@reichhart powershell hoạt động trên linux và mac cũng vậy
noone

Tôi biết. Nhưng không có thẻ cho powershell và "CMake" đã là nền tảng chéo. "Powershell" sẽ là một phụ thuộc bổ sung và rất hiếm khi được sử dụng trên các HĐH khác ngoài Windows. Bạn thậm chí có thể tìm thấy nhiều nhà phát triển C # trên Linux hơn những người có quyền hạn. Và thực tế quan trọng nhất là câu hỏi: "Có thể thực hiện trực tiếp trong CMake không? Làm thế nào?"
reichhart
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.