2010-07-21 5 views
3

Cette question est similaire dans l'esprit à la question 2543127. J'ai un makefile GNU avec une liste de fichiers d'en-tête. Chaque fichier d'en-tête peut se trouver dans un répertoire différent, par exemple,gnu faire copier plusieurs fichiers à un seul emplacement

HEADERS = $(wildcard *.h) $(wildcard foo/*.h) $(wildcard bar/*.h) 

et je veux avoir le makefile copier tous les en-têtes à un include

INCDIR = ../include 

et quand une cible factice, par exemple, ALL est invoquée, il mettra à jour les fichiers d'en-tête dans le répertoire include de manière appropriée, à savoir,

.PHONY: ALL 
ALL : $(addprefix $(INCDIR)/,$(notdir $(HEADERS))) 

de toute évidence, je pouvais accomplir ce que je veux assez facilement si je savais ce que les listes de répertoires wer e. Si je le faisais, je pourrais écrire quelques règles (quelque chose) comme si (pas tout à fait correct, mais vous obtenez le jist):

$(addprefix $(INCDIR)/,$(notdir $(filter foo/%.h,$(HEADERS)))) : %.h : foo/%.h 
    @cp -f $< [email protected] 

$(addprefix $(INCDIR)/,$(notdir $(filter bar/%.h,$(HEADERS)))) : %.h : bar/%.h 
    @cp -f $< [email protected] 

$(addprefix $(INCDIR)/,$(notdir $(filter-out bar/%.h,$(filter-out foo/%.h,$(HEADERS))))) : %.h : %.h 
    @cp -f $< [email protected] 

Il y a deux problèmes avec cette approche, (1) Il devient fastidieux que la le nombre de répertoires augmente et (2) j'écris ceci dans un makefile include, qui ne connaît pas les répertoires, tout ce qu'il sait, ce sont les variables INCDIR et HEADERS; il ne connait pas directement les répertoires foo /, bar /, et ./ autre que $ (trier $ (dir $ (HEADERS)))

Question: Comment puis-je écrire une règle pour obtenir l'effet désiré sous contraintes de ne fournir que les variables INCDIR et HEADERS.

Répondre

1

OK. La réponse est assez "facile", bien qu'elle nécessite l'utilisation de quelque gnou que je n'ai pas utilisé auparavant. Ma solution, crée un sous-programme qui nécessite 2 arguments: (1) le nom du fichier (sans répertoire) et (2) le nom du répertoire dans lequel il résidait. Le "sous-programme" est un modèle pour une règle. Quand on évalue l'appel au sous-programme, on initie une autre règle, comme si on l'avait explicitement écrit.

define COPY_HEADER 
$$(INCDIR)/$(2) : $(1)$(2) 
    @cp -f $$< [email protected] 
endef 

On évalue ensuite ce sous-programme pour chaque fichier d'en-tête et passe dans la partie du répertoire et la partie de chaque fichier d'en-tête.

$(foreach file,$(HEADERS),$(eval $(call COPY_HEADER,$(dir $(file)),$(notdir $(file))))) 
8

Cela devrait le faire:

HFILES = $(notdir $(HEADERS)) 
DIRS = $(dir $(HEADERS)) 

TARGETS = $(addprefix $(INCDIR)/, $(HFILES)) 

all: $(TARGETS) 

$(INCDIR)/%.h: %.h 
    cp $< [email protected] 

vpath %.h $(DIRS) 
Questions connexes