2010-01-12 7 views
12

C'è un modo per far funzionare GNU correttamente con nomi di file che contengono due punti?Faccine di escape nei nomi di file in un Makefile

Il problema specifico che sto incontrando riguarda una regola di modello. Ecco una versione semplificata che non dipende da caratteri di tabulazione taglia e incolla:

% make --version 
GNU Make 3.81 
Copyright (C) 2006 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. 
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE. 

This program built for x86_64-redhat-linux-gnu 
% cat Makefile 
COLON := \: 
all: ; true 
%.bar: ; cp $< [email protected] 
x.bar: x.foo 
%.foo: ; touch [email protected] 
a$(COLON)b.bar: a$(COLON)b.foo 
all: x.bar a$(COLON)b.bar 
clean: ; rm -f *.foo *.bar 
% make clean 
rm -f *.foo *.bar 
% make 
touch x.foo 
cp x.foo x.bar 
cp a\:b.bar 
cp: missing destination file operand after `a:b.bar' 
Try `cp --help' for more information. 
make: *** [a\:b.bar] Error 1 

Sostituzione $ (due punti) con un letterale: produce esattamente lo stesso risultato. Senza la barra inversa, lo fa:

Makefile:6: *** target pattern contains no `%'. Stop. 

risposta

2

Il seguente hack ha funzionato per me, anche se sfortunatamente si basa su $ (shell).

# modify file names immediately 
PRE := $(shell rename : @[email protected] *) 
# example variables that I need 
XDLS = $(wildcard *.xdl) 
YYYS = $(patsubst %.xdl,%.yyy,$(XDLS)) 
# restore file names later 
POST = $(shell rename @[email protected] : *) 

wrapper: $(YYYS) 
    @# restore file names 
    $(POST) 

$(YYYS): 
    @# show file names after $(PRE) renaming but before $(POST) renaming 
    @ls 

Poiché PRE viene assegnata: =, il suo comando shell associato viene eseguito prima viene valutata la variabile xDLS. La chiave è quindi rimettere i due punti dopo aver fatto esplicitamente invocare $ (POST).

+0

Abbastanza bravo! Sto bene con $ (shell), la mia domanda era specifica per fare GNU comunque. Immagino che questo sarebbe un esempio di "cattiva disposizione dei file temporanei" di cui stava parlando l'altra risposta. Mi preoccupo un po 'di ciò che accade nel caso in cui la cosa che "ls" è un segnaposto per fallire e $ (POST) quindi non funziona. Voglio dire, suppongo che sia probabilmente tutto OK perché $ (PRE) è idempotente, giusto? E se potresti avere @ COLON @ nei tuoi nomi di file, basta usare un segnaposto ancora più lungo e ridicolo, magari con una lunga stringa casuale incorporata in esso .... – zaphod

0

Non sto positivie questo dovrebbe funzionare, ma la ragione si dice "file di destinazione mancante" è semplice:

%.bar: ; cp $< [email protected] 

Quella linea dice di copiare il bersaglio dalla dipendenza prima. il tuo a: b.bar non ha alcuna dipendenza, quindi il cp fallisce. cosa volevi che copiasse? a: b.foo? in tal caso, si avrebbe bisogno:

%.bar: %.foo ; cp $< [email protected] 
+0

La regola generale non ha dipendenze, ma fornisco una prima dipendenza per due casi specifici nelle regole successive. Sì, non mi rendevo conto che anche tu potevi farlo, ma si scopre che puoi. Noterai che è in grado di capire come creare x.bar da x.foo bene. – zaphod

9

Dubito che sia possibile: vedi this discussion about colons in Makefiles. In sintesi, GNU make non ha mai funzionato bene con nomi di file che contengono spazi vuoti o due punti. Il maintainer, Paul D. Smith, afferma che l'aggiunta del supporto per l'escape tenderebbe a break existing makefiles. Inoltre, l'aggiunta di tale supporto richiederebbe modifiche significative al codice.

Si potrebbe essere in grado di aggirare con una sorta di brutto accordo di file temporaneo.

Buona fortuna!

+0

buona scoperta. Questo è quello di cui avevo paura quando ho detto che non ero sicuro che avrebbe dovuto funzionare! – Bahbar

+0

Wow! non è divertente. Make è parte integrante del mio flusso di lavoro. Sono imbestialito che questo non è possibile – AndyL

1

C'è un altro modo che ho trovato oggi quando si tratta di variabili Makefile che definiscono nomi di file (contenenti due punti).

# definition 
SOME_FNAME = $(NAME)__colon__$(VERSION) 

# usage in target 
foo: 
    $(do_something) $(subst __colon__,:,$(SOME_FNAME))