web-dev-qa-db-fra.com

cmake: add_subdirectory () vs include ()

Disons que j'ai un projet de test unitaire C++ utilisant cmake comme ceci:

$ tree
.
├── C-API-ConditionVariable-unit-test
│   ├── C-API-ConditionVariable-compile-link-test.c
│   ├── C-API-ConditionVariable-unit-test-0.cpp
│   └── C-API-ConditionVariable-unit-test-1.cpp
├── C-API-Mutex-unit-test
│   ├── C-API-Mutex-compile-link-test.c
│   ├── C-API-Mutex-unit-test-0.cpp
│   └── C-API-Mutex-unit-test-1.cpp
├── some
│   └── deeply
│       └── nested
│           └── path
│               └── SomeFeature-unit-test
│                   ├── SomeFeature-compile-link-test.c
│                   ├── SomeFeature-unit-test-0.cpp
│                   └── SomeFeature-unit-test-1.cpp
└── CMakeLists.txt

Chaque fichier source des sous-dossiers crée un exécutable distinct. J'aimerais que chaque sous-dossier du projet soit un module non autonome, c'est-à-dire que chaque sous-dossier est (plus ou moins) autonome, mais n'est PAS un projet autonome de cmake pouvant être compilé séparément. J'aimerais pouvoir ne construire que tout ou rien. Par exemple, je ne veux pas donner l’impression que vous pouvez exécuter cmake uniquement à partir de some/deeply/nested/path/SomeFeature-unit-test Pour ne construire que cela.

Quelle option devrais-je choisir?

  1. CMakeLists.txt Fichier dans chaque sous-dossier + add_subdirectory() au niveau supérieur CmakeLists.txt;
  2. some-random-name.cmake Dans chaque sous-dossier + include() au plus haut niveau CmakeLists.txt;
  3. ignorer l'idée que chaque sous-dossier doit être autonome et mettre toutes les informations de construction pertinentes dans le niveau supérieur CMakeLists.txt, les fichiers cmake supplémentaires uniquement en tant qu'aides (macros, fonctions, ...);

La première option est la plus pratique, mais elle suggère que chaque sous-dossier est en fait un projet autonome pouvant être compilé séparément.

La deuxième option semble clairement suggérer qu’il n’ya qu’un seul projet cmake ici. Mais dans chaque some-random-name.cmake Dans les sous-dossiers, je dois utiliser le chemin d'accès complet aux fichiers sources, ce qui va à l'encontre de mon désir que chacun d'eux soit autonome. S'il n'y a qu'un seul niveau d'imbrication (comme pour les deux premiers exemples de sous-dossiers), c'est bon, mais pour some/deeply/nested/path/SomeFeature-unit-test, Ce n'est pas très gentil. Je devrais aussi préfixer les noms des fichiers de sortie.

La troisième option semble être un moyen facile de créer rapidement un fichier CMakeLists.txt Avec une longueur de spaghetti, il est donc possible que je préfère autre chose.

Je voudrais savoir quelle est la voie "préférée" dans un projet cmake "moderne". Tous les tutoriels que j'ai pu trouver pour un projet multi-répertoires traitent du cas où il y a une bibliothèque autonome dans un dossier, une application autonome utilisant cette bibliothèque dans un autre dossier et des tests autonomes utilisant la même bibliothèque dans un autre répertoire. En regardant les projets utilisant cmake, je ne vois aucune cohérence, cela n'aide donc pas beaucoup.

(Je suis un cmake noob, essayant de convertir un projet relativement volumineux pour utiliser cmake)

21
Freddie Chopin

La règle la plus couramment utilisée est "Un CMakeLists.txt Par cible". Donc, votre option n ° 1.

Pour ce faire, votre structure de projet devra peut-être s'adapter si "chaque fichier source des sous-dossiers crée un exécutable séparé".

Et la racine CMakeLists.txt Est votre point de départ et contient la commande project().

Il est important de noter que

Ce que vous devriez éviter, c'est d'avoir à référencer des fichiers source à partir d'autres sous-répertoires avec quelque chose comme ../some_other_dir/some_other_source.cpp. Cela montre que votre structure CMake n'est pas configurée conformément à la règle générale citée ci-dessus.

Extraits de documentation

  1. CMake: add_subdirectory() commande

    Ajouter un sous-répertoire à la construction. Le source_dir Spécifie le répertoire dans lequel se trouvent la source CMakeLists.txt Et les fichiers de code.

  2. CLion: Fichier CMakeLists

    Lorsqu'un projet a la structure complexe et comprend un ou plusieurs sous-répertoires (racine et sous-répertoires du projet), vous pouvez créer des fichiers de sous-répertoire CMakeList.txt. Les fichiers de sous-répertoire CMakeLists.txt Décrivent les règles de construction, de contenu et de cible d'un sous-répertoire.

  3. C++ Now 2017: Daniel Pfeifer "Effective CMake: une sélection aléatoire de meilleures pratiques

    Les répertoires contenant un CMakeLists.txt Constituent le point d'entrée du générateur de système de génération. Des sous-répertoires peuvent être ajoutés avec add_subdirectory() et doivent également contenir un CMakeLists.txt.

Références

21
Florian