Raar voor elk + door de gebruiker gedefinieerd functiegedrag in Makefiles

Ik heb de volgende Makefile:

X=a.jar b.jar c.jar
Y=/var/tmp/abc/a.jar /var/tmp/abc/b.jar /var/tmp/abc/c.jar

all: $(addprefix /var/tmp/abc/tmp/, $(X))

define AddRule
dst=$1
src=$2
/var/tmp/abc/tmp/$(dst): $(src)
        @echo [email protected]
        @echo $$^
        @mkdir -p $$(dir [email protected])
        @cp $$^ [email protected]
endef
$(foreach jar, $(X), $(eval $(call AddRule, $(jar), $(filter %$(jar), $(Y)))))

(/var/tmp/abc/{a,b,c}.jar bestaat)

Eigenlijk wil ik voor elke bestandsnaam in $ X het volledige pad in $ Y vinden en een regel maken die dat bestand kopieert naar/var/tmp/abc/tmp (ik weet dat er een veel eenvoudigere manier is om dit te doen, maar mijn werkelijke Makefile is ingewikkelder en heeft een constructie als deze nodig).

Wanneer ik deze Makefile start, krijg ik de volgende uitvoer:

/var/tmp/abc/tmp/a.jar
/var/tmp/abc/a.jar
/var/tmp/abc/tmp/b.jar
/var/tmp/abc/b.jar
make: *** No rule to make target `/var/tmp/abc/tmp/c.jar', needed by `all'.  Stop.

Nu het "grappige" gedeelte: als ik de volgende regel toevoeg na het declareren van de "alles" -regel:

X+=d

alle drie de jar-bestanden worden verwerkt, 'make' vermeldt niets over 'd' (zelfs als bestand 'd' niet bestaat) en de run is een succes.

Dus het lijkt erop dat de foreach-lus niet de laatste iteratie doormaakt (of hoogstwaarschijnlijk iets anders dat tot dezelfde resultaten leidt). Weet iemand wat het probleem is en hoe het op te lossen?

Bedankt!

1

1 antwoord

Het is niet alleen de laatste iteratie van de lus die slecht is. In principe breidt aanroep $ (dst) uit tot de waarde wanneer aanroep wordt aangeroepen , niet wanneer de nieuwe code wordt geëvalueerd. Vervolgens wordt de nieuwe code geëvalueerd en in de volgende iteratie wordt de definitie uitgebreid - met de waarden die zijn ingesteld door het vorige blok nieuwe code. Dus in plaats van {a, b, c} geeft het {, a, b} (je moet hier een tijdje naar staren voordat het zinvol is).

Oplossing: plaats een paar extra $ s:

define AddRule
dst=$1
src=$2
/var/tmp/abc/tmp/$$(dst): $$(src)
    ...
endef
2
toegevoegd
Bedankt! Dat maakte het!
toegevoegd de auteur user1042699, de bron