unix 如何创建一个可以远程自我更新的Makefile?

yr9zkbsy  于 2022-11-04  发布在  Unix
关注(0)|答案(2)|浏览(165)

我对一个makefile做了一些修改,使其看起来更一般化

.PHONY:
        bash hash.sh

all: .PHONY lab tests.zip

lab: .PHONY lab.cpp
        g++ -o lab lab.cpp -g -Wall -std=c++11

tests.zip:
        curl -L -O https://url/tests.zip
        unzip tests.zip

tests: .PHONY lab tests.zip
        bash scripts/test.bash lab.cpp

clean:
        rm -rf scripts tests bitset-tests.zip

我是大学里一门入门级计算机科学课程的助教,我在这里创建了一个makefile,供我的学生用来无缝地编译和测试他们的代码。
我想做的一件事是,每当远程仓库有一个新版本的makefile时,它就更新自己。我知道我可以让他们自己更新文件,但我的工作是让学生们少关注设置,而更多地关注编码,因为它是入门级的。因此,为了达到这个目的,我坚持我的想法。
目前,我使用脚本hash.sh来实现这一点,该脚本从repo中获取makefile的哈希值,并将其与student目录中的makefile的哈希值进行比较。然后获取更新的makefile并替换旧的makefile。这是在.PHONY方法中完成的。我不想添加一个像make update这样的更新方法,因为我再次希望这个过程是无缝的。你会惊讶于有多少学生不会利用这个特性,所以我想把它构建到他们肯定会使用的特性中。
有没有更好的方法,或者我做错了什么?

hc2pp10m

hc2pp10m1#

托马斯的想法是对的,但是你不能在这里使用.PHONY,因为这意味着makefile总是过时的; make知道这一点,因此如果它包含的makefile标记为. PHONY,它不会重新执行自己。
您需要为make创建一种方法,以了解自上次本地运行makefile后makefile是否被更改。我建议您这样做:

<normal makefile here>

Makefile: FORCE
        curl https://.../Makefile -o Makefile.tmp
        cmp -s Makefile Makefile.tmp && rm -f Makefile.tmp || mv -f Makefile.tmp Makefile

FORCE:

首先,它使用a FORCE target,这是一种老式的方法来模拟.PHONY目标,它总是过时的,而没有实际使用.PHONY(正如我上面提到的,在这种情况下,GNU make专门处理了.PHONY)。
其次,它检索Makefile,但只更新本地makefile文件(如果它已更改)。如果它未更改,它不会更新本地makefile文件,因此make不会重新执行自身。

pb3s4cty

pb3s4cty2#

获取散列的整个过程听起来过于复杂。如果无论如何都要进行获取,为什么不无条件地获取整个makefile呢?这节省了网络往返,而这可能是限制因素;实际数据可能只有几KB。
如果您使用的是curl,请注意--time-cond选项,例如:

curl https://... --time-cond Makefile -o Makefile

如果Makefile比当前文件的mtime更新,那么它只会获取并更新Makefile。它通过发送一个If-Modified-Since HTTP头来工作,所以你需要服务器的一些配合才能使它可靠地工作。
如果使用GNU make,你可以使用另一个巧妙的技巧:如果你有一个目标是Makefile的规则,它将在其他任何事情发生之前被执行,并且make将在继续之前重新读取更新的Makefile

.PHONY: Makefile
Makefile:
    curl https://... --time-cond Makefile -o Makefile

请注意,如果--time-cond由于某种原因导致无条件更新,这将导致无限循环,因此防范这种情况不会有什么坏处:

.PHONY: Makefile
Makefile:
    [[ ! -v MAKE_RESTARTS ]] && \
        curl https://... --time-cond Makefile -o Makefile

相关问题