Makefile问题:如何避免已存在可执行文件时重复构建release目标
Makefile 构建优化问题解决方案
原Makefile内容
release: comprel a2s: release libtelopa.so: cd telop/neta/lib && make && cp libtelopa.so ../../../ comprel: libtelopa.so go build -ldflags="-s -w" . upx --best --lzma a2ssvr clean: cd telop/neta/lib && make clean git clean -fdX distclean: clean rm -fr a2s_*.deb deb: a2s libtelopa.so rm -fr debian.deb cp libtelopa.so debian/opt/a2s/bin cp libjson/* debian/opt/a2s/bin cp a2ssvr debian/opt/a2s/bin/a2s dpkg-deb --build --root-owner-group debian rm -fr a2s*.deb dpkg-name debian.deb
问题现象与需求
- 全新拉取代码构建正常,但生成
a2ssvr后再次执行make deb,release目标会被重复调用;而libtelopa.so文件存在时不会重复构建。 - 尝试添加
.PHONY标记无效,将a2s改为直接依赖libtelopa.so虽有效,但不想改写所有构建脚本。 - 需求:
a2s对应的可执行文件存在时直接使用,不存在才触发构建规则。
问题根源
a2s是一个无对应实体文件的逻辑目标,Make默认会判定这类目标「始终需要更新」,因此每次执行make deb时都会触发其依赖的release目标,进而重复执行comprel的构建命令。而libtelopa.so是有实体文件的,Make会通过文件时间戳判断是否需要重新构建,因此不会重复执行。
解决方案
核心思路
让a2s目标关联到实际生成的a2ssvr文件,让Make可以通过文件的存在性和时间戳来判断是否需要触发构建。
修改步骤
调整
comprel与a2ssvr的规则:
将comprel的构建命令拆分到a2ssvr的目标规则中,让a2ssvr成为明确的实体文件目标:comprel: libtelopa.so a2ssvr a2ssvr: libtelopa.so go build -ldflags="-s -w" . upx --best --lzma a2ssvr这样Make会检查
a2ssvr是否存在且最新,只有当它不存在或依赖的libtelopa.so更新时,才会执行构建命令。修改
a2s的依赖关系:
让a2s直接依赖a2ssvr,而非release:a2s: a2ssvr此时
a2s作为逻辑目标,会继承a2ssvr的文件状态——只要a2ssvr存在且最新,a2s就会被判定为已完成,不会触发后续的release与comprel。
修改后的完整Makefile
release: comprel a2s: a2ssvr libtelopa.so: cd telop/neta/lib && make && cp libtelopa.so ../../../ comprel: libtelopa.so a2ssvr a2ssvr: libtelopa.so go build -ldflags="-s -w" . upx --best --lzma a2ssvr clean: cd telop/neta/lib && make clean git clean -fdX distclean: clean rm -fr a2s_*.deb deb: a2s libtelopa.so rm -fr debian.deb cp libtelopa.so debian/opt/a2s/bin cp libjson/* debian/opt/a2s/bin cp a2ssvr debian/opt/a2s/bin/a2s dpkg-deb --build --root-owner-group debian rm -fr a2s*.deb dpkg-name debian.deb
验证效果
执行make deb生成a2ssvr后,再次执行make deb时,Make会检测到a2ssvr已存在且无依赖更新,因此不会重复调用release与comprel,直接进入deb打包流程。
内容的提问来源于stack exchange,提问作者xrfang
相关产品推荐
相关产品推荐

