根据文件的使用期限,在Makefile中运行不同的代码

根据文件的使用期限,在Makefile中运行不同的代码,makefile,Makefile,我正在尝试为共享的、继承的基本makefile代码创建一个自动更新机制,我只希望它每天检查一次更新。修复后,我想我最不需要弄清楚的是,为什么我比较的值没有按照预期的表现 我试图在文件上使用上次修改的时间戳。makefile update ts指示上次运行更新的时间,并使用查找来检查-mtime+24h-name'.makefile update ts'以指示它是否足够旧。我没有发现任何语法错误,而且从各种find命令返回的值似乎是正确的,所以我不明白为什么,但我的逻辑不起作用 因此,让我们从最基

我正在尝试为共享的、继承的基本makefile代码创建一个自动更新机制,我只希望它每天检查一次更新。修复后,我想我最不需要弄清楚的是,为什么我比较的值没有按照预期的表现

我试图在文件
上使用上次修改的时间戳。makefile update ts
指示上次运行更新的时间,并使用
查找来检查-mtime+24h-name'.makefile update ts'
以指示它是否足够旧。我没有发现任何语法错误,而且从各种
find
命令返回的值似乎是正确的,所以我不明白为什么,但我的逻辑不起作用

因此,让我们从最基本的方面入手,逐步提高:

从一个非常普通的Makefile开始:

work:
ifeq (a,a)
    @echo "A"
else
    @echo "not A"
endif
✅ 工作如期进行

如果我随后开始使用变量存储“a”值:

✅ 工作如期进行

因此,让我们切换到使用
find
来获取文件是否存在以及是否>=24小时旧的一些指示

ts-filename=.makefile-update-ts
exists=`find . -name '$(ts-filename)'`
old=`find . -mtime +24h -name '$(ts-filename)'`
match=./$(ts-filename)

work:
    @echo "$(match) (match)"
    @echo "$(exists) (exists)"
    @echo "$(old) (old)"
✅ 似乎
find
命令正在获取我想要的值,并且我能够将它们返回出来。因为我刚刚创建了文件,“旧”搜索没有找到任何东西,这是意料之中的

是时候毕业到最后的剧本了。。。至少我是这么想的。在下面的makefile中,我添加了一些额外的
echo
s来说明比较时的状态,当与执行的各种命令的输出一起使用时,这是没有意义的

ts-filename=.makefile-update-ts
exists=`find . -name '$(ts-filename)'`
old=`find . -mtime +24h -name '$(ts-filename)'`
match=./$(ts-filename)

work: .check-for-update
    @echo "working..."

.check-for-update:
# is the file > 24 hours old?
ifeq ($(old),$(match))
    @echo checking for Makefile updates...
    @make .update
else
    @echo $(match) - "match"
    @echo $(old) - "old"
# if the file doesn't exist at all yet, pull the update
ifeq ($(exists),$(match))
    @echo "last update was recent, not updating..."
else
    @echo $(exists) - "exists"
    @echo Getting base Makefile...
    @make .update
endif
endif

.update:
    touch $(ts-filename)


❌ 为什么,如果文件存在,并且它不是“旧的”(
$(旧的)
为空),它会打印“Getting base Makefile…”???我希望它会打印“上次更新是最近的,不是更新……”

问题又回到了最初的误解。makefile不是shell脚本。考虑这一点:

exists=`find . -name '$(ts-filename)'`
old=`find . -mtime +24h -name '$(ts-filename)'`
反勾号是一个shell功能。Make对他们一无所知。这里声明了两个变量,它们包含包含反勾号的文本字符串和命令,而不是像在shell中那样运行这些命令的输出

为此:

ifeq ($(old),$(match))
它展开以比较文字字符串:

显然,这些字符串并不相等

如果要运行shell脚本并将其输出分配给make变量,则必须使用make,如下所示:

exists := $(shell find . -name '$(ts-filename)')
old := $(shell find . -mtime +24h -name '$(ts-filename)')
这里有几点:

我使用
:=
而不是
=
来提高效率

我强烈建议您在处理make变量时,在赋值运算符周围使用空格,而不是像处理shell变量那样将它们一起运行而不使用空格。也许这种认知失调将有助于强化这种差异。另外,它只是更好

哦,你可能会问,为什么你的第三个例子有效?很简单,这是因为您正在将文本字符串传递给shell,而shell正在为您进行扩展。如果删除shell脚本行中的
@
前缀,您可以很容易地看到这一点。另一个技巧是,<强>绝对不要>强> >添加“代码> @ /代码>直到任何100%个文件文件配方,直到你确信它是完美的(甚至,你可能会考虑不这样做)。 如果删除它们,您将看到:

work:
        echo "$(old) (old)"
这将打印:

echo "`find . -mtime +24h -name '$(ts-filename)'` `find . -mtime +24h -name '$(ts-filename)'`"
./.makefile-update-ts ./.makefile-update-ts
如果make变量包含已扩展的内容,则会出现以下情况:

echo "./.makefile-update-ts ./.makefile-update-ts"
./.makefile-update-ts ./.makefile-update-ts
另一个技巧是,当您试图在shell脚本中使用MAKE变量时,您应该始终使用单引号(除非该值可能包含单引号),以便shell不会与该值混淆:

work:
        echo '$(old) (old)'
将打印:

echo '`find . -mtime +24h -name '$(ts-filename)'` `find . -mtime +24h -name '$(ts-filename)'`'
`find . -mtime +24h -name '$(ts-filename)'` `find . -mtime +24h -name '$(ts-filename)'`

太棒了,谢谢你!
exists := $(shell find . -name '$(ts-filename)')
old := $(shell find . -mtime +24h -name '$(ts-filename)')
work:
        echo "$(old) (old)"
echo "`find . -mtime +24h -name '$(ts-filename)'` `find . -mtime +24h -name '$(ts-filename)'`"
./.makefile-update-ts ./.makefile-update-ts
echo "./.makefile-update-ts ./.makefile-update-ts"
./.makefile-update-ts ./.makefile-update-ts
work:
        echo '$(old) (old)'
echo '`find . -mtime +24h -name '$(ts-filename)'` `find . -mtime +24h -name '$(ts-filename)'`'
`find . -mtime +24h -name '$(ts-filename)'` `find . -mtime +24h -name '$(ts-filename)'`