Unix 在Makefile中转义文件名中的冒号

Unix 在Makefile中转义文件名中的冒号,unix,makefile,gnu-make,Unix,Makefile,Gnu Make,有没有办法让GNU make正确处理包含冒号的文件名 我遇到的具体问题恰好涉及一个模式规则。以下是一个简化版本,它不依赖于剪切和粘贴制表符: % 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

有没有办法让GNU make正确处理包含冒号的文件名

我遇到的具体问题恰好涉及一个模式规则。以下是一个简化版本,它不依赖于剪切和粘贴制表符:

% 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

我不认为这会起作用,但它说“缺少目标文件”的原因很简单:

%.bar: ; cp $< $@
%.条:;cp$<$@
该行表示从第一个依赖项复制目标。您的a:b.bar没有任何依赖项,因此cp失败。你想让它复制什么?a:b.foo?在这种情况下,您需要:

%.bar: %.foo ; cp $< $@
%.bar:%.foo;cp$<$@

我怀疑这是否可能:请参阅。总之,gnumake从来没有很好地处理过包含空格或冒号的文件名。维护人员Paul D.Smith说,增加对转义的支持将有助于解决问题。此外,添加此类支持需要对代码进行重大更改

你也许可以处理一些讨厌的临时文件安排


祝你好运

下面的hack对我有效,但不幸的是它依赖于$(shell)


因为PRE被赋值为:=,所以在计算XDLS变量之前会运行其关联的shell命令。关键是通过显式调用$(POST)将冒号放回原处。

在处理定义文件名(包含冒号)的Makefile变量时,我发现了另一种方法


这里的答案似乎太复杂了,没有什么帮助。我终于找到了解决办法:

然后将文件名中的宏用作:

filename$(:)

经评估,该文件已成功转换为“文件名”

我无法让@navjotk发布的答案正常工作,所以我要作弊并这么做

FILENAME:=foo:bar
foo_bar:
    touch $(FILENAME)

run:
    if [ ! -e "$(FILENAME)" ]; then $(MAKE) foo_bar; fi
输出:

$ make run
if [ ! -e "foo:bar" ]; then /Library/Developer/CommandLineTools/usr/bin/make foo_bar; fi
touch foo:bar

$ ls
Makefile foo:bar

离我够近了。

好发现。这就是我所害怕的,当我说我不确定它应该起作用!哇!那不好玩。Make是我工作流程中不可或缺的一部分。我很遗憾这是不可能的一般规则没有依赖项,但我在后续规则中为两个特定情况提供了第一个依赖项。是的,我也不知道你能做到,但事实证明你能做到。您会注意到,它能够很好地解决如何从x.foo创建x.bar的问题。非常好的破解!我对$(shell)很满意,我的问题是针对GNU make的。我想这是另一个答案所说的“讨厌的临时文件安排”的一个例子。我确实有点担心在“ls”作为占位符的情况下会发生什么,因为它失败,$(POST)因此无法运行。我的意思是,我想这大概是可以的,因为$(PRE)是幂等的,对吧?如果你有实际的@COLON@s在文件名中,您只需使用一个更长、更可笑的占位符,可能还嵌入了一个长随机字符串……这在目标路径或先决条件路径中不起作用。
colon := :
$(colon) := :
filename$(:)
FILENAME:=foo:bar
foo_bar:
    touch $(FILENAME)

run:
    if [ ! -e "$(FILENAME)" ]; then $(MAKE) foo_bar; fi
$ make run
if [ ! -e "foo:bar" ]; then /Library/Developer/CommandLineTools/usr/bin/make foo_bar; fi
touch foo:bar

$ ls
Makefile foo:bar