在Makefile中提取与%匹配的字符串部分

时间:2018-04-02 10:21:42

标签: makefile gnu-make

我正在做我的CS作业,其中包含许多单文件程序。我的工作目录如下所示:

133.c 134.c 220.c 281.c 337.c 338.c 339.c makefile

我写了一个像这样的Makefile:

%: %.c
    ${CC} ${CFLAGS} -o $@ $^

因此,当我想编译问题220的程序时,我输入:

ibug@wsl:~ $ make 220
gcc  -o 220 220.c
ibug@wsl:~ $

问题

我想写一个clean-%规则,这样当我在shell中运行它时,结果应该如下所示

ibug@wsl:~ $ make clean-133
rm -f 133
ibug@wsl:~ $ make clean-281
rm -f 281
ibug@wsl:~ $ make clean-337
rm -f 337

我已经走了这么远:

.PHONY: clean-%

SRC = $(wildcard %.c)
BIN = $(patsubst %.c,%,$(SRC))

clean-%:
    rm -f ??????

我应该用什么来代替问号?

我正在使用GNU Make 4.1(在Windows的Linux子系统上)。

2 个答案:

答案 0 :(得分:4)

您正在寻找automatic variable $*,其中包含词干(即与%匹配的部分):

clean-%:
    rm -f $*

但是,继续阅读。

假目标,模式和隐含规则

将先决条件clean-%添加到.PHONY目标:

.PHONY: clean-%

不会将模式规则 clean-%转换为虚假目标,而是转变显式规则,其实际目标名称是clean-%(不是模式),变成虚假的目标。

原因是只有显式规则的目标可以成为虚假目标,模式不能成为假目标。因此,看起来像模式的虚假目标(即包含%)实际上并不是一种模式(即,%实际上是%)。

添加所有可能的值clean-%可以与.PHONY无法帮助匹配,因为虚假目标 匹配隐式模式规则。所以,如果你这样做:

.PHONY: clean-foo

clean-foo永远不会匹配隐式模式规则(即,它永远不会与您的clean-%模式规则匹配)。

clean-xxx定义为虚假目标

我猜你确实希望这些clean-xxx目标是虚假目标,因为这些目标不代表文件系统上的实际文件。

使用静态模式规则

与隐式模式规则不同,static pattern rules可以匹配虚假目标。以下方法包括定义一个可以匹配clean-xxx虚假目标的静态模式规则:

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

# list of clean-xxx targets
clean-targets := $(addprefix clean-,$(list))

.PHONY: $(clean-targets)

$(clean-targets): clean-%:
    rm -f $*

上面的静态模式规则将匹配其目标列表中指定的任何clean-xxx虚假目标(即$(clean-targets)

使用显式规则

以下方法包括将这些clean-xxx规则动态生成为显式规则而不是单个模式规则:

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

define create-clean-target
    $(eval .PHONY: clean-$1);
    $(eval clean-$1:; rm -f $1)
endef


# dynamically generate the clean-xxx targets
$(foreach t,$(list),$(call create-clean-target,$t))

用户定义函数create-target定义显式目标clean-xxx,传递给函数的参数为​​xxx。由于要定义的目标是一个明确的目标,因此它也可以成为假的目标。

答案 1 :(得分:1)

使用您的文件命名约定,您不需要任何makefile ,因为GNU Make's built-in rules已经执行了您想要的操作。试试这个:

$ mv Makefile Makefile.bak
$ rm -f 220
$ make 220       # make magic happening here!
$ rm -f 220
$ make CC=cc CFLAGS="-Wall -O2" 220

如您所见, make 知道如何使用C编译器将 foo .c转换为 foo 可执行文件。

要检索内置规则列表,请在不存在Makefile的情况下运行make -p

至于清理可执行文件,为什么如此冗长并在make clean-NNNrm -f NNN输入rm -f [0-9]??时输入AsyncTaskHandleJson().execute(url) inner class AsyncTaskHandleJson : AsyncTask<String, String, String>() { override fun doInBackground(vararg url: String?): String { var text: String var connection = URL(url[0]).openConnection() as HttpURLConnection try { connection.connect() text = connection.inputStream.use { it.reader().use { reader -> reader.readText() } } } finally { connection.disconnect() } return text } override fun onPostExecute(result: String?) { super.onPostExecute(result) handleJson(result) } }