首页 > 解决方案 > Makefile:避免重新编译克隆的存储库

问题描述

我正在尝试从 git 克隆存储库并在本地编译它。Makefile 的相关部分粘贴在下面。

BUILDDIR = $(PWD)/build 
# rest of the Makefile 
...
all: release 

release: $(BUILDDIR)/buildr/Makedir $(BUILDDIR)/depqbf

$(BUILDDIR)/buildr/Makedir: 
    mkdir -p $(BUILDDIR)/buildr

$(BUILDDIR)/depqbf: 
    cd $(BUILDDIR); rm -rf depqbf; git clone git@github.com:lonsing/depqbf.git 
    cd $(BUILDDIR)/depqbf;./compile.sh

问题是如果我使用rm -rf depqbf,每次运行 make 时都会发生编译过程。

如果我删除它,然后再次执行make

致命:目标路径“depqbf”已经存在并且不是空目录。

如果目录不存在,是否可以仅克隆和编译。

标签: makefiledirectorygnu-make

解决方案


每次我运行 make 时都会发生编译过程

你的食谱的目标:

$(BUILDDIR)/depqbf/depqbf:
    cd $(BUILDDIR); rm -rf depqbf; git clone git@github.com:lonsing/depqbf.git
    cd $(BUILDDIR)/depqbf;./compile.sh

是文件$(BUILDDIR)/depqbf/depqbf。您是在告诉 Make,如果目标$(BUILDDIR)/depqbf/depqbf 不存在,那么 Make 将通过运行以下命令来制作目标:

cd $(BUILDDIR); rm -rf depqbf; git clone git@github.com:lonsing/depqbf.git
cd $(BUILDDIR)/depqbf;./compile.sh

但是这些命令永远不会创建一个名为$(BUILDDIR)/depqbf/depqbf. 他们永远不会成为目标。

因此,每次 Make 考虑目标时,它都会通过运行这些命令来决定必须制作的目标。

如果您删除rm -rf depqbf,那么当 Make 尝试目标时:

fatal: destination path 'depqbf' already exists and is not an empty directory.

自然,因为您无法克隆到现有的非空目录中。这与配方始终在运行这一事实无关。它一直在运行,因为它从未达到目标。

你的另一个食谱:

$(BUILDDIR)/buildr/Makedir:
    mkdir -p $(BUILDDIR)/buildr

同样是一个永远不会成为目标的人。命令:

mkdir -p $(BUILDDIR)/buildr

永远不会创建文件$(BUILDDIR)/buildr/Makedir。我看不出这个配方的目的,所以我假设它只是应该创建文件 $(BUILDDIR)/buildr/Makedir,如果它不存在,出于某种原因。

然后,当且仅当目标不存在时,此 makefile 将尝试创建目标:

生成文件

BUILDDIR := $(PWD)/build

.PHONY: all release

all: release

release: $(BUILDDIR)/buildr/Makedir $(BUILDDIR)/depqbf

$(BUILDDIR)/buildr/Makedir: | $(BUILDDIR)/buildr
    touch $@

$(BUILDDIR)/depqbf: | $(BUILDDIR)
    cd $(dir $@); git clone git@github.com:lonsing/depqbf.git 
    cd $@; ./compile.sh

$(BUILDDIR) $(BUILDDIR)/buildr:
    mkdir -p $@

GNU Make 手册中的有用参考资料:-


推荐阅读