运行 Makefile 中的所有目标

Running all targets at once in a Makefile

我有如下的 Makefile

all:
    bison -d -v parser.y
    flex  -o parser.lex.c parser.lex
    gcc  -o cparser parser.lex.c parser.tab.c -lfl -lm 
clean:
    rm parser.tab.h parser.tab.c parser.output parser.lex.c     

当我 运行 在终端中创建时,它只运行目标 all

我试过添加 .PHONY:all clean.PHONY:clean 即使它只运行 all 。 我应该在 Makefile 中进行哪些更改才能运行所有目标?

系统配置:
Ubuntu14.10
GNU 制作 4.0

您想 运行 allclean 当您只输入 make 时?这通常没有用,因为这会清理您刚刚构建的内容(尽管在您的情况下我看到您的 clean 目标实际上并没有这样做)。

为此,您需要类似的东西。

all: cparser clean

cparser:
    bison -d -v parser.y
    flex  -o parser.lex.c parser.lex
    gcc  -o cparser parser.lex.c parser.tab.c -lfl -lm

clean:
    rm parser.tab.h parser.tab.c parser.output parser.lex.c

虽然这仍然是一个相当糟糕的 makefile 并且没有利用 任何 make 为您提供的好处(比如仅在它们的时候智能地重建东西先决条件发生变化)。

我建议你可能想要更多这样的东西。

.PHONY: all
all: cparser

parser.lex: parser.y
    bison -d -v parser.y

parser.lex.% parser.tab.%: parser.lex
    flex  -o parser.lex.c parser.lex

cparser: parser.lex.c parser.tab.c
    gcc  -o cparser parser.lex.c parser.tab.c -lfl -lm

.PHONY: clean    
clean:
    rm parser.tab.h parser.tab.c parser.output parser.lex.c cparser

假设我没有记错,flex 将同时生成 parser.lex.cparser.tab.c 文件。

另请注意,先决条件是链接的,clean 现在也会清理二进制文件。您不需要 运行 make clean 以这种方式正确重建。

如果你真的想要 make Makefile 中的所有目标(你 真的 不想,这通常不是你使用 makefile 的方式),你可以添加一个目标,该目标具有 Makefile 的所有其他目标作为先决条件:

.PHONY: all_targets
all_targets: all clean

.PHONY: all
all:
    # ... command script
.PHONY: clean
clean:
    # ... command script

在这个特定的例子中,all 后跟 clean 完全是胡说八道,因为 all 会构建所有文件,而 clean 会删除它们。如果你想在构建 all 之前清理所有文件(你也不想这样做),你实际上可以绕过 all_targets:

的先决条件
.PHONY: all_targets
all_targets: clean all

.PHONY: all
all:
    # ...
.PHONY: clean
clean:
    # ...

同样,这确实不是您想要使用的方式 make,因为它旨在跳过构建过程中所有不必要的工作(即,不重新编译那些不需要的文件重新编译等)。

另请记住,您可以调用 make 来构建多个目标。因此,在您的示例中,您还可以通过执行

来构建所有目标
make all clean

请注意,目标将按照传递给命令行的顺序构建,因此此处要构建的第一个目标是 all,然后是 clean(这又是废话).

如果您想了解更多有关如何正确使用 makefile 的信息,我建议您阅读这本书 Managing Projects with GNU Make。它对几乎所有 (GNU) Make 功能进行了相当全面的解释。

编辑:正如tripleee所指出的,上述示例中的all_targets目标当然应该是一个虚假目标。