2012-12-03 4 views
6

j'ai une structure de répertoires suivante dans mon projet:Bonnes pratiques de Makefile

bin/ 
dist/ 
include/ 
├── module_a/ 
└── module_b/ 
Makefile 
src/ 
├── module_a/ 
└── module_b/ 

dossier include/ contient *.hpp 's tandis que *.cpp' s sont src/. Je voudrais compiler toutes les sources à bin/, puis les lier ensemble à . Semble un souhait assez raisonnable pour moi.

Je voudrais connaître les meilleures pratiques pour un Makefile pour ce cas. Tout ce que je peux trouver est %.o: %.cpp cible, mais cela ne fonctionne pas vraiment, en raison de la source différente et le dossier binaire.

je tentais d'utiliser quelque chose comme ceci:

D_SRC = src 
D_BIN=bin 

F_CPP := $(shell find $(D_SRC) -iname '*.cpp' -type f) 
F_OBJ := $(shell echo $(F_CPP) | sed s:\ :\\n:g | sed s:$(D_SRC):$(D_BIN): | sed 's:^\(.*\)\.cpp$$:\1\.o:') 

$(F_OBJ): $(F_SRC)                 
    $(foreach file, $(F_SRC), \              
     $(GXX) $(CXXFLAGS) -c $(file)\            
    ) 

Cet objectif ne fonctionne pas, car $(F_OBJ) chemins commencent par bin/, tandis que foreach compile les sources de répertoire de travail courant. Je pourrais le faire compiler à bin/, mais cela n'arriverait qu'avec quelques autres expressions sed et c'est assez moche comme ça.

C'est probablement si difficile pour moi, parce que je ne connais pas très bien le make, mais je ne peux pas être le seul avec cette configuration de projet. À mon avis, il doit être assez commun. Je sais que je peux écrire un Makefile pour chaque module séparément, mais est-ce vraiment le meilleur choix ici?

EDIT: Je me demandais maintenant ce que j'allais obtenir avec plusieurs Makefiles. Si l'un était à la racine et l'autre au src/module_a, comment ce dernier connaîtrait-il le bin/? Si vous l'exécutez avec make -f src/module_a/Makefile, ce serait comme si vous l'exécutiez à partir du répertoire racine, car son répertoire de travail serait root. Une autre façon, je suppose, serait de changer de répertoire avant de l'exécuter, comme ceci: make -C include/module_a, mais dans ce cas, comment trouverait-il bin/? Je ne voudrais pas avoir quelque chose comme D_BIN = ../../bin dans un Makefile.

+0

Mis à jour ma réponse ... –

Répondre

6

Ce que je fais d'habitude est d'avoir un Makefile dans le répertoire src (qui peut être invoqué à partir du haut niveau Makefile si vous le souhaitez), puis utiliser des règles comme ceci:

D_BIN = ../bin 
$(D_BIN)/%.o: %.cpp 

Vous pouvez également expérimenter avec juste un makefile dans le répertoire de haut niveau, et les règles d'utilisation qui ressemblent à ceci:

D_BIN = bin 
D_SRC = src 
$(D_BIN)/%.o: $(D_SRC)/%.cpp 

mais je ne l'ai pas utilisé ces règles, donc je ne sais pas les avantages/inconvénients contre la façon dont je le fais normalement. La façon dont je le fais normalement il fonctionne très bien, j'ai même des règles qui construire dépendances comme ceci:

$(D_BIN)/%.d: %.cpp 

et la règle de lien serait comme:

../dist/outexe: $(F_OBJ) 

L'utilisation d'un foreach est généralement mal vus parce qu'il n'utilise pas toutes les fonctionnalités intégrées dans les règles makefile normales (ie il n'y a pas de contrôle dépend par fichier, soit vous construisez tout ou rien), et donc foreach ne doit être utilisé qu'en dernier recours, mais dans ce cas cas, vous serez en mesure de le faire fonctionner sans foreach. En plus de cela, il existe des moyens beaucoup plus faciles de construire vos listes de fichiers, vous n'avez pas besoin d'utiliser le shell ou sed.

F_CPP = $(wildcard *.cpp) 
F_OBJ = $(F_CPP:.cpp=.o) 

Mise à jour: Voici comment j'émets rend normalement récursives:

SUBDIRS = src 
.PHONY: $(SUBDIRS) 
all: $(SUBDIRS) 

$(SUBDIRS): 
    @echo "Building [email protected]" 
    $(MAKE) -C [email protected] $(MFLAGS) 

Alors, en effet dans votre submake, vous devez utiliser ../bin par exemple.

Cependant, avec un projet aussi simple que le vôtre, vous pourriez être mieux avoir juste un makefile au niveau des racines et en utilisant des règles comme ceci:

D_BIN = bin 
D_SRC = src 
$(D_BIN)/%.o: $(D_SRC)/%.cpp 

makefiles récursives sont ok (ok, mais pas super) si vous disposez d'une structure de répertoires vraiment complexe, dans laquelle vous ajouterez/supprimerez/modifierez de nouveaux arbres dir au fil du temps. Mais pour un projet simple où vous voulez juste avoir des répertoires séparés pour le code et les obj, c'est probablement trop.

+0

Cela ressemble à tout ce que je cherchais. Je ne peux pas le tester maintenant, mais pour autant que je sache, cela fonctionnera. Merci beaucoup. –