git - 确保生成的尚未签入的文件在 git sync 后不会重建
问题描述
我不确定这是一个 git 问题还是一个 make 问题,或者两者兼而有之,但是这里有......
想象一下,您有一个foo.cpp
由生成器程序生成的文件,gen.py
. 如果生成器程序被修改,则必须再次运行以生成新版本的foo.cpp
.
编码此行为的 makefile 规则可能如下1:
foo.cpp: gen.py
gen.py
对于积极的发展gen.py
,我认为这是理想的。
但是,请考虑通过 git 远程提供项目的情况,例如在 github 或类似站点上。用户将下载并制作您的项目。
传统的处理生成文件的方式是不要全部检查:不要全部包含foo.cpp
在git中(添加到你的`.gitignore),当用户构建你的项目时,会生成文件。
但是,另一种方法是将生成的文件包含foo.cpp
在 git 中。这增加了一种可能性,gen.py
并且foo.cpp
可能是“不同步” 2如果一个在没有更新另一个的情况下被更改但具有其他一些优点:
- 只想构建项目但从不更新的用户
gen.py
不需要具备运行的先决条件gen.py
(例如,Python)。 - 未修改的构建速度更快,因为生成步骤不运行。
foo.cpp
您会在暂存/提交期间获得有关隐含的更改的直接反馈gen.py
,因为该文件将成为 diff 的一部分。
我对签入生成的文件与始终在本地生成它们的优点不感兴趣。您可能会假设,对于某些项目,已做出签入生成文件的决定,并且该决定没有争议。
那么,在这种情况下,我的问题是:
对于新克隆项目或同步涉及两个文件的提交的用户,我如何确保make
不会尝试生成foo.cpp
?默认情况下,git 在同步文件时将使用当前时间,因此foo.cpp
和gen.py
将具有相同的时间戳,并且foo.cpp
将被重建。
我不能要求用户更改他们的 git 配置。
1也许会有额外的依赖关系foo.cpp
也将作为先决条件出现,但这是“基本情况”。
2一种合理的方法是通过 git 挂钩强制它们同步。
解决方案
您可以比较输出,并且仅在目标不同时才更新目标。比如说,你gen.py
会将它的输出写入标准输出,所以通常你会有这样的规则:
foo.cpp: gen.py
./gen.py > $@
您可以将其更改为:
foo.cpp: gen.py
./gen.py > $@.tmp
cmp -s $@ $@.tmp && rm -f $@.tmp || mv -f $@.tmp $@
这里的缺点是,在您更新之前foo.cpp
,gen.py
配方将始终运行。但是,不会构建任何依赖的目标foo.cpp
,因为它的时间戳没有改变。
如果这很昂贵并且您想解决这个问题,您将不得不做一些更复杂的事情:如果比较是真的(没有区别),那么您需要重置时间戳gen.py
,使其与目标相同;这可确保目标在未来不再被视为过时。像这样的东西:
foo.cpp: gen.py
./gen.py > $@.tmp
if test -e $@ && cmp -s $@ $@.tmp; then \
rm -f $@.tmp; \
touch -r $@ gen.py; \
else \
mv -f $@.tmp $@; \
fi
如果您不能轻易更改输出文件名,gen.py
那么您将不得不做一些更令人作呕的事情,例如在运行之前重命名$@
为,然后将其改回或酌情使用新的。$@.old
./gen.py
ETA如果您只是想避免gen.py
在相同版本的情况下运行,这更像是一个 Git 问题而不是一个 makefile 问题,因为您真正要问的是如何知道这些文件是否在同一个 Git 提交中。这很容易,但正如我在下面的评论中所说,我认为这实际上是不对的:
foo.cpp: gen.py
tver=$$(git log -n1 --oneline $@ 2>/dev/null); \
pver=$$(git log -n1 --oneline $< 2>/dev/null); \
if test -z "$$tver" || test -z "$$pver" || test "$$tver" != "$$pver"; then ./gen.py; fi
推荐阅读
- oracle - 使用 Informatica 将 Oracle 存储过程输出 clob 参数(以创建 JSON 格式)保存到文件中
- powershell - 一键重命名计算机并加入域的批处理脚本
- django - Django:如何从不同的数据库表中获取相关数据并将其显示为一个
- python - 如何从素数列表中获取不同的因子?
- graphql - 如何将 GraphQL 查询的结果(响应)作为参数(输入)传递给突变?
- android - RecyclerView 未使用 submitList() 和 LiveData 自动刷新
- php - 在运行 XAMPP 和 IIS 的电脑上设置 WordPress
- python - 如何在 Anaconda 上下载 OpenCV?
- ajax - 无法从 ajax 打印或回显控制器中的 post 值
- php - 如何设置 cookie_httponly?