web-dev-qa-db-fra.com

Comment puis-je créer un projet C ++ avec plusieurs sous-répertoires interdépendants?

J'ai un projet C++ où j'ai utilisé des répertoires comme plus d'un élément organisationnel - la façon dont on pourrait utiliser des packages en Java ou des répertoires en PHP. Les répertoires ne sont pas destinés à être autosuffisants éléments, mais plutôt juste une façon d'organiser l'ensemble du projet et de m'empêcher d'être submergé par les sources. Comment puis-je construire mes fichiers CMakeLists.txt pour y faire face? Faire les bibliothèques de répertoires ne semble pas correspondre ici, car ils sont tous interdépendants et ne sont pas destinés à être utilisés de cette façon.

Comme problème connexe, la plupart des exemples que j'ai vus de plusieurs sous-répertoires dans CMake (et il n'y en a pas beaucoup) ont ignoré ou ignoré le problème de la définition de include_directories, ce qui me pose problème. À moins de peigner mes fichiers source pour déterminer quel fichier dépend de quel répertoire et dans quel répertoire, existe-t-il de toute façon de définir tous les répertoires sous /src/ comme potentiel, inclure les répertoires et laisser CMake déterminer ceux qui sont réellement dépendants?

Voici un exemple de structure:

--src
  --top1
    --mid1
      --bot1
        --src1.cpp
        --hdr1.h
      --bot2
        --src2.cpp
        --hdr2.h
    --mid2
      --bot3
        --src3.cpp
        --src4.cpp
        --hdr3.h
  --top2
    --mid3
      --src5.cpp
      --hdr4.h

Etc., etc. Comment puis-je structurer mon CMakeLists.txt fichiers pour gérer ce type de structure?

65
Daniel Bingham

Puisque la structure de répertoires de votre projet est juste là pour garder vos fichiers organisés, une approche consiste à avoir un CMakeLists.txt Qui trouve automatiquement tous les fichiers sources dans le répertoire src et ajoute également tous les répertoires comme include répertoires contenant un fichier d'en-tête. Le fichier CMake suivant peut servir de point de départ:

cmake_minimum_required(VERSION 3.0)

project (Foo)

file(GLOB_RECURSE Foo_SOURCES "src/*.cpp")
file(GLOB_RECURSE Foo_HEADERS "src/*.h")

set (Foo_INCLUDE_DIRS "")
foreach (_headerFile ${Foo_HEADERS})
    get_filename_component(_dir ${_headerFile} PATH)
    list (APPEND Foo_INCLUDE_DIRS ${_dir})
endforeach()
list(REMOVE_DUPLICATES Foo_INCLUDE_DIRS)

add_executable (FooExe ${Foo_SOURCES})
target_include_directories(FooExe PRIVATE ${Foo_INCLUDE_DIRS})

Les deux commandes file(GLOB_RECURSE ... Déterminent l'ensemble des fichiers source et d'en-tête. La boucle foreach calcule l'ensemble des répertoires d'inclusion à partir de la liste de tous les fichiers d'en-tête.

Un inconvénient du calcul de l'ensemble des fichiers source est que CMake ne détectera pas automatiquement lorsque de nouveaux fichiers sont ajoutés à votre arborescence source. Vous devez ensuite recréer manuellement vos fichiers de construction.

59
sakra

Je ne suis pas un expert de CMake mais comme il n'y a pas d'autre réponse, je vais jeter un œil à la documentation et l'essayer. Organiser les fichiers source et inclure dans différents répertoires est à peu près la norme.

Il semble que CMake vous permet de donner une liste de répertoires d'inclusion: http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories

Donc quelque chose comme:

include_directories("src/top1/mid1/bot1" "src/top1/mid1/bot2/" ... )

Celles-ci sont transmises au compilateur afin qu'il puisse trouver les fichiers d'en-tête et seront transmises pour chacun des fichiers source. Donc, n'importe lequel de vos fichiers source devrait pouvoir inclure n'importe lequel des fichiers d'en-tête (ce que je pense que c'est ce que vous demandez).

De même, vous devriez pouvoir lister tous vos fichiers sources dans la commande add_executable :

add_executable(name "src/top1/mid1/bot1/src1.cpp" "src/top1/id1/bot2/src2.cpp" ...)

Ce serait donc un moyen naïf de tout construire. Chaque fichier source sera compilé et recherchera les en-têtes dans tous ces répertoires, puis les fichiers objets seront liés ensemble. Considérez s'il existe un moyen de simplifier cela de sorte que vous n'ayez pas besoin d'autant de dossiers d'inclusion, il n'y a peut-être que quelques fichiers d'en-tête communs qui doivent être référencés par tous les fichiers source. Si les choses deviennent plus complexes, vous pouvez créer des sous-hiérarchies dans les bibliothèques, etc. Envisagez également de séparer les fichiers source et les en-têtes (par exemple dans src et include).

2
Guy Sirton