【问题标题】:Directory wildcard in Makefile pattern ruleMakefile 模式规则中的目录通配符
【发布时间】:2013-04-03 15:36:40
【问题描述】:

我正在尝试创建一个 Makefile,它将通过 tic 编译驻留在目录中的 terminfo 文件。 tic 还将它自动创建的 termcap 文件复制到系统或用户特定的目标文件夹。对于普通用户,如果 terminfo 文件是例如screen-256color-bce-s.terminfo,会编译复制到~/.terminfo/s/screen-256color-bce-s。所以它看起来像这样:

terminfo/screen-256color-bce-s.terminfo => /home/user/.terminfo/s/screen-256color-bce-s
terminfo/screen-256color-s.terminfo => /home/user/.terminfo/s/screen-256color-s

如果我将这样的内容放入我的 Makefile 中:

TISRC = $(wildcard terminfo/*.terminfo)
TIDST = $(foreach x, $(TISRC), $(HOME)/.terminfo/$(shell basename $x|cut -c 1)/$(shell basename $x .terminfo))

$(HOME)/.terminfo/s/%: terminfo/%.terminfo
    @echo "$< => $@"
    @tic $<

install: $(TIDST)

它有效。但是,我想使其通用,并在目标中使用通配符,即:

$(HOME)/.terminfo/**/%: terminfo/%.terminfo
    @echo "$< => $@"
    @tic $<

能够将 terminfo 文件添加到我的本地存储库。但是,上述方法不起作用。如何在模式规则中指定通配符目录?

【问题讨论】:

  • 我不认为你可以; Make 不太适合使用通配符。

标签: makefile gnu-make


【解决方案1】:

您可以使用GNU Make Secondary Expansion feature

all : ${HOME}/.terminfo/x/a
all : ${HOME}/.terminfo/y/b

.SECONDEXPANSION:
${HOME}/.terminfo/%: terminfo/$$(notdir $$*).terminfo
    @echo "$< ---> $@"

输出:

[~/tmp] $ make
terminfo/a.terminfo ---> /home/max/.terminfo/x/a
terminfo/b.terminfo ---> /home/max/.terminfo/y/b

附带说明,make 提供了some path manipulation functions,因此您实际上不需要为此调用 shell。

【讨论】:

  • @Beta 好吧,有时一个愿望有类似正则表达式模式匹配的东西,例如/([[:word:]]+)/([[:word:]]+) : /build/\1/obj/\2.o。但这会使选择更具体的规则变得困难。如果我没记错的话,% 模式中最具体的模式是 % 匹配的字符数最少。
【解决方案2】:

我不认为你可以按照你想要的方式使用通配符,但如果你不介意使用 eval 诡计,你可以得到你想要的效果而无需明确说明所有目录路径:

TISRC = $(wildcard terminfo/*.terminfo)
BASENAMES = $(notdir $(basename ${TISRC}))

MKDST = ${HOME}/.terminfo/$(shell echo $1 | cut -c 1)/$1
TIDST := $(foreach s,${BASENAMES},$(call MKDST,$s))
DIRLTRS = $(notdir $(patsubst %/,%,$(sort $(dir ${TIDST}))))

install: ${TIDST}

# $1 - Directory Name
# $2 - File name
define T
${HOME}/.terminfo/$1/$2 : terminfo/$2.terminfo
    @echo "$$< => $$@"
    tic $$<
endef

# This is the tricky part: use template T to make the rules you need.
$(foreach d,${DIRLTRS},$(foreach f,${BASENAMES},$(eval $(call T,$d,$f))))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    相关资源
    最近更新 更多