2010-11-02 4 views
0

Je sais que la marque récursive est réputée maléfique, etc. S'il vous plait, gardez-moi de toute façon.make récursif Q .: cible générique * après * autres cibles?

Nous gérons un projet relativement volumineux avec GNU make, qui utilise beaucoup make pour garder les fichiers individuels simples. Je voudrais ajouter une cible qui est exécutée après autres ciblés. Plus précisément, le problème est le suivant:

J'ai un Makefile comme ceci:

PROJ_SRC = a.cpp b.cpp 
PROJ_LIB = ab 

PROJ_SUBDIRS = x/ y/ z/ 
PROJ_EXAMPLES = example/ 

Je voudrais d'abord appeler faire dans le SUBDIRS x, y, z, puis construire la lib dans PWD lui-même , et seulement ensuite allez dans le sous-répertoire 'example' pour construire les exemples en utilisant cette lib.

Tout sauf le bit d'exemple fonctionne bien, mais je ne peux pas envelopper ma tête autour d'une solution propre pour ce dernier bit. Voici les choses que j'ai essayé:

# works ok for the target 'all', but nothing else 
all: subdirs ... $(PROJ_OBJ) $(PROJ_LIB_FULL) ... $(PROJ_EXAMPLES) 

# ugly, needs to be adde on all targets, and runs into examples 
# repeatedly if multiple targets get invoked. 
full_lib:: $(PROJ_LIB_FULL) 
$(PROJ_LIB_FULL):: subdirs 
    $(CXX) ... 
ifdef PROJ_EXAMPLES 
    $(MAKE) -C $(PROJ_EXAMPLES) 
endif 

# this does not make sense, as it builds the lib even on 'make clean' etc 
$(PROJ_EXAMPLES):: full_lib 

Une idée sur la façon de généraliser cela?

PS .: désolé si les extraits ci-dessus ne sont pas 100% propre syntaxe - ils sont juste censés illustrer le problème ...

Répondre

3

Il existe un moyen avancé pour « faire » un répertoire, de sorte que, pour Par exemple, vous ne devrez pas exécuter Make inutilement dans les sous-répertoires. Mais même sans cela, vous pouvez obtenir une solution assez propre:

$(PROJ_LIB): $(PROJ_SUBDIRS) 
    $(CXX) ... 

$(PROJ_EXAMPLES): $(PROJ_LIB) 
    $(MAKE) -C [email protected] 

.PHONY: clean 
clean: TARG=clean 
clean: $(PROJ_SUBDIRS) 
    $(MAKE) -C $(PROJ_EXAMPLES) [email protected] 

.PHONY: $(PROJ_SUBDIRS) 
$(PROJ_SUBDIRS): 
    $(MAKE) -C [email protected] $(TARG) 

Et si vous ne le faites pas comme ce truc pour éviter la construction de la bibliothèque lors du nettoyage, vous pouvez toujours avoir le example/ makedir être celui qui appelle à la bâtiment de la bibliothèque. Après tout, cette dépendance appartient vraiment à example.

EDIT:

Si vous êtes prêt à laisser example/Makefile gérer la dépendance lib, qui simplifie les choses. Vous pouvez très bien emballer les cibles récursives:

$(PROJ_LIB): $(PROJ_SUBDIRS) 
    $(CXX) ... 

RECURSIVES = clean distclean veryclean squeakyclean 
.PHONY: $(RECURSIVES) 

$(RECURSIVES): [email protected] 

ALL_SUBDIRS = $(PROJ_SUBDIRS) $(PROJ_EXAMPLES) 

# Maybe you want them all to recurse into the same directories: 
$(RECURSIVES): $(ALL_SUBDIRS) 

#...or maybe not: 
clean veryclean squeakyclean: $(ALL_SUBDIRS) 
distclean: $(PROJ_EXAMPLES) 

# This part does the recursion: 
.PHONY: $(ALL_SUBDIRS) 
$(ALL_SUBDIRS) 
    $(MAKE) -C [email protected] $(TARG) 

# And you still have to define the top-level rules: 

clean: 
    rm ... 

# Maybe nothing to do at this level for distclean 

veryclean: 
    rm ... and ... 

squeakyclean: 
    rm * 
+0

Salut bêta, merci pour vos commentaires! En effet, je n'aime pas l'astuce pour la cible de nettoyage - il y a trop de cibles que je devrais polluer comme ça. Mais je pense que vous avez raison: avoir la lib comme dépendance pour le répertoire des exemples devrait faire l'affaire, et est probablement la solution la plus propre. Merci beaucoup! :-) –

+0

Hmm, en y réfléchissant bien plus: la dépendance seule n'aide pas à passer en 'exmaple' sur 'make clean'. Nous revenons donc à la case départ: il faut ajouter le 'make -C' à toutes les cibles fausses (clean, distclean, ...)? –

+0

Hey, merci encore pour votre réponse! :-) Oui, c'est essentiellement comment nous gérons la récursivité en ce moment, ça marche bien. J'aime ton "squeakyclean" BTW ;-) –

Questions connexes