Pergunta

Existe uma maneira de fazer o GNU make funcionar corretamente com nomes de arquivos que contêm dois pontos?

O problema específico que estou enfrentando envolve uma regra padrão.Aqui está uma versão simplificada que não depende de recortar e colar caracteres de tabulação:

% 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 $< $@
x.bar: x.foo
%.foo: ; touch $@
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

Substituindo $(COLON) por um literal:produz exatamente o mesmo resultado.Sem a barra invertida, faz o seguinte:

Makefile:6: *** target pattern contains no `%'.  Stop.
Foi útil?

Solução

O hack seguinte funcionou para mim, embora infelizmente dependa de $ (shell).

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

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

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

Porque o PRE é atribuído com: =, seu comando shell associado é executado antes que a variável XDLS seja avaliada. A chave é colocar os dois pontos de volta no lugar após o fato, invocando explicitamente $ (post).

Outras dicas

Duvido que seja possível: veja Esta discussão sobre os pontos em makefiles. Em resumo, a GNU Make nunca funcionou bem com os nomes de arquivos que contêm espaço em branco ou colonos. O mantenedor, Paul D. Smith, diz que a adição de apoio à fuga tenderia a quebrar o makefiles existentes. Além disso, adicionar esse suporte exigiria alterações significativas ao código.

Você pode ser capaz de contornar com algum tipo de arranjo de arquivo temporário desagradável.

Boa sorte!

Existe outra maneira que encontrei hoje ao lidar com variáveis ​​​​Makefile que definem nomes de arquivos (contendo dois pontos).

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

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

Não sou positivie, isso deve funcionar, mas a razão pela qual diz "Falta de Arquivo de Destino" é simples:

%.bar: ; cp $< $@

Essa linha diz para copiar o alvo do primeiro dependência. Seu A: B.bar não tem algum Dependência, então o CP falha. O que você queria copiar? A: B.FOO? Nesse caso, você precisaria:

%.bar: %.foo ; cp $< $@
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top