web-dev-qa-db-fra.com

Comment ajouter correctement des répertoires d'inclusion avec CMake

Il y a environ un an, j'ai posé une question sur dépendances d'en-tête dans CMake .

J'ai réalisé récemment que le problème semblait être que CMake considérait que ces fichiers d'en-tête étaient externes au projet. Au moins, lors de la génération d'un projet Code :: Blocks, les fichiers d'en-tête n'apparaissent pas dans le projet (les fichiers source le font). Il me semble donc que CMake considère que ces en-têtes sont externes au projet et ne les suivent pas dans les dépendances.

Une recherche rapide dans le tutoriel CMake a seulement indiqué include_directories qui ne semble pas faire ce que je veux ...

Quelle est la bonne façon de signaler à CMake qu’un répertoire particulier contient des en-têtes à inclure, et que ces en-têtes doivent être suivis par le fichier Makefile généré?

195
Matthieu M.

Deux choses doivent être faites.

Ajoutez d’abord le répertoire à inclure:

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

Si vous êtes coincé avec une très ancienne version de CMake (2.8.10 ou plus ancienne) sans la prise en charge de target_include_directories, vous pouvez également utiliser l'héritage include_directories:

include_directories(${YOUR_DIRECTORY})

Ensuite, vous devez également ajouter les fichiers d'en-tête à la liste de vos fichiers source pour la cible actuelle, par exemple:

set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(test ${SOURCES})

De cette façon, les fichiers d'en-tête apparaîtront comme des dépendances dans le Makefile et, par exemple, dans le projet Visual Studio généré, si vous en générez un.

Comment utiliser ces fichiers d'en-tête pour plusieurs cibles:

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

Tout d’abord, vous utilisez include_directories() pour indiquer à CMake d’ajouter le répertoire sous le nom -I à la ligne de commande de la compilation. Deuxièmement, vous listez les en-têtes dans votre appel add_executable() ou add_library().

Par exemple, si les sources de votre projet sont dans src et que vous avez besoin des en-têtes de include, vous pouvez le faire comme ceci:

include_directories(include)

add_executable(MyExec
  src/main.c
  src/other_source.c
  include/header1.h
  include/header2.h
)
59
Angew

CMake s'apparente davantage à un langage de script si on le compare à d'autres méthodes pour créer un fichier Makefile (par exemple make ou qmake). Ce n'est pas très cool comme Python, mais quand même.

Il n’existe pas de méthode " correcte " si vous regardez dans différents projets opensource comment les gens incluent les répertoires. Mais il y a deux façons de le faire.

  1. Crude include_directories ajoutera un répertoire au projet actuel et à tous les autres projets descendants que vous ajouterez via une série de commandes add_subdirectory . Parfois, les gens disent qu'une telle approche est un héritage.

  2. Une méthode plus élégante consiste à utiliser target_include_directories . Il permet d’ajouter un répertoire pour un projet/cible spécifique sans héritage inutile (ou peut-être) inutile ni conflit entre plusieurs répertoires d’inclusion. Permet également d'effectuer même une configuration subtile et d'ajouter l'un des marqueurs suivants pour cette commande.

PRIVATE - à utiliser uniquement pour cette cible de construction spécifiée

PUBLIC - utilisez-le pour la cible spécifiée et pour les cibles liées à ce projet

INTERFACE - ne l'utilisez que pour les cibles reliées au projet en cours

PS:

  1. Les deux commandes permettent de marquer un répertoire en tant que SYSTEM afin d'indiquer que ce n'est pas votre entreprise que les répertoires spécifiés contiennent des avertissements.

  2. Une réponse similaire est avec d'autres paires de commandes target_compile_definitions / add_definitions , target_compile_options / CMAKE_C_FLAGS

11
bruziuz

J'ai eu le même problème.

Le répertoire de mon projet était comme ceci:

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

Et ce que j’avais l'habitude d'inclure les fichiers dans tous ces dossiers:

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

    add_executable(Server ${source_files})

Et cela a totalement fonctionné.

5

Ajouter include_directories("/your/path/here").

Ce sera similaire à l'appel de gcc avec l'option -I/your/path/here/.

Assurez-vous de mettre des guillemets doubles autour du chemin. D'autres personnes n'en ont pas parlé et cela m'a fait rester bloqué pendant 2 jours. Cette réponse s'adresse donc aux personnes très novices et très confuses dans CMake.

3
off99555