在 CentOS 7 系统上:
$ tar xf ome-cmake-superbuild-0.1.0.tar.xz
tar: ome-cmake-superbuild-0.1.0/cmake/GitVersion.cmake: implausibly old time stamp 1970-01-01 01:00:00
$ ls -l ome-cmake-superbuild-0.1.0/cmake/GitVersion.cmake
-rw-r--r-- 1 rleigh lsd 236 Jan 1 1970 ome-cmake-superbuild-0.1.0/cmake/GitVersion.cmake
这个源档案被错误地打包,单个文件的 mtime 为零(即 Unix 纪元的开始)。
$ mkdir build
$ cd build
$ cmake -G Ninja ../ome-cmake-superbuild-0.1.0
$ ninja
[1/1] Re-running CMake...
[cmake re-run repeated 100 times]
ninja: error: manifest 'build.ninja' still dirty after 100 tries
原因:
$ ninja -d explain
ninja explain: output /tmp/ome-cmake-superbuild-0.1.0/cmake/GitVersion.cmake of phony edge with no inputs doesn't exist
显然,该文件确实存在。 如果我touch /tmp/ome-cmake-superbuild-0.1.0/cmake/GitVersion.cmake
将时间戳更新为当前时间,则ninja
运行完美。 Ninja 似乎将 mtime 为零的文件视为不存在,这似乎是不正确的。 请问你能考虑改变这种行为吗? 虽然这是一个不寻常的极端情况——文件不应该有这么旧的时间戳——它可能并且确实由于各种原因发生,如果 Ninja 能够在这些情况下正常工作,那就太好了。
亲切的问候,
罗杰
bool Cleaner::FileExists(const string& path) {
string err;
TimeStamp mtime = disk_interface_->Stat(path, &err);
if (mtime == -1)
Error("%s", err.c_str());
return mtime > 0; // Treat Stat() errors as "file does not exist".
^^^^^^^^^
}
看起来像一个可能的候选人。 和
void MarkMissing() {
mtime_ = 0;
}
还有RealDiskInterface::Stat
和DiskInterface::MakeDirs
。 从根本上说,您使用 mtime 作为时间戳和错误代码,这是不可能的,因为所有有效的 mtime 值也是有效的时间戳(甚至是负的)。 这个假设甚至在 src/disk_interface.h 中说明:
/// stat() a file, returning the mtime, or 0 if missing and -1 on
/// other errors.
在其他一些地方也假设了这一点。 我不认为您当前的策略是安全的,特别是当在例如存档格式中未指定时,零通常是默认值。 考虑到基础stat
(2) 系统调用在目录条目不存在时返回ENOENT
,独立于 st_mtime。 也许您可以使用包含valid
标志或枚举(-1 和 0 情况)加上mtime
的小型Stat
结构。 它可以提供operator<
用于mtime
比较和operator(bool)
或operator!
用于有效性检查,这将明确提供这两个功能并消除此处观察到的有问题的行为。
这是#795 的骗局。 有人建议让 mtime 为 1 而不是 0 表示“文件不存在”:-)
在#795 上,最新的状态是现在可以轻松打印诸如“ninja 无法处理 mtime 为 0 的文件”之类的消息,而不是混淆并默默地将它们标记为脏。 这对你来说足够好吗?
为什么系统上文件的 mtime 为 0?
1 的 mtime 是一个聪明的黑客! 也可以只在所有 mtimes 中添加一个,以
使 0 可用。 (我们不关心 mtime 的具体值,
它们只是一个神奇的 cookie,会在文件更改时更改。 在 Windows 上
它们是其他一些随机值,而不是纪元秒计数器。)
2016 年 4 月 5 日星期二下午 6:36,Nico Weber通知@github.com 写道:
这是#795 https://github.com/ninja-build/ninja/issues/795 的骗局。
有人建议让 mtime 为 1 而不是 0 表示“文件没有
存在” :-)在 #795 https://github.com/ninja-build/ninja/issues/795 上,最新的
状态是现在很容易打印“忍者无法处理”之类的消息
mtime 为 0" 的文件,而不是混淆并默默地将它们标记为
肮脏的。 这对你来说足够好吗?为什么系统上文件的 mtime 为 0?
—
您收到此消息是因为您订阅了此线程。
直接回复此邮件或在 GitHub 上查看
https://github.com/ninja-build/ninja/issues/1120#issuecomment -206067067
在此特定实例中 mtime 为零的原因是使用 Python tarfile
模块而没有在保存到 tar 文件中的TarInfo
对象上显式设置mtime
除非手动设置,否则默认为零。 这与zipfile
模块中类似接口的行为不同,后者默认为当前系统时间(创建新文件时可能会预期)。 但我见过其他工具也做类似的事情——零通常是结构中的默认值,这不可避免地导致在各种条件下创建的文件时间为零。
使用 1 的 mtime 确实是一个“聪明的黑客”,肯定会在这里解决这个问题。 另一方面,像我建议的那样的修复不会花费太多精力,并且根本不需要任何特殊值,使其在所有情况下都很强大。 无论哪种方式对我来说都很好。
感谢您关注此事,
罗杰
但是 0 mtime 从来不是故意的,对吧? 似乎出错可能是最好的前进方式。
这不是故意的,不是。 但它_是_一些偶然发生的相对普遍的事情。 我不认为出错是合适的; 如果有人发布带有未设置时间戳的源代码,那实际上是 ninja 无法构建的。 将其设置为 1 将是一个更好的策略。
将文件系统表示时间戳转换为
忍者时间戳类型在这里:
https://github.com/ninja-build/ninja/blob/master/src/disk_interface.cc#L60
我建议更改此代码:
https://github.com/ninja-build/ninja/blob/master/src/disk_interface.cc#L193
返回 st.st_mtime+1;
我相信它会以我们没有正确处理为代价来解决所有问题
具有最大纪元日期的文件(但我们将拥有各种 y2k38
一旦我们接近那个区域,就会出现该区域的问题)。
2016 年 4 月 8 日星期五上午 7:56,Roger Leigh通知@github.com
写道:
这不是故意的,不是。 但它_是_相对发生的事情
通常是偶然的。 我不认为出错是合适的; 如果
任何人都曾发布未设置时间戳的源代码,这是事实
无法用忍者建造。 将其设置为 1 将是一个更好的策略。—
您收到此消息是因为您发表了评论。
直接回复此邮件或在 GitHub 上查看
https://github.com/ninja-build/ninja/issues/1120#issuecomment -207466847
对于 flatpak,我会将https://github.com/flatpak/flatpak/issues/607#issuecomment -287952697 中的补丁添加到我们的 ninja 版本中,直到弄清楚为止。
我想我在 #1293 中有更彻底的修复
还要注意的是,我还提交了在 Flatpak 中使用的 Patrick Griffis 补丁作为 pull request #1292,这是一个很好的解决问题的方法,我们知道它已经过良好测试(至少应用了构建定期通过)。
但是我确实在 #1293 中做了一些努力,以便彻底改变语义并且任何 mtime 都是有效的,包括 0 和负 mtime,它们也应该是有效的(不确定代码库如何抵抗负 mtime,不过)。 虽然我认为 #1293 是正确的解决方法,但它当然更像是一个侵入性的更改,并且最好回顾一下(我最终没有修改 deps_log.[cc,h],我不确定是否需要更改以区分文件存在和 mtimes)。 然而,我使用 #1293 分支构建了很多 GNOME 模块,没有问题。
无论采用哪条路线,最好在上游忍者中对此进行一些修复。
谢谢,我合并了你的#1292。 正如其他地方所说,这对我来说似乎是最好的解决方案,所以如果你没问题的话,我现在会忽略 #1293。
非常感谢您的修复!
谢谢,我合并了你的#1292。 正如其他地方所说,这对我来说似乎是最好的解决方案,所以如果你没问题的话,我现在会忽略 #1293。
不用担心,我很高兴我不需要下游补丁:)
也许你也可以关闭#795
最有用的评论
在flatpak沙箱中构建时,我在这里看到类似的东西,基本上所有由ostree处理的文件,这意味着“系统”文件的 mtime = 0(不知道他们为什么这样做,但我认为它与文件 de -复制系统)。 这些系统文件不被视为不存在,而是“脏”,每次我在该环境中运行 ninja 时都会触发完全重建。
使用
ninja -d explain
重建时,它表示文件很脏,例如: