Как правильно добавить включаемые каталоги с CMake

112

Примерно год назад я спросил о зависимостях заголовка в CMake.

Недавно я понял, что проблема заключается в том, что CMake считает, что эти файлы заголовков являются внешними по отношению к проекту. По крайней мере, при создании проекта Code:: Blocks заголовочные файлы не отображаются в проекте (исходные файлы). Поэтому мне кажется, что CMake считает, что эти заголовки являются внешними по отношению к проекту и не отслеживают их в зависимости.

Быстрый поиск в учебнике CMake указывает только на include_directories, который, похоже, не делает того, что я хочу...

Каким образом можно сигнализировать CMake, что конкретный каталог содержит заголовки, которые должны быть включены, и чтобы эти заголовки отслеживались сгенерированным Makefile?

  • 0
    Изменения, внесенные в этот вопрос, приводят к путанице. Первоначальный вопрос и ответы были о том, как отслеживать файлы заголовков в IDE. Это сильно отличается от сгенерированных Makefile отсутствующих зависимостей заголовочного файла и способа решения этой проблемы.
  • 0
    @ Фред: Понятия не имею, о чем ты говоришь. Как ясно показывает редакция редактирования, последнее предложение всегда было там. По этому вопросу были сделаны только косметические изменения, и ни одно слово не было введено (или удалено).
Показать ещё 1 комментарий
Теги:
cmake

3 ответа

130
Лучший ответ

Должны быть сделаны две вещи.

Сначала добавьте каталог, который будет включен:

include_directories(${YOUR_DIRECTORY})

Затем вы также должны добавить файлы заголовков в список исходных файлов для текущей цели, например:

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

Таким образом, файлы заголовков будут отображаться как зависимости в Makefile, а также, например, в сгенерированном проекте visual studio, если вы его создаете.

Изменить: Как использовать эти файлы заголовков для нескольких целей

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

add_library(mylib libsrc.cpp ${HEADER_FILES})
add_executable(myexec execfile.cpp ${HEADER_FILES})
  • 0
    Ах! Я знал, что это должно быть что-то глупое. Действительно, я не перечислил заголовки ... Нужно ли перечислять заголовки только этой библиотеки или также всех заголовков, от которых она может зависеть (помимо объявления зависимости от библиотеки)? Это растущий проект, и я очень боюсь добавить заголовок ко всем зависимостям, когда добавляю заголовок в корневую библиотеку.
  • 0
    Для лучшего отслеживания зависимостей (например, чтобы убедиться, что изменение файла заголовка запускает компиляцию для всех затронутых целей), да. Однако вы можете использовать переменные cmake, чтобы перечислять заголовочные файлы только один раз и использовать их в нескольких местах, см. Мое редактирование.
Показать ещё 12 комментариев
38

Сначала вы используете include_directories(), чтобы сообщить CMake добавить каталог как -I в командную строку компиляции. Во-вторых, вы указываете заголовки в своем вызове add_executable() или add_library().

В качестве примера, если ваши источники проекта находятся в src, и вам нужны заголовки из include, вы можете сделать это следующим образом:

include_directories(include)

add_executable(MyExec
  src/main.c
  src/other_source.c
  include/header1.h
  include/header2.h
)
  • 13
    Вам действительно нужно добавить заголовки в add_executable ? Я думал, что CMake выяснил зависимости включаемого файла автоматически.
  • 43
    @ColinDBennett Вам не нужно перечислять их по причинам зависимости - CMake вычисляет зависимости сборки, если вы этого не сделаете. Но если вы перечислите их, они будут считаться частью проекта и будут перечислены как таковые в IDE (что и было темой вопроса).
Показать ещё 1 комментарий
2

CMake больше похож на язык script, если сравнить его с другими способами создания Makefile (например, make или qmake). Это не очень круто, как python, но все же.

Нет такой вещи, как "правильный путь", если вы смотрите в разных проектах с открытым исходным кодом, как люди включают каталоги. Но есть два способа сделать это.

  • Crude include_directories будет прикреплять каталог к ​​текущему проекту и всем другим проектам потомков, которые вы добавите через серию add_subdirectory. Иногда люди говорят, что такой подход является наследием.

  • Более элегантный способ target_include_directories. Это позволяет добавлять каталог для конкретного проекта/цели без (возможно) ненавязчивого наследования или столкновения различных каталогов inlude. Также разрешите выполнить даже сублимированную конфигурацию и добавьте один из следующих маркеров для этой команды.

PRIVATE - используйте только для указанной заданной цели сборки

PUBLIC - используйте его для указанной цели и для целей, которые связаны с этим проектом

ИНТЕРФЕЙС - используйте его только для целей, которые связаны с текущим проектом

p.s.

  • Обе команды позволяют отмечать каталог как SYSTEM, чтобы дать подсказку, что если это не ваша компания, указанные каталоги будут содержать предупреждения.

  • Аналогичный ответ с другими парами команд target_compile_definitions/add_definitions, target_compile_options/CMAKE_C_FLAGS

Ещё вопросы

Сообщество Overcoder
Наверх
Меню