Обработка зависимостей заголовков файлов с cmake

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

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

Поэтому я полагаю, что я делаю что-то неправильно.

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

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

В главном каталоге есть:

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 ничего не принес, поэтому я думаю, это очень просто или должно работать из коробки...

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

ИЗМЕНИТЬ

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

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

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

Ответ 1

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

Ответ 2

Я просто попал в ту же проблему. После изменения путей в 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)

Ответ 3

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

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

Ответ 4

По-видимому, система удаления 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 во время компиляции.