CMake kullanarak bir klasördeki tüm dosyaları otomatik olarak bir hedefe eklensin mi?


163

Bir çapraz platform projesi Visual C ++, XCode ve makefiles CMake için ayrı yapı yönetim sistemlerinden geçiş düşünüyorum.

İhtiyacım olan önemli bir özellik, bir dizindeki tüm dosyaları bir hedefe otomatik olarak eklemektir. Bu yapmak ile yapmak kolay olsa da, Visual C ++ ve XCode ile kolayca yapılabilir değil (yanlışsam beni düzelt). Doğrudan CMake'de yapmak mümkün mü? Nasıl?


Btw. Visual Studio'da, en azından C # projelerinde, proje gezgininde tüm dosyaları göster adlı bir araç çubuğu düğmesi vardır. Bir projenin tüm alt dizinlerini görünür kılar, projeye mantıksal olarak dahil edilmiş herhangi bir dosya içermiyorsa gri renkte görünür. Bu dizinleri, özyinelemeli olarak içindeki tüm kaynak dosyaları içeren bağlam menüsü aracılığıyla dahil edebilirsiniz :)
yeoman

Yanıtlar:


228

Bu mümkün. Örneğin file(GLOB:

cmake_minimum_required(VERSION 2.8)

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

add_executable(helloworld ${helloworld_SRC})

Oluşturulan derleme sistemi, CMake'den ne zaman yeniden oluşturulmasını isteyeceğini bilmediğinden ve her derlemede bunu yapmak derleme süresini artıracağından, kaynak dosya eklenirse veya kaldırılırsa bunun manuel olarak yeniden çalıştırılması gerektiğini unutmayın cmake.


11
Cmake'yi manuel olarak yeniden çalıştırmanın bir alternatifi, make'i çalıştırmadan önce CMakeLists.txt dosyasına dokunmaktır.
Seamus Connor


8
> "Kaynak ağacınızdan kaynak dosyalarının bir listesini toplamak için GLOB kullanılmasını önermiyoruz. Bir kaynak eklendiğinde veya kaldırıldığında CMakeLists.txt dosyası değişmezse, oluşturulan derleme sistemi CMake'den ne zaman yeniden oluşturulmasını isteyeceğini bilemez." Bu artık Hand1Cloud tarafından bağlanan CMAKE3.7 dokümanında önerilmiyor
üçlü

4
o zaman GLOB alternatifi nedir?
Shayne

13
Burada v3.1'den bu yana daha iyi bir yol öneriliyor: target_sources () crascit.com/2016/01/31/…
Sheen

34

Kleist'in cevabı kesinlikle işe yarıyor, ancak önemli bir uyarı var:

MakefileManuel olarak yazdığınızda , SRCStüm dosyaları .cppve .hdosyaları seçmek için bir işlev kullanarak bir değişken oluşturabilirsiniz . Bir kaynak dosya daha sonra eklenirse, yeniden çalıştırılması dosyayı makeiçerecektir.

Ancak, CMake (gibi bir komutla file(GLOB ...)) açıkça bir dosya listesi oluşturur ve otomatik olarak oluşturulan dizine yerleştirir Makefile. Yeni bir kaynak dosyanız varsa, Makefileyeniden çalıştırarak yeniden oluşturmanız gerekir cmake.

edit: Makefile kaldırmak gerek yok.


4
Cmake yeniden çalıştırılamaz, bu güncel olmayan Makefile'yi kaldırmalı / değiştirmelidir?
Ethan

25
Bu bir cevap değil, @ Kleist'in cevabı hakkında bir yorum.
Neowizard

3
@Neowizard Stackoverflow terminolojisinde değil.
kara deniz

1
Bu yorum güzel, ama "standart" değil mi? Asker cmake'yi zaten kullanıyor, bu yüzden make'in "daha akıllı" olabileceğini düşündürmek faydalı değil.
frankliuao

Yani yeni kaynak dosyaları eklemek ve daha sonra cmake yeniden çalıştırmadan oluşturmak için bir yolu var mı?
artin

6

Uzatma için @Kleist cevap :

CMake yana 3.12 ek seçenek CONFIGURE_DEPENDS edilir desteklenen komutlarla file(GLOB)ve file(GLOB_RECURSE). Bu seçenekle orada hiçbir ihtiyaçlarını için elle dizininde bir kaynak dosyasının eklenmesi / silindikten sonra yeniden çalıştırmak CMake - CKağıt yeniden çalıştırmak sonraki projesini oluşturmaya otomatik olacak.

Bununla birlikte, CONFIGURE_DEPENDS seçeneği, bina her istendiğinde ilgili dizinin yeniden kontrol edileceği anlamına gelir, bu nedenle derleme işlemi CONFIGURE_DEPENDS olmadan daha fazla zaman harcar .

Hatta ile CONFIGURE_DEPENDS seçeneği CKağıt belgelerine hala önermez kullanarak file(GLOB)veya file(GLOB_RECURSE)ödemeli kaynakları için.


"CMake belgeleri hala kaynakları kullanmayı file(GLOB)veya file(GLOB_RECURSE)toplamayı önermiyor" O zaman ne öneriyorlar? Kaynakları toplamak veya her bir kaynak dosyasını el ile listelemek için başka bir şey mi kullanıyorsunuz?
Thomas

1
@Thomas: Her kaynak dosyayı manuel olarak listelemelerini önerirler. Bu cevap , tavsiyenin büyük bir açıklamasını verir.
Tsyvarev

-2

Peki neden sizin için kaynak dosyalarının listesini oluşturmak için powershell kullanmıyorsunuz. Bu senaryoya bir göz atın

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;

Bu yapıya sahip bir klasörünüz olduğunu varsayalım

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

Şimdi bu dosyayı örneğin "createSourceList.ps1" olarak kaydedin ve betiği şu şekilde çalıştırın:

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

out.txt dosyası

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

Soru çapraz platform olarak etiketlendi - powershell çapraz platform değil.
reichhart

@reichhart powershell linux ve mac üzerinde de çalışıyor
noone

Biliyorum. Ancak powershell için bir etiket yok ve "CMake" zaten platformlar arası. "Powershell" ek bir bağımlılık olacaktır ve Windows dışındaki diğer işletim sistemlerinde nadiren kullanılır. Linux'ta powershell kullanan insanlardan daha fazla C # geliştiricisi bulabilirsiniz. Ve en önemli gerçek şu sorudur: "Bunu doğrudan CMake'de yapmak mümkün mü? Nasıl?"
reichhart
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.