Secara otomatis menambahkan semua file dalam folder ke target menggunakan CMake?

163

Saya sedang mempertimbangkan untuk mengalihkan proyek lintas platform dari sistem manajemen build terpisah dalam Visual C ++, XCode dan makefiles ke CMake.

Salah satu fitur penting yang saya butuhkan adalah menambahkan secara otomatis semua file dalam direktori ke target. Walaupun ini mudah dilakukan dengan make, tidak mudah dilakukan dengan Visual C ++ dan XCode (koreksi saya jika saya salah). Apakah mungkin melakukannya secara langsung di CMake? Bagaimana?

martjno
sumber
Btw. di Dalam Visual Studio, setidaknya dalam proyek C #, ada tombol bilah alat di penjelajah proyek, bernama tampilkan semua file. Itu membuat semua sub-direktori proyek terlihat, berwarna abu-abu jika mereka tidak mengandung file apa pun yang secara logis termasuk dalam proyek. Anda dapat memasukkan direktori-direktori ini melalui menu konteks, yang mencakup semua file sumber di dalamnya, secara rekursif :)
yeoman

Jawaban:

228

Itu mungkin. Misalnya dengan file(GLOB:

cmake_minimum_required(VERSION 2.8)

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

add_executable(helloworld ${helloworld_SRC})

Perhatikan bahwa ini membutuhkan pengaktifan ulang secara manualcmake jika file sumber ditambahkan atau dihapus, karena sistem build yang dihasilkan tidak tahu kapan harus meminta CMake untuk melakukan regenerasi, dan melakukannya di setiap build akan menambah waktu build.

Kleist
sumber
11
Alternatif untuk menjalankan cmake secara manual adalah dengan menyentuh file CMakeLists.txt sebelum menjalankan make.
Seamus Connor
8
> "Kami tidak menyarankan menggunakan GLOB untuk mengumpulkan daftar file sumber dari hierarki sumber Anda. Jika tidak ada file CMakeLists.txt yang berubah ketika sumber ditambahkan atau dihapus, sistem build yang dihasilkan tidak tahu kapan harus meminta CMake untuk membuat ulang." Ini tidak lagi direkomendasikan dalam CMAKE3.7 dokumen yang ditautkan oleh Hand1Cloud
triple
4
apa alternatifnya bagi GLOB?
Shayne
13
Cara yang lebih baik sejak v3.1 disarankan di sini: target_sources () crascit.com/2016/01/31/…
Sheen
34

Jawaban oleh Kleist tentu berhasil, tetapi ada peringatan penting:

Saat Anda menulis Makefilesecara manual, Anda mungkin membuat SRCSvariabel menggunakan fungsi untuk memilih semua .cppdan .hfile. Jika file sumber ditambahkan kemudian, menjalankan kembali makeakan memasukkannya.

Namun, CMake (dengan perintah seperti file(GLOB ...)) akan secara eksplisit menghasilkan daftar file dan menempatkannya di hasil otomatis Makefile. Jika Anda memiliki file sumber baru, Anda harus membuat Makefileulang dengan menjalankan kembali cmake.

sunting: Tidak perlu menghapus Makefile.

deniz kara
sumber
4
Tidak bisakah cmake dijalankan kembali, yang seharusnya menghapus / memodifikasi Makefile yang kedaluwarsa?
Ethan
25
Ini bukan jawaban, ini komentar tentang jawaban @ Kleist.
Neowizard
3
@Neowizard tidak dalam terminologi Stackoverflow.
kara deniz
1
Komentar ini bagus, tapi "standar", kan? Penanya sudah menggunakan cmake, jadi menyarankan make bisa "lebih pintar" tidak terlalu membantu.
frankliuao
Jadi apakah ada cara untuk menambahkan file sumber baru dan kemudian membangun tanpa menjalankan kembali cmake?
artin
6

Ekstensi untuk jawaban @leading :

Sejak CMake 3.12 opsi tambahan CONFIGURE_DEPENDS yang didukung oleh perintah file(GLOB)dan file(GLOB_RECURSE). Dengan pilihan ini tidak ada kebutuhan untuk secara manual kembali menjalankan CMake setelah penambahan / penghapusan file sumber dalam direktori - CMake akan kembali dijalankan secara otomatis pada berikutnya membangun proyek.

Namun, opsi CONFIGURE_DEPENDS menyiratkan bahwa direktori yang sesuai akan diperiksa ulang setiap kali membangun diminta, sehingga proses pembangunan akan menghabiskan lebih banyak waktu daripada tanpa CONFIGURE_DEPENDS .

Bahkan dengan opsi CONFIGURE_DEPENDS tersedia, dokumentasi CMake masih tidak merekomendasikan penggunaan file(GLOB)atau file(GLOB_RECURSE)untuk mengumpulkan sumber.

Tsyvarev
sumber
"Dokumentasi CMake masih tidak merekomendasikan penggunaan file(GLOB)atau file(GLOB_RECURSE)untuk mengumpulkan sumber" Apa yang mereka rekomendasikan? Menggunakan sesuatu yang lain untuk mengumpulkan sumber atau mendaftar secara manual setiap file sumber tunggal?
Thomas
1
@ Thomas: Mereka merekomendasikan untuk mendaftar secara manual setiap file sumber Jawaban itu memberikan penjelasan yang bagus tentang rekomendasi tersebut.
Tsyvarev
-2

Jadi Mengapa tidak menggunakan PowerShell untuk membuat daftar file sumber untuk Anda. Lihatlah skrip ini

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;

Misalkan Anda memiliki folder dengan struktur ini

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

Sekarang simpan file ini sebagai "generateSourceList.ps1" misalnya, dan jalankan skrip sebagai

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

file out.txt akan berisi

set(SOURCE "A/a.cpp" "B/b.cpp")
alcoforado
sumber
Pertanyaan ditandai lintas-platform - PowerShell bukan lintas-platform.
reichhart
@reichhart PowerShell berfungsi di linux dan dan mac juga
noone
Aku tahu. Tapi tidak ada tag untuk powershell dan "CMake" sudah lintas platform. "Powershell" akan menjadi ketergantungan tambahan dan sangat jarang digunakan pada OS selain Windows. Anda mungkin menemukan lebih banyak pengembang C # di Linux daripada orang dengan PowerShell. Dan fakta yang paling penting adalah pertanyaan: "Apakah mungkin untuk melakukannya secara langsung di CMake? Bagaimana?"
reichhart