makefile执行另一个目标


122

我有一个makefile结构如下:

all : 
    compile executable

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

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

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

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

Answers:


171

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

.PHONY : clearscr fresh clean all

all :
    compile executable

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

fresh : clean clearscr all

clearscr:
    clear

通过调用make fresh您首先获得clean目标,然后clearscreen运行目标,clear最后all完成目标。

编辑8月4日

如果使用make -j选项进行并行构建,会发生什么情况?有固定订单的方法。在制造手册的第4.2节中:

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

正常的先决条件部分当然可以为空。同样,您仍然可以为同一目标声明多行先决条件:它们会适当地附加。请注意,如果您将同一文件声明为常规和仅订购的前提条件,则以常规前提条件为准(因为它们是仅订购的前提条件的行为的严格超集)。

因此,makefile变为

.PHONY : clearscr fresh clean all

all :
    compile executable

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

fresh : | clean clearscr all

clearscr:
    clear

编辑12月5日

运行多个makefile实例并没有什么大不了的,因为任务中的每个命令仍然是子shell。但是您可以使用call函数拥有可重用的方法。

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!")

6
@ sas4740:基本上所有后续操作都.PHONY : 被视为始终执行的某些关键字,而非语音目标旨在作为文件。
达卡夫

“仅订购的先决条件”是有条件的吗?对于目标t2,我希望首先执行t0,而不是仅在t0成功运行t1时且仅当两个成功都在t3中运行某些任务时
幻想2015年

1
@fantastory,不,我认为他们是独立的。t2将取决于t0t1t3。如果你需要这个,你应该把 t3所要求的t2t1所要求的t3t0所要求的t1。这意味着3个不同的规则。但是,您应该对此进行验证。我不确定100%。
达卡夫

3
“仅订购的先决条件”是独立的
幻想曲

2
我看不出“干净”先于“全部”执行的保证在哪里?您将它们从| | 不能使它们按顺序执行。仅顺序依赖性意味着在执行此操作后不必不必要地更新目标。它与依存元素的排序无关...还是?
CygnusX1 2016年

6

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

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

您可以简单地运行命令make fresh all,该命令将以方式执行make fresh; make all

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.