Jaka jest różnica między include_directories a target_include_directories w CMake?

148

Mam strukturę katalogów dla mojego kodu C ++, która wygląda następująco:

|
|->include
|->src

Piszę plik CMakeLists.txt dla mojego kodu. Chcę zrozumieć różnicę między include_directoriesi target_include_directoriesw CMake.

Jaka jest różnica między ich użyciem i aby dodać ścieżkę do pliku dołączanego, której powinienem użyć?

Ujjwal Aryan
źródło
4
Czy przeczytałeś dokumentację programu include_directoriesi target_include_directories? Czego nie rozumiesz na temat różnicy między nimi?
Jakiś programista,
82
Dokumentacja nie jest jasna. Przeczytałem to i domyśliłem się, co napisał Angew w swojej odpowiedzi, ale nie ma tam opisów, przykładów, a dla systemu przeznaczonego do budowania projektów nie ma przykładów opartych na projektach w dokumentacji CMake. Gdyby istniała dobra i wyczerpująca dokumentacja CMake, nie obciążałbym społeczności tymi pytaniami.
Ujjwal Aryan
1
Koncepcje cmake są słabo udokumentowane. Szczególnie ukierunkowane i „nieukierunkowane”.
John Greene,
Zgadzam się, że dokumentacja CMake jest zła, ile wysiłku oszczędza, aby nie podawać przykładów? Kiedy byłem nowy w CMake, często mylono mnie ze starą / nową składnią.
Tien Do

Odpowiedzi:

162

include_directories(x/y)wpływa na zakres katalogu. Wszystkie cele w tym CMakeList, a także te we wszystkich podkatalogach dodanych po punkcie jego wywołania, będą miały ścieżkę x/ydodaną do ich ścieżki dołączania.

target_include_directories(t x/y)ma zasięg docelowy - dodaje x/ydo ścieżki dołączania celu t.

Chcesz tego pierwszego, jeśli wszystkie cele używają wymienionych katalogów włączania. Potrzebujesz tego drugiego, jeśli ścieżka jest specyficzna dla celu lub jeśli chcesz mieć lepszą kontrolę nad widocznością ścieżki. To ostatnie wynika z faktu, że target_include_directories()podpiera PRIVATE, PUBLICi INTERFACEkwalifikatorów.

Angew nie jest już dumny z SO
źródło
36
Myślę, że generalnie powinno być preferowane to drugie (o ile używa się cmake 3). Dodatkową zaletą jest umieszczenie x/yścieżki dołączania dowolnych zależnych celów, które używają tw swoich target_link_librariespoleceniach. Oczywiście jest miejsce na to pierwsze, ale uważam, że to drugie jest generalnie lepsze.
Phil
2
Oryginalna odpowiedź stwierdzała, że include_directorieswpłynie to tylko na cele i podkatalogi dodane później . Edytuję odpowiedź: dokumentacja wyraźnie stwierdza, że dotyczy to wszystkich obiektów docelowych w bieżących CMakeLists. Dokumentacja nie wspomina, ale dotyczy to tylko podkatalogów po wezwaniu (jak słusznie stwierdzono w oryginalnej odpowiedzi)
tamas.kenez
@Phil, target_include_directorieszostał wprowadzony w CMake 2.8.11 (maj 2013)
tamas.kenez
@ tamas.kenez Dzięki za zwrócenie mi na to uwagi, naprawione. Byłem całkiem przekonany, że to coś „od teraz”.
Angew nie jest już dumny z SO
47

Oprócz tego, co poprawnie mówi odpowiedź Angew , kolejną bardzo ważną różnicą między include_directoriesi target_include_directoriesjest to, że gdy jest używane z PUBLIClub INTERFACE, to drugie wypełnia INTERFACE_INCLUDE_DIRECTORIESwłaściwość celu. Ta właściwość jest przydatna, gdy inny cel używa target_link_librariesdo łączenia się z pierwotnym celem, ponieważ cel łączenia będzie miał automatycznie dodane te zawierające katalogi. Zobacz przykład .

Ta ważna funkcja jest dość dobrze ukryta w dokumentacji: target_include_directories wspomina o wypełnianiuINTERFACE_INCLUDE_DIRECTORIES , którego dokumentacja mówi:

Gdy zależności docelowe są określone za pomocą target_link_libraries () , CMake odczyta tę właściwość ze wszystkich zależności docelowych, aby określić właściwości kompilacji konsumenta.

Antonio
źródło
1
Po raz pierwszy przeczytałem zrozumiałe wyjaśnienie PUBLICwłaściwości itd.! Dzięki: D
RL-S
Usunięcie niejednoznaczności: gdy używasz PUBLIClub INTERFACEz target_include_directories, właściwość INTERFACE_INCLUDE_DIRECTORIES jest wypełniana katalogami włączania wymaganymi do kompilacji względem nagłówków celu.
Thiago Navarro
1
Sprawdzić tutaj , jeśli chcesz dowiedzieć się więcej na temat znaczenia słowa kluczowe PRIVATE, PUBLICa INTERFACEza pomocątarget_include_directories
Thiago Navarro
4

Jak powiedział @Angew, różnica polega na:

1, funkcja include_directories () jest dostępna dla wszystkich plików w drzewie źródłowym. 2, target_include_directories () jest dostępna tylko dla określonego celu podczas kompilacji.

Nick.Rhan
źródło