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

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

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

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

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

Ответ 1

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

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

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

В случае, если вы застряли с очень старой версией CMake (2.8.10 или более старой) без поддержки target_include_directories, вы также можете использовать устаревшие include_directories:

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})
target_include_directories(mylib PRIVATE ${YOUR_DIRECTORY})
add_executable(myexec execfile.cpp ${HEADER_FILES})
target_include_directories(myexec PRIVATE ${YOUR_DIRECTORY})

Ответ 2

Во-первых, вы используете 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
)

Ответ 3

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

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

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

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

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

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

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

PS:

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

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

Ответ 4

У меня такая же проблема.

Моя директория проекта была такой:

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

И что я использовал, чтобы включить файлы во всех этих папках:

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

    add_executable(Server ${source_files})

И это полностью сработало.

Ответ 5

Добавьте include_directories("/your/path/here").

Это будет похоже на вызов gcc с -I/your/path/here/.

Убедитесь, что вы поместили двойные кавычки вокруг пути. Другие люди не упоминали об этом, и это заставило меня застрять на 2 дня. Таким образом, этот ответ для людей, которые очень плохо знакомы с CMake и очень смущены.