转义Makefile中文件名中的冒号

时间:2010-01-12 21:10:03

标签: 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 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.

6 个答案:

答案 0 :(得分:11)

我怀疑这是可能的:见this discussion about colons in Makefiles。总之,GNU make从未与包含空格或冒号的文件名一起使用。维护者Paul D. Smith说,增加对转义的支持往往会break existing makefiles。此外,添加此类支持需要对代码进行重大更改。

您可能可以使用某种令人讨厌的临时文件安排。

祝你好运!

答案 1 :(得分:3)

这里的答案似乎都太复杂了,无法提供帮助。我终于找到了解决方法here

colon := :
$(colon) := :

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

filename$(:)

经评估成功转换为“文件名:”。

答案 2 :(得分:2)

以下黑客为我工作,但不幸的是它依赖于$(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

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

答案 3 :(得分:2)

今天我在处理定义文件名(包含冒号)的Makefile变量时还有另一种方法。

function my_scripts() {


    wp_enqueue_style( 'google-styles', get_template_directory_uri() . '/css/mdb.css');
    wp_enqueue_style( 'bootstrap-styles', get_template_directory_uri() . '/css/goldbootstrap.css', array(), '3.3.4', 'all' );

    wp_enqueue_style( 'font-awesome', get_template_directory_uri() . '/css/font-awesome.min.css', array(), '4.3.0', 'all' );

    wp_enqueue_style( 'my-style', get_stylesheet_uri() );





    wp_enqueue_script( 'bootstrap-js', get_template_directory_uri() . '/js/bootstrap.min.js', array('jquery'), '3.3.4' );
    wp_enqueue_script('mdb-js', get_template_directory_uri() . '/js/mdb.js' );


    if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
        wp_enqueue_script( 'comment-reply' );
    }
}
add_action( 'wp_enqueue_scripts', 'my_scripts' );

答案 4 :(得分:0)

我不认为这应该有用,但它说“丢失目标文件”的原因很简单:

%.bar: ; cp $< $@

该行表示从第一个依赖项中复制目标。你的a:b.bar没有任何依赖关系,所以cp失败了。你想要它复制什么? a:b.foo?在这种情况下,你需要:

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

答案 5 :(得分:0)

我无法得到@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

对我来说足够近了。