如果尚未安装,我想将要构建的软件包添加到构建列表中。
目标是在没有 pip 的情况下从本地源安装一些 Python 包。我无权访问 pip...
所以我写了一个看起来像这样的 Makefile:
all: natsort foo bar foobar ...
natsort: natsort-4.0.4.tar.gz
tar xvzf $<
cd $(patsubst %.tar.gz,%, $<) && python setup.py install
rm -rf $(patsubst %.tar.gz,%, $<)
python -c 'import natsort'
echo -e "Installation of $< [done]\n" >> install.log
这个实现的问题是每次我运行 Make 命令时,所有的包都会被重建和重新安装。我想检查模块是否已经安装。我的想法是做这样的事情:
ifdef $(shell python -c 'import natsort')
all: natsort
endif
我怎样才能重写它以使其工作?
最佳答案
你绝对可以做这样的事情。但是每次运行 make
都会“花费”一次 shell 调用和一次 python 调用,这是一个相对较高的成本。
基本上,有两种方法可以以更便宜的方式完成您想要的事情。
配方中的标记文件和短路逻辑。
标记文件方法基本上就是您所拥有的方法,只是您将 touch $@
添加到配方的末尾。
natsort: natsort-4.0.4.tar.gz
tar xvzf $<
cd $(patsubst %.tar.gz,%, $<) && python setup.py install
rm -rf $(patsubst %.tar.gz,%, $<)
python -c 'import natsort'
echo -e "Installation of $< [done]\n" >> install.log
touch $@
以这种方式第一次运行配方会创建 stamp 文件,直到 natsort-4.0.4.tar.gz
变得比 stamp 文件更新或 stamp 文件被删除,配方将永远不会运行再次。
请注意第二点。删除 stamp 文件,然后重新安装。
这就是短路逻辑解决方案解决的问题。
与原来的多条命令规则不同,您将它们全部打包在一个命令中(这是可选的,但可以节省重复检查的成本),并在执行任何工作之前检查要安装的模块。
natsort: natsort-4.0.4.tar.gz
if ! python -c 'import natsort'; then \
tar xvzf $< || exit 1; \
cd $(patsubst %.tar.gz,%, $<) && python setup.py install || exit 1; \
rm -rf $(patsubst %.tar.gz,%, $<); \
python -c 'import natsort' || exit 1; \
echo -e "Installation of $< [done]\n" >> install.log; \
fi
注意需要添加|| exit 1
因为我们不再为我们处理它。另请注意,这现在总是运行规则(我们应该标记natsort
和.PHONY
)但在最常见的情况下它会在之后停止if
测试。
综上所述,您可以结合使用这些方法来获得两全其美的效果。
natsort: natsort-4.0.4.tar.gz
if ! python -c 'import natsort'; then \
tar xvzf $< || exit 1; \
cd $(patsubst %.tar.gz,%, $<) && python setup.py install || exit 1; \
rm -rf $(patsubst %.tar.gz,%, $<); \
python -c 'import natsort' || exit 1; \
echo -e "Installation of $< [done]\n" >> install.log; \
fi
touch $@
您将获得这两种方法的好处。第一次运行 make
时,natsort
文件不存在,并且运行了配方。 natsort
未安装,因此 if
测试失败并开始安装。之后 natsort
文件被 touch
编辑。下次安装 make 时,natsort
比 natsort-4.0.4.tar.gz
更新,所以 make
认为它没有任何问题做。如果出于某种原因,您删除了 natsort
文件,那么下次 make
运行时,它会检查模块是否存在,跳过安装并touch
再次输入 natsort
文件以恢复同步。
关于linux - 使用 Make 在 shell 条件下构建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33630829/