2010-01-12 11 views
12

¿Hay alguna manera de hacer que GNU funcione correctamente con nombres de archivo que contienen dos puntos?Escapar dos puntos en nombres de archivo en un Makefile

El problema específico que me encuentro pasa a involucrar una regla de patrón. Aquí hay una versión simplificada que no depende de cortar y pegar caracteres de tabulación:

% 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 

Sustitución $ (colon) con un literal: produce exactamente el mismo resultado. Sin la barra invertida, lo hace:

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

Respuesta

2

El siguiente truco funcionó para mí, aunque lamentablemente se basa en $ (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 

Debido PRE se asigna con: =, su comando shell asociado se ejecuta antes se evalúa la variable xDLS. La clave es volver a poner los dos puntos en su lugar después del hecho al invocar explícitamente $ (POST).

+0

¡Bastante bien hack! Estoy bien con $ (shell), mi pregunta fue específica para GNU make de todos modos. Supongo que este sería un ejemplo de un "desagradable arreglo temporal de archivos" del que la otra respuesta estaba hablando. Me preocupa un poco lo que sucede en el caso en que lo que "ls" es un marcador de posición para fail y $ (POST) no se ejecuta. Quiero decir, creo que probablemente sea más que correcto porque $ (PRE) es idempotente, ¿no? Y si puede tener @ COLON @ s reales en los nombres de sus archivos, simplemente use un marcador de posición aún más largo y más ridículo, tal vez con una larga secuencia aleatoria incrustada en él .... – zaphod

0

No estoy positivie esto debería funcionar, pero la razón por la que dice "falta archivo de destino" es simple:

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

Esa línea dice que copiar el objetivo de la primera dependencia. su a: b.bar no tiene ninguna dependencia, por lo que la cp falla. ¿Qué quieres que copie? a: b.foo? en ese caso, sería necesario:

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

La regla general no tiene dependencias, pero proporciono una primera dependencia para dos casos específicos en reglas posteriores. Sí, no me di cuenta de que podrías hacer eso tampoco, pero resulta que puedes. Notarás que es capaz de descubrir cómo crear x.bar desde x.foo bien. – zaphod

9

Dudo que sea posible: ver this discussion about colons in Makefiles. En resumen, la creación de GNU nunca funcionó bien con los nombres de archivo que contienen espacios en blanco o dos puntos. El responsable, Paul D. Smith, dice que agregar soporte para escaparse tendería a break existing makefiles. Además, agregar tal soporte requeriría cambios significativos en el código.

Es posible que pueda trabajar con algún tipo de organización desagradable de archivos temporales.

¡Buena suerte!

+0

buen descubrimiento. ¡Eso es a lo que le tenía miedo cuando dije que no estaba seguro de que debería funcionar! – Bahbar

+0

¡Guau! eso no es divertido. Hacer es parte integral de mi flujo de trabajo. Estoy triste de que esto no sea posible – AndyL

1

Hay otra forma que he encontrado hoy en día cuando se trata de variables Makefile que definen nombres de archivo (que contienen dos puntos).

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

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