makefile 执行另一个目标

Posted

技术标签:

【中文标题】makefile 执行另一个目标【英文标题】:makefile execute another target 【发布时间】:2011-03-17 01:54:07 【问题描述】:

我有一个类似这样结构的生成文件:

all : 
    compile executable

clean :
    rm -f *.o $(EXEC)

我意识到在运行“make all”之前,我一直在终端中运行“make clean”,然后是“clear”。在尝试筛选令人讨厌的 C++ 编译错误之前,我喜欢有一个干净的终端。所以我尝试添加第三个目标:

fresh :
    rm -f *.o $(EXEC)
    clear
    make all

这可行,但是这会运行第二个 make 实例(我相信)。是否有正确的方法可以在不运行第二个 make 实例的情况下获得相同的功能?

【问题讨论】:

我不确定这是否应该是一个单独的问题,但为什么调用嵌套的 make 命令不好? 【参考方案1】:

实际上你是对的:它运行另一个 make 实例。 一个可能的解决方案是:

.PHONY : clearscr fresh clean all

all :
    compile executable

clean :
    rm -f *.o $(EXEC)

fresh : clean clearscr all

clearscr:
    clear

通过调用make fresh,您首先会获得clean 目标,然后是运行clearclearscreen,最后是完成这项工作的all

8 月 4 日编辑

在使用 make 的 -j 选项进行并行构建的情况下会发生什么? 有一种固定顺序的方法。来自制作手册,第 4.2 节:

但是,有时您会遇到这样的情况,即您希望对要调用的规则施加特定的顺序,而不是在执行这些规则之一时强制更新目标。在这种情况下,您想要定义仅订单的先决条件。可以通过在先决条件列表中放置管道符号 (|) 来指定仅订单先决条件:管道符号左侧的任何先决条件都是正常的;右侧的任何先决条件都是仅订购的:目标:正常先决条件|仅订购的先决条件

正常的先决条件部分当然可能是空的。此外,您仍然可以为同一目标声明多行先决条件:它们被适当地附加。请注意,如果您将同一个文件声明为普通先决条件和仅订单先决条件,则普通先决条件优先(因为它们是纯订单先决条件行为的严格超集)。

因此makefile变成了

.PHONY : clearscr fresh clean all

all :
    compile executable

clean :
    rm -f *.o $(EXEC)

fresh : | clean clearscr all

clearscr:
    clear

12 月 5 日编辑

运行多个 makefile 实例并不是什么大不了的事,因为任务中的每个命令无论如何都是sub-shell。但是您可以使用call function 来拥有可重用的方法。

log_success = (echo "\x1B[32m>> $1\x1B[39m")
log_error = (>&2 echo "\x1B[31m>> $1\x1B[39m" && exit 1)

install:
  @[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
  command1  # this line will be a subshell
  command2  # this line will be another subshell
  @command3  # Use `@` to hide the command line
  $(call log_error, "It works, yey!")

uninstall:
  @[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
  ....
  $(call log_error, "Nuked!")

【讨论】:

@sas4740:基本上.PHONY : 之后的所有内容都被视为始终执行的某个关键字,而非虚假目标则旨在成为文件。 @fantastory,不,我认为他们是独立的。 t2 将取决于 t0t1t3。如果您需要这个,您应该按照t2 的要求输入t3,按照t3t0 的要求按照t1 的要求输入t1。这意味着 3 个不同的规则。但是,您应该验证这一点。我不是 100% 确定。 “仅订购的先决条件”是独立的 我看不出“干净”在“全部”之前执行的保证在哪里?事实上,你把它们从 |不会使它们按顺序执行。仅订单依赖意味着在此类操作之后不需要更新目标。它与依赖元素的排序无关......或者? 你是对的@CygnusX1,order-only依赖与按一定顺序执行依赖无关;仅在引用它的目标之前对依赖项进行排序。这个答案的EDIT Aug 4 部分是错误的。【参考方案2】:

如果您从“新鲜”目标中删除了 make all 行:

fresh :
    rm -f *.o $(EXEC)
    clear

您可以简单地运行命令make fresh all,它将以make fresh; make all 执行。

有些人可能会认为这是 make 的第二个实例,但它肯定不是 make 的子实例(make 中的 make),这正是您的尝试似乎导致的结果。

【讨论】:

make -j12 fresh all 失败了。不要破坏并行制作!

以上是关于makefile 执行另一个目标的主要内容,如果未能解决你的问题,请参考以下文章

Makefile:执行多行功能不起作用

如果另一个配方在 Makefile 中创建目标,如何跳过目标的配方

Makefile将变量传递给bash脚本

Makefile伪目标

为啥这个makefile在'make clean'上执行一个目标

目标嵌入在包含的Makefile中时找不到目标命令