在makefile中调用bash命令

时间:2016-09-13 21:46:33

标签: bash makefile

a.col2 in (select test from TableC) OR a.col3 in (select test from TableC) OR a.col4 in (select test from TableC) OR a.col5 in (select test from TableC) OR a.col6 in (select test from TableC) OR a.col7 in (select test from TableC) OR a.col8 in (select test from TableC)` 内,我正在尝试检查fileA是否比fileB更新。使用一些先前的帖子(thisthis)作为参考,我想出这个尝试将自上次文件修改以来的时间存储为变量:

(我宁愿这是一个makefile食谱之外的函数,但一次只有一步。)

make

我以为我会将 .PHONY: all clean all : (stuff happens here) radio : BASE_MOD_TIME="$( expr $(date +%s) - $(date +%s -r src/radio_interface/profile_init.c) )" @echo "$(BASE_MOD_TIME)" 命令的输出分配给变量expr,但输出为:

BASE_MOD_TIME

我在这里做错了什么?保存 bash-4.1$ BASE_MOD_TIME="" echo "" 输出的简单尝试也没有这样做。

3 个答案:

答案 0 :(得分:1)

Make变量通常是全局变量,通常不会在配方中设置make变量。配方只是一个由shell执行的命令列表,因此看起来像配方中的变量赋值是shell变量赋值。

但是,make配方中的每一行都在自己的shell子进程中运行。因此,在一行中设置的变量将不会在另一行中显示;他们并不执着。这使得在配方中设置shell变量不那么有用。 [注1]

但是你可以使用行尾的反斜杠转义将一个配方的多行组合成一个shell命令,并记住用分号终止各个命令(或者更好的是,用&&链接它们),因为反斜杠转义的换行符不会传递给shell。另外,不要忘记转义$字符,以便将它们传递给shell,而不是由make解释。

所以你可以做到以下几点:

radio:
    @BASE_MOD_TIME="$$( expr $$(date +%s) - $$(date +%s -r src/radio_interface/profile_init.c) )"; \
    echo "$$BASE_MOD_TIME"; \
    # More commands in the same subprocess

但是,如果有多个命令,这会变得非常尴尬,并且通常更好的解决方案是编写shell脚本并从配方中调用它(尽管这意味着Makefile不再是自包含的。)

Gnu make提供了两种在配方中设置make变量的方法:

1。特定目标变量。

您可以通过添加以下行来创建特定于目标的变量(对于目标而言不完全是本地变量):

target: var := value

要从shell命令设置变量,请使用shell函数:

target: var := $(shell ....)

此变量将在目标配方和目标触发的所有依赖项中可用。请注意,依赖项仅评估一次,因此如果它可以由不同的目标触发,则特定于目标的变量可能在依赖项中可用,也可能不在依赖项中,具体取决于make解析依赖项的顺序。 / p>

2。使用eval函数

由于配方的扩展总是延迟,您可以使用配方中的eval函数来推迟赋值变量的赋值。 eval函数可以很好地放在配方中的任何位置,因为它的值是空字符串。但是,eval变量赋值使变量赋值全局;它将在整个makefile中可见,但它在其他配方中的值将再次取决于make评估配方的顺序,这不一定是可预测的。

例如:

radio:
    $(eval var = $(shell ...))

注意:

  1. 您可以使用.ONESHELL:伪目标更改此行为,但这将适用于整个Makefile;没有办法将单个配方标记为在单个子流程中执行。由于改变行为可能会以意想不到的方式破坏食谱,我通常不建议使用此功能。

答案 1 :(得分:1)

这有什么问题?

fileB: fileA
    @echo $< was modified more recently than $@

答案 2 :(得分:0)

我没有强迫makefile通过一些bash命令完成所有繁重的工作,而只是调用了一个单独的bash脚本。这为像我这样的bash脚本新手提供了更多的清晰度,因为我没有必要担心逃避make使用的当前shell。

最终解决方案:

    .PHONY: all clean

    all      : (stuff happens here)

    radio    :
            ./radio_init_check.sh
            $(MKDIR_P) $(OBJDIR)
            make $(radio_10)

radio_init_check.sh是我的缝制脚本。