Comment ajouter correctement les répertoires include avec CMake

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

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

une recherche rapide dans le tutoriel CMake n'a indiqué que include_directories qui ne semble pas faire ce que je souhaite...

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 Makefile généré?

149
demandé sur Peter Mortensen 2012-12-04 17:04:54

4 réponses

Deux choses doivent être faites.

ajouter D'abord le répertoire à inclure:

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

dans le cas où vous êtes coincé avec une très ancienne version de CMake (2.8.10 ou plus ancienne) sans support pour target_include_directories , vous pouvez également utiliser l'héritage include_directories à la place:

include_directories(${YOUR_DIRECTORY})

ensuite, vous devez aussi 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 aussi 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})
178
répondu SirDarius 2018-09-15 23:07:05

tout d'abord, vous utilisez include_directories() pour dire à CMake d'ajouter le répertoire -I à la ligne de commande de compilation. Deuxièmement, vous énumérez les en-têtes dans votre appel add_executable() ou add_library() .

par exemple, si les sources de votre projet sont dans src , et 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
)
48
répondu Angew 2018-09-15 23:07:46

CMake est plus comme un langage de script si on le compare avec d'autres façons de créer Makefile (par exemple make ou qmake). Il n'est pas très cool comme Python, mais tout de même.

il n'y a pas une telle chose comme un " de la bonne façon " si on regarde dans divers projets opensource comment les gens incluent des répertoires. Mais il y a deux façons de le faire.

  1. Brut include_directories ajouter un répertoire du projet en cours et de tous les autres projets descendants que vous ajouterez par une série de commandes add_subdirectory . Parfois les gens disent qu'une telle approche est l'héritage.

  2. une façon plus élégante est avec target_include_directories . Il permet d'ajouter un répertoire pour un projet/cible spécifique sans (peut-être) hériter inutilement ou se heurter à divers répertoires include. Également permet d'effectuer même une configuration subtile et ajoute un des marqueurs suivants pour cette commande.

privé - utiliser seulement pour cette cible de construction spécifiée

PUBLIC - utilisez-le pour les cibles spécifiées et pour les cibles qui sont liées à ce projet

INTERFACE -- utilisez-le seulement pour les cibles qui se lient avec le courant projet

PS:

  1. " les deux commandes permettent de marquer un répertoire en tant que système pour donner une indication que ce n'est pas votre entreprise que les répertoires spécifiés contiendront 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

6
répondu bruziuz 2018-09-15 23:13:15

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

mon répertoire de projet était comme ceci:

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

et ce que j'ai utilisé pour inclure les fichiers dans tous ces dossiers:

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

    add_executable(Server ${source_files})

et ça a marché.

1
répondu Seyed Hussein Mirzaki 2018-09-15 23:13:49