Обработка зависимостей заголовочных файлов с помощью cmake - PullRequest
41 голосов
/ 18 сентября 2011

Я использую CMake в небольшом проекте C ++, и пока он отлично работает ... с одним поворотом: x

Когда я изменяю заголовочный файл, обычно требуется перекомпилировать несколько исходных файлов (те,которые включают это, прямо или косвенно), однако кажется, что cmake обнаруживает только некоторые исходных файлов для перекомпиляции, что приводит к поврежденному состоянию.Я могу обойти это, уничтожив проект и перестроив его с нуля, но это позволяет обойти цель использования утилиты make: перекомпилировать только то, что нужно.

Поэтому, я полагаю, я делаю что-то не так.

Мой проект очень просто организован:

  • верхний каталог, в котором находятся все ресурсы, там находится главный CMakeLists.txt
  • каталог "include", где все публичные заголовкилежит (в разных подкаталогах)
  • каталог "src", где находятся все подкаталоги исходных файлов, там находится src CMakeLists.txt
  • CMakeLists.txt для каждого подкаталога в "src"directory

Основной каталог содержит:

cmake_minimum_required(VERSION 2.8)

project(FOO)

set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)

# Compiler Options
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++0x -Wall -Wextra -Werror")

include_directories($(FOO_SOURCE_DIR)/include)

add_subdirectory(src)

Каталог "src":

add_subdirectory(sub1)
add_subdirectory(sub2)
add_subdirectory(sub3)
add_subdirectory(sub4)

add_executable(foo main.cpp)

target_link_libraries(foo sub1 sub2 sub3 sub4)

Где sub4 зависит от sub3, что зависитна sub2, который зависит от sub1

И пример подкаталога (sub3):

set(SUB3_SRCS
    File1.cpp
    File2.cpp
    File3.cpp
    File4.cpp
    File5.cpp
    File6.cpp
    )

add_library(sub3 ${SUB3_SRCS})

target_link_libraries(sub3 sub1 sub2)

Я был бы рад, если бы кто-нибудь мог указать мне на мою ошибку, ищаздесь или на CMake ничего не далоg, так что я думаю, что это очень просто или должно работать из коробки ...

(для справки, я использую cmake версии 2.8.2 на MSYS)

EDIT :

Благодаря предложению Билла я проверил файл depend.make, сгенерированный CMake, и он действительно отсутствует (строго).Вот пример:

src/sub3/CMakeFiles/sub3.dir/File1.cpp.obj: ../src/sub3/File1.cpp

Да, вот и все, ни на один из включений не было ссылок вообще: x

Ответы [ 4 ]

14 голосов
/ 21 сентября 2011

Вы должны посмотреть на файлы depend.make в вашем двоичном дереве.Это будет в CMakeFiles/target.dir/depend.make.Попробуйте найти один из тех, в котором отсутствует файл .h, который, как вы думаете, должен иметь.Затем создайте отчет об ошибке для cmake или отправьте по электронной почте список рассылки cmake.

9 голосов
/ 04 ноября 2014

Я просто столкнулся с той же проблемой.После изменения путей в include_directories() с абсолютного на относительный он добавил соответствующие зависимости.

Похоже, CMake пытается угадать, какие заголовки являются системными, а какие связаны с проектом.Я подозреваю, что каталоги, которые начинаются с /, передаются как -isystem /some/path и, следовательно, не представлены в сгенерированных зависимостях.

Если вы не можете заменить ${FOO_SOURCE_DIR} относительным путем, вы можете попытаться вычислить относительный путь, используясоответствующие функции CMake.Т.е.:

file(RELATIVE_PATH FOO_SOURCE_REL_DIR
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${FOO_SOURCE_DIR}/.)
include_directories(${FOO_SOURCE_REL_DIR}/include)
2 голосов
/ 23 марта 2016

Очевидно, что cmake удаляет системные пути включения из деревьев зависимостей (спасибо @ony за этот совет).Это, вероятно, имеет смысл в большинстве случаев, но иногда cmake не знает, что компилятор считает системным путем или нет.Мы используем пользовательскую сборку gcc, которая игнорирует /usr/include, но cmake считает, что не игнорирует ее.Чтобы заставить cmake сделать /usr/include зависимость, которая НЕ оптимизирована, попробуйте этот трюк: добавьте /. к пути.

Я пытаюсь заставить все зависимости библиотеки использовать функцию зависимостей cmake,включая определенные «сторонние» библиотеки, которые не всегда устанавливаются по умолчанию в Linux или даже доступны.Например, сжатие Z-lib.

Следующая цель интерфейса работала нормально, если бы включенные в Z lib не были в /usr/include, но сломалась бы, если бы они были.

find_package(ZLIB REQUIRED)
message(status "found zlib ${ZLIB_LIBRARIES}")
message(status "found zlib includes ${ZLIB_INCLUDE_DIRS}")
target_link_libraries(zlib_target INTERFACE ${ZLIB_LIBRARIES})
target_include_directories(zlib_target INTERFACE ${ZLIB_INCLUDE_DIRS})

Я изменилпоследняя строка в

target_include_directories(zlib_target INTERFACE /.${ZLIB_INCLUDE_DIRS})

и все заработало.Теперь цели, которые зависели от zlib_target, автоматически получат -I/./usr/include во время компиляции.

2 голосов
/ 30 декабря 2012

Вы запускали cmake до или после добавления включений в ваши файлы cpp?

Я столкнулся с этой проблемой, и повторный запуск cmake устранил ее. Я добавил добавление post-cmake.

...