相同的代码和相同的编译器可以在不同的机器上生成不同的二进制文件吗?

Can the same code and same compiler produce a different binary on different machines?

Nixos binary caches 的想法让我考虑了这个问题。

在 nix 中,每个编译的二进制文件都与一个哈希键相关联,该哈希键是通过对所有依赖项和构建脚本进行哈希处理而获得的,即 nix 中的 'derivation'。无论如何,这是我的理解。

但是在不同的机器上编译时,相同的推导不能导致不同的二进制文件吗? 如果机器 A 的处理器的指令集与机器 B 的处理器略有不同,并且编译器考虑了这种不同的指令集,那么在机器 A 上编译推导生成的二进制文件是否可以与在机器 A 上编译推导生成的二进制文件区分开来机器乙?如果是这样,那么不同的二进制文件不能有相同的推导,从而有相同的 nix 哈希吗?

在具有不同指令集的机器上构建的相同推导是否总是产生相同的二进制文件?

这取决于编译器实现和传递给它的选项。例如,默认情况下 GCC 似乎不会关注当前处理器的细节,除非您指定 -march=native-mtune=native.

所以是的,如果您使用像这些标志或具有像这些标志这样的默认行为的编译器,您将在具有不同型号 cpu 的机器上获得不同的输出。

构建也可能由于其他原因而无法重现,例如时钟值或随机值的不当使用,甚至线程以非确定性交错模式访问的计数器。

Nix 确实提供了一个沙箱来移除一些熵源;主要是机器上可能存在的假定不相关的软件。出于实际原因,它不会删除所有这些来源。

出于这些原因,即使在使用 Nix 打包时,也必须考虑可再现性;不是它能完全解决的问题

我将引用菜单“实现确定性构建 ” 来自 https://reproducible-builds.org/docs/ 并据我所知用 Nix 的效果对其进行注释。不要在此引用我的话。

  • SOURCE_DATE_EPOCH:已解决;由 Nixpkgs 设置
  • 确定性构建系统:部分解决; Nixpkgs 可能包含补丁
  • 不稳定的输入可能会消失:如果您将源上传到(二进制)缓存,则可以使用 Nix 解决。赫拉克勒斯 CI 做到了这一点。
  • 输入的稳定顺序:大部分已解决。 Nix 语言保留源代码顺序并对属性进行排序。
  • 值初始化:Nix 未解决的低级问题
  • 版本信息:未解决;可以在沙箱中访问时钟
  • 时间戳:同上
  • 时区:由沙盒解决
  • 语言环境:由沙盒解决
  • 存档元数据:未解决
  • 输出的稳定顺序:使用沙盒无法解决的随机性
  • 随机性:相同
  • 构建路径:部分; linux 使用 /build; macOS 可能因安装方法而异
  • 系统图像:从以前的项目中提取元素的广泛问题
  • JVM:相同