CMake ile dizinleri düzgün bir şekilde ekleme


243

Yaklaşık bir yıl önce CMake'deki başlık bağımlılıklarını sordum .

Geçenlerde, CMake'nin bu başlık dosyalarının projenin dışında olduğunu düşündüğünü fark ettim . En azından, bir Code :: Blocks projesi oluştururken başlık dosyaları proje içinde görünmez (kaynak dosyalar yapar). Nedenle CKağıt olmak için bu başlıkları dikkate geliyor bana dış projeye ve bağlı onları takip etmez.

CMake eğitiminde hızlı bir arama sadece include_directoriesistediğimi yapmıyor gibi görünüyor ...

Belirli bir dizinin dahil edilecek başlıklar içerdiğini ve bu üstbilgilerin oluşturulan Makefile tarafından izlenmesi gerektiğini CMake'e bildirmenin doğru yolu nedir?


Bu soruda yapılan düzenlemeler kafa karıştırıcıdır. Orijinal soru ve cevaplar, bir IDE'deki Başlık Dosyalarının nasıl izleneceği idi. Bu, oluşturulan bir Makefile eksik başlık dosyası bağımlılıklarından ve bu sorunun nasıl çözüleceğinden oldukça farklıdır.
fdk1342

@Fred: Neden bahsettiğiniz hakkında hiçbir fikrim yok. Düzenleme revizyonunun açıkça gösterdiği gibi, son cümle her zaman orada olmuştur. Bu soruda sadece kozmetik düzenlemeler yapıldı ve hiçbir kelime tanıtılmadı (veya kaldırılmadı).
Matthieu M.

O zaman bu benim yanlış anlama. Bana bir paragraf eklenmiş gibi görünüyordu. stackoverflow.com/questions/13703647/… , ortak anlayışın IDE'deki başlık dosyasının nasıl listeleneceği olduğunu söylüyor. Bu .cbpproje dosyasına atıfta bulunmalıydı . Eğer cmake bağımlılık tarayıcısı bir başlık dosyasını bir Makefile için bir bağımlılık olarak doğru bir şekilde tanımlayamazsa, bunu düzeltmenin yolları vardır, ancak bazı durumlarda tam önişlemci içermediğinden yanlış olur.
fdk1342

Yanıtlar:


267

İki şey yapılmalıdır.

Önce dahil edilecek dizini ekleyin:

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

Çok eski bir CMake sürümü (2.8.10 veya daha eski) ile desteklenmediyseniz target_include_directoriesinclude_directories bunun yerine eski da kullanabilirsiniz :

include_directories(${YOUR_DIRECTORY})

Ardından, başlık dosyalarını geçerli hedef için kaynak dosyalarınızın listesine eklemelisiniz, örneğin:

set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(test ${SOURCES})

Bu şekilde, üstbilgi dosyaları Makefile dosyasında ve örneğin oluşturduğunuz Visual Studio projesinde bağımlılıklar olarak görünür.

Bu başlık dosyaları birkaç hedef için nasıl kullanılır:

set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)

add_library(mylib libsrc.cpp ${HEADER_FILES})
target_include_directories(mylib PRIVATE ${YOUR_DIRECTORY})
add_executable(myexec execfile.cpp ${HEADER_FILES})
target_include_directories(myexec PRIVATE ${YOUR_DIRECTORY})

Ah! Bunun aptalca bir şey olması gerektiğini biliyordum. Gerçekten de, başlıkları listelemedim ... Sadece bu kütüphanenin başlıklarını mı yoksa bağlı olabileceği tüm başlıkları da listelemem gerekiyor mu? Büyüyen bir proje ve kök kütüphaneye bir tane eklediğimde tüm bağımlılıklara bir başlık ekleme fikrinden oldukça korkuyorum .
Matthieu M.

Daha iyi bağımlılık izlemeye izin vermek için (örneğin, bir başlık dosyasını değiştirmenin etkilenen tüm hedefler için derlemeyi tetiklediğinden emin olmak için), evet. Ancak, başlık dosyalarını yalnızca bir kez listelemek ve bunları birkaç yerde kullanmak için cmake değişkenlerini kullanabilirsiniz, düzenlememe bakın.
SirDarius

1
Benim sorum daha çok birbirine bağlı birkaç kütüphanem olması anlamındaydı: libroot, liba libroot'a, libb libroot'a bağlıdır. LIBROOT_HEADER_FILESDeğişkeni liba/CMakefileve libb/CMakefilesonra kullanabilir miyim ?
Matthieu M.

2
Bu yanlış, sen gerektiğini asla kullanmayın include_directoriesüzerinde target_include_directories. Birincisi, bu dizindeki tüm hedefler için yinelemeli olarak ayarlar; oysa ikincisi onu bir hedef için belirler. İlkini yapmak CMake'te hedef grafik kavramını kırar ve bunun yerine dosya hiyerarşinizin yan etkilerine dayanır.
Andy

1
Cevabı, target_include_directoriesmodern CMake kodu için mevcut tercih kavramını yansıtacak şekilde düzenledim . Değişikliklere katılmıyorsanız beni sohbete davet etmekten çekinmeyin.
ComicSansMS

74

İlk olarak, include_directories() CMake'e dizini -Iderleme komut satırına eklemesini söyleyin . İkincisi, sizin add_executable()veya add_library()çağrınızdaki başlıkları listelersiniz .

Örnek olarak, projenizin kaynakları srciçerdiyse ve üstbilgilere ihtiyacınız includevarsa, bunu şu şekilde yapabilirsiniz:

include_directories(include)

add_executable(MyExec
  src/main.c
  src/other_source.c
  include/header1.h
  include/header2.h
)

19
Gerçekten üstbilgi eklemeniz add_executablemi gerekiyor ? CMake'in dosya bağımlılıklarını otomatik olarak çözdüğünü düşündüm.
Colin D Bennett

57
@ColinDBennett Onları bağımlılık nedenleriyle listelemenize gerek yok - C: Yapı bağımlılıklarını iyi bulmazsanız yapmayın. Ancak bunları listelerseniz, projenin bir parçası olarak kabul edilir ve IDE'lerde (sorunun konusu olan) listelenir.
Angew artık SO

En azından QtCreator için, bir class.cpp olması durumunda class.h ifadesinin eklenmesi gerekmez. Kaynağa yalnızca lonely.h eklenmesi gerekir. Bkz. Www.th-thielemann.de/cmake
Th. Thielemann

19

CMake, Makefile (örneğin make veya qmake) oluşturmanın diğer yollarıyla karşılaştırılırsa daha çok bir komut dosyası dili gibidir. Python gibi çok havalı değil ama yine de.

İnsanların dizinleri nasıl içerdiği çeşitli açık kaynaklı projelere bakıldığında " uygun bir yol " diye bir şey yoktur . Ama bunu yapmanın iki yolu var.

  1. Ham include_directories , geçerli projeye ve bir dizi add_subdirectory komutları aracılığıyla ekleyeceğiniz diğer tüm alt projelere bir dizin ekler . Bazen insanlar böyle bir yaklaşımın miras olduğunu söylerler.

  2. Daha zarif bir yol target_include_directories . Belirli bir proje / hedef için bir dizi eklemenize izin verir (belki de) gereksiz kalıtım veya çeşitli içerme dizinlerinin çakışması olmadan. Ayrıca, ince bir yapılandırma bile gerçekleştirmeye izin verin ve bu komut için aşağıdaki işaretlerden birini ekleyin.

ÖZEL - yalnızca bu belirtilen oluşturma hedefi için kullan

HALKA AÇIK - belirtilen hedef ve bu projeyle bağlantı kuran hedefler için kullanın

ARAYÜZ - yalnızca mevcut projeyle bağlantı kuran hedefler için kullanın

Not:

  1. Her iki komut da, bir dizinin SİSTEM olarak işaretlenmesine izin vererek, belirtilen dizinlerin sizin işiniz olmadığına dair uyarılar içerdiğine dair bir ipucu verir.

  2. Benzer bir cevap, target_compile_definitions / add_definitions , target_compile_options / CMAKE_C_FLAGS diğer komut çiftlerinde de geçerlidir.


13

Ekle include_directories("/your/path/here").

Bu seçenekle çağrı gccyapmaya benzer -I/your/path/here/.

Yolun etrafına çift tırnak işareti koyduğunuzdan emin olun. Diğer insanlar bundan bahsetmedi ve bana 2 gün sıkışmış yaptı. Yani bu cevap CMake için çok yeni ve kafası karışmış insanlar içindir.


7

Ben de aynı problemi yaşadım.

Proje dizinim şöyleydi:

    --project
    ---Classes
    ----Application
    -----.h and .c files
    ----OtherFolders
    --main.cpp

Ve tüm bu klasörlere dosyaları dahil etmek için ne kullandım:

    file(GLOB source_files
            "*.h"
            "*.cpp"
            "Classes/*/*.cpp"
            "Classes/*/*.h"
    )

    add_executable(Server ${source_files})

Ve tamamen işe yaradı.


Cmake'nin dosya glob'u kullanan bir 'build system' değil 'build system generator' olduğunu hatırlamak, modern cmake'de (3.0 ve üzeri sürümlerle CMake) iyi bir fikir değildir, çünkü file globları 'build' zamanında değil, 'build' olarak değerlendirilir sistem üretim zamanı. Bkz. Bağlantı: gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1
ggulgulia
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.