在 Makefile 中转义文件名中的冒号
有没有办法让 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
用文字 : 替换 $(COLON) 会产生完全相同的结果。如果没有反斜杠,它会执行以下操作:
Makefile:6: *** target pattern contains no `%'. Stop.
Is there a way to get GNU make to work correctly with filenames that contain colons?
The specific problem I'm running into happens to involve a pattern rule. Here's a simplified version that does not depend on cutting and pasting tab characters:
% 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 lt; $@
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
Replacing $(COLON) with a literal : produces exactly the same result. Without the backslash, it does this:
Makefile:6: *** target pattern contains no `%'. Stop.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我怀疑这是可能的:请参阅 关于 Makefile 中冒号的讨论< /a>.总之,GNU make 从来不能很好地处理包含空格或冒号的文件名。维护者 Paul D. Smith 表示,添加对转义的支持往往会破坏现有的 makefile。此外,添加此类支持需要对代码进行重大更改。
您也许可以通过某种令人讨厌的临时文件安排来解决问题。
祝你好运!
I doubt it's possible: see this discussion about colons in Makefiles. In summary, GNU make has never worked well with filenames that contain whitespace or colons. The maintainer, Paul D. Smith, says that adding support for escaping would tend to break existing makefiles. Furthermore, adding such support would require significant changes to the code.
You might be able to work around with some sort of nasty temporary file arrangement.
Good luck!
这里的答案似乎都太复杂而没有帮助。我终于找到了一个解决方案这里:
然后使用文件名中的宏为:,
在评估后成功转换为“文件名:”。
The answers here all seemed too complex to be helpful. I finally found a solution here:
and then used the macro in the filename as:
which successfully translated to "filename:" upon evaluation.
以下黑客对我有用,但不幸的是它依赖于 $(shell)。
由于 PRE 是用 := 分配的,因此其关联的 shell 命令会在计算 XDLS 变量之前运行。关键是在事后通过显式调用 $(POST) 将冒号放回原位。
The following hack worked for me, though it unfortunately relies on $(shell).
Because PRE is assigned with :=, its associated shell command is run before the XDLS variable is evaluated. The key is to then put the colons back in place after the fact by explicitly invoking $(POST).
今天我在处理定义文件名(包含冒号)的 Makefile 变量时发现了另一种方法。
There is another way i've found today when dealing with Makefile variables defining filenames (containing colons).
我并不肯定这应该有效,但它说“缺少目标文件”的原因很简单:
该行表示从 first 依赖项复制目标。您的 a:b.bar 没有任何依赖项,因此 cp 失败。你想让它复制什么? a:b.foo ?在这种情况下,您将需要:
I am not positivie this should work, but the reason it says "missing destination file" is simple:
That line says to copy the target from the first dependency. your a:b.bar does not have any dependency, so the cp fails. what did you want it to copy ? a:b.foo ? in that case, you would need:
正如您所做的那样,用
\:
转义冒号应该可行。唯一的问题是,您不能使用这样的转义分号来二次扩展(阅读.SECONDEXPANSION:
)变量,否则分号将保留在路径名中。下面是一些使用简单 Makefile 的测试:
$ cat Makefile
与这些交互的另一个功能是
$(wildcard ...)
。它没有转义冒号,因此您可能需要在它之后再次转义。Escaping the colon with
\:
, as you did, should work. The only problem is that it you can't second-expand (read about.SECONDEXPANSION:
) variables with such an escaped semicolon, or the semicolon will stay in the pathname.Here's some test that works with a simple Makefile:
$ cat Makefile
Another feature that interacts with these is
$(wildcard ...)
. It unescapes the colons, so you may need to escape again after it.这对我有用:
This works for me:
我无法得到@navjotk 发布的答案来工作,所以我只是作弊并这样做;
输出:
对我来说足够接近了。
I could not get the answer posted by @navjotk to work, so I am just gonna cheat and do this;
output:
Close enough for me.