В чем разница между include_directories и target_include_directories в CMake?

134

У меня есть структура каталогов для моего кода на C ++, которая выглядит следующим образом:

|
|->include
|->src

Я пишу файл CMakeLists.txt для своего кода. Я хочу понять разницу между include_directoriesи target_include_directoriesв CMake.

В чем разница между их использованием и тем, что я должен использовать для добавления пути к включаемому файлу?

Удджвал Ариан
источник
4
Вы читали документацию по include_directoriesи target_include_directories? Что вы не понимаете в разнице между ними?
Какой-то чувак-программист,
74
В документации нет ясности. Я прочитал его и предположил, что написал Энгью в своем ответе, но нет ни описаний, ни примеров, а для системы, предназначенной для построения проекта, в документации CMake нет примеров на основе проекта. Если бы по CMake была хорошая и исчерпывающая документация, я бы не стал обременять сообщество этими вопросами.
Ujjwal Aryan
Понятия cmake плохо документированы. Особенно целевые и «нецелевые».
John Greene

Ответы:

148

include_directories(x/y)влияет на область каталога. Все цели в этом CMakeList, а также во всех подкаталогах, добавленных после точки его вызова, будут иметь путь, x/yдобавленный к их пути включения.

target_include_directories(t x/y)имеет целевую область - он добавляет x/yк пути включения для цели t.

Вам нужен первый, если все ваши цели используют рассматриваемые каталоги include. Последний вам нужен, если путь специфичен для цели или если вам нужен более точный контроль над видимостью пути. Последнее исходит из того , что target_include_directories()поддерживающем PRIVATE, PUBLICи INTERFACEклассификаторов.

Angew больше не гордится SO
источник
35
Я думаю, что последнее, как правило, следует предпочесть (если используется cmake 3). Он имеет дополнительное преимущество, заключающееся x/yв том, что включает путь включения любых зависимых целей, которые используются tв своих target_link_librariesкомандах. Конечно, первое место есть, но я считаю, что второе в целом лучше.
Фил
2
В исходном ответе говорилось, что include_directoriesбудут затронуты только цели и подкаталоги, добавленные после . Я редактирую ответ: в документации четко указано, что затронуты все цели в текущих CMakeLists. В документации не упоминается, но затрагиваются только подкаталоги после вызова (как было правильно указано в исходном ответе)
tamas.kenez
@Phil, target_include_directoriesбыл представлен в CMake 2.8.11 (май 2013 г.)
tamas.kenez
@ tamas.kenez Спасибо, что обратил на это мое внимание, исправлено. Я был совершенно убежден, что это «отныне».
Энгью больше не гордится SO
40

Помимо того, что правильно говорит ответ Энгью, еще одно очень важное различие между include_directoriesи target_include_directoriesзаключается в том, что при использовании с PUBLICили INTERFACEпоследние заполняют INTERFACE_INCLUDE_DIRECTORIESсвойство цели. Это свойство полезно, когда другая цель использует target_link_librariesдля ссылки на исходную цель, так как цель связывания будет автоматически добавлять эти включаемые каталоги. Смотрите пример .

Эта важная функция довольно хорошо скрыта в документации: target_include_directories упоминает заполнениеINTERFACE_INCLUDE_DIRECTORIES , документация которого гласит:

Когда целевые зависимости указаны с помощью target_link_libraries () , CMake будет читать это свойство из всех целевых зависимостей, чтобы определить свойства сборки потребителя.

Антонио
источник
Я впервые читаю понятное объяснение PUBLICсвойств и т. Д.! Спасибо: D
RL-S
2

Как сказал @Angew, разница в следующем:

1, include_directories () доступен для всех файлов в исходном дереве 2, target_include_directories () доступен только для определенной цели при компиляции.

Nick.Rhan
источник