makefile中%和*之间的区别是什么

时间:2015-12-11 08:36:39

标签: makefile pattern-matching gnu-make

GNU make manual并不擅长解释这一部分,我找不到解释,或者我无法在其他地方推断出这些信息。

我意识到%是一种通配符,但%*targetsdependenciescommandstarget: dependencies ... commands 之间有什么区别? {1}}?我在哪里可以使用它并且在任何地方都具有相同的含义?

function paginate_posts() {
    global $wp_query, $wp_rewrite;
    $wp_query->query_vars['paged'] > 1 ? $current = $wp_query->query_vars['paged'] : $current = 1;
    $current = str_pad($current, 2, '0', STR_PAD_LEFT);
    $total = str_pad($wp_query->max_num_pages, 2, '0', STR_PAD_LEFT);
    $pagination_args = array(
        'base' => @add_query_arg('page', '%#%'),
        'format' => '',
        'total' => $wp_query->max_num_pages,
        'current' => $current,
        'show_all' => false,
        'end_size' => 0,
        'mid_size' => 0,
        'next_text' => _("»"),
        'prev_text' => _("«"),
    );
    if ($wp_rewrite->using_permalinks())
        $pagination_args['base'] = user_trailingslashit(trailingslashit(remove_query_arg('s', get_pagenum_link(1))) . 'page/%#%/', 'paged');

    if (!empty($wp_query->query_vars['s']))
        $pagination_args['add_args'] = array('s' => get_query_var('s'));
    $prev = get_previous_posts_link('');
    $next = get_next_posts_link('');
    $links = "<div class='pagination_box'><span class='prev page-num'>$prev</span> <span>Page $current/$total</span> <span class='next page-num'>$next</span></div>";
    echo $links;
}

2 个答案:

答案 0 :(得分:3)

通配符*用于简单地生成当前目录中的匹配文件列表。模式替换字符%是文件的占位符,此文件目前可能存在,也可能不存在。

要扩展您已经发现的手册中的Wildcard pitfall示例,

objects = *.o

简单地为变量赋予相当无用的文字值*.o - 一个目标文件,它可能依赖于一个名为字面*.c的文件,当然也不存在。所以你得到一个错误和/或不稳定的行为。

短语的正确方法就像是

objects := $(patsubst %.c,%.o,$(wildcard *.c))

make本身在此上下文中不执行通配符扩展,但当然,如果将文字值*.o传递给shell,那就是扩展发生时(如果有匹配),这样就可以了有点难以调试。 make 在规则目标中执行通配符扩展,因此您可以说

foo: *.o

并使其完全按照您的意图工作(前提是在评估此依赖关系时保证所需的文件存在)。

相比之下,您可以拥有一个带有模式占位符的规则,该模式占位符将填充任何匹配的名称,因为make尝试查找可用于生成所需依赖项的配方。有内置规则,如

%.o: %.c
        $(CC) $(CCFLAGS) $^ -o $@

(近似于此处的真实情况)说“给定文件匹配%.c,相应的文件%.o可以如下生成。”这里,%是占位符,可以被任何东西取代;因此,如果将其应用于现有文件foo.c,则会说明如何生成foo.o

您可以将其改为说*匹配每个匹配文件,而%匹配任何匹配文件。

答案 1 :(得分:3)

%*都是制作配方行中的普通字符;它们只是传递给shell。

%表示模式替换中的文件“词干”,如$(patsubst %.o,%.c,$(OBJS))中所示。模式%.o应用于$(OBJS)中的每个元素,%捕获匹配的部分。然后在替换模式%.c中,将捕获的部分替换为%,并将patsubst中的替换列表作为返回值。

*$(wildcard ...)运算符的参数中很有用,它类似于shell * glob在匹配文件系统中某些路径时的操作。

patsubst的左侧,其中%表示匹配,它类似于*,因为它匹配某些字符。但是,%有一些限制,例如它只能出现一次!例如,我们可以扩展通配符*/*.c,当然,我们不能像$(patsubst %/%.o,%/foo/%.c,...)那样使用双干模式替换。这个限制可以在GNU Make的某个未来版本中解除,但据我所知,它目前仍然存在。

%*之间存在细微差别,因为%非空字符序列匹配。通配符模式fo*o.cfoo.c匹配。替换模式fo%o.c 匹配foo.c,因为干%将为空,这是不允许的。