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 en tant qu’élément d’organisation – comme on pourrait utiliser des packages en Java ou des répertoires en PHP. Les répertoires ne sont pas conçus pour être des éléments autosuffisants, mais plutôt comme un moyen d’organiser l’ensemble du projet et de ne pas être submergé par des 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 elles sont toutes interdépendantes et non destinées à être utilisées de cette manière.

En tant que problème connexe, la plupart des exemples de plusieurs sous-répertoires de CMake (et peu nombreux) que j’ai vus ont ignoré ou dissimulé la question de la définition de include_directories , avec laquelle j’ai eu des problèmes. . En dehors de combiner mes fichiers source pour déterminer quel fichier dépend de quel répertoire et dans quel répertoire, est-il toujours possible de définir tous les répertoires sous /src/ comme répertoires d’inclusion potentiels et de 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 mes fichiers CMakeLists.txt pour gérer ce type de structure?

Comme 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 en tant que répertoires include contenant un fichier d’en-tête. . Le fichier CMake suivant peut servir de sharepoint 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 file(GLOB_RECURSE ... 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 include à partir de la liste de tous les fichiers d’en-tête.

Un inconvénient avec le calcul de l’ensemble des fichiers sources est que CMake ne détectera pas automatiquement les nouveaux fichiers ajoutés à votre arbre source. Vous devez manuellement recréer vos fichiers de génération alors.

Je ne suis pas un expert en CMake mais, comme il n’y a pas d’autres réponses, je vais jeter un coup d’œil à la documentation. Organiser la source et inclure des fichiers dans différents répertoires est à peu près la norme.

Il semble que CMake vous permette de donner une liste de répertoires inclus: 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/" ... ) 

Ceux-ci sont transmis au compilateur afin qu’il puisse trouver les fichiers d’en-tête et seront transmis pour chacun des fichiers source. Tous vos fichiers sources doivent donc pouvoir inclure tous les fichiers d’en-tête (ce que je pense être 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 une façon naïve de tout construire. Chaque fichier source sera compilé et cherchera les en-têtes dans tous ces répertoires, puis les fichiers objects seront liés ensemble. Considérez s’il existe un moyen de simplifier cela, de sorte que vous n’ayez pas besoin de tant de dossiers d’inclusion, il y a peut-être seulement quelques fichiers d’en-tête communs qui doivent être référencés par tous les fichiers sources. Si les choses deviennent plus complexes, vous pouvez créer des sous-hiérarchies dans des bibliothèques, etc. Envisagez également de séparer les fichiers source et les en-têtes (par exemple, dans src et include).