web-dev-qa-db-fra.com

Quelle est la bonne structure de répertoires pour les grands projets C ++ utilisant Makefile?

Quelle est la bonne structure de répertoires pour les grands projets C++ utilisant Makefile?

Voici à quoi ressemble ma structure de répertoire en ce moment:

lib/ (class implementations *.cpp)
include/ (class definitions *.h)
tests/ (main.cpp for quick tests)

Maintenant, je ne sais pas à quoi devrait ressembler mon Makefile ... il ne semble pas fonctionner lorsque les fichiers .cpp et .h ne se trouvent pas dans le même répertoire. Quelqu'un pourrait-il m'indiquer une structure de répertoire commune avec un Makefile d'accompagnement afin que je ne réinvente pas la roue?

48
Olivier Lalonde

Séparer le .cpp du fichier .h n'est pas toujours une bonne solution. Généralement, je les sépare quand il est utilisé comme bibliothèque (en-tête public dans include et en-tête privé avec le code source).

S'il s'agit d'une bibliothèque, cette structure est correcte.

lib/ (class implementations *.cpp .h)
include/ (class definitions *.h) <- Only those to be installed in your system
tests/ (main.cpp for quick tests)
doc/ (doxygen or any kind of documentation)

S'il s'agit d'une application

src/ (source for the application)
lib/ (source for the application library *.cpp *.hpp)
include/ (interface for the library *.h)
tests/ (main.cpp for quick tests) <- use cppunit for this part
doc/ (doxygen or any kind of documentation)

Utilisez l'indicateur -I $ (PROJECT_BASE)/include pour spécifier le chemin d'inclusion pour la compilation

Si c'est un gros projet, il peut être bon d'utiliser des outils comme autoconf/automake ou cmake pour tout construire. Cela facilitera le développement.

57
Phong

Il n'y a pas de structure de répertoire spécifique ou requise.

Vous pouvez le configurer comme vous le souhaitez. Votre problème est simple à résoudre. Demandez simplement à Makefile de regarder dans les sous-répertoires ou de placer les objets compilés dans les sous-répertoires au lieu d'utiliser uniquement le répertoire courant.

Vous utiliseriez simplement dans les chemins Makefile:

%.o : %.cpp

remplacer par

bin/%.o : %.cpp

Ainsi, il vérifiera si le fichier binaire dans le répertoire bin existe et ainsi de suite, vous pouvez appliquer la même chose aux emplacements où les fichiers sont compilés.

Il existe des moyens d'ajouter/supprimer/modifier les chemins des fichiers source et objet.

Jetez un œil à gnu make manual , en particulier la section 8.3 Fonctions pour les noms de fichiers , et celle qui précède 8.2 Fonctions de substitution et d'analyse de chaînes .

Vous pouvez faire des choses comme:

obtenir une liste d'objets à partir de la liste des fichiers source dans le répertoire courant:

OBJ     = $(patsubst %.cpp, %.o, $(wildcard *.cpp))

Sortie:

Application.o Market.o ordermatch.o

Si les objets binaires sont dans le sous-répertoire bin mais que le code source est dans le répertoire courant, vous pouvez appliquer le préfixe bin aux fichiers objets générés:

OBJ     = $(addprefix bin/,$(patsubst %.cpp, %.o, $(wildcard *.cpp)))

Sortie:

bin/Application.o bin/Market.o bin/ordermatch.o

Etc.

12
stefanB

Si vous disposez de nombreux fichiers source, il peut également être judicieux de subdiviser davantage votre répertoire source. Par exemple, un sous-répertoire pour les fonctionnalités de base de votre application, un pour l'interface graphique, etc.

src/core
src/database
src/effects
src/gui
...

Cela vous oblige également à éviter les relations inutiles entre vos "modules", ce qui est une condition préalable au code Nice et réutilisable.

12
Gnurou

Il n'y a pas de "bonne structure de répertoires". Choisissez une structure avec laquelle vous êtes à l'aise et respectez-la. Certains aiment placer les fichiers source (en-têtes et fichiers d'implémentation) dans un src/ répertoire, donc le répertoire racine du projet n'a rien d'autre qu'un makefile, un readme et rien d'autre. Certains aiment placer les bibliothèques d'assistance sous un lib/ répertoire, unittests sous test/ ou src/test/, documentation sous doc/ etc.

Je n'ai encore entendu parler de personne divisant les fichiers d'en-tête et les fichiers d'implémentation en deux répertoires distincts. Personnellement, je n'aime pas trop diviser les fichiers en répertoires. Je place habituellement toute ma source dans un seul répertoire et toute la documentation dans un autre répertoire. Si je compte sur de bons outils de recherche de toute façon, il n'est pas nécessaire d'avoir une structure de répertoire complexe.

make peut gérer le type de structure où le makefile réside dans un répertoire différent de celui de la source. La seule chose est qu'il invoquera les règles du répertoire du makefile - les compilateurs n'ont généralement aucun problème à compiler la source qui se trouve dans un sous-répertoire. Vous n'avez pas besoin de spécifier de chemins relatifs dans votre #includes; spécifiez simplement le chemin d'inclusion avec les drapeaux du compilateur (gcc's -I drapeau etc).

6
wilhelmtell

Si vous ne l'avez pas vu avant lire Récursif Rendre Considéré Nocif .

Version courte et courte: Bien que très courant, l'idiome make récursif soit loin d'être optimal et s'aggrave à mesure que les projets deviennent plus grands et plus compliqués. Une alternative est présentée.

Lien connexe: Quelle est votre expérience avec la marque non récursive?

3
dmckee