確実なビルドシステム(Deterministic build systems)
ファイルシステム上の並び順や現在時刻のように、調整するのが難しい、あるいは不可能な要因によってソースコードが変化してしまう場合、再現性のあるビルドを実現するのは簡単なことではありません。
境界線を越えない
ビルドシステムを確実にする(決定論的に振る舞うようにする)ために必要な要因は、 ビルド環境 の定義の一部と強く結びついています。
例えば、異なるバージョンのコンパイラは異なるビルド結果を生成するから、ビルド環境には使用するコンパイラのバージョンを含めなければなりませんでした。
grep
や sed
のように単純なツールについて同じような想定をする必要はありません。
ビルド環境としては「いわゆる Unix 風のシステム」という緩い定義で十分でしょう。
しかし、ビルドを実行する直前にシステムの疑似乱数生成器を任意の値で初期化するのはいい方法だとは思えません。 ビルド結果が乱数に影響されないようにするほうがいいでしょう。
他にも境界線に関する具体例があります。 ビルドを実行するパスをビルド環境の定義に含めている場合、ビルドシステムがビルド結果として常に同じパスを出力する必要はありません。 ただし、違うパスでビルドしても、同じパスでビルドした結果と一致しなければなりません。
簡単な説明
確実な(決定論的な)ビルドシステムを構築するために守るべき事項は次のとおりです。
- 安定した入力を保証する(Ensure stable inputs.)
- 安定した出力を保証する(Ensure stable outputs.)
- 環境から収集する情報は最小限にする(Capture as little as possible from the environment.)
以降の例は、同じソースコードで複数回ビルドしていると異なる結果になってしまう一般的な問題に関する助言です。
CMake notes
初期設定の CMake はビルドを実行したディレクトリをビルド環境の一部として扱うようになっています。 次の一覧は既知の問題と推奨する設定です。
- CMake sets a
RPATH
for binaries that link to a library in the the same project. Even when this is stripped at installation time, the build-id section will be different. Possible workarounds:- Users can set
CMAKE_SKIP_RPATH=ON
to disable the use of RPATH. Disadvantage: programs from the build directory cannot be run without settingLD_LIBRARY_PATH
. - Projects can set
CMAKE_BUILD_WITH_INSTALL_RPATH=ON
to ensure a deterministic RPATH. Disadvantage: programs from the build directory cannot be run without settingLD_LIBRARY_PATH
. - Set
CMAKE_BUILD_RPATH_USE_ORIGIN=ON
to enable the use of relative directories in RPATH (requires CMake 3.14). This is an appropriate option for both upstream projects and downstream distributions.
- Users can set
- Qt projects can use rcc to embed
resources such as translations and images. Since Qt 5.8, rcc includes
the file modification time of source files in the build output.
This is especially problematic for translation files that are
generated at build time. Possible workarounds:
- (Since Qt 5.9) If a project does not rely on an accurate
QFileInfo::lastModified,
pass
--format-version 1
torcc
. IfAUTORCC
is enabled, this can be done by settingCMAKE_AUTORCC_OPTIONS
to--format-version;1
. Upstream projects are encouraged to do this after checking that Qt 5.9 or newer is in use. - (Since Qt 5.11) Set the
QT_RCC_SOURCE_DATE_OVERRIDE
environment variable which behaves similar toSOURCE_DATE_EPOCH
. - (Since Qt 5.13) Set the
SOURCE_DATE_EPOCH
environment variable. - Ensure that generated source files are touched with a fixed timestamp before rcc is called. See also https://bugs.debian.org/894476.
- (Since Qt 5.9) If a project does not rely on an accurate
QFileInfo::lastModified,
pass
- Qt projects that use
Q_OBJECT
macros require moc to generate additional C++ files. CMake will automatically do this whenAUTOMOC
is enabled, but then the relative path from the build directory to the source directory will become part of the build environment. For example, if the build directory is/tmp/build
and the source file is at/tmp/foo/widget.h
, then the generated file will include../[...]/../foo/widget.h
. Possible workarounds:- Use the
-p
option to override the include prefix. This requires the prefix plus the header filename to be available from the include path. See also https://gitlab.kitware.com/cmake/cmake/issues/18815. - Ensure that the build directory and source directory remains fixed
across builds. For example, if users always create a
build
directory in the source tree, then reproducibility won’t be affected.
- Use the
Disclaimer
Not all problems have solutions currently. Some tools that might be used in a build process might require fixes to become non-deterministic. The Debian effort keeps a list of all issues found while investigating reproducibility problems in its 22,000+ source packages. While some require changes in the package source itself, some can be fixed by improving or fixing the tools used to perform the builds.
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