如何从目标的外部shell调用设置Makefile变量

时间:2015-09-22 14:06:32

标签: shell makefile

我需要逐行读取某个文本文件中的文件列表,然后将其翻译为-a filename1 -a filename2 -a filename3的序列。 我试图这样做,但看起来设置FILES变量的语法在该上下文中是错误的:

files_pack:
    @while read -r file; do \
         FILES += "-a $$file"; \
    done <$(LIST_FILE)
    some_util $(FILES)

4 个答案:

答案 0 :(得分:1)

外壳分配不能在= / +=附近留出空格。

同样$(FILES)将由make扩展。你想要"$${FILES[@]}"

我还修改了你的代码以使用数组而不是字符串,以便带有空格/等的文件。在名称中可以正常工作。

files_pack:
    @while read -r file; do \
         FILES+=(-a "$$file"); \
    done <$(LIST_FILE)
    some_util "$${FILES[@]}"

尽管如此,正如Jens所指出的那样,在许多系统上都不会使用/bin/sh,并且需要告诉make使用/bin/bash作为此目标的shell:

files_pack: SHELL := /bin/bash

或全球:

SHELL := /bin/bash

答案 1 :(得分:1)

如果LIST_FILE每行有一个文件,而您需要做的只是在-a前面添加每行,那么您想要的是

files_pack:
       some_util $$(sed 's/^/-a /' $(LIST_FILE))

答案 2 :(得分:1)

这也有效:

FILES=$(shell cat ${LIST_FILE) FILES_OPT=$(addprefix -a,${FILES})

这个解决方案并不依赖于bash,适用于每个通用shell,并且不需要&#39; sed&#39;待安装。

答案 3 :(得分:1)

Anton Kochkov's answer的启发,这是一个适用于任何shell的简单解决方案,但如果文件名包含空格或元字符则会失败:

files_pack:
    some_util $(shell printf " -a %s" $$(cat $(FILES)))

这可以改进以处理具有除撇号之外的空格或特殊字符的文件名:

files_pack:
    some_util $(shell IFS="$$(printf '\n+')"; IFS="$${IFS%+}"; printf " -a '%s'" $$(cat $(FILES)))

IFS设置为 newline + ,然后删除 + 的特殊顺序是唯一与Posix兼容的方式知道将IFS设置为单个换行符,该换行符不涉及带有物理换行符的命令行。 (无论IFS的设置如何,简单命令替换都会删除尾随换行符。)

使用bash,可以使用%q printf格式(以及其他一些基本原理来简化)来简化并使其更加健壮:

files_pack: SHELL := /bin/bash
    some_util $(shell IFS=$$'\n'; printf " -a %q" $$(<$(FILES)))