7
votes

Dépendances de fichiers d'en-tête entre les modules C ++

À ma place, nous avons une grosse base de code C ++ et je pense qu'il y a un problème à quel point les fichiers d'en-tête sont utilisés.

Il y a de nombreux projets Visual Studio, mais le problème est dans le concept et n'est pas lié à vs. Chaque projet est un module, effectuant une fonctionnalité particulière. Chaque projet / module est compilé à la bibliothèque ou au binaire. Chaque projet dispose d'un répertoire contenant tous les fichiers source - * .cpp et * .h. Certains fichiers d'en-tête sont des API du module (je veux dire au sous-ensemble des fichiers d'en-tête déclarant API de la bibliothèque créée), certains sont internes à celui-ci.

Maintenant au problème - Lorsque le module A a besoin de fonctionner avec le module B, un répertoire source ajouté B pour inclure le chemin de recherche. Par conséquent, tous les en-têtes internes du module B de B sont visibles par un temps de compilation.

Comme effet secondaire, le développeur n'est pas obligé de concentrer quelle est l'API exacte de chaque module, que je considère comme une mauvaise habitude de toute façon.

Je considère comme une option comment elle devrait être sur la première place. J'ai pensé à créer dans Chaque projet Un répertoire dédié contenant uniquement des fichiers d'en-tête d'interface uniquement. Un module client souhaitant utiliser le module est autorisé à inclure uniquement le répertoire d'interface.

Cette approche est-elle ok? Comment le problème est résolu chez vous?

upd sur mon précédent endroit, le développement a été effectué sous Linux avec g ++ / gmake et nous avons en effet utilisé pour installer des fichiers d'en-tête API dans un répertoire commun. Certaines réponses proposent-elles. Nous avons maintenant un projet Windows (Visual Studio) / Linux (G ++) à l'aide de CMAKE pour générer des fichiers de projet. Comment dois-je forcer l'installation de Prebuild des fichiers d'en-tête API dans Visual Studio?

merci Dmitry


0 commentaires

6 Réponses :


3
votes

On dirait que vous êtes sur la bonne voie. De nombreuses bibliothèques tiers font ce même genre de choses. Par exemple:

3RDPARTY / MYLIB / SRC / -Contient les en-têtes et les fichiers source nécessaires pour compiler la bibliothèque
3RDParty / MyLib / Inclure / MyLib / - Contient les en-têtes nécessaires à des applications externes pour inclure P>

Certaines personnes / projets ne font que mettre les en-têtes à inclure par des applications externes dans / 3RDParty / mylib / incluent / incluent le Le répertoire myLib supplémentaire peut aider à éviter les collisions de noms. P>

Assumant votre utilisation de la structure: 3RDParty / MyLib / Inclure / MyLib / P>


In Makefile of external app:
---------------
INCLUDE =-I$(3RD_PARTY_PATH)/myLib/include
INCLUDE+=-I$(3RD_PARTY_PATH)/myLib2/include
...
...

In Source/Headers of the external app
#include "myLib/base.h"
#include "myLib/object.h"

#include "myLib2/base.h"


0 commentaires

2
votes

ne serait-il pas plus intuitif de mettre les en-têtes d'interface à la base du projet et de faire un sous-dossier (appelez-le «interne» ou «assistant» ou quelque chose comme ça) pour les en-têtes non-API?


1 commentaires

Je crois que Google place tous leurs en-têtes internes dans un dossier nommé interne.



0
votes

J'ai vu des problèmes comme celui-ci adressé en disposant d'un ensemble d'en-têtes dans le module B qui est copié dans le répertoire de publication avec la LIB dans le cadre du processus de construction. Le module A ne voit alors que ces en-têtes et n'a jamais accès aux internes de B. Habituellement, je n'ai vu que cela dans un grand projet publié publiquement.

Pour les projets internes, cela n'arrive pas. Ce qui arrive habituellement, c'est que quand ils sont petits, cela n'a pas d'importance. Et quand ils grandissent, il est si désordonné de le séparer personne ne veut le faire.


0 commentaires

0
votes

En règle générale, je viens de voir un répertoire incluant que tous les en-têtes d'interface sont emballés. Cela facilite parfaitement les en-têtes. Les gens doivent encore réfléchir à quels modules qu'ils prennent des dépendances lorsqu'ils spécifient les modules de la lieur.

Cela dit, je suis un peu comme votre approche. Vous pouvez même éviter d'ajouter ces répertoires au chemin Inclure, de sorte que les gens puissent indiquer quels modules un fichier source dépend des chemins relatifs de la page # par le haut.

En fonction de la manière dont votre projet est défini, cela peut être problématique lorsque vous y comprendez des en-têtes, cependant, car le chemin relatif d'un en-tête provient du fichier .CPP, non du fichier. Le fichier .h ne sait pas nécessairement où se trouvent ses fichiers .CPP.

Si vos projets ont une hiérarchie plate, cependant, cela fonctionnera. Dites que vous avez xxx

maintenant tout fichier d'en-tête peut inclure
#include ".. \ baz \ inc \ baz.h
et cela fonctionnera car tous les fichiers du CPP sont un niveau plus profond que la base.


0 commentaires

2
votes

où je travaille, nous avons une structure de dossiers de livraison créée à la hauteur de la construction. Les fichiers d'en-tête qui définissent des bibliothèques sont copiés dans un dossier Inclure. Nous utilisons des scripts de construction personnalisés qui permettent au développeur désigner quels fichiers d'en-tête doivent être exportés.

Notre construction est ensuite enracinée sur un STI ED Drive Cela nous permet d'utiliser des chemins absolus pour inclure des répertoires.

Nous avons également une version de référence basée sur le réseau qui nous permet d'utiliser un lecteur mappé pour inclure et des références libérations libres.

mise à jour: notre version de référence est une part réseau sur notre serveur de construction. Nous utilisons un script de référence de référence qui configure l'environnement et les cartes de construction (à l'aide de Utilisation nette ) la Nommé partager sur le serveur de construction (c.-à-d. \ bld_srv \ référence_build_share). Ensuite, pendant une construction hebdomadaire (ou manuellement), nous définissons la part (à l'aide de Share net ) pour pointer à la nouvelle construction.

Nos projets alors une liste de chemins absolus pour inclure et références libérences.

par exemple: xxx

Cela vous faudra d'abord des changements locaux, puis si vous n'avez pas fait de modifications locales (ou au moins, vous ne les avez pas construits), il utilisera les en-têtes et les libs de votre dernière construction sur le serveur de construction. < / p>


0 commentaires

0
votes

Dans un groupe, tout ce qui est public a été conservé dans un dossier spécifique au module, tandis que des trucs privés (en-tête privé, le fichier CPP, etc.) ont été conservés dans un dossier _IMP CODE> dans ce document:

#include <foo/foo.h>


0 commentaires