アーカイブのメタデータ(Archive metadata)
ほとんどのアーカイブ形式は、特別に指定しない限り、ビルド環境に由来する情報をメタデータとして記録するようになっています。 わかりやすいのはファイルの最終更新日時ですが、ファイルの並び順、ユーザー、グループ、(数値の)ID、権限も気になるところです。 このセクションでは説明用に Tar 形式を使用しますが、他の形式についてもだいたい同じことが言えると思います。
ファイル変更日時
ほとんどのアーカイブ形式ではファイルの最終変更日時と作成日時を記録します。
Tar では指定した変更日時を全てのファイルに設定できます。
(日時文字列末尾の Z
は タイムゾーン が UTC であることを示しています)
Tar 以外のアーカイブ形式では、アーカイブを作成する前に touch
コマンドで 任意の変更日時 を設定できます。
ビルドプロセスで作成、変更しないファイルについては元の日時を残すほうが望ましいでしょう。
GNU Tar について後者の場合を簡単に扱うための修正パッチが作成されています。
Debian の tar についてはバージョン 1.28-1 から利用できるようになりました。
少し待てば upstream に反映されるでしょうけど、使うときは注意が必要です。
新しいフラグ --clamp-mtime
を指定すると、--mtime
で指定した日時より変更日時が新しいファイルの日時を変更するようになります。
元から存在するファイルの変更日時を変更したくないときは便利な機能です。
ファイルの並び順
たいていのアーカイブ形式では、ディレクトリの内容を読み取るとき、ファイルの並び順はファイルシステムと同じようになります。 つまり、実行するたびに変化する場合があります。
GNU Tar では、バージョン 1.28 で導入した --sort=name
フラグを使用すると、ロケールに依存せずファイルを並び替えることができるようになりました。
それより古いバージョン、あるいは他のアーカイブ形式では、find
コマンドと sort
コマンドを組み合わせれば同じ結果を生成できます。
sort
コマンドを実行するとき、意図しない照合順序で並び替えが行われないよう、ロケールを C
にするのを忘れないようにしましょう。
ユーザー、グループ、(数値の)ID
アーカイブ形式によってはファイル所有者のユーザーやグループを記録できます。 文字列の場合もありますし、対応する(数値の)IDの場合もあります。
既定のシステムグループに所属するファイルなら何も問題はありません。 しかし、ほとんどの場合ビルドを実行するのは一般ユーザーです。 アカウント名や関連するIDを記録してしまうと、ビルドの再現性を損ねてしまう場合があります。
Tar ではファイル所有者のユーザーやグループを指定できます。
ユーザーとグループに 0
を指定して --numeric-owner
も一緒に指定するのが安全です。
そうすれば確実に 0 を記録するからです。
PAX ヘッダ
GNU Tar で PAX 形式を使用するときに環境変数 POSIXLY_CORRECT
を設定すると、ファイルの作成日時、アクセス日時、tar プロセスのプロセスIDを非決定論的に決まるメタデータとして追加するようになります。
この振る舞いを止めるには、POSIXLY_CORRECT
を設定しないか(tar 1.32 より新しいバージョン が必要です)、tar の引数に --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime
や --format=gnu
を追加するか(どちらも GNU Tar で使用できるフラグです)、特に問題なければ --format=usatr
を使用します。
完全な例
Tar コマンドでアーカイブを作成するときのお手本です。
後処理
再現性のあるアーカイブを作成できないツールでも、後処理でどうにかなる場合があります。
strip-nondeterminism は Zip や Jar アーカイブの正規化に対応しています(制限 はあります)。 Tor Browser の使用するスクリプト re-dzip.sh のような方法もあるでしょう。
静的ライブラリ
UNIX 風システムでは、ar というアーカイブ形式の静的ライブラリ(.a
ファイル)を使用します。
他のアーカイブ形式と同様に、タイムスタンプやユーザーID、グループID、ファイル権限をメタデータとして記録しています。
どれもライブラリとして使用するときは不要な情報です。
GNU Ar や binutils 由来のツールは、ユーザーID、グループID、タイムスタンプを 0 にして全てのファイルを同じ種類として扱う deterministic mode に対応しています。
./configure
の引数に --enable-deterministic-archives
を指定すると、有効になります。
ディストリビューションによっては有効化された状態で配布しているし[distros-with-default]、Makefile のターゲットが archive.a(foo.o)
になっている場合を除けば安全だと言えるでしょう(関連する不具合)。
binutils を --enable-deterministic-archives
でビルドしていない場合、ビルドシステムは ar
や関連するコマンドに適切な引数を渡さないといけません。
たいていのビルドシステムでは環境変数 ARFLAGS
に Dcvr
を設定すれば、deterministic mode を有効化できます。
関数索引を作成するために ranlib
を使っているときは -D
を渡すのを忘れないようにしてください。
後処理の方法として、strip-nondeterminism を使う方法や、objcopy
を使う方法があります。
objcopy --enable-deterministic-archives libfoo.a
前の実行方法では ファイルの並び順 を固定できません。
Initramfs イメージ
initramfs イメージは cpio 形式のアーカイブです。
cpio ヘッダー形式(詳しくは man 5 cpio
してください)にはデバイスやiノード番号を記録できますが、これらはシステムによって異なります。
これらの情報を除外する方法として、bsdtar
をパイプで連結する方法があります。
決定論的な結果にならない例です。
echo ucode.bin |
bsdcpio -o -H newc -R 0:0 > ucode.img
決定論的な結果になる例です。
echo ucode.bin |
bsdtar --uid 0 --gid 0 -cnf - -T - |
bsdtar --null -cf - --format=newc @- > ucode.img
タイムスタンプなどの問題も解決する必要があるので注意してください。
GNU Libtool
コミットハッシュが 74c8993c
以前(最初に取り込まれたバージョンは 2.2.7b)の GNU Libtool では、find コマンドの結果を並び替えていませんでした。
そういう状態で作成された(ブートストラップされた)パッケージは大量に存在します。
GNU GCC の ltmain.sh
は libtool 2.2.7a が生成した、と報告するのですが、GNU GCC は独自に libtoo.m4
と ltmain.sh
を保守しており、再現性の問題については d41cd173e23
で解消済みになっています。
この修正が取り込まれた最初のバージョンは 9.1.0 なので、それより前のバージョンの GCC にはビルドの再現性を損ねる可能性が残っていると言えます。
Introduction
Achieve deterministic builds
- SOURCE_DATE_EPOCH
- 確実なビルドシステム(Deterministic build systems)
- 揮発性のある入力データは消える場合がある(Volatile inputs can disappear)
- 入力データの順序を固定する(Stable order for inputs)
- 値を初期化する(Value initialization)
- バージョン情報(Version information)
- タイムスタンプ(Timestamps)
- タイムゾーン(Timezones)
- ロケール(Locales)
- アーカイブのメタデータ(Archive metadata)
- 出力データの順序を固定する(Stable order for outputs)
- 無作為性(Randomness)
- ビルド時のファイルシステムパス(Build path)
- システムイメージ(System images)
- JVM
Define a build environment
- ビルド環境に含む要素(What's in a build environment?)
- ビルド環境を記録する(Recording the build environment)
- ビルド環境の定義における戦略(Definition strategies)
- Proprietary operating systems
Distribute the environment
Verification
Specifications
Follow us on Twitter @ReproBuilds, Mastodon @reproducible_builds@fosstodon.org & Reddit and please consider making a donation. • Content licensed under CC BY-SA 4.0, style licensed under MIT. Templates and styles based on the Tor Styleguide. Logos and trademarks belong to their respective owners. • Patches welcome via our Git repository (instructions) or via our mailing list. • Full contact info