如何使用g++生成确定性二进制输出?

20

我在一个非常受监管的环境中工作,在这里我们需要能够根据同一份源代码每次构建产品时生成完全相同的二进制输入。目前我们使用的是一个古老版本的g++,已经被修补程序修改,以便在结果二进制文件中不写入日期/时间之类的任何东西,以免从构建到构建发生变化,但我想更新到g++ 4.7.2。有人知道是否有相应的修补程序,或者有什么建议可以让我找到如何获取相同源代码并生成相同的二进制输出的方法吗?

3个回答

18

Debian的可重复构建项目试图逐字节标准化Debian软件包,并在2016年获得了Linux基金会的资助

虽然这可能不仅仅包括编译,但你应该看一下它。

它还指向了这篇文章,该文章补充了@Employed所说的以下要点:

  • 将源代码放置在一个固定的文件夹中(例如/tmp/build),以处理__FILE__
  • 对于__DATE____TIME____TIMESTAMP__
    • libfaketime:https://github.com/wolfcw/libfaketime
    • 使用-D覆盖这些宏
    • -Wdate-time-Werror=date-time:如果使用了__TIME____DATE____TIMESTAMP__则警告或失败。Linux内核4.4默认使用此选项。
  • 使用ar时使用D标志,或使用https://github.com/nh2/ar-timestamp-wiper/tree/master清除时间戳
  • -fno-guess-branch-probability旧版本手册指出它是不确定性的来源,但现在不再是。不确定是否被-frandom-seed覆盖。

Buildroot有一个BR2_REPRODUCIBLE选项,可能对包级别提供一些思路,但目前还远未完善。

相关主题:


一个相关的问题是:如果我没有采取任何措施来实现确定性构建,那么我有机会找到二进制文件生成的日期吗? - Johan Boulé
@JohanBoulé 我猜只有在使用了__DATE____TIME____TIMESTAMP__的情况下才能知道编译源代码的日期。更具体的问题请参考:https://dev59.com/O4nca4cB1Zd3GeqP80c3 - Ciro Santilli OurBigBook.com
谢谢。我发现另一个有趣的部分,称为.note.gnu.build-id ELF部分。有时候你会后悔没有这种信息。所以,下一次我们会提前计划并将全局字符串常量放入二进制文件中。无论如何,我离题了,可以说是“反题”,但矛盾的是,如果我们有确定性构建,我们可以从每个SCM提交中重新构建二进制文件,直到找到与客户端拥有的未知二进制文件相匹配的版本,然后我们就知道对应的源代码版本了。 - Johan Boulé

8
我们还依赖于比特完全一致的重建,并使用gcc-4.7.x。除了设置和使用<-frandom-seed=<input-file-name>>之外,还有一些补丁可以在分支中找到。

1
PWD=/proc/self/cwd 是什么意思? - Steven Behnke
6
@StevenBehnke 我们在构建时使用调试信息。在Linux上,GCC将PWD(由shell设置为当前工作目录)记录为当前编译目录。由于我们希望无论在哪个目录中执行构建,都能产生完全相同的构建结果,因此我们将PWD设置为可预测的值。 - Employed Russian
3
GCC中随机性的主要应用是什么? - Ciro Santilli OurBigBook.com

-1

使用'DATE'宏会使构建过程不确定性


4
你好,这个和我提到的 __DATE__ 有区别吗?https://dev59.com/CWUq5IYBdhLWcg3wQ-NF#31019307 - Ciro Santilli OurBigBook.com

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接