【问题标题】:How to avoid duplication in Makefile targets with similar recipes?如何避免在具有相似配方的 Makefile 目标中重复?
【发布时间】:2016-10-13 03:39:34
【问题描述】:

我有一个包含很多目标的 Makefile,每个目标的配方都非常相似。

foo:
    gcc foo.c -o foo
    mv foo ~/bin

bar:
    gcc bar.c -o bar
    mv bar ~/bin

baz:
    gcc baz.c -o baz
    mv baz ~/bin

我想避免所有这些重复。我想要类似下面的东西(这不是有效的语法;这只是表达我的意图)。

TARGET_NAME:
    gcc $(TARGET_NAME).c -o $(TARGET_NAME)
    mv $(TARGET_NAME) ~/bin

有可能做这样的事情吗?如果不是,我能写出的最好的 Makefile 是什么,可以最大限度地减少配方中的重复?

【问题讨论】:

  • 就像@beta 在其他地方已经指出的那样,您的Makefile 已损坏,因为您移动了您制作的文件,以便每次都重新制作它们,无论是否有必要。此外,gcc-o 选项可以显着地采用子目录。 bin/%: %.c; gcc $< -o $@

标签: makefile dry


【解决方案1】:

您的 makefile 错误,因为您的目标(foobar 等)不依赖于它们的源文件(foo 不依赖于 foo.c 等)所以,更改源代码不会导致目标被重建。

另外,您的 makefile 说您正在创建一个文件 foo,但您的配方实际上创建了一个文件 ~/bin/foo,这不是一回事。

无论如何,这正是pattern rules 的用途:

EXES = foo bar baz

all: $(addprefix $(HOME)/bin/,$(EXES))

$(HOME)/bin/%:: %.c
        gcc $< -o $@

(感谢 Beta 指出我在原文中的想法)

【讨论】:

  • 您没有违反your own rules 之一吗?确切地说,6 个中的第 2 个:目标模式应该与正在构建的事物的实际名称匹配 (~/bin/%)。
  • 你应该使用static pattern rules来避免使用implicit rules。类似的东西:foo bar baz: %: %.c
  • 你是对的。我在想它是cp 而不是mv。我会更新的。关于“静态模式规则”:我一直看到这个建议,你“应该”使用它们。我几乎从不使用它们。事实上,我总是使用普通模式规则,并且只在我有一个应该以不同方式构建的目标子集时才使用静态模式规则。我认为这是一种风格/观点;我不会告诉人们他们“应该”在没有任何理由的情况下使用它们。
【解决方案2】:

make 规则实际上可以匹配多个目标:

foo bar baz:
    gcc $@.c -o $@
    mv $@ ~/bin

但是,您应该在规则中明确说明依赖关系:

foo: foo.c
bar: bar.c
baz: baz.c

foo bar baz:
    gcc $< -o $@
    mv $@ ~/bin

前三行仅指定依赖项,没有任何实际构建它们的操作。您可以在 gcc 的帮助下生成这些:gcc -MM foo.c 将为foo.c 打印一条规则。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-20
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多