J'utilise CMake sur un petit projet C++ et jusqu'à présent cela fonctionne très bien ... avec une torsion: x
Lorsque je modifie un fichier d'en-tête, cela 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 n'en détecte que certains des fichiers source à recompiler, conduisant à un état corrompu. Je peux contourner cela en effaçant le projet et en reconstruisant à partir de zéro, mais cela contourne l'objectif d'utiliser un utilitaire make: recompiler uniquement ce qui est nécessaire.
Par conséquent, je suppose que je fais quelque chose de mal.
Mon projet est très simplement organisé:
Le répertoire principal a:
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)
Où 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 me signaler mon erreur, la recherche ici ou sur CMake n'a rien donné, donc je suppose que c'est très facile ou devrait fonctionner 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 depend.make
fichier généré par CMake, et il manque en effet (gravement). Voici un exemple:
src/sub3/CMakeFiles/sub3.dir/File1.cpp.obj: ../src/sub3/File1.cpp
Oui, c'est tout, aucun des inclusions n'a été référencé du tout: x
Vous devriez regarder le depend.make
fichiers dans votre arbre binaire. Ce sera dans CMakeFiles/target.dir/depend.make
. Essayez de trouver l'un de ceux auxquels il manque un .h
fichier que vous pensez qu'il devrait avoir. Créez ensuite un rapport de bogue pour cmake ou envoyez un e-mail à la liste de diffusion cmake.
Je viens de toucher le même problème. Après avoir changé les chemins dans include_directories()
d'absolu en relatif, il a ajouté les dépendances appropriées.
On dirait que CMake essaie de deviner quels en-têtes sont du système et lesquels sont liés au projet. Je soupçonne que les répertoires commençant par /
passé comme -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}
avec un chemin relatif, vous pouvez essayer de calculer le 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)
Avez-vous exécuté cmake avant ou après avoir ajouté les inclusions à vos fichiers cpp?
J'ai rencontré ce problème et relancer cmake l'a corrigé. J'avais ajouté l'inclusion post-cmake.
Apparemment, cmake supprime les chemins d'accès au système des arbres de dépendance (merci @ony pour ce conseil). 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 non. Nous utilisons une version gcc personnalisée qui ignore /usr/include
, mais cmake pense qu'il ne l'ignore pas. Pour forcer cmake à faire /usr/include
une dépendance qui n'est PAS optimisée, essayez cette astuce: ajoutez /.
au chemin.
J'essaie de faire en sorte que toutes les dépendances de bibliothèque utilisent la fonction 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 a bien fonctionné si les inclusions de la bibliothèque Z n'étaient pas dans /usr/include
, mais se casserait s'ils 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 ça a marché. Désormais, les cibles qui dépendaient de zlib_target
obtiendrait automatiquement -I/./usr/include
lors de la compilation.