Make:我们可以优化 make 文件目标吗?

Make: Can we Optimize make file targets?

我们在 workflow.For 中支持 32 位和 64 位构建,我们在 makefile 中有多个规则,分别用于 32 位和 64 位。让我展示一对相同的规则,除了字符串“32”和“64”。

Makefile 片段:-

$(TGTDIR32)/logdir/set_user.c: $(CURDIR)/slv/set_user.c
    $(file_transfer)

$(TGTDIR64)/logdir/set_user.c: $(CURDIR)/slv/set_user.c
    $(file_transfer)

如果你注意到,除了字符串“32”和“64”之外,我们有相同的目标,我想用单个 rule/definition 替换它们。因为我们的基础设施代码中有数百条上述规则。

我们在 GNUmake 中有任何简化的方法来做到这一点吗?

提前致谢!

可以简单地组合具有相同先决条件和配方的目标,如下所示:

$(TGTDIR32)/logdir/set_user.c $(TGTDIR64)/logdir/set_user.c: $(CURDIR)/slv/set_user.c
    $(file_transfer)

或更一般地说:

THESE_TARGETS := $(TGTDIR32)/logdir/set_user.c $(TGTDIR64)/logdir/set_user.c # More...?
...
$(THESE_TARGETS): $(CURDIR)/slv/set_user.c
    $(file_transfer)

如果 Make 确定 $(THESE_TARGETS) 的任何成员在先决条件方面已过时,那么它将 运行 该目标的配方 .

这个生成文件:

.PHONY: all clean

all: a b c

a: d e
    touch $@

b: d e
    touch $@

c: d e
    touch $@

d:
    touch $@

e:
    touch $@

clean:
    $(RM) a b c d e

相当于这个:

.PHONY: all clean

all: a b c

a b c: d e
    touch $@

d e:
    touch $@

clean:
    $(RM) a b c d e

稍后

There are some static pattern rules...

同理。这个具有静态模式规则的 makefile:

.PHONY: default clean

default: a.k b.k

a.k: %.k: %.j
    cp -f $< $@

b.k: %.k: %.j
    cp -f $< $@

a.j:
    touch $@

b.j:
    touch $@


clean:
    $(RM) a.k b.k a.j b.j

相当于这个:

.PHONY: default clean

JS := a.j b.j
KS := $(JS:.j=.k)

default: $(KS)

$(KS): %.k: %.j
    cp -f $< $@

$(JS):
    touch $@

clean:
    $(RM) $(JS) $(KS)

这两个规则在语义上是相同的,它们只是使用不同的方式来引用 "parameterized" 目标。为什么你不只使用一个目标

$(TGTDIR)/logdir/set_user.c: $(CURDIR)/slv/set_user.c
    $(file_transfer)

并使用正确配置的 TGTDIR(我怀疑这类似于 "xxxx_32" 与 "xxxx_64")?

您可以通过多种方式实现这一目标;一个典型的是

ifdef choose32
  TGTDIR=xxxx_32
else
  TGTDIR=xxxx_64
endif

在我看来,这是使用递归 make 的合适位置,至少对于顶级构建而言。

在这种情况下你可以这样做:

TGTDIR64 = ...
TGTDIR32 = ...

.PHONY: all all32 all64 build

all: all32 all64

all32:
        $(MAKE) TGTDIR=$(TGTDIR32) build
all64:
        $(MAKE) TGTDIR=$(TGTDIR64) build

# Things below here should just use TGTDIR

build: $(TGTDIR)/b1 $(TGTDIR)/b2

$(TGTDIR)/logdir/set_user.c: $(CURDIR)/slv/set_user.c
        $(file_transfer)

$(HEADERGEN_NOTSPLIT_H_COPY): $(TGTDIR)/%.h: %.h $(copy_file)
        ...