Ninja: mtime 为零的文件被视为不存在

创建于 2016-03-25  ·  14评论  ·  资料来源: ninja-build/ninja

在 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 能够在这些情况下正常工作,那就太好了。

亲切的问候,
罗杰

最有用的评论

flatpak沙箱中构建时,我在这里看到类似的东西,基本上所有由ostree处理的文件,这意味着“系统”文件的 mtime = 0(不知道他们为什么这样做,但我认为它与文件 de -复制系统)。 这些系统文件不被视为不存在,而是“脏”,每次我在该环境中运行 ninja 时都会触发完全重建。

使用ninja -d explain重建时,它表示文件很脏,例如:

ninja explain: /usr/include/glib-2.0/gio/gtcpwrapperconnection.h is dirty

所有14条评论

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::StatDiskInterface::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沙箱中构建时,我在这里看到类似的东西,基本上所有由ostree处理的文件,这意味着“系统”文件的 mtime = 0(不知道他们为什么这样做,但我认为它与文件 de -复制系统)。 这些系统文件不被视为不存在,而是“脏”,每次我在该环境中运行 ninja 时都会触发完全重建。

使用ninja -d explain重建时,它表示文件很脏,例如:

ninja explain: /usr/include/glib-2.0/gio/gtcpwrapperconnection.h is dirty

对于 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

此页面是否有帮助?
0 / 5 - 0 等级