2010-01-12 13 views
12

Existe-t-il un moyen de faire fonctionner GNU make avec des noms de fichiers contenant des deux-points?Echapper des deux-points dans les noms de fichiers dans un Makefile

Le problème spécifique que je rencontre concerne une règle de modèle. Voici une version simplifiée qui ne dépend pas de tabulation couper et coller des caractères:

% 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 

Remplacement $ (COLON) avec un littéral: produit exactement le même résultat. Sans la barre oblique inverse, il le fait:

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

Répondre

2

Le hack suivant a fonctionné pour moi, bien qu'il se repose malheureusement sur $ (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 

Comme PRE est affecté avec: =, sa commande shell associée est exécutée avant la variable de xDLS est évaluée. La clé est alors de remettre les deux-points en place après le fait en invoquant explicitement $ (POST).

+0

Assez bon hack! Je vais bien avec $ (shell), ma question était spécifique à GNU make de toute façon. Je suppose que ce serait un exemple de «mauvais agencement de fichiers temporaires» dont l'autre réponse parlait. Je m'inquiète un peu de ce qui se passe dans le cas où la chose qui "ls" est un espace réservé pour échouer et $ (POST) ne fonctionne donc pas. Je veux dire, je suppose que c'est probablement la plupart du temps OK parce que $ (PRE) est idempotent, non? Et si vous avez des @ COLON @ s réels dans vos noms de fichiers, vous utilisez simplement un espace réservé encore plus long et plus ridicule, peut-être avec une longue chaîne aléatoire intégrée .... – zaphod

0

Je ne suis pas positivie cela devrait fonctionner, mais la raison pour laquelle il est dit « manquant fichier de destination » est simple:

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

Cette ligne dit à copier la cible à partir de la première dépendance. votre a: b.bar n'a pas aucune dépendance, donc le cp échoue. qu'est-ce que tu voulais copier? un: b.foo? dans ce cas, vous devez:

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

La règle générale n'a aucune dépendance, mais je fournis une première dépendance pour deux cas spécifiques dans les règles suivantes. Ouais, je ne savais pas que tu pouvais faire ça non plus, mais il s'avère que tu peux. Vous remarquerez qu'il est capable de comprendre comment créer x.bar à partir de x.foo très bien. – zaphod

9

Je doute qu'il est possible: voir this discussion about colons in Makefiles. En résumé, GNU make n'a jamais bien fonctionné avec les noms de fichiers contenant des espaces ou des deux-points. Le mainteneur, Paul D. Smith, dit que l'ajout du support pour l'évasion aurait tendance à break existing makefiles. De plus, l'ajout d'un tel support nécessiterait des changements importants au code.

Vous pourriez être en mesure de contourner une sorte de mauvais agencement de fichiers temporaires.

Bonne chance!

+0

bonne trouvaille. C'est ce dont j'avais peur quand j'ai dit que je n'étais pas certain que ça devrait marcher! – Bahbar

+0

Wow! ce n'est pas amusant. Make fait partie intégrante de mon flux de travail. Je suis dégouté que ce n'est pas possible – AndyL

1

Il y a un autre moyen que j'ai trouvé aujourd'hui en traitant des variables Makefile définissant des noms de fichiers (contenant des deux-points).

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

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