【问题标题】:Make: Can we Optimize make file targets?Make:我们可以优化 make 文件目标吗?
【发布时间】:2023-03-06 04:49:02
【问题描述】:

我们在工作流程中支持 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”之外,我们有相同的目标,我想用单个规则/定义替换它们。因为我们的基础设施代码中有数百条类似上面的规则。

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

提前致谢!

【问题讨论】:

    标签: makefile compilation gnu-make


    【解决方案1】:

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

    $(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) 的任何成员在先决条件方面已经过时,那么它将为该目标运行配方

    这个makefile:

    .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
    

    稍后

    有一些静态模式规则...

    同样适用。这个带有静态模式规则的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)
    

    【讨论】:

    • Mike, $(file_transfer) 定义如下。定义 file_transfer mkdir -p $(@D) cp -f $
    • @santosh 在配方中,所有 automatic variables - $@ 等 - 将根据 Make 确定必须制作的 $(THESE_TARGETS) 中的 实际目标 进行扩展, 及其先决条件。这里没什么特别的。 $(THESE_TARGETS) 只是一个目标还是一系列目标都没有区别。
    • 谢谢迈克!我会在本地测试它。看看它是否有效。
    • Mike,有一些静态模式规则如下: '$(HEADERGEN_NOTSPLIT_H_COPY32): $(TGT32)/%.h: %.h $(copy_file)' 我们如何按顺序处理这种情况只有一个目标?
    • @santosh 更新了答案
    【解决方案2】:

    在我看来,这是使用递归 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)
            ...
    

    【讨论】:

    • Mike Kinghan 的回答似乎有效.. 但不确定我如何处理静态模式规则,例如:'$(HEADERGEN_NOTSPLIT_H_COPY32): $(TGT32)/%.h: %.h $(copy_file )'
    • 你不能将 Mike 的方法与静态模式规则或模式规则一起使用:对于那些你仍然需要编写两个单独的规则。它只适用于普通的显式规则。当然,即使在那里,您仍然要编写两次目标(尽管规则的其余部分已合并)。
    • 您好,不幸的是,您在上面的框中的回答对我们的流程没有帮助.. 有没有其他方法可以在没有递归 make 的情况下实现它?
    • 当然,有很多选择。但是由于您显然有某些要求,您没有在这里提供,也没有描述为什么已经提出的现有建议还不够,所以我很犹豫是否继续随机建议更多的东西。请说明您的具体要求是什么以及为什么这些不起作用,也许我们可以提出一些可行的建议。
    • MadScientist,问题是我们有一个 config.mak,我们在其中声明所有变量(分别用于 32 位和 64 位),即 TGT32 分配了 32 位路径和 TGT64 分配了 64 位路径。我们在所有项目 makefile 中都包含 config.mak 文件。其中有单独的目标,指的是 32 位和 64 位路径。现在我们要优化我们的 makefile 以使 32 位和 64 位都有一个目标。
    【解决方案3】:

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

    $(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
    

    【讨论】:

    • 这个建议的一个缺点是您不能在同一运行中构建两个目标。还有更好的方法。
    • 是的,我要提到同样的事情......我们不能同时构建 32 位和 64 位版本......用户有时会同时使用 32 位和 64 位版本构建代码......就像我们的目标是 all -> 构建 32 位和 64 位版本,all32 只构建 32 位版本。 all64 仅构建 64 位构建。
    猜你喜欢
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 2020-09-26
    • 1970-01-01
    • 2010-12-02
    • 2014-07-08
    • 2014-04-10
    • 2019-12-02
    相关资源
    最近更新 更多