Gestion des dépendances de fichiers d'en-tête avec cmake

J'utilise CMake sur un petit projet C++ et jusqu'à présent ça marche très bien... avec une torsion: x

quand je change un fichier d'en-tête, il nécessite généralement de recompiler un certain nombre de fichiers sources (ceux qui l'incluent, directement ou indirectement), mais il semble que cmake ne détecte qu'une partie des fichiers sources à recompiler, conduisant à un État corrompu. Je peux contourner cela en éliminant le projet et en reconstruisant à partir de zéro, mais ceci contourne l'objectif d'utiliser un utilitaire make: uniquement recompiler ce qui est nécessaire.

donc, je suppose que je fais quelque chose de mal.

mon projet est très simplement organisé:

  • un répertoire supérieur où se trouvent toutes les ressources, les listes principales.txt se trouve là
  • un "include" répertoire où tous les en-têtes des mensonges (dans différents sous-répertoires)
  • un répertoire "src" où tous les sous-répertoires pour les fichiers sources sont, les listes cmakel de src.txt se trouve là
  • a CMakeLists.txt par sous-répertoire dans le répertoire" src

Le répertoire principal est:

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)

Le répertoire "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 dépend de sub3 qui dépend de sub2 qui dépend de sub1

Et un exemple de sous-répertoire (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)

je serais heureux si quelqu'un pouvait pointer mon erreur à moi, la recherche ici ou sur CMake n'a rien donné donc je suppose que c'est très facile ou devrait travailler hors de la boîte...

(pour référence, j'utilise la version 2.8.2 de cmake sur MSYS)

MODIFIER :

grâce à la suggestion de Bill, j'ai vérifié le fichier depend.make généré par CMake, et il est en effet manquant (sévèrement). Voici un exemple:

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

ouais, c'est tout, non de l'inclut étaient référencés à tous :x

37
demandé sur Matthieu M. 2011-09-18 14:54:01

4 réponses

vous devriez regarder les fichiers depend.make dans votre arborescence binaire. Ce sera dans CMakeFiles/target.dir/depend.make . Essayez de trouver l'un de ceux qui est manquant .h le fichier que vous pensez qu'il devrait avoir. Ensuite, créez un rapport de bogue pour cmake ou envoyez un courriel à la liste de diffusion cmake.

14
répondu Bill Hoffman 2013-02-19 12:29:55

je viens de taper le même numéro. Après avoir changé les chemins dans include_directories() d'absolu à relatif il a ajouté des dépendances appropriées.

ressemble à CMake tente de deviner quels en-têtes sont système et qui sont liés au projet. Je soupçonne que les répertoires qui commencent par / passent par -isystem /some/path et ne sont donc pas présentés dans les dépendances générées.

si vous ne pouvez pas remplacer ${FOO_SOURCE_DIR} par le chemin relatif, Vous pouvez essayer de calculer chemin relatif en utilisant les fonctions CMake appropriées. C'est-à-dire:

file(RELATIVE_PATH FOO_SOURCE_REL_DIR
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${FOO_SOURCE_DIR}/.)
include_directories(${FOO_SOURCE_REL_DIR}/include)
9
répondu ony 2014-11-06 12:42:01

apparemment, cmake supprime les chemins d'inclusion du système des arbres de dépendance (merci @ony pour cet indice). Cela a probablement du sens la plupart du temps, mais parfois cmake ne sait pas ce que le compilateur pense être un chemin système ou pas. Nous utilisons une construction gcc personnalisée qui ignore /usr/include , mais cmake pense qu'elle ne l'ignore pas. Pour forcer cmake à faire de /usr/include une dépendance qui n'est pas optimisée, essayez cette astuce: préparez /. au chemin.

j'essaie de faire en sorte que toutes les dépendances des bibliothèques utilisent la fonctionnalité de dépendance cmake, y compris certaines bibliothèques" tierces " qui ne sont pas toujours installées par défaut sur Linux ou même disponibles. Par exemple, la compression Z-lib.

la cible d'interface suivante fonctionnait très bien si les inclusions Z lib n'étaient pas dans /usr/include , mais se casseraient si elles l'étaient.

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})

j'ai changé la dernière ligne en

target_include_directories(zlib_target INTERFACE /.${ZLIB_INCLUDE_DIRS})

et cela a fonctionné. Maintenant les cibles qui dépendaient de zlib_target obtiendraient automatiquement -I/./usr/include pendant la compilation.

2
répondu Mark Lakata 2016-03-22 21:50:08

avez-vous lancé cmake avant ou après avoir ajouté les includes à vos fichiers cpp?

j'ai rencontré ce problème et j'ai relancé cmake. J'avais ajouté le comprennent post-cmake.

1
répondu Crazy Eddie 2012-12-30 02:28:31