# German translations for PACKAGE package # Copyright (C) 2020 Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2020. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2024-07-11 20:48+0000\n" "PO-Revision-Date: 2020-04-24 09:05+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. type: Yaml Front Matter Hash Value: title #: _docs/archives.md #, no-wrap msgid "Archive metadata" msgstr "" #. type: Plain text #: _docs/archives.md msgid "Most archive formats record metadata that will capture details about the build environment if no care is taken. File last modification time is obvious, but file ordering, users, groups, numeric ids, and permissions can also be of concern. Tar will be used as the main example but these tips apply to other archive formats as well." msgstr "" #. type: Title - #: _docs/archives.md #, no-wrap msgid "File modification times" msgstr "Datei-Änderungszeiten" #. type: Plain text #: _docs/archives.md msgid "Most archive formats will, by default, record file last modification times, while some will also record file creation times." msgstr "" #. type: Plain text #: _docs/archives.md msgid "Tar has a way to specify the modification time that is used for all archive members:" msgstr "" #. type: Plain text #: _docs/archives.md msgid "{% highlight sh %} $ tar --mtime='2015-10-21 00:00Z' -cf product.tar build {% endhighlight %}" msgstr "" #. type: Plain text #: _docs/archives.md msgid "(Notice how `Z` is used to specify that time is in the UTC [timezone]({{ \"/docs/timezones/\" | relative_url }}).)" msgstr "" #. type: Plain text #: _docs/archives.md msgid "For other archive formats, it is always possible to use `touch` to reset the modification times to a [predefined value]({{ \"/docs/timestamps/\" | relative_url }}) before creating the archive:" msgstr "" #. type: Plain text #: _docs/archives.md #, no-wrap msgid "" "{% highlight sh %}\n" "$ find build -print0 |\n" " xargs -0r touch --no-dereference --date=\"@${SOURCE_DATE_EPOCH}\"\n" "$ zip -r product.zip build\n" "{% endhighlight %}\n" msgstr "" #. type: Plain text #: _docs/archives.md msgid "In some cases, it is preferable to keep the original times for files that have not been created or modified during the build process:" msgstr "" #. type: Plain text #: _docs/archives.md #, no-wrap msgid "" "{% highlight sh %}\n" "$ find build -newermt \"@${SOURCE_DATE_EPOCH}\" -print0 |\n" " xargs -0r touch --no-dereference --date=\"@${SOURCE_DATE_EPOCH}\"\n" "$ zip -r product.zip build\n" "{% endhighlight %}\n" msgstr "" #. type: Plain text #: _docs/archives.md #, no-wrap msgid "" "In `tar` >= 1.29, the `--clamp-mtime` flag can be used to only set the\n" "when the file is more recent than the value specified with `--mtime`:\n" msgstr "" #. type: Plain text #: _docs/archives.md msgid "{% highlight sh %} $ tar --mtime='2015-10-21 00:00Z' --clamp-mtime -cf product.tar build {% endhighlight %}" msgstr "" #. type: Plain text #: _docs/archives.md msgid "This has the benefit of leaving the original file modification time untouched." msgstr "" #. type: Title - #: _docs/archives.md #, no-wrap msgid "File ordering" msgstr "" #. type: Plain text #: _docs/archives.md msgid "When asked to record directories, most archive formats will read their content in the order returned by the filesystem which is [likely to be different on every run]({{ \"/docs/stable-inputs/\" | relative_url }})." msgstr "" #. type: Plain text #: _docs/archives.md msgid "With version 1.28, GNU Tar has gained the `--sort=name` option which will sort filenames in a locale independent manner:" msgstr "" #. type: Plain text #: _docs/archives.md msgid "{% highlight sh %}" msgstr "" #. type: Title # #: _docs/archives.md #, no-wrap msgid "Works with GNU Tar 1.28" msgstr "" #. type: Plain text #: _docs/archives.md msgid "$ tar --sort=name -cf product.tar build {% endhighlight %}" msgstr "" #. type: Plain text #: _docs/archives.md msgid "For older versions or other archive formats, it is possible to use `find` and `sort` to achieve the same effect:" msgstr "" #. type: Plain text #: _docs/archives.md #, no-wrap msgid "" "{% highlight sh %}\n" "$ find build -print0 | LC_ALL=C sort -z |\n" " tar --no-recursion --null -T - -cf product.tar\n" "{% endhighlight %}\n" msgstr "" #. type: Plain text #: _docs/archives.md msgid "Care must be taken to ensure that `sort` is called in the context of the C locale to avoid any surprises related to collation order." msgstr "" #. type: Title - #: _docs/archives.md #, no-wrap msgid "Users, groups and numeric ids" msgstr "" #. type: Plain text #: _docs/archives.md msgid "Depending on the archive format, the user and group owning the file can be recorded. Sometimes it will be using a string, sometimes using the associated numeric ids." msgstr "" #. type: Plain text #: _docs/archives.md msgid "When files belong to predefined system groups, this is not a problem, but builds are often performed with regular users. Recording of the account name or its associated ids might be a source of reproducibility issues." msgstr "" #. type: Plain text #: _docs/archives.md msgid "Tar offers a way to specify the user and group owning the file. Using `0`/`0` and `--numeric-owner` is a safe bet, as it will effectively record 0 as values:" msgstr "" #. type: Plain text #: _docs/archives.md msgid "{% highlight sh %} $ tar --owner=0 --group=0 --numeric-owner -cf product.tar build {% endhighlight %}" msgstr "" #. type: Title - #: _docs/archives.md #, no-wrap msgid "PAX headers" msgstr "" #. type: Plain text #: _docs/archives.md msgid "GNU tar defaults to the pax format and if `POSIXLY_CORRECT` is set, that adds files' ctime, atime and the PID of the tar process as non-deterministic metadata." msgstr "" #. type: Plain text #: _docs/archives.md #, no-wrap msgid "" "To avoid this, either `unset POSIXLY_CORRECT` (only works with [tar>1.32](https://git.savannah.gnu.org/cgit/tar.git/commit/?id=ef0f882382f6)) or add to the tar call\n" "`--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime` or `--format=gnu` (both only available in GNU tar)\n" "or use `--format=ustar` if the limitations in that format are not a problem.\n" msgstr "" #. type: Title - #: _docs/archives.md #, no-wrap msgid "Full example" msgstr "" #. type: Plain text #: _docs/archives.md msgid "The recommended way to create a Tar archive is thus:" msgstr "" #. type: Plain text #: _docs/archives.md #, no-wrap msgid "" "
\n" "{% highlight sh %}\n" msgstr "" #. type: Title # #: _docs/archives.md #, no-wrap msgid "requires GNU Tar 1.28+" msgstr "" #. type: Plain text #: _docs/archives.md #, no-wrap msgid "" "$ tar --sort=name \\\n" " --mtime=\"@${SOURCE_DATE_EPOCH}\" \\\n" " --owner=0 --group=0 --numeric-owner \\\n" " --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime \\\n" " -cf product.tar build\n" "{% endhighlight %}\n" "
\n" msgstr "" #. type: Title - #: _docs/archives.md #, no-wrap msgid "Zip files" msgstr "" #. type: Plain text #: _docs/archives.md msgid "Zip files can additionally store metadata in \"extra file attributes\". We believe these were intended as a cross-platform means of storing, say, Extended Attributes on OS/2 as well as user/group information. Crucially, it can store multiple file timestamps on Unix, including creation, modification *and* access time. (NB. You may not see access time changes under Linux system is your filesystems are mounted with `noatime` or `norelatime`)." msgstr "" #. type: Plain text #: _docs/archives.md msgid "When creating `.zip` files, it is [recommended to use the `--no-extra` / `-X`](https://lists.reproducible-builds.org/pipermail/rb-general/2024-March/003283.html) argument to not save these fields. It is also recommended that [developers unzip archives with `TZ=UTC`](https://lists.reproducible-builds.org/pipermail/rb-general/2023-April/002927.html)." msgstr "" #. type: Title - #: _docs/archives.md #, no-wrap msgid "Post-processing" msgstr "" #. type: Plain text #: _docs/archives.md msgid "If tools do not support options to create reproducible archives, it is always possible to perform post-processing." msgstr "" #. type: Plain text #: _docs/archives.md msgid "[strip-nondeterminism](https://packages.debian.org/sid/strip-nondeterminism) already has support to normalize Zip and Jar archives (with [limitations](https://bugs.debian.org/859103)). Custom scripts like Tor Browser's [re-dzip.sh](https://gitweb.torproject.org/builders/tor-browser-bundle.git/tree/gitian/build-helpers/re-dzip.sh) might also be an option." msgstr "" #. type: Title - #: _docs/archives.md #, no-wrap msgid "Static libraries" msgstr "" #. type: Plain text #: _docs/archives.md msgid "Static libraries (`.a`) on Unix-like systems are *ar* archives. Like other archive formats, they contain metadata, namely timestamps, UIDs, GIDs, and permissions. None are actually required for using them as libraries." msgstr "" #. type: Plain text #: _docs/archives.md msgid "GNU `ar` and other tools from [binutils](https://www.gnu.org/software/binutils/) have a *deterministic mode* which will use zero for UIDs, GIDs, timestamps, and use consistent file modes for all files. It can be made the default by passing the `--enable-deterministic-archives` option to `./configure`. It is already enabled by default for some distributions[^distros-with-default] and so far it seems to be pretty safe [except for Makefiles](https://bugs.debian.org/798804) using targets like `archive.a(foo.o)`." msgstr "" #. type: Plain text #: _docs/archives.md msgid "When binutils is not built with deterministic archives by default, build systems have to be changed to pass the right options to `ar` and friends. `ARFLAGS` can be set to `Dcvr` with many build systems to turn on the deterministic mode. Care must also be taken to pass `-D` if `ranlib` is used to create the function index." msgstr "" #. type: Plain text #: _docs/archives.md msgid "Another option is post-processing with [strip-nondeterminism](https://packages.debian.org/sid/strip-nondeterminism) or `objcopy`:" msgstr "" #. type: Plain text #: _docs/archives.md #, no-wrap msgid " objcopy --enable-deterministic-archives libfoo.a\n" msgstr "" #. type: Plain text #: _docs/archives.md msgid "The above does not fix [file ordering]({{ \"/docs/stable-inputs/\" | relative_url }})." msgstr "" #. type: Plain text #: _docs/archives.md msgid "[^distros-with-default]: Debian since [version 2.25-6](https://tracker.debian.org/news/675691)/stretch, Ubuntu since version 2.25-8ubuntu1/artful 17.10. It is the default for Fedora 22 and Fedora 23, but it seems this will be [reverted in Fedora 24](https://bugzilla.redhat.com/show_bug.cgi?id=1195883)." msgstr "" #. type: Title - #: _docs/archives.md #, no-wrap msgid "Initramfs images" msgstr "" #. type: Plain text #: _docs/archives.md #, no-wrap msgid "" "*cpio* archives are commonly used for initramfs images. The *cpio* header\n" "format (see `man 5 cpio`) can contain device and inode numbers, which whilst\n" "deterministic, can vary from system to system.\n" msgstr "" #. type: Plain text #: _docs/archives.md msgid "One way to filter these is by piping through bsdtar." msgstr "" #. type: Plain text #: _docs/archives.md msgid "Example of non-deterministic code:" msgstr "" #. type: Fenced code block #: _docs/archives.md #, no-wrap msgid "" "echo ucode.bin |\n" " bsdcpio -o -H newc -R 0:0 > ucode.img\n" msgstr "" #. type: Plain text #: _docs/archives.md msgid "Example of deterministic code:" msgstr "" #. type: Fenced code block #: _docs/archives.md #, no-wrap msgid "" "echo ucode.bin |\n" " bsdtar --uid 0 --gid 0 -cnf - -T - |\n" " bsdtar --null -cf - --format=newc @- > ucode.img\n" msgstr "" #. type: Plain text #: _docs/archives.md msgid "Note that other issues such as timestamps may still require rectification prior to archival." msgstr "" #. type: Title ## #: _docs/archives.md #, no-wrap msgid "GNU Libtool" msgstr "" #. type: Plain text #: _docs/archives.md msgid "[GNU Libtool](https://www.gnu.org/software/libtool/) prior to `74c8993c` (first included in version 2.2.7b) did not sort the find output. It appears that many packages are bootstrapped with a version prior to this." msgstr "" #. type: Plain text #: _docs/archives.md msgid "Confusingly, although [GNU GCC](https://gcc.gnu.org/)'s `ltmain.sh` claims to have been generated by libtool 2.2.7a, GNU GCC actually maintains their own version of `libtool.m4` and `ltmain.sh`, which fixed this issue independently in `d41cd173e23`. This aforementioned change was first included in version 9.1.0, meaning that the reproducibility issue remains in GCC versions below that." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/build_path.md #, no-wrap msgid "Build path" msgstr "" #. type: Plain text #: _docs/build_path.md msgid "Some tools will record the path of the source files in their output." msgstr "" #. type: Plain text #: _docs/build_path.md msgid "Most compilers write the path of the source in the debug information in order to locate the associated source files." msgstr "" #. type: Plain text #: _docs/build_path.md msgid "Some tools have flags (like gzip's `-n`) that prevent them from writing the path in their output. Proposing patches to add a similar feature in other tools might be sufficiently easy." msgstr "" #. type: Plain text #: _docs/build_path.md msgid "In most cases however, post-processing is required to either remove the build path or to normalize it to a predefined value." msgstr "" #. type: Plain text #: _docs/build_path.md msgid "For the specific case of [debug symbols](https://en.wikipedia.org/wiki/DWARF), there is currently no good post-processing tool to change them to a pre-determined value[^debugedit]. A work-around is to [define the build path as part of the build environment]({{ \"/docs/perimeter/\" | relative_url }}), however `reprotest` changes it so this makes it harder to assess reproducibility. Certain compiler flags can work around the issue:" msgstr "" #. type: Bullet: ' * ' #: _docs/build_path.md msgid "[`-fdebug-prefix-map=OLD=NEW`](https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#index-fdebug-prefix-map) can strip directory prefixes from debug info. (available in all GCC versions, Clang 3.8)" msgstr "" #. type: Bullet: ' * ' #: _docs/build_path.md msgid "[`-fmacro-prefix-map=OLD=NEW`](https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html#index-fmacro-prefix-map) is similar to `-fdebug-prefix-map`, but addresses unreproducibility due to the use of `__FILE__` macros in `assert` calls for example. (available since GCC 8 and [Clang 10](https://bugs.llvm.org/show_bug.cgi?id=38135))" msgstr "" #. type: Bullet: ' * ' #: _docs/build_path.md msgid "`-ffile-prefix-map=OLD=NEW` is an alias for both `-fdebug-prefix-map` and `-fmacro-prefix-map`. (available since GCC 8 and [Clang 10](https://bugs.llvm.org/show_bug.cgi?id=38135))" msgstr "" #. type: Plain text #: _docs/build_path.md #, no-wrap msgid "" "With dpkg >= 1.19.1, first shipped with Debian Buster, packages can enable the\n" "`-ffile-prefix-map=OLD=NEW` flag by adding the `fixfilepath` [build\n" "flag](https://manpages.debian.org/dpkg-buildflags.1) to their `debian/rules`\n" "file. For example:\n" msgstr "" #. type: Fenced code block #: _docs/build_path.md #, no-wrap msgid "export DEB_BUILD_MAINT_OPTIONS = hardening=+all reproducible=+fixfilepath\n" msgstr "" #. type: Plain text #: _docs/build_path.md msgid "Note that some packages save the compile options in the build output." msgstr "" #. type: Plain text #: _docs/build_path.md msgid "[^debugedit]: [debugedit](https://fedoraproject.org/wiki/Releases/FeatureBuildId) can replace the path used at build time by a predefined one but it does that by rewriting bytes in place. As this does not reorder the hash table of strings, the resulting bytes are still depending on the original build path." msgstr "" #. type: Plain text #: _docs/build_path.md msgid "This is also problematic because this will also apply to intermediate source files that other tools generate. As they typically will use [random file names]({{ \"/docs/randomness/\" | relative_url }}), having a fixed build path is not enough in such cases." msgstr "" #. type: Plain text #: _docs/build_path.md msgid "A [build-path-prefix-map](https://reproducible-builds.org/specs/build-path-prefix-map/) specification is in discussion with the GCC developers." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/build_toolchain_from_source.md #, no-wrap msgid "Building from source" msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "Building the tools that make the environment from source is one way to allow user to reproduce it. Using the source code directly makes it easier to rely on new features, and easily works on a variety of platforms. It might not scale well for a long list of dependencies, and asking users to rebuild GCC for every piece of software they use might make them slightly unhappy." msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "What follows are suggestions on how to handle building the compilation tools from source." msgstr "" #. type: Title - #: _docs/build_toolchain_from_source.md #, no-wrap msgid "Building using external resources" msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "The source for the different components can be retrieved from online repositories. Using release tarballs might be preferable as they are easier to cache, [mirror, checksum and verify]({{ \"/docs/volatile-inputs/\" | relative_url }}). When retrieving the source from a version control system repository, it's best to have a precise reference to the code version. With Git, using a tag with a verified signature or a commit hash will work best." msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "The compilation itself can be driven by shell scripts or an extra target in the project `Makefile`." msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "coreboot is a good example. The build documentation mandates to first run `make crossgcc` before building coreboot itself." msgstr "" #. type: Title - #: _docs/build_toolchain_from_source.md #, no-wrap msgid "Check-in everything" msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "Another approach is to check the source of the entire toolchain in the project's version control system." msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "This is how several integrated operating systems like \\*BSD are developed. “Building the world” will start by building the toolchain in the version control system before building the rest of the system." msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "Also Google's internal projects operate in this way. They have released [Bazel](https://bazel.io/) which is based on their internal compilation tool. Bazel is designed to drive large scale builds with speed and reproducibility in mind." msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "Outside of fully integrated operating systems or corporate environments, it might be hard to push the idea of adding ten or more times the actual code base in the toolchain…" msgstr "" #. type: Title - #: _docs/build_toolchain_from_source.md #, no-wrap msgid "Ship the toolchain as a build product" msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "As it might be hard to ask every user to spend time rebuilding a whole toolchain, OpenWrt gives a good example of a middle ground. An “SDK” that can be downloaded alongside the system images which contains everything that is needed to build—or rebuild—extra packages." msgstr "" #. type: Plain text #: _docs/build_toolchain_from_source.md msgid "In that case the SDK becomes another build product, and it has to be possible to build it reproducibly." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/buy_in.md #, no-wrap msgid "Buy-in" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Working on *reproducible builds* might look like a lot of effort with little gain at first. While [this applies to many types of work related to security](https://www.schneier.com/blog/archives/2008/09/security_roi_1.html), there are already some good arguments and testimonies on why *reproducible builds* matter." msgstr "" #. type: Title - #: _docs/buy_in.md #, no-wrap msgid "Resisting attacks" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "In March 2015, The Intercept [published](https://theintercept.com/2015/03/10/ispy-cia-campaign-steal-apples-secrets/) from the Snowden leaks the abstract of a talk at an [internal CIA conference in 2012](https://theintercept.com/document/2015/03/10/tcb-jamboree-2012-invitation/) about [Strawhorse: Attacking the MacOS and iOS Software Development Kit](https://theintercept.com/document/2015/03/10/strawhorse-attacking-macos-ios-software-development-kit/). The abstract clearly explains how unnamed researchers have been creating a modified version of XCode that would — without any knowledge of the developer — watermark or insert spyware in the compiled applications." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "A few months later, a malware dubbed “XcodeGhost” has been found targeting developers to make them unknowingly distribute malware embedded in iOS applications. Palo Alto Networks [describes](http://researchcenter.paloaltonetworks.com/2015/09/novel-malware-xcodeghost-modifies-xcode-infects-apple-ios-apps-and-hits-app-store/) it as:" msgstr "" #. type: Plain text #: _docs/buy_in.md #, no-wrap msgid "" "> XcodeGhost is the first compiler malware in OS X. Its malicious code is\n" "> located in a Mach-O object file that was repackaged into some versions\n" "> of Xcode installers. These malicious installers were then uploaded to\n" "> Baidu’s cloud file sharing service for use by Chinese iOS/OS X\n" "> developers\n" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "The purpose of *reproducible builds* is exactly to resist such attacks. Recompiling these applications with a clean compiler would have made the problem easily visible, especially given the size of the added payload." msgstr "" #. type: Plain text #: _docs/buy_in.md #, no-wrap msgid "" "As Mike Perry and Seth Schoen explained in December 2014 during [a talk at\n" "31C3](https://media.ccc.de/events/31c3_-_6240_-_en_-_saal_g_-_201412271400_-_reproducible_builds_-_mike_perry_-_seth_schoen_-_hans_steiner),\n" "problematic changes might be more subtle, and a single bit\n" "might be the only thing required to create a remotely exploitable\n" "security hole. Seth Schoen also demonstrated a kernel-level\n" "malware that would compromise the source code while it is read by\n" "the compiler, without leaving any traces on disk. While to the best of\n" "our knowledge such attacks have not been observed in the wild,\n" "reproducible builds are the only way to detect them\n" "early.\n" msgstr "" #. type: Title - #: _docs/buy_in.md #, no-wrap msgid "Quality assurance" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Regular tests are required to make sure that the software can be built reproducibly in various environments. Debian and other free software distributions require that their users must be able to build the software they distribute. Such regular tests help in avoiding *fail to build from source* bugs and can uncover rare build problems such as timing problems, race conditions, or builds affected by locale." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Build environments may evolve after a project is no longer receiving major developments. While working on Debian, several high impact but hard to detect bugs were identified by testing builds in varying environments. To give some examples: [a library had a different application binary interface for every build](https://bugs.debian.org/773916), [garbled strings due to encoding mismatch](https://bugs.debian.org/801855), [missing translations](https://bugs.debian.org/778486), or [changing dependencies](https://bugs.debian.org/778707)." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "The constraint of having to reflect about the build environment also helps developers to think about the relationship with external software or data providers. Relying on external sources with no backup plans might cause serious troubles in the long term." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Reproducible builds also enable the recreation of matching [debug symbols](https://en.wikipedia.org/wiki/Debugging_data_format) for a distributed build which can help understanding issues in software used in production." msgstr "" #. type: Title - #: _docs/buy_in.md #, no-wrap msgid "Smaller Binary Differences" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Having reproducible builds means that only changes in source code or build environment (such as the compiler version) will lead to differences in the generated binaries. This minimizes the changes in artifacts which reduces storage requirements and network traffic for delta updates." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "With similar artifacts, testing can focus on parts that changed while still preserving confidence about unchanged code. This can speed up quality assurance and development speed." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Changes to the build system can be tested easily with reproducible builds: If the output artifacts are identical, the changes will not affect runtime behavior." msgstr "" #. type: Title - #: _docs/buy_in.md #, no-wrap msgid "Increased Development Speed" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Dependent packages do not need to be rebuilt and dependent tasks do not need to be rerun if a rebuild of a package does not yield different results. This can significantly reduce build times and lead to faster development speeds and lower cost." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Build speeds can also be improved by showing that cross-compilation produces the same result as native compilation and then doing the majority of builds with cross-compilation on faster machines." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "“But how can I trust my compiler?”" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "A common question related to *reproducible builds* is how is it possible to know if the build environment is not compromised if everyone is using the same binaries? Or how can I trust that the compiler I just built was not compromised by a backdoor in the compiler I used to build it?" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "The latter is known in the academic literature since the [Reflections on trusting trust](https://dx.doi.org/10.1145%2F358198.358210) paper from Ken Thompson published in 1984. It's the paper mentioned in the description of the talk about “Strawhorse” mentioned earlier." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "The technique known as [Diverse Double-Compilation](http://www.dwheeler.com/trusting-trust/), formally defined and researched by David A. Wheeler, can answer this question. To sum up quickly how it works: given two compilers, one trusted and one under test, the compiler under test is built twice, once with each compiler. Using the compilers created from this build, the compiler under test is built again. If the output is the same, then we have a proof that no backdoors have been inserted during the compilation. For this scheme to work, the output of the final compilations need to be the same. And that's exactly where *reproducible builds* are useful." msgstr "" #. type: Title - #: _docs/buy_in.md #, no-wrap msgid "Dependency Tree Awareness and Software Bill of Materials (SBOM)" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Reproducible builds significantly enhance the transparency and integrity of software development by making sure developers have complete awareness of the dependency tree, ensuring that all dependencies are exactly as intended, without any undisclosed changes or additions. This level of control is crucial for security, as it helps in identifying and mitigating vulnerabilities that often reside in overlooked components." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Therefore, this facilitates the creation of Software Bill of Materials (SBOM), a comprehensive inventory of all components, libraries, and modules included in a piece of software. This is increasingly important in today's software development landscape, where open-source components and third-party libraries are ubiquitous. SBOMs are indispensable for regulatory compliance, vulnerability management, and risk assessment, making reproducible builds not just beneficial but essential for maintaining software integrity, reliability, and security in the face of evolving cyber threats and regulatory requirements." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "By enhancing the ability to generate accurate SBOMs and ensuring a deep understanding of software dependencies, reproducible builds support security and compliance objectives effectively, aligning with broader industry trends towards more secure and accountable software development practices." msgstr "" #. type: Title - #: _docs/buy_in.md #, no-wrap msgid "Ephemeral Development Environments" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "Ephemeral development environments, empowered by reproducible builds, represent a significant shift in software development. This approach facilitates the on-demand creation of identical development environments and dependencies, moving away from traditional static setups to dynamic, task-specific configurations that are disposed of after use. This shift not only minimizes setup times and configuration conflicts but also enhances security by reducing exposure to vulnerable components." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "The cornerstone of this transformative approach is the consistent application of reproducible builds, which ensures that environments are precisely provisioned whenever needed. This consistency is critical for integrating with modern practices such as containerization and Infrastructure as Code (IaC), streamlining the onboarding process for new team members by automating setup and reducing the likelihood of errors." msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "These practices align with the principles of DevSecOps, supporting a more agile development cycle through automated testing and CI/CD pipelines, while also improving security by isolating tasks and providing dependencies temporarily. The adoption of ephemeral environments and reproducible builds signifies a move towards more flexible, efficient, and secure software development, facilitating rapid onboarding and promoting continuous innovation within teams." msgstr "" #. type: Title - #: _docs/buy_in.md #, no-wrap msgid "Other resources" msgstr "" #. type: Plain text #: _docs/buy_in.md msgid "The following articles might contain even more arguments:" msgstr "" #. type: Bullet: ' * ' #: _docs/buy_in.md msgid "[Cyberwar and Global Compromise](https://blog.torproject.org/blog/deterministic-builds-part-one-cyberwar-and-global-compromise) by Mike Perry from the Tor Project, 2013-08-20" msgstr "" #. type: Bullet: ' * ' #: _docs/buy_in.md msgid "[Software Transparency: Part 1](https://zyan.scripts.mit.edu/blog/software-transparency/) by yan, 2014-07-11." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/checksums.md #, no-wrap msgid "Cryptographic checksums" msgstr "" #. type: Plain text #: _docs/checksums.md msgid "How can users know that the build they just made has successfully reproduced the original build?" msgstr "" #. type: Plain text #: _docs/checksums.md msgid "The easiest way is to make sure that the build outputs are always byte-for-byte identical. Byte-for-byte comparison is a trivial operation and can be performed in many different environments." msgstr "" #. type: Plain text #: _docs/checksums.md msgid "The other benefit of having identical bytes is that it makes it possible to use [cryptographic checksums](https://en.wikipedia.org/wiki/Cryptographic_hash_function). Such checksums are really tiny compared to the full build products. They are easily exchanged even in very low bandwidth situation." msgstr "" #. type: Plain text #: _docs/checksums.md msgid "For example, it makes it possible to build a software release both on a well-connected (but hard to trust) server and on a laptop behind a bad mobile connection. The digital signature can be made locally on the laptop. As the build products will be identical, the signature will be valid for the files produced on the well-connected server." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/commandments.md #, no-wrap msgid "commandments of reproducible builds" msgstr "" #. type: Plain text #: _docs/commandments.md msgid "Commandments by the church of reproducible builds:" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall not record the name of thy maker nor the place of thy making (username, hostname)" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall not record the date nor time of thy making, unless you respect the holy [SDE spec](https://reproducible-builds.org/docs/source-date-epoch/) ([date+time](https://github.com/bmwiedemann/theunreproduciblepackage/tree/master/timestamp))" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall not use memory without initialization or use memory addresses to decide outcomes ([ASLR](https://github.com/bmwiedemann/theunreproduciblepackage/tree/master/aslr))" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall do all your work in order - not use [filesystem-readdir-order](https://github.com/bmwiedemann/theunreproduciblepackage/tree/master/filesystem) nor random order of hash elements" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall not *(gamble and)* record random numbers ([UUID, private/public key](https://github.com/bmwiedemann/theunreproduciblepackage/tree/master/random), [hash-seed](https://github.com/bmwiedemann/theunreproduciblepackage/tree/master/hash), ASLR)" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall only do one thing at a time or ensure races do no harm ([parallelism](https://github.com/bmwiedemann/theunreproduciblepackage/tree/master/race))" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall not look at build machine processor capabilities ([CPU](https://github.com/bmwiedemann/theunreproduciblepackage/tree/master/compile-time-check/cpu-detection))" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall not look at build machine [benchmarks for optimizations](https://github.com/bmwiedemann/theunreproduciblepackage/tree/master/compile-time-check/benchmark)" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall be careful with [profile-guided-optimization](https://github.com/bmwiedemann/theunreproduciblepackage/tree/master/pgo) for it can amplify any sin (non-determinism)" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall keep your workspace [environment](https://github.com/bmwiedemann/theunreproduciblepackage/tree/master/environment) clean of timezones, locales and umasks or ensure they do no harm" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "Thou shall allow for offline builds (aka \"vendoring\" as servers can be down, contents can change)" msgstr "" #. type: Bullet: ' 1. ' #: _docs/commandments.md msgid "If Thou publishst binaries, Thou shall take note of your build inputs" msgstr "" #. type: Plain text #: _docs/commandments.md msgid "License: [CC-BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)" msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/definition.md #, no-wrap msgid "Definitions" msgstr "" #. type: Title ## #: _docs/definition.md #, no-wrap msgid "When is a build reproducible?" msgstr "" #. type: Plain text #: _docs/definition.md msgid "A build is **reproducible** if given the same source code, build environment and build instructions, any party can recreate bit-by-bit identical copies of all specified artifacts." msgstr "" #. type: Plain text #: _docs/definition.md msgid "The relevant attributes of the build environment, the build instructions and the source code as well as the expected reproducible artifacts are defined by the authors or distributors. The artifacts of a build are the parts of the build results that are the desired primary output." msgstr "" #. type: Title ## #: _docs/definition.md #, no-wrap msgid "Explanations" msgstr "" #. type: Plain text #: _docs/definition.md #, no-wrap msgid "" "**Source code** is usually a checkout from version control at a specific\n" "revision or a source code archive.\n" msgstr "" #. type: Plain text #: _docs/definition.md #, no-wrap msgid "" "**Relevant attributes of the build environment** would usually include\n" "dependencies and their versions, build configuration flags and environment\n" "variables as far as they are used by the build system (eg. the locale). It is\n" "preferable to reduce this set of attributes.\n" msgstr "" #. type: Plain text #: _docs/definition.md #, no-wrap msgid "" "**Artifacts** would include executables, distribution packages or filesystem\n" "images. They would not usually include build logs or similar ancillary outputs.\n" msgstr "" #. type: Plain text #: _docs/definition.md msgid "The reproducibility of artifacts is **verified** by bit-by-bit comparison. This is usually performed using cryptographically secure hash functions." msgstr "" #. type: Plain text #: _docs/definition.md #, no-wrap msgid "" "**Authors or distributors** means parties that claim reproducibility of a set\n" "of artifacts. These may be upstream authors, distribution maintainers or any\n" "other distributor.\n" msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/definition_strategies.md #, no-wrap msgid "Definition strategies" msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "There are multiple ways to define the build environment in a way that it can be distributed. The following methods are not exclusive and multiple aspects can be used for a single project." msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "Defining the build environment as part of the development process has a very desirable aspect: changes in the build environment can be vetted like any other changes. Updating to a new compiler version can be subject to reviews, automatic testing, and—in case things break—rollback." msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "{% comment %} XXX: maybe we want to add examples? Orig example in first paragraph One can specify a reference Linux distribution and build a specific compiler version from source. {% endcomment %}" msgstr "" #. type: Title - #: _docs/definition_strategies.md #, no-wrap msgid "Build from source" msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "One simple way to have users reproduce the tools that are used to perform the build is making them start building the right version of these tools from source." msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "Using `make` or any other compilation driver, the required tools will be downloaded, built, and locally installed before compiling the software." msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "Like any other [inputs from the network]({{ \"/docs/volatile-inputs/\" | relative_url }}), the content of the archive where the required source for the tools is stored should be backed up and verified using cryptographic checksums." msgstr "" #. type: Title - #: _docs/definition_strategies.md #, no-wrap msgid "Reference distribution" msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "Using a specific version of a free software distribution is another viable option for a build environment." msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "Ideally, it should offer stable releases (like Debian, CentOS, or FreeBSD) to avoid having constant updates to the documentation or building scripts." msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "Recording the exact versions of the installed packages might be helpful to diagnose issues. Some distributions also keep a complete history of source packages or binary packages available for later reinstallation." msgstr "" #. type: Title - #: _docs/definition_strategies.md #, no-wrap msgid "Virtual machines / containers" msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "Some aspects of the build environment can be quite simplified by using virtual machines or containers. With a virtual machine you can easily perform the build in a more controlled environment. The build user, system hostname, network configuration, or other aspects can be enforced easily on all systems." msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "The downside is that it can introduce a lot of software that has to be trusted somehow. For example, it's currently not possible to install Debian in a reproducible manner[^reproducible-install]. This makes it harder to compare different installations." msgstr "" #. type: Plain text #: _docs/definition_strategies.md msgid "[^reproducible-install]: Some [preliminary work](https://wiki.debian.org/ReproducibleInstalls) has been done, mainly to identify the issues. Having byte-for-byte identical installations is a requirement to make *live* distributions build in a reproducible manner, so there is interest by multiple parties in fixing the problem." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/deterministic_build_systems.md #, no-wrap msgid "Deterministic build systems" msgstr "" #. type: Plain text #: _docs/deterministic_build_systems.md msgid "A software cannot easily be built reproducibly if the source varies depending on factors that are hard or impossible to control like the ordering of files on a filesystem or the current time." msgstr "" #. type: Title - #: _docs/deterministic_build_systems.md #, no-wrap msgid "Drawing the line" msgstr "" #. type: Plain text #: _docs/deterministic_build_systems.md msgid "Which aspect of the build system needs to be made deterministic is deeply linked to what is defined as part of the [build environment]({{ \"/docs/perimeter/\" | relative_url }})." msgstr "" #. type: Plain text #: _docs/deterministic_build_systems.md msgid "For example, we assume that different versions of a compiler will produce different output and so usage of a specific compiler version is mandated as part of the build environment. The same assumption does not necessarily hold for more simple tools like `grep` or `sed` where the requirement for the environment can be as loose as “any recent Unix-like system”." msgstr "" #. type: Plain text #: _docs/deterministic_build_systems.md msgid "But it's hardly a good idea to mandate that the system pseudo-random number generator be initialized with a given value before performing a build, so better not having randomness affect a build output." msgstr "" #. type: Plain text #: _docs/deterministic_build_systems.md msgid "Another concrete example on where to draw the line: there is no need to care about making the build system give constant output when run in different build paths when the build path is considered part of the build environment, and thus requiring rebuilds to be performed in the same directory as the original build." msgstr "" #. type: Title - #: _docs/deterministic_build_systems.md #, no-wrap msgid "In a nutshell" msgstr "" #. type: Plain text #: _docs/deterministic_build_systems.md msgid "The basics on how to make a build system deterministic can be summarized as:" msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "Ensure stable inputs." msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "Ensure stable outputs." msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "Capture as little as possible from the environment." msgstr "" #. type: Plain text #: _docs/deterministic_build_systems.md msgid "What follows are some advices on common issues that can affect source code or build systems that make multiple builds from the exact same source different." msgstr "" #. type: Title - #: _docs/deterministic_build_systems.md #, no-wrap msgid "CMake notes" msgstr "" #. type: Plain text #: _docs/deterministic_build_systems.md msgid "The default configuration of CMake makes the build directory part of the build environment. Here are some known issues and recommendations:" msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "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:" msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "Users can set [`CMAKE_SKIP_RPATH=ON`](https://cmake.org/cmake/help/latest/variable/CMAKE_SKIP_RPATH.html) to disable the use of RPATH. Disadvantage: programs from the build directory cannot be run without setting `LD_LIBRARY_PATH`." msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "Projects can set [`CMAKE_BUILD_WITH_INSTALL_RPATH=ON`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_WITH_INSTALL_RPATH.html) to ensure a deterministic RPATH. Disadvantage: programs from the build directory cannot be run without setting `LD_LIBRARY_PATH`." msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "Set [`CMAKE_BUILD_RPATH_USE_ORIGIN=ON`](https://cmake.org/cmake/help/latest/prop_tgt/BUILD_RPATH_USE_ORIGIN.html) 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." msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "Qt projects can use [rcc](https://doc.qt.io/qt-5/rcc.html) 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:" msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "(Since Qt 5.9) If a project does not rely on an accurate [QFileInfo::lastModified](https://doc.qt.io/qt-5/qfileinfo.html#lastModified), pass `--format-version 1` to `rcc`. If [`AUTORCC`](https://cmake.org/cmake/help/latest/prop_tgt/AUTORCC.html) is enabled, this can be done by setting [`CMAKE_AUTORCC_OPTIONS`](https://cmake.org/cmake/help/latest/variable/CMAKE_AUTORCC_OPTIONS.html) to `--format-version;1`. Upstream projects are encouraged to do this after checking that Qt 5.9 or newer is in use." msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "(Since Qt 5.11) Set the `QT_RCC_SOURCE_DATE_OVERRIDE` environment variable which behaves similar to [`SOURCE_DATE_EPOCH`](https://reproducible-builds.org/specs/source-date-epoch/)." msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "(Since Qt 5.13) Set the `SOURCE_DATE_EPOCH` environment variable." msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "Ensure that generated source files are touched with a fixed timestamp before rcc is called. See also ." msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "Qt projects that use `Q_OBJECT` macros require [moc](https://doc.qt.io/qt-5/moc.html) to generate additional C++ files. CMake will automatically do this when [`AUTOMOC`](https://cmake.org/cmake/help/latest/prop_tgt/AUTOMOC.html) 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:" msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "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 ." msgstr "" #. type: Bullet: ' * ' #: _docs/deterministic_build_systems.md msgid "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." msgstr "" #. type: Title - #: _docs/deterministic_build_systems.md #, no-wrap msgid "Disclaimer" msgstr "" #. type: Plain text #: _docs/deterministic_build_systems.md msgid "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](https://reproducible.debian.net/index_issues.html) 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." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/embedded_signatures.md #, no-wrap msgid "Embedded signatures" msgstr "" #. type: Plain text #: _docs/embedded_signatures.md msgid "Software that is distributed using embedded cryptographic signatures can pose a challenge to allow users to reproduce identical results. By definition, they will not be able to generate an identical signature. This can either be solved by making the signature part of the build process input or by offering tools to transform the distributed binaries to pristine build results." msgstr "" #. type: Title - #: _docs/embedded_signatures.md #, no-wrap msgid "Pasting signatures" msgstr "" #. type: Plain text #: _docs/embedded_signatures.md msgid "One way to handle embedded cryptographic signatures is to make the signature an (optional) input of the build process. When a signature is available, it just gets copied at the right location." msgstr "" #. type: Plain text #: _docs/embedded_signatures.md msgid "This enables the following workflow:" msgstr "" #. type: Bullet: '1. ' #: _docs/embedded_signatures.md msgid "An initial build is made by the developers who have access to the private key." msgstr "" #. type: Bullet: '2. ' #: _docs/embedded_signatures.md msgid "The build result is signed to an external file." msgstr "" #. type: Bullet: '3. ' #: _docs/embedded_signatures.md msgid "The signature is made part of the released source code." msgstr "" #. type: Bullet: '4. ' #: _docs/embedded_signatures.md msgid "The build that is going to be distributed is made from the latter source." msgstr "" #. type: Plain text #: _docs/embedded_signatures.md msgid "The `wireless-regdb` package in Debian is an example on [how this can be be implemented](https://sources.debian.net/src/wireless-regdb/latest/debian/rules/)." msgstr "" #. type: Plain text #: _docs/embedded_signatures.md msgid "Another example is [F-Droid's use of APK signature copying](https://f-droid.org/docs/Reproducible_Builds/) using [`apksigcopier`](https://github.com/obfusk/apksigcopier)." msgstr "" #. type: Title - #: _docs/embedded_signatures.md #, no-wrap msgid "Ignoring signatures" msgstr "" #. type: Plain text #: _docs/embedded_signatures.md msgid "A specific comparison tool can be made available that is able to compare to builds skipping the signatures. Ideally, it should also be able to produce cryptographic checksums to make downloading the original build unneeded to solely compare the results." msgstr "" #. type: Plain text #: _docs/embedded_signatures.md msgid "Such a tool must be **very** easy to audit and understand. Otherwise, it's hard to trust that the script is not ignoring bytes that would make it behave differently." msgstr "" #. type: Title - #: _docs/embedded_signatures.md #, no-wrap msgid "Stripping signatures" msgstr "" #. type: Plain text #: _docs/embedded_signatures.md msgid "Another option is to ship a tool that can strip the signatures from the official releases. The result can then be compared byte-for-byte with the results from the user." msgstr "" #. type: Plain text #: _docs/embedded_signatures.md msgid "This method has the downside that it requires a user to download the official releases to do the comparison. It's also harder to attest that the data that is being removed will not make the software behave differently." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/environment_variations.md #, no-wrap msgid "Variations in the build environment" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "We identify 16 variations in the environment variables that might lead to unreproducible builds. Each environment variable serves as a valuable resource for understanding and addressing the challenges associated with achieving reproducible builds." msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Archive Metadata" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "When working with compressed file formats like zip and tar, it is important to consider the presence of Archive Metadata. This metadata includes information such as file owners, permissions, and timestamps." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "Extracting compressed files within a build environment introduces the risk of inconsistencies in file ownership and permissions compared to the original source. This variation in file metadata can result in files being assigned different owners and permissions during the extraction process." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "Additionally, when these compressed files are uncompressed, the resulting files inherit timestamps that may differ from the originally generated file timestamps. These inconsistencies further contribute to the unreproducibility of packages." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "In certain scenarios, compressed files store modified timestamps (mtimes) that can undergo changes during the build process. When multiple distinct builds are executed, the inconsistent timestamps from compressed files are incorporated into the resulting executables, leading to unreproducible builds. For further details on the archive metadata environment variation, please refer to the provided [documentation]({{ \"/docs/archives/\" | relative_url }})." msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Architecture Information" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "Architecture information refers to crucial details concerning the Linux kernel version and hardware architecture name, which are obtained through the use of the `uname` utility. When builds are conducted on different build systems, invoking the `uname` utility may yield diverse hardware architecture and kernel versions, which are then compiled into the resulting artifacts. This variation in architecture information leads to unreproducible builds, as the artifacts produced on different build systems will differ due to the discrepancies in the kernel version and hardware architecture used during the build process." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For instance, during the build process of the `systemd` package, a call is made to the `uname` utility for debugging purposes. This call retrieves the hardware architecture of the build system. In one scenario, the build was performed on a system with the `i686` architecture, while in another, it was executed on a system with the `x86_64` architecture. Consequently, this difference in architectural information is reflected in the resulting artifacts, causing the builds to become unreproducible due to the varying hardware architectures used during the build process as seen [here](https://tests.reproducible-builds.org/debian/issues/unstable/captures_build_arch_issue.html)" msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Build ID" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "The Build ID is a special hash code generated during the build process, derived from specific portions of the software binary content. Its primary function is to generate identical hash codes for identical binaries, enabling unique identification based on their identity rather than their contents. If different builds of the same code artifacts produce distinct Build IDs in their resulting build artifacts, it indicates an unreproducible build process." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "It is important to note that the generation of the Build ID can be influenced by various factors, including noise, as highlighted in a [bug report](https://tests.reproducible-builds.org/debian/index_issues.html). Notably, when builds are executed on different build systems, [inconsistent UUIDs](https://fedoraproject.org/wiki/Releases/FeatureBuildId\\#Unique_build_ID) can result in varying Build IDs, leading to unreproducible builds." msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Build Path" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "The build path is a critical component in achieving reproducible builds as it provides the necessary build configurations and dependencies for the compiler. It is important to understand that discrepancies in the build path can result in unreproducible builds." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For instance, in a [specific scenario](https://tests.reproducible-builds.org/debian/issues/unstable/captures_build_path_issue.html), one build utilized a relative build path while another adopted an absolute path. As a consequence, variations in the recorded build paths within the resulting biuld artifacts led to unreproducible builds." msgstr "" #. type: Plain text #: _docs/environment_variations.md #, no-wrap msgid "**Workaround:** In order to address and mitigate the challenges related to unreproducible builds caused by variations in the build path, a collaborative effort was undertaken with developers involved in the GCC community. This collaborative effort resulted in the introduction of a flag `BUILD_PATH_PREFIX_MAP` that facilitate the usage of relative paths, enabling the reproducibility of distinct builds. For further details on the flag and their implementation, please refer to the provided [documentation]({{ \"/docs/build-path/\" | relative_url }}).\n" msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Build Timestamp" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "The [build timestamp]({{ \"/docs/timestamps/\" | relative_url }}) refers to the information associated with the date and time of a specific build execution. It is important to consider that during the build process, any files that are generated, modified, or accessed may embed compile-time timestamps in the form of logs within the resulting build artifacts. These timestamps can lead to differences in the content of the build artifacts when distinct builds are performed due to changes in build time." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "However, it is essential to recognize that relying solely on timestamps provides limited insight into the software build itself. This is because builds can be executed on an older version of the software while still having a more recent timestamp." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "An example of a timestamp variation would be the [C pre-defined macros](https://tests.reproducible-builds.org/debian/issues/unstable/timestamps_from_cpp_macros_issue.html) such as `_Date_` and `_Time_` are utilized to output the current time. It is important to note that when these macros are invoked by distinct build systems, different timestamps are incorporated into the compiled code, resulting in variations in the generated build artifacts." msgstr "" #. type: Plain text #: _docs/environment_variations.md #, no-wrap msgid "**Workaround:** The SOURCE_DATE_EPOCH environment variable has been introduced as a solution to address the challenges related to build timestamps and facilitate reproducible builds. The value assigned to the SOURCE_DATE_EPOCH variable represents the timestamp of the most recent modification made to the source code for a specific release. This timestamp is usually derived from the source changelog file, ensuring consistent and accurate build time determination across various build systems\n" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For comprehensive details on the usage and implementation of the SOURCE_DATE_EPOCH variable, we refer to the provided [specification]({{ \"/docs/source-date-epoch/\" | relative_url }})." msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "File Encoding" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "File Encoding refers to the specific encoding scheme used for files, playing a critical role in ensuring the reproducibility of builds. When builds are executed on different build systems, employing distinct encoding schemes can result in variations in build artifact patterns, potentially leading to unreproducible packages." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "In [one scenario](https://tests.reproducible-builds.org/debian/issues/unstable/bundle_name_in_java_manifest_mf_issue.html), during the build process of a package, files on different machines were built using different encoding schemes. Specifically, one build utilized a non-UTF encoder, while the other employed a UTF-8 encoder. These differing encoding strategies led to distinct content in the resulting build artifacts, rendering the builds unreproducible." msgstr "" #. type: Plain text #: _docs/environment_variations.md #, no-wrap msgid "**Workaround:** To ensure the reproducibility of builds, it is crucial to proactively manage and harmonize the encoding schemes across various build systems. By standardizing encoding practices, developers can mitigate the risks associated with unreproducible builds, promoting consistent and reliable outcomes in the build process.\n" msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Filesystem Ordering" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "The order in which files are created and displayed within the filesystem can have a significant impact on the reproducibility of artifacts. When distinct builds are executed, variations in the file order can occur, which, in turn, leads to a different ordering of segments inside the generated artifacts." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For instance, in the case of Ruby 2.3, the presence of `mkmf.rb` is notable. This script is responsible for automatically generating Makefiles for multiple Ruby applications. However, a critical issue arises from the fact that the generated Makefiles do not sort the list of object files. Consequently, when distinct builds are performed, the resulting build logs capture the compilation process in an unordered manner. This lack of order in the compilation can directly impact the resulting artifacts, rendering them unreproducible. More information on this issue can be found [here](https://tests.reproducible-builds.org/debian/issues/unstable/ruby_mkmf_makefile_unsorted_objects_issue.html)." msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "File Permission" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "During a software build, new files are created, inheriting predefined file permissions from the containing folder. However, the default file permissions assigned to these new files can vary across different build systems. This discrepancy in default permissions can introduce inconsistencies when attempting to reproduce the build process, ultimately affecting the reliability and trustworthiness of the resulting software." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For instance, during the execution of distinct builds, the usage of the `umask` utility has been observed to introduce unreproducibility. When the umask value varies across different build systems, the default permissions assigned to files during the build process can differ as seen [here](https://tests.reproducible-builds.org/debian/issues/unstable/different_due_to_umask_issue.html). For example, one build system may have a more permissive umask value, resulting in wider permissions for files, while another build system may have a more restrictive umask value. These disparities in file permissions become embedded in the compiled artifacts, making it challenging to reproduce identical builds." msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Locale" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "Locale plays a crucial role in enabling users to utilize language-specific settings, which are subsequently translated into the corresponding binary code. Each locale maps words to distinct binary codes, facilitating language-specific functionality. However, it is essential to note that variations in the locale settings during the execution of distinct builds can lead to unreproducible outcomes." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "When different locales are employed between two build systems during the execution of distinct builds, the resulting build artifact will exhibit varying content. This discrepancy arises due to the mapping of words to different binary codes within each locale. Consequently, the builds become unreproducible, hindering the consistent generation of build artifact." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "In certain cases, unreproducible builds have been observed due to discrepancies in locale settings during the build process. Specifically, when default parameter values for functions are set according to the user's locale rather than the build system's locale, the builds can become unreproducible." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For comprehensive details on the usage of locales, we refer to the provided [documentation]({{ \"/docs/locales\" | relative_url }})." msgstr "" #. type: Plain text #: _docs/environment_variations.md #, no-wrap msgid "**Workaround:** To ensure the reproducibility of builds, one should carefully manage and synchronize the locale settings across different build systems. By standardizing the locale configurations, one can minimize the risks associated with unreproducible builds, promoting consistent and predictable outcomes in the build process.\n" msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Package Dependency" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "In the context of reproducible builds, package dependencies refer to critical software components that must be present for a package to operate efficiently. By preventing code duplication within the source package, they contribute to maintaining a consistent build process. Nevertheless, if packages do not explicitly define the precise versions of their dependencies, it can lead to various complications concerning build dependencies. Challenges related to package dependencies encompass absent dependencies, conflicting dependencies, and the utilization of incompatible or outdated dependencies during the build process. As a result, these issues can cause the builds to become unreproducible. Furthermore, the behavior or execution of a build dependency can also introduce disparities in the build process, adding to the complexity of achieving reproducibility." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For instance, [ftbfs_due_to_virtual_dependencies](https://tests.reproducible-builds.org/debian/issues/unstable/ftbfs_uninvestigated_unsatisfiable_dependencies_issue.html) highlights specific cases where packages encounter build failures due to their inability to locate or satisfy essential virtual dependencies. These failures could arise from inadequately specified virtual dependencies or a scarcity of available packages in the build environment, which are meant to provide the required functionalities or features expected by these virtual dependencies." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/environment_variations.md _docs/randomness.md #, no-wrap msgid "Randomness" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "Randomness introduces an element of unpredictability to data stored in data structures and tasks executed in parallel. During the build process on different build systems, the order in which parallel jobs are executed may vary. As a consequence, the generated logs of these parallel build executions can be captured differently, leading to unreproducible builds in the resulting artifacts." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "One specific manifestation of this randomness can be observed in the context of software packaging in Debian. Here, `control.tar.gz` is a compressed file that contains metadata about the package such as the list of files in the package and their respective checksums (md5sums). This is crucial for verifying the integrity of the files in the package." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "When creating a Debian package, non-determinism may arise due to the varying order of files listed in md5sums between different builds, found in the `control.tar.gz` file. This usually happens when the package does not use `dh_md5sums`, and the `find` command is used to list the files, which does not guarantee a consistent order. More information on this issue can be found [here](https://tests.reproducible-builds.org/debian/issues/unstable/random_order_in_md5sums_issue.html)." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For comprehensive details on the randomness, we refer to the provided [documentation]({{ \"/docs/randomness/\" | relative_url }})." msgstr "" #. type: Plain text #: _docs/environment_variations.md #, no-wrap msgid "**Workaround:** To mitigate the issues caused by randomness in unordered data structures or file listings from commands like `find`, developers are strongly advised to implement a sorting mechanism when retrieving data from these data structures. By applying the sort operation, the data can be arranged in a specific and consistent order, regardless of the inherent randomness.\n" msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Reference to Memory Address" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "In the context of reproducible builds, a reference to a memory address pertains to numerical representations of particular memory locations within build environments. These memory addresses are utilized by data structures in various programming languages like C and Python to access specific locations in memory. The issue arises when, during the execution of separate builds, the same object is allocated different memory addresses, leading to varying content stored in the resulting artifacts. This disparity in memory allocation causes the build process to become unreproducible, as the output artifacts are no longer identical." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For instance, the `ldaptor` package relies on a python module called [weakref](https://docs.python.org/3/library/weakref.html). Within this `weakref` python module, the \"_repr_\" [function](https://docs.python.org/3/library/functions.html#repr) is utilized. This particular function is responsible for generating the memory address of the instance passed to it. However, the instances provided to this function yield different memory addresses, which ultimately become part of the compiled artifacts. As a consequence, this discrepancy in memory addresses leads to unreproducible builds as seen [here](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=827416)." msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Snippet Encoding" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "Snippet Encoding is the process of encoding strings or specific segments of a file using random numbers. These random numbers, functioning as security keys, are utilized to encode data and prevent unauthorized usage. Within the build execution, these randomized digits are incorporated into the resulting artifacts. Since distinct build systems generate different sets of randomized digits, the resulting build artifacts exhibit varying content." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For instance, during the execution of distinct builds, the usage of the `srandom` utility has been observed to introduce unreproducibility. This utility is employed to provide a seed value to the randomization function, ensuring randomness in the generated output. However, it was found that the seed value stored in the resulting build artifact differed for each build, leading to unreproducible outcomes as seen [here](https://tests.reproducible-builds.org/debian/issues/unstable/markdown_random_email_address_html_entities_issue.html)." msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "System DNS Name" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "System DNS Name refers to the hostname of a host computer within a specified network, serving as the identifier for that system. This name, also known as the system's hostname, is crucial in distinguishing the host within the network. However, variations in DNS names can occur across different build systems leading to potential unreproducibility in the resulting artifacts." msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "Uninitialized Memory" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "In the context of reproducible builds, uninitialized memory refers to the unutilized memory assigned to resources like data structures or file systems. For example, data structures in various programming languages may receive larger memory allocations than necessary, and to optimize performance, this extra memory is filled with randomized padding. The issue arises when resources utilizing this uninitialized memory are stored in files, which could be linked into the resulting artifact during the execution of different builds. As a consequence, this variation in the inclusion of uninitialized memory in the files leads to unreproducible builds, as the resulting artifacts differ due to the random padding introduced during the build process." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For instance, during the build process of the `ipadic` package, a `.dat` file is created, which includes uninitialized memory. To address this, randomized padding is applied to fill the uninitialized memory. However, when different build systems execute builds for the `ipadic` package, the resulting artifacts contain the `.dat` files with varying randomized padding. As a consequence, this discrepancy in the content of the `.dat` files causes the `ipadic` package to become unreproducible on Debian and openSUSE platforms as seen [here](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=881231)." msgstr "" #. type: Title - #: _docs/environment_variations.md #, no-wrap msgid "User Information" msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "User information refers to data that discloses a user's identity, including their username, which has the potential to be included in the build logs. If this user information becomes captured in the resulting artifacts, it can lead to divergent build outputs, causing the builds to become unreproducible." msgstr "" #. type: Plain text #: _docs/environment_variations.md msgid "For instance, during the build process of the `gnustep-base` package, the string `generated by $USER` is executed, where `$USER` represents the name of the system's user who is executing the build. The issue arises when builds are performed on different build systems, as the `$USER` variable outputs distinct usernames for each system. As a result, this variation in the captured user information causes the builds to become unreproducible, as the resulting artifacts will contain different usernames due to the diverse build environments as seen [here](https://tests.reproducible-builds.org/debian/issues/unstable/user_in_documentation_generated_by_gsdoc_issue.html)." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/formal_definition.md #, no-wrap msgid "Formal definition" msgstr "" #. type: Plain text #: _docs/formal_definition.md msgid "Most free software distributions are self-contained: all tools required to build their components are part of the distribution. In such cases, it's possible to specify the build environment in a machine readable format that can be later used to reinstall the environment." msgstr "" #. type: Plain text #: _docs/formal_definition.md msgid "It is also useful for the relationship of these parts to be discoverable. This currently only works within each software distributions. Even across distributions that use the same formats (e.g. Debian and Ubuntu) it does not yet work out of the box. But builds often use other build artefacts as source inputs." msgstr "" #. type: Plain text #: _docs/formal_definition.md msgid "E.g. a container image was created by installing Debian packages, those Packages often use tar archives, build from some git source repositiry, and some git repos contain code developers generated with a build step. So to recursively verify a specific artefact reproduces one needs to indentify all the sources, mirror them and run some build jobs, across distributions. For container images it is currently not specified how to look up the source from an artefact or embed a identifier for the source in the artifact. And for many artefact types looking up the source control revision is guess work instead of a specification that can be followed, much less it being verified when a change is submitted to a distribution." msgstr "" #. type: Plain text #: _docs/formal_definition.md msgid "Files that serve this goal are sometimes called a software bill of materials (SBOM). Various formats are in use or were proposed for this:" msgstr "" #. type: Bullet: '* ' #: _docs/formal_definition.md msgid "[Debian Buildinfo specification](https://wiki.debian.org/ReproducibleBuilds/BuildinfoSpecification), ([example Debian Buildinfo file](https://buildinfo.debian.net/d6a4da6e62bf21c9459197a4bf22d45725dc40f3/0ad_0.0.23.1-5_amd64))" msgstr "" #. type: Bullet: '* ' #: _docs/formal_definition.md msgid "[openSUSE OBS Buildinfo documentation with example](https://api.opensuse.org/apidocs/#/Build/get_build__project_name___repository_name___architecture_name___package_name___buildinfo)" msgstr "" #. type: Plain text #: _docs/formal_definition.md #, no-wrap msgid "" "* [slsa provenance specification](https://slsa.dev/spec/v1.0/provenance),\n" " ([example of slsa povenance file produced by openSUSE\n" "OBS](https://download.opensuse.org/update/leap/15.5/sle/x86_64/389-ds-2.2.8~git17.48834f1-150500.3.5.1.x86_64.slsa_provenance.json))\n" "* [in-toto Attestation specification can include multiple formats that are\n" " related](https://github.com/in-toto/attestation/tree/main/spec/predicates)\n" msgstr "" #. type: Plain text #: _docs/formal_definition.md msgid "As example, the .buildinfo control files used by Debian specifies the sources, the generated binaries, and all packages used to perform this build (with the exact version number). This is signed by reproducers to attest what their build result was. (This alone does not indicate if it is reproducible, as every repeated build result could be different.)" msgstr "" #. type: Plain text #: _docs/formal_definition.md msgid "A Debian binary package containes the name and version of the source used. A [Debian package repository contains a file with the hashes, names and versions of included packages](https://wiki.debian.org/DebianRepository/Format#A.22Packages.22_Indices). [Each update of the Debian repositories is archived](https://snapshot.debian.org/) to be able to reproduce package builds." msgstr "" #. type: Plain text #: _docs/formal_definition.md msgid "This ensures that from the artifact itself, or the hash of an artifact, or the repository identifier and name and version of a binary, or the Buildinfo file one can find the exact source code and and build environment that was used for building it." msgstr "" #. type: Plain text #: _docs/formal_definition.md msgid "Distributions that are built in a rolling way are more complicated to reproduce, than a distribution that is built only with the package versions that it itself contains. For the later the build dependencies can just be installed from itself. That it is self contained (though with self-referential dependency loops) and reproducible can be ensured by rebuilding again after bootsrapping from outside binaries (and only keeping the rebuilt binaries). But for rolling distributions the dependencies are in some past version of it, but not necessarly in the current one. So to install the build dependencies one needs to either search an archive of them for which repo version included all their versions or install the neceassry binaries directly or assemble a new package repo from just these versions taken from the archive." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/history.md #, no-wrap msgid "History" msgstr "" #. type: Plain text #: _docs/history.md msgid "A history of *reproducible builds* in and around Debian." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "An old idea" msgstr "" #. type: Plain text #: _docs/history.md msgid "The idea of *reproducible builds* is not very new. It was implemented for GNU tools in [the early 1990s](https://lists.reproducible-builds.org/pipermail/rb-general/2017-January/000309.html) (which we learned, much later in 2017). In Debian world, it was mentioned first in [2000](https://lists.debian.org/debian-devel/2000/11/msg01758.html), and then more explicitly in [2007](https://lists.debian.org/debian-devel/2007/09/msg00746.html) on `debian-devel`: \"*I think it would be really cool if the Debian policy required that packages could be rebuild bit-identical from source.\"* The reactions were unfortunately not really enthusiastic both times." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Private property + Snowden effect" msgstr "" #. type: Plain text #: _docs/history.md msgid "The interest on reproducible builds picked up again with Bitcoin. Users of bitcoins needed a way to trust that they were not downloading corrupted software. Initial versions of [Gitian](http://gitian.org/) were written in 2011 to solve the problem. It drives builds using virtual machines and Git." msgstr "" #. type: Plain text #: _docs/history.md msgid "The [global surveillance disclosures](https://en.wikipedia.org/wiki/Global_surveillance_disclosures_%282013%E2%80%93present%29) in 2013 raised the interest even further. Mike Perry worked on [making the Tor Browser build reproducibly](https://blog.torproject.org/blog/deterministic-builds-part-two-technical-details) in [fear](https://blog.torproject.org/blog/deterministic-builds-part-one-cyberwar-and-global-compromise) of a \"*malware that attacks the software development and build processes themselves to distribute copies of itself to tens or even hundreds of millions of machines in a single, officially signed, instantaneous update*\"." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Kick-off" msgstr "" #. type: Plain text #: _docs/history.md msgid "The success of making such a large piece of software build reproducibly proved that it was feasible for other projects. This prompted Lunar to organize a [discussion at DebConf13](http://penta.debconf.org/dc13_schedule/events/1063.en.html) happening July 2013. Even scheduled at the last minute, there was still about thirty attendees who were very much interested, amongst them members of the [technical committee](https://www.debian.org/devel/tech-ctte) and a few other core teams. [Minutes](../history-dc13-minutes.txt) are available." msgstr "" #. type: Plain text #: _docs/history.md msgid "After some more research during the conference, a [wiki page](https://wiki.debian.org/ReproducibleBuilds?action=recall&rev=1) was created. The initial approach was to get Debian to \"buy-in\" on the idea by making five packages from different maintainers build reproducibly. However, it quickly appeared that before fixing issues in the toolchain, it would not be possible to even get a single package to be reproducible." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "First mass-rebuilds" msgstr "" #. type: Plain text #: _docs/history.md msgid "Lunar came up with the first patches for DebianPts:dpkg during August 2013. This enabled DebianPts:hello to build reproducibly. The [first large scale rebuild](https://wiki.debian.org/ReproducibleBuilds/Rebuild20130907) was performed soon after by David Suárez, with variations on time and build path. 24% of 5240 source packages were identified as reproducible. The [first version of a \"smart\" comparison script](https://wiki.debian.org/ReproducibleBuilds?action=recall&rev=83#Crude_bash_script_to_compare_two_binary_packages) was written to help reviewing differences." msgstr "" #. type: Plain text #: _docs/history.md msgid "A [second mass rebuild](https://wiki.debian.org/ReproducibleBuilds/Rebuild20140126) was made before the [presentation in the distro devroom at FOSDEM'14](https://fosdem.org/2014/schedule/event/reproducibledebian/). It used a slightly different approach regarding build paths and had `binutils` built in deterministic mode. 67% of 6887 source packages were found reproducible. A result applauded by the FOSDEM crowd." msgstr "" #. type: Plain text #: _docs/history.md msgid "The presentation sparked interest and woke up the [mailing-list](https://lists.alioth.debian.org/mailman/listinfo/reproducible-builds) created some months ago. Tomasz Buchert wrote a [lintian check for gzip files](http://lists.alioth.debian.org/pipermail/reproducible-builds/Week-of-Mon-20140210/000038.html). Stéphane Glondu worked on sorting logs and [experimenting with alternatives for build path issues](http://lists.alioth.debian.org/pipermail/reproducible-builds/Week-of-Mon-20140217/000053.html)." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid ".buildinfo control files" msgstr "" #. type: Plain text #: _docs/history.md msgid "In parallel, several approaches on where and how to record the build environment were considered. The first idea was to use the [.changes control file](https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-debiansourcecontrolfiles) through a substitution variable (Bug:719854). Instead, Guillem Jover suggested to add new fields by passing `--changes-option=\"-DBuild-Env=...` to `dpkg-buildpackage`. As for the value, we discovered `dh-buildinfo` written by Yann Dirson, described as a \"debhelper addon to track package versions used to build a package\". Fit for reproducible builds!" msgstr "" #. type: Plain text #: _docs/history.md msgid "[What happened for a year](https://summit.debconf.org/debconf14/meeting/78/reproducible-builds-for-debian/) was presented at [DebConf14](http://debconf14.debconf.org/). The reception was unexpectedly good and the follow-up BoF truly productive. For one thing, a suitable way to record the build environment was sketched out." msgstr "" #. type: Plain text #: _docs/history.md msgid "One issue about using `.changes` files is that they are not kept in the archive. So to be used as a way to record the environment, they would need to be distributed with the archive. But this would be a misunderstanding of their purpose. As their name implies, `.changes` control files represent *changes* to archive. They were inherently designed to be transient." msgstr "" #. type: Plain text #: _docs/history.md msgid "So instead, we had the idea of a new `.buildinfo` control file which would be added to the archive alongside binary packages --- and be uploaded by referencing them in `.changes`. We quickly drafted a [specification](https://wiki.debian.org/ReproducibleBuilds/BuildinfoSpecification), and a couple of days later Niko Tyni came up with [an addition to debhelper](https://anonscm.debian.org/cgit/reproducible/debhelper.git/tree/dh_genbuildinfo?h=pu/reproducible_builds_2014&id=1543ea2535160bf9578149c681eb7ff324901471) which created a `.buildinfo` using the output of the aforementioned `dh-buildinfo`." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "strip-nondeterminism" msgstr "" #. type: Plain text #: _docs/history.md msgid "Before DebConf14, an explicit *timestamp* was given during rebuilds, extracted from the `.changes` file. However, during the discussions, there was a consensus that the date of the latest entry in the [debian/changelog](https://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog) file could be used as the reference timestamp when needed." msgstr "" #. type: Plain text #: _docs/history.md msgid "This helped another idea: a generic tool that would post-process different file formats to remove timestamps or other source of non-determinism. Andrew Ayer further took the task of creating `strip-nondeterminism`. The first released version handled files created by gzip, Zip, Jar, Javadoc, and `.a` files." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Giving up on build paths" msgstr "" #. type: Plain text #: _docs/history.md msgid "Initially we though that variations happening when building the package from different build path should be eliminated. This has proven difficult. The main problem that has been identified is that full path to source files are written in debug symbols of ELF files." msgstr "" #. type: Plain text #: _docs/history.md msgid "First attempt used the [-fdebug-prefix-map](https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Debugging-Options.html) option which allows to map the current directory to a canonical one in what gets recorded. But compiler options get written to debug file as well. So it has to be doubled with `-gno-record-gcc-switches` to be used for reproducibility. The [first large scale rebuild](https://wiki.debian.org/ReproducibleBuilds/Rebuild20130907) has proven that it was also hard to determine what the actual build path has been accurately." msgstr "" #. type: Plain text #: _docs/history.md msgid "Second attempt used `debugedit` which is used by Fedora and other to change the source paths to a canonical location after the build. Unfortunately, `gcc` write debug strings in a *hashtable*. `debugedit` will not reorder the table after patching the strings, so the result is still unreproducible. Adding this feature to `debugedit` looked difficult. We can still make the approach work by passing `-fno-merge-debug-strings` but this is space expensive. The [second large scale rebuild](https://wiki.debian.org/ReproducibleBuilds/Rebuild20140126) used the latter approach. It was still difficult to guess the initial build path properly. Stéphane Glondu was the first to [suggest to using a canonical build path](http://lists.alioth.debian.org/pipermail/reproducible-builds/Week-of-Mon-20140217/000065.html) to solve the issue." msgstr "" #. type: Plain text #: _docs/history.md msgid "During [discussions at DebConf14](http://lists.alioth.debian.org/pipermail/reproducible-builds/Week-of-Mon-20140901/000198.html), we revisited the idea, and felt it was indeed appropriate to decide on a canonical build path. It has an added benefit of making it easier to use debug packages: one simply has to unpack the source in the right place, no extra configuration required." msgstr "" #. type: Plain text #: _docs/history.md msgid "Finally, it was [agreed](http://lists.alioth.debian.org/pipermail/reproducible-builds/Week-of-Mon-20141117/000560.html) to add a `Build-Path` field to `.buildinfo` as it made it easier to reproduce the initial build if the canonical build location would change." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Improved comparison tool" msgstr "" #. type: Plain text #: _docs/history.md msgid "After `strip-nondeterminism` initial upload and integrating some more changes discussed during DebConf14 in DebianPts:dpkg and DebianPts:debhelper, Lunar [experimented with 172 core packages](http://lists.alioth.debian.org/pipermail/reproducible-builds/Week-of-Mon-20140915/000441.html). 30% were reproduced without further modifications." msgstr "" #. type: Plain text #: _docs/history.md msgid "As the current tools to understand differences between builds were slow and hard to read, Lunar wrote `debbindiff`. It [replaced](http://lists.alioth.debian.org/pipermail/reproducible-builds/Week-of-Mon-20140929/000492.html) inefficient shell scripts by structured Python with a HTML output." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Continuous integration" msgstr "" #. type: Plain text #: _docs/history.md msgid "At the end of September 2014, Holger Levsen started to work on extending [jenkins.debian.net](Services/jenkins.debian.net) to perform continuous integration for build reproducibility. Packages from *sid* started to be built and rebuild. This initially introduced variations for time and file ordering, and was extended later on to also use different users, groups, hostnames, and locales." msgstr "" #. type: Plain text #: _docs/history.md msgid "The results were visible through a new [reproducible.debian.net](https://reproducible.debian.net/) website. The process of analyzing reproducibility failures could now be more easily shared. New contributors indeed showed up and started submitting sorting out common issues and providing patches." msgstr "" #. type: Plain text #: _docs/history.md msgid "In July of 2015, [Vagrant begins hosting ARM boards](https://lists.alioth.debian.org/pipermail/reproducible-builds/Week-of-Mon-20150727/002492.html) for reproducibility testing the armhf architecture. They were added to jenkins in August of 2015, and by December, nearly all packages on armhf had been tested at least once." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "dpkg-genbuildinfo" msgstr "" #. type: Plain text #: _docs/history.md msgid "The turn of 2015 saw the replacement of the prototype `.buildinfo` generator by a new implementation suitable for proper inclusion in `dpkg`. Previously, only packages using `dh` could generate `.buildinfo` and could thus be considered reproducible. After updating the experimental toolchain, the change allowed to reach the mark of [80% source packages reproducible](https://people.debian.org/~lunar/blog/posts/eighty_percent/)." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "FOSDEM 2015 and aftermath" msgstr "" #. type: Plain text #: _docs/history.md msgid "The presentation [Stretching out for trustworthy reproducible builds](https://fosdem.org/2015/schedule/event/stretching_out_for_trustworthy_reproducible_builds/) was well received at FOSDEM 2015 and was followed up by" msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid "[tracker.debian.org](https://tracker.debian.org) inclusion, see [739497](https://bug.debian.org/739497)" msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid "[Debian Developer's Packages Overview](https://qa.debian.org/developer.php) (DDPO) inclusion" msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid "debbindiff gained .rpm support" msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid "[Debian Maintainer Dashbord](https://udd.debian.org/dmd/) inclusion" msgstr "" #. type: Plain text #: _docs/history.md msgid "Finally, for now, not even two weeks after FOSDEM 2015 a mail with the subject \"[Reproducible Builds --- proof of concept successful for 83% of all sources in main](https://lists.debian.org/debian-devel-announce/2015/02/msg00007.html)\" was send to [debian-devel-announce@lists.ddebian.org](https://lists.debian.org/debian-devel-announce/) officially anouncing the project to the Debian developer community at large." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "To be sorted out" msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid " 2015-03-26: [`binutils` `2.25-6` is built with `--enable-deterministic-archives`](https://tracker.debian.org/news/675691)" msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid " testing *`testing*` and *`experimental*` now, pkg sets available too." msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid " 2015-05-27: [`iceweasel` `38.0.1-5`](https://tracker.debian.org/news/687110) is reproducible." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Google Summer of Code 2015" msgstr "" #. type: Plain text #: _docs/history.md msgid "During the summer of 2015 akira and Dhole will be working on moving forward reproducible builds as a Google Summer of Code project. Follow the links to check the accepted [akira's application](SummerOfCode2015/StudentApplications/MariaValentinaMarinRodrigues) and [Dhole's application](SummerOfCode2015/StudentApplications/EduardSanou). Dhole also made a [blog post about how Dhole got into GSoC 2015](https://dhole.github.io/post/reproducible_builds_debian_gsoc2015/)." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "CCCamp 2015" msgstr "" #. type: Plain text #: _docs/history.md msgid "Short mention of Lunar's talk to be written here. Add links." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "DebConf15" msgstr "" #. type: Plain text #: _docs/history.md msgid "To be written: the first real life meeting of the Debian team. Talk given, roundstable discussion, hacking session. Mentioned in several talks, incl DPL key note. `SOURCE_DATE_EPOCH` was invented around this time too." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Continous tests for Coreboot, OpenWrt, NetBSD, FreeBSD, Arch Linux and Fedora" msgstr "" #. type: Plain text #: _docs/history.md msgid "to be written: tests for these six projects have been added between June and December 2015..." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Reproducible World Summit, December 1-3, 2015, Athens, Greece" msgstr "" #. type: Plain text #: _docs/history.md msgid "to be written, maybe some photos to be shared, pointers to reports, new mailinglists, new irc channel, an even wider community has started to grow, [website](https://reproducible-builds.org/events/athens2015/)." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "2016 and 2017" msgstr "" #. type: Plain text #: _docs/history.md msgid "Are largely missing here, we should fix this, rather sooner than later." msgstr "" #. type: Plain text #: _docs/history.md msgid "In January 2017 we learned, that John Gilmore [wrote an interesting mail about how Cygnus.com worked on reproducible builds in the early 1990s](https://lists.reproducible-builds.org/pipermail/rb-general/2017-January/000309.html). It's eye opening to see how the dealt with basically the very same problems we're dealing with today, how they solved them and then to realize that most of this has been forgotten and bit-rotted in the last 20 years. How will we prevent history repeating itself here?" msgstr "" #. type: Plain text #: _docs/history.md msgid "On August 21st 2017 reproducible-builds where first mentioned in Debian Policy, 4.1.0." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Archive wide rebuilds" msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid " [2013-09-07](https://wiki.debian.org/ReproducibleBuilds/Rebuild20130907) by David Suárez. 24% of 5240 source packages reproducible. Variations: time, build path." msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid " [2014-01-26](https://wiki.debian.org/ReproducibleBuilds/Rebuild20140126) by David Suárez. 67% of 6887 source packages reproducible. Variations: time, build path." msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid " [2014-09-19](https://wiki.debian.org/ReproducibleBuilds/RebuildCore20140919) by Lunar, 30% of 172 source core packages reproducible. Variations: time, file order." msgstr "" #. type: Bullet: '* ' #: _docs/history.md msgid " [Updated daily since 2014-09-28](https://reproducible.debian.net/userContent/reproducible.html) by jenkins.debian.net. On 2014-11-11, 13213 (61.4%) out of 21448 packages are reproducible." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Publicity" msgstr "" #. type: Plain text #: _docs/history.md msgid "please see the [Publicity](https://wiki.debian.org/ReproducibleBuilds/About#Publicity) page in the Debian wiki which we still need to migrate to reproducible-builds.org." msgstr "" #. type: Title ## #: _docs/history.md #, no-wrap msgid "Contributors" msgstr "" #. type: Plain text #: _docs/history.md msgid "See this page for an [incomplete list of contributors so far]({{ \"/who/people\" | relative_url }})." msgstr "" #. type: Title ### #: _docs/jvm.md _docs/recording.md #, no-wrap msgid "JVM" msgstr "" #. type: Plain text #: _docs/jvm.md msgid "The JVM ecosystem provides many languages (Java, Scala, Groovy, Kotlin, ...) and build tools (Maven, Gradle, sbt, ...)." msgstr "" #. type: Plain text #: _docs/jvm.md msgid "The `javac` compiler generates reproducible bytecode `.class` output as do most language-specific compilers, but JVM packaging (in `.jar` files) is not reproducible-friendly -- particularly timestamp of files in the archive --, each build tool requires some work mostly at packaging step to provide Reproducible Builds." msgstr "" #. type: Title ## #: _docs/jvm.md #, no-wrap msgid "Reproducible Central" msgstr "" #. type: Plain text #: _docs/jvm.md msgid "Whatever the build tool is, binary JVM artifacts are generally published in artifact repositories that use the Maven2 repository format (using groupId/artifactId/version coordinates) like [Maven Central](https://search.maven.org/) or [Google's Android Repository](https://dl.google.com/dl/android/maven2/index.html)." msgstr "" #. type: Plain text #: _docs/jvm.md msgid "[Reproducible Central](https://github.com/jvm-repo-rebuild/reproducible-central#readme) is an effort to rebuild public releases published to [Maven Central](https://search.maven.org/) and check that Reproducible Build can be achieved." msgstr "" #. type: Plain text #: _docs/jvm.md msgid "Contributions are welcome to write additional [`.buildspec` file](https://github.com/jvm-repo-rebuild/reproducible-central/blob/master/doc/BUILDSPEC.md) that will be used to rebuild the release and compare against binaries available in Maven Central." msgstr "" #. type: Title ## #: _docs/jvm.md #, no-wrap msgid "Configuring Build Tools for Reproducible Builds" msgstr "" #. type: Title ### #: _docs/jvm.md _docs/source-date-epoch.md #, no-wrap msgid "Maven" msgstr "" #. type: Plain text #: _docs/jvm.md msgid "Getting reproducible builds with Maven requires some plugins configuration: see [Maven - Guide to Configuring for Reproducible Builds](https://maven.apache.org/guides/mini/guide-reproducible-builds.html) for more details." msgstr "" #. type: Title ### #: _docs/jvm.md _docs/source-date-epoch.md #, no-wrap msgid "Gradle" msgstr "" #. type: Plain text #: _docs/jvm.md msgid "Gradle supports [reproducible archives](https://docs.gradle.org/current/userguide/working_with_files.html#sec:reproducible_archives) as of v3.4." msgstr "" #. type: Plain text #: _docs/jvm.md msgid "Tasks which generate archives, such as ZIPs or JARs, can enforce preserved file timestamps and reproducible file order which fix two of the main sources of non-determinism in JVM artifacts." msgstr "" #. type: Title ### #: _docs/jvm.md #, no-wrap msgid "`sbt`" msgstr "" #. type: Plain text #: _docs/jvm.md msgid "When using [sbt](https://www.scala-sbt.org/), a build tool popular with Scala projects, you can use the [sbt-reproducible-builds](https://github.com/raboof/sbt-reproducible-builds) plugin to strip your artifacts and share buildinfo information." msgstr "" #. type: Title ## #: _docs/jvm.md #, no-wrap msgid "`.buildinfo` file" msgstr "" #. type: Plain text #: _docs/jvm.md msgid "JVM `.buildinfo` file format is a format drafted in 2018 when working initially on Reproducible Builds for the JVM, to try to record full build info data, from source and environment used to rebuild to output result: its intent was to easily compare 2 builds run by independant people." msgstr "" #. type: Plain text #: _docs/jvm.md msgid "After 3 years of work on Reproducible Builds, it has been found more useful as an internal file format: Reproducible Central and its `.buildspec` format is more what we need to check that Reproducible Builds results has been achieved. `.buildinfo` just records a build, be it reproducible or not." msgstr "" #. type: Plain text #: _docs/jvm.md msgid "Buildinfo file format version 1.0-SNAPSHOT is kept here for reference on past work. It uses [Java properties format](https://en.wikipedia.org/wiki/.properties):" msgstr "" #. type: Fenced code block #: _docs/jvm.md #, no-wrap msgid "" "#### Work In Progress ####\n" "buildinfo.version=1.0-SNAPSHOT\n" "\n" "name=\n" "group-id=\n" "artifact-id=\n" "version=\n" "\n" "# source information for rebuilders, as source tarball artifact in repository and/or url and/or scm coordinates\n" "source.artifact=::::\n" "source.url=\n" "source.scm.uri=\n" "source.scm.tag=\n" "\n" "# build instructions\n" "build-tool=\n" "build.setup=\n" "\n" "# effective recorded build environment information\n" "java.version=\n" "java.vendor=\n" "os.name=\n" "source.used=\n" "\n" "# Each build tool or plugin is free to add additional entries to the buildinfo,\n" "# both for build instructions and effective recorded build environment.\n" "# For example, the sbt plugin may add the following for Scala:\n" "sbt.version=1.2.3\n" "scala.version=2.12.6\n" "\n" "# and Maven could add data on rebuild instructions and effective recorded environment:\n" "mvn.rebuild-args=-Dmaven.test.skip package\n" "mvn.build-root=::\n" "mvn.version=Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)\n" "mvn.minimum.version=\n" "\n" "# A buildinfo file can contain checksums for multiple output files, for\n" "# example for the main jar and the accompanying pom.xml (when generated):\n" "outputs.0.filename=\n" "outputs.0.length=\n" "outputs.0.checksums.sha512=\n" "outputs.1.filename=\n" "outputs.1.length=\n" "outputs.1.checksums.sha512=\n" "...\n" msgstr "" #. type: Plain text #: _docs/jvm.md msgid "Notice that `${artifactId}-${version}-sources.jar` files published in Maven repositories are not buildable sources, but [sources for IDEs](https://central.sonatype.org/pages/requirements.html#supply-javadoc-and-sources)." msgstr "" #. type: Plain text #: _docs/jvm.md msgid "Source tarballs, intended for building, are not always published in repositories but only sometimes, with 2 classical naming conventions: - `${artifactId}-${version}-source-release.zip` (see [artifacts in Central providing such source tarballs](https://search.maven.org/search?q=l:source-release)) - `${artifactId}-${version}-src.zip` (see [artifacts in Central providing such source tarballs](https://search.maven.org/search?q=l:src))" msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/locales.md #, no-wrap msgid "Locales" msgstr "" #. type: Plain text #: _docs/locales.md msgid "The locale of the build system might affect the build products. While it is important that developers have access to error messages in the language of their choice, tools which output is influenced by the current locale can make locale a source of reproducibility issues." msgstr "" #. type: Plain text #: _docs/locales.md msgid "There are many aspects regarding locales (see [GNU libc locale(1) manpage](https://manpages.debian.org/locale)). The ones that follow are the most important ones to consider in the context of reproducible builds." msgstr "" #. type: Title - #: _docs/locales.md #, no-wrap msgid "Time format" msgstr "" #. type: Plain text #: _docs/locales.md msgid "Several common time formatting functions will have output depending on the current locale. On a POSIX system the formatting will depend on the `LC_CTIME` environment variable, which can be overridden by `LC_ALL`." msgstr "" #. type: Plain text #: _docs/locales.md msgid "For build systems, it's thus best to use `LC_ALL` directly:" msgstr "" #. type: Plain text #: _docs/locales.md #, no-wrap msgid "" "
\n" "{% highlight sh %}\n" "$ LC_ALL=C date -u -d '2015-10-21'\n" "Wed Oct 21 00:00:00 UTC 2015\n" "{% endhighlight %}\n" "
\n" msgstr "" #. type: Plain text #: _docs/locales.md msgid "The system [timezone]({{ \"/docs/timezones/\" | relative_url }}) and `TZ` environment variable will also affect the output of time formatting functions." msgstr "" #. type: Title - #: _docs/locales.md #, no-wrap msgid "Collation order" msgstr "" #. type: Plain text #: _docs/locales.md msgid "Common sorting functions are affected by the `LC_COLLATE` environment variable, which can be overridden by `LC_ALL`. Some locales can be quite surprising." msgstr "" #. type: Plain text #: _docs/locales.md msgid "This typically shows when using `sort`. The `fr_FR` locale will sort independently of the character case:" msgstr "" #. type: Plain text #: _docs/locales.md #, no-wrap msgid "" "
\n" "{% highlight sh %}\n" "$ echo B a c | tr ' ' '\\n' | LC_ALL=fr_FR.UTF-8 sort\n" "a\n" "B\n" "c\n" "{% endhighlight %}\n" "
\n" msgstr "" #. type: Plain text #: _docs/locales.md msgid "The `C` locale will sort according to the byte values and is always available:" msgstr "" #. type: Plain text #: _docs/locales.md #, no-wrap msgid "" "
\n" "{% highlight sh %}\n" "$ echo B a c | tr ' ' '\\n' | LC_ALL=C sort\n" "B\n" "a\n" "c\n" "{% endhighlight %}\n" "
\n" msgstr "" #. type: Title - #: _docs/locales.md #, no-wrap msgid "Default character encoding" msgstr "" #. type: Plain text #: _docs/locales.md msgid "The default system character encoding will affect both the input and output of many tools. It is defined using the `LC_CTYPE` environment variable, and can also be overridden using `LC_ALL`." msgstr "" #. type: Plain text #: _docs/locales.md msgid "Here's an example when using `lynx` to convert HTML documentation into text:" msgstr "" #. type: Plain text #: _docs/locales.md #, no-wrap msgid "" "
\n" "{% highlight sh %}\n" "LC_ALL=fr_FR lynx -dump -width 72 docs.html | file -\n" "/dev/stdin: ISO-8859 text\n" "{% endhighlight %}\n" "
\n" msgstr "" #. type: Plain text #: _docs/locales.md msgid "The `C.UTF-8` pseudo-locale can always be used to get the default strings with UTF-8 output:" msgstr "" #. type: Plain text #: _docs/locales.md #, no-wrap msgid "" "
\n" "{% highlight sh %}\n" "LC_ALL=C.UTF-8 lynx -dump -width 72 docs.html | file -\n" "/dev/stdin: UTF-8 Unicode text\n" "{% endhighlight %}\n" "
\n" msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/perimeter.md #, no-wrap msgid "What's in a build environment?" msgstr "" #. type: Plain text #: _docs/perimeter.md msgid "Reproducible builds does not mandate that a given piece of source code is turned into the same bytes in all situations. This would be unfeasible. The output of a compiler is likely to be different from one version to another as better optimizations are integrated all the time." msgstr "" #. type: Plain text #: _docs/perimeter.md msgid "Instead, reproducible builds happen in the context of a *build environment*. It usually comprises the set of tools, required versions, and other assumptions about the operating system and its configuration. A description of this environment should typically be [recorded]({{ \"/docs/recording/\" | relative_url }}) and provided alongside any distributed binary package." msgstr "" #. type: Title - #: _docs/perimeter.md #, no-wrap msgid "Requirements" msgstr "" #. type: Plain text #: _docs/perimeter.md msgid "What exactly makes up the build environment is going to be different for each project. There might even be several build environments for a single release to accommodate different target operating systems. But there are some important aspects common to all environments." msgstr "" #. type: Plain text #: _docs/perimeter.md msgid "It should be **easy to install** a matching build environment on the users' systems. Ideally it should only be made of free software available on public Internet sites. The best way to provide the environment is probably using a documented and easily understood script." msgstr "" #. type: Plain text #: _docs/perimeter.md msgid "It should be **auditable**. It must be easy to understand what tools are part of the build environment. And ideally it must be easy to review and rebuild them." msgstr "" #. type: Title - #: _docs/perimeter.md #, no-wrap msgid "Content" msgstr "" #. type: Plain text #: _docs/perimeter.md msgid "{% comment %} XXX: Not really happy with this section. Please help! -- Lunar {% endcomment %}" msgstr "" #. type: Plain text #: _docs/perimeter.md msgid "The scope of the build environment needs to be properly specified as this will determine how much of the build system needs to be [deterministic]({{ \"/docs/deterministic-build-systems/\" | relative_url }})." msgstr "" #. type: Plain text #: _docs/perimeter.md msgid "At least the defined environment has a list of the tools used by the build process and their versions." msgstr "" #. type: Plain text #: _docs/perimeter.md msgid "The rest can be different from one project to the next, as long as it can be reproduced by interested users. To give some examples:" msgstr "" #. type: Bullet: ' * ' #: _docs/perimeter.md msgid "specific operating system (if cross-compiling is not supported)," msgstr "" #. type: Bullet: ' * ' #: _docs/perimeter.md msgid "build system architecture (if cross-compiling is not supported)," msgstr "" #. type: Bullet: ' * ' #: _docs/perimeter.md msgid "directory where the build must happen," msgstr "" #. type: Bullet: ' * ' #: _docs/perimeter.md msgid "name of the user running the build," msgstr "" #. type: Bullet: ' * ' #: _docs/perimeter.md msgid "locale," msgstr "" #. type: Bullet: ' * ' #: _docs/perimeter.md msgid "timezone," msgstr "" #. type: Bullet: ' * ' #: _docs/perimeter.md msgid "specific environment variables (like [`SOURCE_DATE_EPOCH`](https://reproducible-builds.org/specs/source-date-epoch/))." msgstr "" #. type: Plain text #: _docs/perimeter.md msgid "Using virtual machines or containers as the recommended build environment can make it easier to ensure a specific operating system or user configuration. But they might also hide some assumptions on the environment, like specific optimizations enabled because of the [system CPU type](https://trac.torproject.org/projects/tor/ticket/12238#comment:4)." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/plans.md #, no-wrap msgid "Making plans" msgstr "" #. type: Plain text #: _docs/plans.md msgid "The idea of *reproducible builds* is to empower anyone to verify that no flaws have been introduced during the build process by reproducing byte-for-byte identical binary packages from a given source." msgstr "" #. type: Plain text #: _docs/plans.md msgid "Achieving reproducible builds requires cooperation from multiple roles involved in software production. On small projects, all these roles might be carried by a single person, but it helps to differentiate the responsibilities." msgstr "" #. type: Title - #: _docs/plans.md #, no-wrap msgid "Getting a deterministic build system" msgstr "" #. type: Plain text #: _docs/plans.md msgid "In order to allow software to build reproducibly, the source code must not introduce uncontrollable variations in the build output." msgstr "" #. type: Plain text #: _docs/plans.md msgid "Things will work better if such variations are discovered before users are confronted with unreproducible binaries. Setting up a test protocol in which rebuilds are performed under variations in the environment (aspects like time, *username*, CPU, system version, filesystems, amongst many others) will greatly help. A recent empirical study identifies 16 variations in the environment, as demonstrated in the taxonomy below." msgstr "" #. type: Plain text #: _docs/plans.md #, no-wrap msgid " [![]({{ \"/images/docs/taxonomy.jpg#center\" | relative_url }})](taxonomy of variations in the environment variables)\n" msgstr "" #. type: Title - #: _docs/plans.md #, no-wrap msgid "Defining a build environment" msgstr "" #. type: Plain text #: _docs/plans.md msgid "As different versions of compilation tools are likely to produce different outputs, users must be able to recreate a build environment close enough to the original build. It is not required that the toolchain[^toolchain] itself is byte-for-byte identical, but its output has to stay the same." msgstr "" #. type: Plain text #: _docs/plans.md msgid "The build environment can either be defined while the software is being developed or it can be recorded at build time." msgstr "" #. type: Title - #: _docs/plans.md #, no-wrap msgid "Distributing the build environment" msgstr "" #. type: Plain text #: _docs/plans.md msgid "Users need to be able to know what build environment needs to be set up to rebuild the software." msgstr "" #. type: Plain text #: _docs/plans.md msgid "If the build environment is defined ahead and part of the source code, then no further steps are required." msgstr "" #. type: Plain text #: _docs/plans.md msgid "In other cases, it needs to be made available alongside the binaries. The ideal form is a description that can be understood by both humans and machines to make automatic verification possible, while enabling people to review that the environment is sane." msgstr "" #. type: Title - #: _docs/plans.md #, no-wrap msgid "Providing a comparison protocol" msgstr "" #. type: Plain text #: _docs/plans.md msgid "Users must have an easy way to recreate the build environment, get the source code, perform the build, and compare the results." msgstr "" #. type: Plain text #: _docs/plans.md msgid "Ideally, the comparison protocol to verify that resulting binaries are identical should be simple. Comparing bytes or cryptographic hash values is easy to do and understand." msgstr "" #. type: Plain text #: _docs/plans.md msgid "Other technologies might require removing cryptographic signatures or ignore specific parts. Such operations must be both documented and scripted. The rationale and code must be easy to understand by reviewers." msgstr "" #. type: Plain text #: _docs/plans.md #, no-wrap msgid "" "[^toolchain]:\n" " By *toolchain*, we mean all pieces of software needed to create the build output.\n" msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/proprietary_os.md #, no-wrap msgid "Proprietary operating systems" msgstr "" #. type: Plain text #: _docs/proprietary_os.md msgid "On proprietary operating systems, it is hard to determine if they are tampered with. Typically, they also require non-free compilation tools that can be hard to obtain for users." msgstr "" #. type: Plain text #: _docs/proprietary_os.md msgid "The good news is that for some cases, we have free software tools which are able to cross-compile software for proprietary operating systems on free operating systems. Both Bitcoin and Tor Browser have pioneered the technique to build their Windows and Mac OS X versions." msgstr "" #. type: Title - #: _docs/proprietary_os.md #, no-wrap msgid "Windows" msgstr "" #. type: Plain text #: _docs/proprietary_os.md msgid "For Windows, [mingw-w64](https://mingw-w64.org/) will build Windows binaries on POSIX compatible operating systems." msgstr "" #. type: Plain text #: _docs/proprietary_os.md msgid "[NSIS](http://nsis.sourceforge.net/) can be used to create integrated installation package." msgstr "" #. type: Plain text #: _docs/proprietary_os.md msgid "Both are readily available in several free software distributions." msgstr "" #. type: Title - #: _docs/proprietary_os.md #, no-wrap msgid "Mac OS X" msgstr "" #. type: Plain text #: _docs/proprietary_os.md msgid "crosstool-ng [should work](https://bugs.torproject.org/9711#comment:73) to build software for Mac OS X. Sadly this seems to require a non-redistributable part of the Apple SDK. It can be extracted from XCode which can be downloaded at no charge." msgstr "" #. type: Plain text #: _docs/proprietary_os.md msgid "Software from Mac OS X is often distributed as disk images (`.dmg`) which can be created under GNU/Linux, but it seems to [require multiple tools at the moment](https://gitweb.torproject.org/builders/tor-browser-bundle.git/tree/gitian/build-helpers/ddmg.sh)." msgstr "" #. type: Title ### #: _docs/publications.md #, no-wrap msgid "Academic publications" msgstr "" #. type: Title ### #: _docs/publications.md #, no-wrap msgid "Citing reproducible-builds.org" msgstr "" #. type: Plain text #: _docs/publications.md msgid "The [CITATION.cff](https://salsa.debian.org/reproducible-builds/reproducible-website/-/blob/master/CITATION.cff) file is available at the root of the repository. It can be used to generate citations in various formats using [`cffconvert`](https://github.com/citation-file-format/cffconvert)." msgstr "" #. type: Plain text #: _docs/publications.md msgid "If you are preparing a paper or article and wish to reference the [reproducible-builds.org](https://reproducible-builds.org) project, the following BibTeX entry is recommended:" msgstr "" #. type: Plain text #: _docs/publications.md msgid "{% raw %}" msgstr "" #. type: Plain text #: _docs/publications.md #, no-wrap msgid "" " @misc{ReproducibleBuildsOrg,\n" " author = {{Reproducible Builds}},\n" " title = {Reproducible Builds Website},\n" " url = {https://reproducible-builds.org/}\n" " }\n" msgstr "" #. type: Plain text #: _docs/publications.md msgid "{% endraw %}" msgstr "" #. type: Plain text #: _docs/publications.md msgid "In addition to the resources mentioned, our repository also includes a [bibliography.bib](https://salsa.debian.org/reproducible-builds/reproducible-website/-/blob/master/bibliography.bib) file, which contains BibTeX entries for all the academic publications listed here. This file is continuously updated to reflect the most recent scholarly works related to reproducible builds. It serves as a comprehensive source for researchers and practitioners looking to cite relevant literature in their work. The file can be found within the repository, making it easy for anyone to access and utilize in their own scholarly writings." msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Thompson, K. (1984). Reflections on trusting trust. _Commun. ACM_, _27_(8), 761–763. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Wheeler, D. A. (2010). _Fully countering trusting trust through diverse double-compiling_. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Courtès, L. (2013). _Functional package management with guix_. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Courtès, L., & Wurmus, R. (2015, August). Reproducible and User-Controlled Software Environments in HPC with Guix. _2nd International Workshop on Reproducibility in Parallel Computing (RepPar)_. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Ren, Z., Jiang, H., Xuan, J., & Yang, Z. (2018, May). Automated localization for unreproducible builds. _Proceedings of the 40th International Conference on Software Engineering_. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Tapas, N., Longo, F., Merlino, G., & Puliafito, A. (2019). Transparent, provenance-assured, and secure software-as-a-service. _2019 IEEE 18th International Symposium on Network Computing and Applications (NCA)_, 1–8. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Torres-Arias, S., Afzali, H., Kuppusamy, T. K., Curtmola, R., & Cappos, J. (2019). In-toto: Providing farm-to-table guarantees for bits and bytes. _Proceedings of the 28th USENIX Conference on Security Symposium_, 1393–1410. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Ohm, M., Plate, H., Sykosch, A., & Meier, M. (2020). Backstabber’s knife collection: A review of open source software supply chain attacks. In _Lecture notes in computer science_ (pp. 23–43). Springer International Publishing. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Navarro Leija, O. S., Shiptoski, K., Scott, R. G., Wang, B., Renner, N., Newton, R. R., & Devietti, J. (2020). Reproducible containers. _Proceedings of the Twenty-Fifth International Conference on Architectural Support for Programming Languages and Operating Systems_, 167–182. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Ohm, M., Sykosch, A., & Meier, M. (2020). Towards detection of software supply chain attacks by forensic artifacts. _Proceedings of the 15th International Conference on Availability, Reliability and Security_. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Lamb, C., & Zacchiroli, S. (2022). Reproducible builds: Increasing the integrity of software supply chains. _IEEE Software_, _39_(2), 62–70. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Shi, Y., Wen, M., Cogo, F. R., Chen, B., & Jiang, Z. M. (2022). An experience report on producing verifiable builds for large-scale commercial systems. _IEEE Transactions on Software Engineering_, _48_(9), 3361–3377. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Ren, Z., Sun, S., Xuan, J., Li, X., Zhou, Z., & Jiang, H. (2022). Automated patching for unreproducible builds. _Proceedings of the 44th International Conference on Software Engineering_, 200–211. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Enck, W., & Williams, L. (2022). Top five challenges in software supply chain security: Observations from 30 industry and government organizations. _IEEE Security & Privacy_, _20_(2), 96–100. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Butler, S., Gamalielsson, J., Lundell, B., Brax, C., Mattsson, A., Gustavsson, T., Feist, J., Kvarnström, B., & Lönroth, E. (2023). On business adoption and use of reproducible builds for open and closed source software. _Software Quality Journal_, _31_(3), 687–719. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Fourne, M., Wermke, D., Enck, W., Fahl, S., & Acar, Y. (2023). It’s like flossing your teeth: On the importance and challenges of reproducible builds for software supply chain security. _2023 IEEE Symposium on Security and Privacy (SP)_, 1527–1544. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Schorlemmer, T. R., Kalu, K. G., Chigges, L., Ko, K. M., Isghair, E. A.-M. A., Baghi, S., Torres-Arias, S., & Davis, J. C. (2024). _Signing in four public software package registries: Quantity, quality, and influencing factors_. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Malka, J., Zacchiroli, S., & Zimmermann, T. (2024). _Reproducibility of build environments through space and time_. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Randrianaina, G. A., Khelladi, D. E., Zendra, O., & Acher, M. (2024). Options Matter: Documenting and Fixing Non-Reproducible Builds in Highly-Configurable Systems. _MSR 2024 - 21th International Conference on Mining Software Repository_, 1–11. " msgstr "" #. type: Bullet: '- ' #: _docs/publications.md msgid "Dellaiera, P. (2024). *Reproducibility in software engineering*. University of Mons. " msgstr "" #. type: Plain text #: _docs/randomness.md msgid "Random data will make builds unreproducible and must be avoided." msgstr "" #. type: Plain text #: _docs/randomness.md msgid "If random-like input is required, the solution is to use a predetermined value to seed a [pseudo-random number generator](https://en.wikipedia.org/wiki/Pseudorandom_number_generator). This value can be read from some file, a changelog or the version control system." msgstr "" #. type: Plain text #: _docs/randomness.md msgid "When Link-Time Optimizations are turned on, GCC users will write random identifiers to binary objects they create. Using `-frandom-seed` can be used for this particular case. As it will hash arbitrary data, passing the file name should work in most cases." msgstr "" #. type: Plain text #: _docs/randomness.md msgid "Some compilation tools will write intermediate temporary files. This might lead to reproducibility issues if paths get embedded in the final output. There's no general solutions for such cases, better fix the code directly. One way is to use the `.file` assembler directive [like it has been done in O'Caml](https://sources.debian.net/src/ocaml/4.02.3-5/debian/patches/0010-Add-a-.file-directive-to-generated-.s-files.patch/)." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/rebuilders.md #, no-wrap msgid "Rebuilders" msgstr "" #. type: Plain text #: _docs/rebuilders.md msgid "This page is trying to document the different tools for rebuilding:" msgstr "" #. type: Title # #: _docs/rebuilders.md #, no-wrap msgid "orchestrators" msgstr "" #. type: Bullet: '- ' #: _docs/rebuilders.md msgid " (Agnostic)" msgstr "" #. type: Bullet: '- ' #: _docs/rebuilders.md msgid "" msgstr "" #. type: Title # #: _docs/rebuilders.md #, no-wrap msgid "rebuilder-backends" msgstr "" #. type: Bullet: '- ' #: _docs/rebuilders.md msgid " (Arch Linux)" msgstr "" #. type: Bullet: '- ' #: _docs/rebuilders.md msgid " (Arch Linux)" msgstr "" #. type: Bullet: '- ' #: _docs/rebuilders.md msgid " (Debian)" msgstr "" #. type: Bullet: '- ' #: _docs/rebuilders.md msgid " (Python rewrite of the above, +more)" msgstr "" #. type: Bullet: '- ' #: _docs/rebuilders.md msgid " (Fedora on Qubes OS)" msgstr "" #. type: Title # #: _docs/rebuilders.md #, no-wrap msgid "clients/frontends" msgstr "" #. type: Bullet: '- ' #: _docs/rebuilders.md msgid " (Agnostic)" msgstr "" #. type: Bullet: '- ' #: _docs/rebuilders.md msgid " (Arch Linux)" msgstr "" #. type: Bullet: '- ' #: _docs/rebuilders.md msgid " (Arch Linux)" msgstr "" #. type: Title # #: _docs/rebuilders.md #, no-wrap msgid "verifiers?" msgstr "" #. type: Plain text #: _docs/rebuilders.md #, no-wrap msgid "" " (I wonder how we can contrast a more thorough attestation verification vs regular client/frontends)\n" "- \n" "- \n" "- \n" msgstr "" #. type: Title # #: _docs/rebuilders.md #, no-wrap msgid "outside the above model" msgstr "" #. type: Plain text #: _docs/rebuilders.md msgid "for OCaml / OPAM we have some infrastructure as well - the builder (capturing everything [installed packages, environment variables, sources used]) is `orb build`, the rebuilder is `orb rebuild` (from ) and have a web frontend () -- live at " msgstr "" #. type: Yaml Front Matter Array Element: redirect_from #: _docs/recording.md #, no-wrap msgid "/docs/buildinfo/" msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/recording.md #, no-wrap msgid "Recording the build environment" msgstr "" #. type: Plain text #: _docs/recording.md msgid "It is been customary in user facing software to provide a way for developers investigating bugs to learn how the software has been built. The “about dialog” or output of `--version` typically contains information about the build environment." msgstr "" #. type: Plain text #: _docs/recording.md msgid "In the context of reproducible builds, we either actively make aspects of the [build environment]({{ \"/docs/perimeter/\" | relative_url }}) irrelevant to the build output, or ensure they are available to rebuild the software exactly as distributed." msgstr "" #. type: Plain text #: _docs/recording.md msgid "All relevant information about the build environment should either be defined as part of the development process or recorded during the build process." msgstr "" #. type: Title ## #: _docs/recording.md #, no-wrap msgid "File Format" msgstr "" #. type: Plain text #: _docs/recording.md msgid "Everything that is recorded is stored best as a separate build product that can be easily ignored or distributed separately. This will help identify which variation is irrelevant to the software itself." msgstr "" #. type: Plain text #: _docs/recording.md msgid "This product is called the 'buildinfo', but its exact format and the way it is distributed differs across ecosystems." msgstr "" #. type: Title ### #: _docs/recording.md #, no-wrap msgid "[Debian](/who/#Debian)" msgstr "" #. type: Plain text #: _docs/recording.md msgid "Debian shares its buildinfo files as plain text files following the [control file format](https://www.debian.org/doc/debian-policy/ch-controlfields.html), usually clearsigned with OpenPGP. A detailed description of the expected fields and values, as well as conventions around naming, can be found under [ReproducibleBuilds/BuildinfoFiles](https://wiki.debian.org/ReproducibleBuilds/BuildinfoFiles) on the [Debian wiki](https://wiki.debian.org). Examples can be found on [buildinfo.debian.net](https://buildinfo.debian.net)." msgstr "" #. type: Title ### #: _docs/recording.md #, no-wrap msgid "[Arch Linux](/who/#Arch Linux)" msgstr "" #. type: Plain text #: _docs/recording.md #, no-wrap msgid "" "The Arch Linux [makepkg](https://wiki.archlinux.org/index.php/makepkg) build\n" "tool produces a `.BUILDINFO` file consisting of ` = ` pairs.\n" msgstr "" #. type: Plain text #: _docs/recording.md msgid "Unlike on Debian, this file is not independently signed and distributed, but included into the package (and thus signed as part of the package signature). An example can be found by downloading any Arch package built with a recent version of [makepkg](https://wiki.archlinux.org/index.php/makepkg), such as [archlinux-keyring]( https://www.archlinux.org/packages/core/any/archlinux-keyring)." msgstr "" #. type: Title ### #: _docs/recording.md #, no-wrap msgid "[Tails](/who/#Tails)" msgstr "" #. type: Plain text #: _docs/recording.md msgid "Tails does not record a buildinfo file per se, but instead the [vagrant directory of the main git repo]( https://gitlab.com/Tails/tails/tree/master/vagrant) contains all information necessary to reproducibly rebuild that revision of Tails." msgstr "" #. type: Plain text #: _docs/recording.md msgid "In the JVM ecosystem it is common to distribute libraries as binary (bytecode) jars uploaded to a repository like [Maven Central](https://search.maven.org/) or [Google's Android Repository](https://dl.google.com/dl/android/maven2/index.html)." msgstr "" #. type: Plain text #: _docs/recording.md msgid "It is recommended that the buildinfo describing the build environment used for that official build is published alongside each artifact. Third party attestations can be shared in a separate sig-repo. For a detailed overview of the conventions so far see the separate [JVM page]({{ \"/docs/jvm/\" | relative_url }})." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/sharing_certifications.md #, no-wrap msgid "Sharing certifications" msgstr "" #. type: Plain text #: _docs/sharing_certifications.md msgid "How could users gain trust that a build has not been compromised by exchanging certifications attesting that they all have been able to get the same build results?" msgstr "" #. type: Plain text #: _docs/sharing_certifications.md msgid "Debian is thinking of allowing [multiple Debian Developers to upload signatures](https://wiki.debian.org/ReproducibleBuilds/BuildinfoSpecification#buildinfo_signatures) attesting that they have been able to reproduce a build." msgstr "" #. type: Plain text #: _docs/sharing_certifications.md msgid "The question is also related to the work lead by Ben Laurie on [binary transparency](https://groups.google.com/forum/#!forum/binary-transparency). The idea is to have an append-only log similar to [Certificate Transparency](https://www.certificate-transparency.org/) which could be used to authenticate binaries." msgstr "" #. type: Plain text #: _docs/sharing_certifications.md msgid "More research is required in this area to make reproducible builds more effective in detecting compromise early." msgstr "" #. type: Yaml Front Matter Hash Value: title #: _docs/source-date-epoch.md #, no-wrap msgid "SOURCE_DATE_EPOCH" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "`SOURCE_DATE_EPOCH` is a [standardised environment variable](https://reproducible-builds.org/specs/source-date-epoch/) that distributions can set centrally and have build tools consume this in order to produce reproducible output. In practice, `SOURCE_DATE_EPOCH` specifies the last modification of something, usually the source code, measured in the number seconds since the Unix epoch, ie. `January 1st 1970, 00:00:00 UTC`." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Before added support to a tool for reading this variable, you should scan through [Debian's checklist](https://wiki.debian.org/ReproducibleBuilds/StandardEnvironmentVariables#Checklist) to see if you can avoid implementing it: a number of tools already will do this for you. However, if you find that it's ideal for your use-case, please feel free to jump straight to our **[published specification](https://reproducible-builds.org/specs/source-date-epoch/)**." msgstr "" #. type: Title ## #: _docs/source-date-epoch.md #, no-wrap msgid "Reading the variable" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Python >= 3.x" msgstr "" #. type: Fenced code block (python) #: _docs/source-date-epoch.md #, no-wrap msgid "" "import os\n" "import time\n" "import datetime\n" "\n" "build_date = datetime.datetime.fromtimestamp(\n" " int(os.environ.get('SOURCE_DATE_EPOCH', time.time())),\n" " tz=datetime.timezone.utc,\n" ")\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "… or with fewer imports and rendering to a string:" msgstr "" #. type: Fenced code block (python) #: _docs/source-date-epoch.md #, no-wrap msgid "" "import os\n" "import time\n" "\n" "date_str = time.strftime(\n" " \"%Y-%m-%d\",\n" " time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))\n" ")\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Python >= 2.x" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "If you still require Python 2.x support, you will need to use the non-recommended [`datetime.utcfromtimestamp`](https://docs.python.org/3.8/library/datetime.html#datetime.datetime.utcfromtimestamp) method ([more info](https://blog.ganssle.io/articles/2019/11/utcnow.html)):" msgstr "" #. type: Fenced code block (python) #: _docs/source-date-epoch.md #, no-wrap msgid "" "import os\n" "import time\n" "import datetime\n" "\n" "build_date = datetime.datetime.utcfromtimestamp(\n" " int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))\n" ")\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Bash / POSIX shell" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "For GNU systems:" msgstr "" #. type: Fenced code block (bash) #: _docs/source-date-epoch.md #, no-wrap msgid "BUILD_DATE=\"$(date --utc --date=\"@${SOURCE_DATE_EPOCH:-$(date +%s)}\" +%Y-%m-%d)\"\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "If you need to support BSD date as well you should fallback to trying ther `-r seconds` timestamp variant:" msgstr "" #. type: Fenced code block (bash) #: _docs/source-date-epoch.md #, no-wrap msgid "" "DATE_FMT=\"+%Y-%m-%d\"\n" "SOURCE_DATE_EPOCH=\"${SOURCE_DATE_EPOCH:-$(date +%s)}\"\n" "BUILD_DATE=$(date -u -d \"@$SOURCE_DATE_EPOCH\" \"$DATE_FMT\" 2>/dev/null || date -u -r \"$SOURCE_DATE_EPOCH\" \"$DATE_FMT\" 2>/dev/null || date -u \"$DATE_FMT\")\n" msgstr "" #. type: Title - #: _docs/source-date-epoch.md _docs/stable_outputs.md #, no-wrap msgid "Perl" msgstr "" #. type: Fenced code block (perl) #: _docs/source-date-epoch.md #, no-wrap msgid "" "use POSIX qw(strftime);\n" "my $date = strftime(\"%Y-%m-%d\", gmtime($ENV{SOURCE_DATE_EPOCH} || time));\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Makefile" msgstr "" #. type: Fenced code block (make) #: _docs/source-date-epoch.md #, no-wrap msgid "" "DATE_FMT = +%Y-%m-%d\n" "ifdef SOURCE_DATE_EPOCH\n" " BUILD_DATE ?= $(shell date -u -d \"@$(SOURCE_DATE_EPOCH)\" \"$(DATE_FMT)\" 2>/dev/null || date -u -r \"$(SOURCE_DATE_EPOCH)\" \"$(DATE_FMT)\" 2>/dev/null || date -u \"$(DATE_FMT)\")\n" "else\n" " BUILD_DATE ?= $(shell date \"$(DATE_FMT)\")\n" "endif\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "The above will work with either GNU or BSD date, and fallback to ignore `SOURCE_DATE_EPOCH` if both fails." msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "CMake" msgstr "" #. type: Fenced code block (cmake) #: _docs/source-date-epoch.md #, no-wrap msgid "STRING(TIMESTAMP BUILD_DATE \"%Y-%m-%d\" UTC)\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "... will compile with CMake versions 2.8.11 and higher ([released May 2013](https://cmake.org/pipermail/cmake/2013-May/054792.html)), but it only respects `SOURCE_DATE_EPOCH` since version 3.8.0 ([April 2017](https://cmake.org/pipermail/cmake-developers/2017-April/029946.html)). Note that the final argument `UTC` is required or the timestamp may vary between timezones." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "If you would like to support legacy/archival versions of CMake, you can use this less-preferred variant:" msgstr "" #. type: Fenced code block (cmake) #: _docs/source-date-epoch.md #, no-wrap msgid "" "if (DEFINED ENV{SOURCE_DATE_EPOCH})\n" " execute_process(\n" " COMMAND \"date\" \"-u\" \"-d\" \"@$ENV{SOURCE_DATE_EPOCH}\" \"+%Y-%m-%d\"\n" " OUTPUT_VARIABLE BUILD_DATE\n" " OUTPUT_STRIP_TRAILING_WHITESPACE)\n" "else ()\n" " execute_process(\n" " COMMAND \"date\" \"+%Y-%m-%d\"\n" " OUTPUT_VARIABLE BUILD_DATE\n" " OUTPUT_STRIP_TRAILING_WHITESPACE)\n" "endif ()\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Note that the above will work only with GNU `date`; see the POSIX shell example on how to support BSD date." msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Meson" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "By deliberate design, [Meson does not provide access to environment variables in build files](https://github.com/mesonbuild/meson/issues/9#issuecomment-543780613) which makes accessing `SOURCE_DATE_EPOCH` troublesome." msgstr "" #. type: Fenced code block (meson) #: _docs/source-date-epoch.md #, no-wrap msgid "" "date_exe = find_program('date')\n" "cmd = run_command('sh', '-c', 'echo $SOURCE_DATE_EPOCH')\n" "source_date_epoch = cmd.stdout().strip()\n" "if source_date_epoch == ''\n" "\tsource_date_epoch = run_command(date_exe, '+%s').stdout().strip()\n" "endif\n" "\n" "formatted_date = run_command(date_exe, '-u', '-d', '@' + source_date_epoch, '+%Y-%m-%d').stdout().strip()\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "The above will work only with GNU `date`. See the POSIX shell example on how to support BSD date variants." msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Dockerfile" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "The `SOURCE_DATE_EPOCH` argument value is automaticallly propagated from the `SOURCE_DATE_EPOCH` environment value of the client host, since Docker Buildx v0.10." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "The `SOURCE_DATE_EPOCH` argument value can be captured as an environment value for `RUN` instructions, by putting an `ARG` instruction between `FROM` and `RUN`:" msgstr "" #. type: Fenced code block (dockerfile) #: _docs/source-date-epoch.md #, no-wrap msgid "" "FROM [...]\n" "ARG SOURCE_DATE_EPOCH\n" "RUN [...]\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Capturing the `SOURCE_DATE_EPOCH` argument value is optional. Alternatively, the `SOURCE_DATE_EPOCH` environment value can be declared inside a `RUN` instruction too." msgstr "" #. type: Fenced code block (dockerfile) #: _docs/source-date-epoch.md #, no-wrap msgid "" "FROM [...]\n" "ADD src /src\n" "RUN [...]\n" " SOURCE_DATE_EPOCH=\"$(find /src -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)\"; \\\n" " export SOURCE_DATE_EPOCH; \\\n" "# for logging validation/edification\n" " date --date \"@$SOURCE_DATE_EPOCH\" --rfc-2822; \\\n" " [...]\n" msgstr "" #. type: Title #### #: _docs/source-date-epoch.md #, no-wrap msgid "Scope" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Regardless to whether the `SOURCE_DATE_EPOCH` argument value is captured into Dockerfile with `ARG SOURCE_DATE_EPOCH`, the argument value is also used for: - the `created` timestamp in the [OCI Image Config](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) - the `created` timestamp in the `history` objects in the [OCI Image Config](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) - the `org.opencontainers.image.created` annotation in the [OCI Image Index](https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys) - the timestamp of the files exported with the `local` exporter - the timestamp of the files exported with the `tar` exporter" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "To apply the `SOURCE_DATE_EPOCH` argument value to the timestamps of the files inside the image, specify `rewrite-timestamp=true` as an image exporter option:" msgstr "" #. type: Fenced code block (bash) #: _docs/source-date-epoch.md #, no-wrap msgid "" "docker buildx create --use --name buildkit\n" "docker buildx build --output type=image,name=docker.io/username/image,push=true,rewrite-timestamp=true .\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "The `rewrite-timestamp` option is not set to `true` by default due to the overhead of rewriting image layers." msgstr "" #. type: Title #### #: _docs/source-date-epoch.md #, no-wrap msgid "apt-get" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "`RUN apt-get` does not automatically consume `SOURCE_DATE_EPOCH` to install packages from the past snapshot." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md #, no-wrap msgid "" " can be used for reconfiguring `/etc/apt/sources.list`\n" "to use `https://snapshot.debian.org/archive/debian//`.\n" msgstr "" #. type: Title #### #: _docs/source-date-epoch.md #, no-wrap msgid "Further information" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "See: - https://github.com/moby/buildkit/blob/master/docs/build-repro.md - https://github.com/docker-library/official-images/issues/16044" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "C" msgstr "" #. type: Fenced code block (c) #: _docs/source-date-epoch.md #, no-wrap msgid "" "#include \n" "#include \n" "#include \n" "\n" "struct tm *build_time;\n" "time_t now;\n" "char *source_date_epoch;\n" "unsigned long long epoch;\n" "char *endptr;\n" "\n" "source_date_epoch = getenv(\"SOURCE_DATE_EPOCH\");\n" "if (source_date_epoch) {\n" "\terrno = 0;\n" "\tepoch = strtoull(source_date_epoch, &endptr, 10);\n" "\tif ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))\n" "\t\t\t|| (errno != 0 && epoch == 0)) {\n" "\t\tfprintf(stderr, \"Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\\n\", strerror(errno));\n" "\t\texit(EXIT_FAILURE);\n" "\t}\n" "\tif (endptr == source_date_epoch) {\n" "\t\tfprintf(stderr, \"Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\\n\", endptr);\n" "\t\texit(EXIT_FAILURE);\n" "\t}\n" "\tif (*endptr != '\\0') {\n" "\t\tfprintf(stderr, \"Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\\n\", endptr);\n" "\t\texit(EXIT_FAILURE);\n" "\t}\n" "\tif (epoch > ULONG_MAX) {\n" "\t\tfprintf(stderr, \"Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to %lu but was found to be: %llu \\n\", ULONG_MAX, epoch);\n" "\t\texit(EXIT_FAILURE);\n" "\t}\n" "\tnow = epoch;\n" "} else {\n" "\tnow = time(NULL);\n" "}\n" "build_time = gmtime(&now);\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "If you want less verbose code and are happy with the assumptions stated below, you can use" msgstr "" #. type: Fenced code block (c) #: _docs/source-date-epoch.md #, no-wrap msgid "" "#include \n" "\n" "time_t now;\n" "char *source_date_epoch;\n" "/* This assumes that the SOURCE_DATE_EPOCH environment variable will contain\n" " a correct, positive integer in the time_t range */\n" "if ((source_date_epoch = getenv(\"SOURCE_DATE_EPOCH\")) == NULL ||\n" " (now = (time_t)strtoll(source_date_epoch, NULL, 10)) <= 0)\n" " time(&now);\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "C++" msgstr "" #. type: Fenced code block (cpp) #: _docs/source-date-epoch.md #, no-wrap msgid "" "#include \n" "#include \n" "#include \n" "#include \n" "\n" " time_t now;\n" " char *source_date_epoch = std::getenv(\"SOURCE_DATE_EPOCH\");\n" " if (source_date_epoch) {\n" " std::istringstream iss(source_date_epoch);\n" " iss >> now;\n" " if (iss.fail() || !iss.eof()) {\n" " std::cerr << \"Error: Cannot parse SOURCE_DATE_EPOCH as integer\\n\";\n" " exit(27);\n" " }\n" " } else {\n" " now = std::time(NULL);\n" " }\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Go" msgstr "" #. type: Fenced code block (go) #: _docs/source-date-epoch.md #, no-wrap msgid "" "import (\n" " \"fmt\"\n" " \"os\"\n" " \"strconv\"\n" " \"time\"\n" ")\n" "\n" "[...]\n" "\n" "source_date_epoch := os.Getenv(\"SOURCE_DATE_EPOCH\")\n" "var build_date string\n" "if source_date_epoch == \"\" {\n" " build_date = time.Now().UTC().Format(http.TimeFormat)\n" "} else {\n" " sde, err := strconv.ParseInt(source_date_epoch, 10, 64)\n" " if err != nil {\n" " panic(fmt.Sprintf(\"Invalid SOURCE_DATE_EPOCH: %s\", err))\n" " }\n" " build_date = time.Unix(sde, 0).UTC().Format(http.TimeFormat)\n" "}\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "PHP" msgstr "" #. type: Fenced code block (php) #: _docs/source-date-epoch.md #, no-wrap msgid "\\date('Y', (int)\\getenv('SOURCE_DATE_EPOCH') ?: \\time())\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Emacs-Lisp" msgstr "" #. type: Fenced code block (elisp) #: _docs/source-date-epoch.md #, no-wrap msgid "" "(current-time-string\n" " (when (getenv \"SOURCE_DATE_EPOCH\")\n" " (seconds-to-time\n" " (string-to-number\n" " (getenv \"SOURCE_DATE_EPOCH\"))))))\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "OCaml" msgstr "" #. type: Fenced code block (ocaml) #: _docs/source-date-epoch.md #, no-wrap msgid "" "let build_date =\n" " try\n" " float_of_string (Sys.getenv \"SOURCE_DATE_EPOCH\")\n" " with\n" " Not_found -> Unix.time ()\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Java / gradle" msgstr "" #. type: Fenced code block (groovy) #: _docs/source-date-epoch.md #, no-wrap msgid "" "def buildDate = System.getenv(\"SOURCE_DATE_EPOCH\") == null ?\n" " new java.util.Date() :\n" " new java.util.Date(1000 * Long.parseLong(System.getenv(\"SOURCE_DATE_EPOCH\")))\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Javascript / node.js" msgstr "" #. type: Fenced code block (javascript) #: _docs/source-date-epoch.md #, no-wrap msgid "" "var timestamp = new Date(process.env.SOURCE_DATE_EPOCH ? (process.env.SOURCE_DATE_EPOCH * 1000) : new Date().getTime());\n" "\n" "// Alternatively, to ensure a fixed timezone:\n" "\n" "var now = new Date();\n" "if (process.env.SOURCE_DATE_EPOCH) {\n" " now = new Date((process.env.SOURCE_DATE_EPOCH * 1000) + (now.getTimezoneOffset() * 60000));\n" "}\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Coffeescript" msgstr "" #. type: Fenced code block (coffeescript) #: _docs/source-date-epoch.md #, no-wrap msgid "" "now = new Date()\n" "if process.env.SOURCE_DATE_EPOCH\n" " now = new Date((process.env.SOURCE_DATE_EPOCH * 1000) + (now.getTimezoneOffset() * 60000))\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Ruby" msgstr "" #. type: Fenced code block (ruby) #: _docs/source-date-epoch.md #, no-wrap msgid "" "if ENV['SOURCE_DATE_EPOCH'].nil?\n" " now = Time.now\n" "else\n" " now = Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).gmtime\n" "end\n" "\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Note that Ruby's Datetime.strftime is locale-independent by default." msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Scala" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "To get milliseconds since Epoch:" msgstr "" #. type: Fenced code block (scala) #: _docs/source-date-epoch.md #, no-wrap msgid "sys.env.get(\"SOURCE_DATE_EPOCH\").map(_.toLong * 1000)\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "To get a `java.util.Date`:" msgstr "" #. type: Fenced code block (scala) #: _docs/source-date-epoch.md #, no-wrap msgid "" "sys.env.get(\"SOURCE_DATE_EPOCH\")\n" " .map(sde => new java.util.Date(sde.toLong * 1000))\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Rust" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Using the `chrono` crate:" msgstr "" #. type: Fenced code block (rust) #: _docs/source-date-epoch.md #, no-wrap msgid "" "use chrono::{TimeZone, Utc};\n" "use std::env;\n" "\n" "let now = match env::var(\"SOURCE_DATE_EPOCH\") {\n" " Ok(val) => { Utc.timestamp_opt(val.parse::().unwrap(), 0).unwrap() }\n" " Err(_) => Utc::now(),\n" "};\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "or" msgstr "" #. type: Fenced code block (rust) #: _docs/source-date-epoch.md #, no-wrap msgid "" "use chrono::{DateTime, NaiveDateTime, Utc};\n" "use std::env;\n" "\n" "let now = match env::var(\"SOURCE_DATE_EPOCH\") {\n" " Ok(val) => {\n" " let naive = NaiveDateTime::from_timestamp(val.parse::().unwrap(), 0);\n" " let datetime: DateTime = DateTime::from_utc(naive, Utc);\n" " datetime\n" " }\n" " Err(_) => Utc::now(),\n" "};\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Add the following property in the `pom.xml` file:" msgstr "" #. type: Fenced code block (xml) #: _docs/source-date-epoch.md #, no-wrap msgid "" "\n" " \n" " ${env.SOURCE_DATE_EPOCH}\n" " \n" "\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Set the following properties for the Zip Task that creates the `.jar` file:" msgstr "" #. type: Fenced code block (groovy) #: _docs/source-date-epoch.md #, no-wrap msgid "" "// Normalizes the ZIP and JAR archives\n" "tasks.withType(Zip) {\n" " preserveFileTimestamps = false\n" " reproducibleFileOrder = true\n" "}\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "JDK" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Builds of OpenJDK version 19 or later [support the following new option](https://bugs.openjdk.org/browse/JDK-8276766) in the `jar` and `jmod` commands:" msgstr "" #. type: Fenced code block #: _docs/source-date-epoch.md #, no-wrap msgid "" "--date=TIMESTAMP\n" " The timestamp in ISO-8601 extended offset date-time with optional\n" " time-zone format, to use for the timestamp of the entries,\n" " e.g. \"2022-02-12T12:30:00-05:00\".\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Groovy" msgstr "" #. type: Fenced code block (groovy) #: _docs/source-date-epoch.md #, no-wrap msgid "" "import java.time.Instant\n" "import java.time.temporal.ChronoUnit\n" "\n" "def buildInstant = Instant.now().truncatedTo(ChronoUnit.SECONDS)\n" "def sourceDateEpoch = System.getenv(\"SOURCE_DATE_EPOCH\")\n" "if (sourceDateEpoch != null) {\n" " def epochSeconds = Long.parseLong(sourceDateEpoch)\n" " buildInstant = Instant.ofEpochSecond(epochSeconds)\n" "}\n" "// Creates the timestamp in UTC using the ISO 8601 extended format.\n" "def extendedTimestamp = buildInstant.toString()\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Last-resort using faketime" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "''As a last resort to be avoided where possible'' (e.g. if the upstream tool is too hard to patch, or too time-consuming for you right now to patch, or if they are being uncooperative or unresponsive), package maintainers may try something like the following:" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "`debian/strip-nondeterminism/a2x`:" msgstr "" #. type: Fenced code block (sh) #: _docs/source-date-epoch.md #, no-wrap msgid "" "#!/bin/sh\n" "# Depends: faketime\n" "# Eventually the upstream tool should support SOURCE_DATE_EPOCH internally.\n" "test -n \"$SOURCE_DATE_EPOCH\" || { echo >&2 \"$0: SOURCE_DATE_EPOCH not set\"; exit 255; }\n" "exec env NO_FAKE_STAT=1 faketime -f \"$(TZ=UTC date -d \"@$SOURCE_DATE_EPOCH\" +'%Y-%m-%d %H:%M:%S')\" /usr/bin/a2x \"$@\"\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "`debian/rules`:" msgstr "" #. type: Fenced code block (make) #: _docs/source-date-epoch.md #, no-wrap msgid "export PATH := $(CURDIR)/debian/strip-nondeterminism:$(PATH)\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "`debian/control`:" msgstr "" #. type: Fenced code block #: _docs/source-date-epoch.md #, no-wrap msgid "Build-Depends: faketime\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "But please be aware that this does not work out of the box with pbuilder on Debian 7 Wheezy, see [#778462](https://bugs.debian.org/778462) against faketime and [#700591](https://bugs.debian.org/700591) against pbuilder (fixed in Jessie, but not Wheezy). Adding an according hook to `/etc/pbuilder/hook.d` which mounts `/run/shm` inside the chroot should suffice as local workaround, though." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "TODO: document some other nicer options. Generally, all invocations of `date(1)` need to have a fixed `TZ` environment set." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "NOTE: faketime BREAKS builds on some archs, for example hurd. See #778462 for details." msgstr "" #. type: Title ## #: _docs/source-date-epoch.md #, no-wrap msgid "Setting the variable" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Debian" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "In Debian, this is automatically set to the same time as the latest entry in `debian/changelog`, i.e. the same as the output of `dpkg-parsechangelog -SDate`." msgstr "" #. type: Bullet: '1. ' #: _docs/source-date-epoch.md msgid "For packages using `debhelper` versions >= 9.20151004, [this variable is automatically exported during builds](https://bugs.debian.org/791823), so you probably don't need to change anything. One exception is if your `debian/rules` needs this variable in non-debhelper parts, in which case you can try (3) or (4)." msgstr "" #. type: Bullet: '2. ' #: _docs/source-date-epoch.md msgid "For packages using CDBS, versions >= 0.4.131 [this variable is also exported automatically during builds](https://bugs.debian.org/794241), so no changes are needed." msgstr "" #. type: Bullet: '3. ' #: _docs/source-date-epoch.md msgid "With `dpkg` >= 1.18.8 you can either `include /usr/share/dpkg/pkg-info.mk` or `include /usr/share/dpkg/default.mk`. This was added in Debian bug [#824572](https://bugs.debian.org/824572)." msgstr "" #. type: Bullet: '4. ' #: _docs/source-date-epoch.md msgid "If none of the above options are good (you should have a ''very good reason'') then package maintainers may set and export this variable manually in `debian/rules`:" msgstr "" #. type: Fenced code block (make) #: _docs/source-date-epoch.md #, no-wrap msgid "export SOURCE_DATE_EPOCH ?= $(shell dpkg-parsechangelog -STimestamp)\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "If you need/want to support dpkg versions earlier than 1.18.8:" msgstr "" #. type: Fenced code block (make) #: _docs/source-date-epoch.md #, no-wrap msgid "export SOURCE_DATE_EPOCH ?= $(shell dpkg-parsechangelog -SDate | date -f- +%s)\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "If you need/want to support dpkg versions earlier than 1.17.0:" msgstr "" #. type: Fenced code block (make) #: _docs/source-date-epoch.md #, no-wrap msgid "export SOURCE_DATE_EPOCH ?= $(shell dpkg-parsechangelog | grep -Po '^Date: \\K.*' | date -f- +%s)\n" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "This snippet is believed to work on dpkg versions as far back as 2003." msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Git" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "To set `SOURCE_DATE_EPOCH` to the last modification of a Git repository you can use `git log`. For example:" msgstr "" #. type: Fenced code block (make) #: _docs/source-date-epoch.md #, no-wrap msgid "export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)\n" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "Tool support" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "We are persuading upstream tools to support `SOURCE_DATE_EPOCH` directly. You may help by writing patches for these tools; please add links to the bug reports here so we know, and to act as an example resource for future patch writers." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Complete:" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[busybox](http://lists.busybox.net/pipermail/busybox/2021-June/088880.html) (`>` 1.33.1)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[clang](https://github.com/llvm/llvm-project/commit/2c090162746a6b901c5639562c090e4bb2b7327e) (`>=` 16.0.0)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[cmake](https://gitlab.kitware.com/cmake/cmake/merge_requests/432) (`>=` 3.8.0)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[debhelper](https://bugs.debian.org/791823) (`>=` 9.20151004)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[distro-info](https://bugs.debian.org/1034422) (`>=` 1.6)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[docbook-utils](https://bugs.debian.org/800797) (Debian `>=` 0.6.14-3.1, upstream TODO)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[doxygen](https://bugs.debian.org/792201) (`>=` [1.8.12](https://github.com/doxygen/doxygen/commit/9a2c7bbfb0c53b4532db7280e6804c7ce76d70a3), Debian pending)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[epydoc](https://bugs.debian.org/790899) (`>=` 3.0.1+dfsg-8, upstream [pending](https://sourceforge.net/p/epydoc/bugs/368/))" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[gcc](https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=e3e8c48c4a494d9da741c1c8ea6c4c0b7c4ff934) (`>=` 7, Debian `>=` 5.3.1-17, Debian `>=` 6.1.1-1)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[gettext](https://bugs.debian.org/792687) (`>=` 0.20)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[ghostscript](https://bugs.debian.org/794004) (Debian `>=` 9.16~dfsg-1, upstream [unfortunately rejected](http://bugs.ghostscript.com/show_bug.cgi?id=696765) due to additional constraints they have)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[groff](https://bugs.debian.org/762854) (Debian `>=` 1.22.3-2, upstream [pending](https://lists.gnu.org/archive/html/groff/2015-11/msg00038.html))" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[help2man](https://bugs.debian.org/787444) (`>=` 1.47.1)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[libxslt](https://bugs.debian.org/791815) (`>=` [1.1.29](https://bugzilla.gnome.org/show_bug.cgi?id=758148), Debian `>=` 1.1.28-3)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[man2html](https://bugs.debian.org/796130) (Debian `>=` 1.6g-8, [needs forwarding](https://sources.debian.net/src/man2html/1.6g-8/debian/patches/035-source-date-epoch.patch/))" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[mkdocs](https://bugs.debian.org/824266) (`>=` [0.16](https://github.com/mkdocs/mkdocs/pull/939/commits/8b006bd7fda55e47e29412896c511c7244398f82), Debian pending)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[ocamldoc](https://bugs.debian.org/794586) (`>=` [4.03.0](https://github.com/ocaml/ocaml/commit/0319173b7d02008e4ce6b81dceaf7c32cf5f8a6f), Debian `>=` 4.02.3-1)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[pydoctor](https://bugs.debian.org/807166) (`>=` 0.5+git20151204)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[rcc](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=894476) (Qt5 `>=` [5.13.0](https://code.qt.io/cgit/qt/qtbase.git/commit/?id=1ffcca4cc208c48ddb06b6a23abf1756f9724351), Debian TODO)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[rpm upstream](https://github.com/rpm-software-management/rpm/pull/144) (`>` 4.13 other relevant patches linked in there)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[sphinx](https://github.com/sphinx-doc/sphinx/pull/1954) (`>=` 1.4, Debian `>=` 1.3.1-3)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[texi2html](https://bugs.debian.org/783475) (Debian `>=` 1.82+dfsg1-4, [needs forwarding](https://sources.debian.net/src/texi2html/1.82%2Bdfsg1-5/debian/patches/05_reproducible-build/))" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[texlive-bin](https://bugs.debian.org/792202) (`>=` 2016.20160512.41045)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[txt2man](https://bugs.debian.org/790801) (`>=` [1.5.7](https://github.com/mvertes/txt2man/pull/1), Debian `>=` 1.5.6-4)" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "[docker buildx](https://github.com/docker/buildx/pull/1489) (`>=` 0.10)" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Or you can [search in all Debian sources](https://codesearch.debian.net/search?perpkg=1&q=SOURCE_DATE_EPOCH)." msgstr "" #. type: Title ## #: _docs/source-date-epoch.md #, no-wrap msgid "More detailed discussion" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Sometimes developers of build tools do not want to support `SOURCE_DATE_EPOCH`, or they will tweak the suggestion to something related but different. We really do think the best approach is to use `SOURCE_DATE_EPOCH` exactly as-is described above in our proposal, without any variation. Here we explain our reasoning versus the arguments we have encountered." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "(See *Standard Environment Variables* for general arguments.)" msgstr "" #. type: Title ### #: _docs/source-date-epoch.md #, no-wrap msgid "\"Lying about the time\" / \"violates language spec\"" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "This argument arises when the tool processes some input which contains a static instruction to the effect of \"get_current_time()\". The input has a specification that defines what this means. The tool executes this instruction, then embeds the result in the output. It is argued that `SOURCE_DATE_EPOCH` would break these semantics and violate the specification." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "In most cases, this argument places too much weight on the absoluteness of time. Regardless of what any specification says, the user can set their own system clock and achieve an effect similar to `SOURCE_DATE_EPOCH`. Note: Setting the system clock is not enough for ''reliable'' reproducible builds - we need `SOURCE_DATE_EPOCH` for long-running build processes that take varying amounts of time. If the tool was run near the end of the process, then merely setting the system clock would not make timestamps here reproducible. It is not up to the tool to judge whether the user is lying with their system clock, and likewise, it is not up to the tool to judge whether `SOURCE_DATE_EPOCH` is a \"lie\" or not." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "For all intents and purposes, if the user has set `SOURCE_DATE_EPOCH` then they are taking a position that \"this **is** the current time; please use this instead of whatever clock you normally use\". Yes, the project developer wrote \"get_current_time()\" but I as the user, by setting `SOURCE_DATE_EPOCH`, am choosing to override this with my own idea of what time it is. Please execute the build as if the current time was `SOURCE_DATE_EPOCH`. FOSS software should generally prefer to respect end-users' wishes rather than developers' wishes. (And in practise, we haven't seen ''any'' instance where a project developer really really prefers \"time of build\" over \"modtime of source\".)" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "In conclusion, the tool may choose to ignore `SOURCE_DATE_EPOCH` for other reasons, but to judge that this is a ''lie'' is to disrespect the user's wishes. Furthermore, choosing to support this is unlikely to ''actually'' violate any specifications, since they generally don't define \"current\". This does not take into account, if the specification needs to interoperate consistently with other programs in a strong cryptographic ledger protocol where time values ''must'' be consistent across multiple entities. However this scenario is unlikely to apply, in the context of build tools where `SOURCE_DATE_EPOCH` would be set.)" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Many tools allow the user to override the \"current\" date - e.g. `-D__TIME__=xxx`, `\\\\year=yyy`, etc. In these cases, it makes even less sense to ignore `SOURCE_DATE_EPOCH` for data integrity reasons - you ''already'' have a mechanism where the user can \"lie\" or \"break the spec\"; `SOURCE_DATE_EPOCH` would just be adding an extra mechanism that makes it easier to do this globally across all tools." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "If for some reason you're still conflicted on suddenly changing the meaning of your \"now()\" function and desire another switch other than `SOURCE_DATE_EPOCH` being set or not, the `texlive` project came up with the variable `FORCE_SOURCE_DATE`; when that environment variable is set to `1` cases that wouldn't normally obey `SOURCE_DATE_EPOCH` will do. We **strongly discourage** the usage of such variable; `SOURCE_DATE_EPOCH` is meant to be already a flag forcing a particular timestamp to be used." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "OTOH, one alternative we can agree with, that also avoids `SOURCE_DATE_EPOCH`, would be to translate the static instruction \"get_current_time()\" from the input format to ''an equivalent instruction'' in the output format, if the output format supports that." msgstr "" #. type: Title ## #: _docs/source-date-epoch.md #, no-wrap msgid "Interaction of `SOURCE_DATE_EPOCH` with automatic rebuilds" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "When build dependencies change, it is sometimes necessary to rebuild a package without otherwise changing the source. This is especially the case when a security bug is embedded from the build dependency into the build output, as a rebuild is required to fix the security issue. There are, however, many are other situations. Whilst rebuilds of this kind are a manual process in many distributions, some do this automatically." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Debian only performs these rebuilds via a manual developer request called Binary Non-Maintainer Upload (binNMU). For this, `SOURCE_DATE_EPOCH` is incremented by 1 to avoid creating a situation where two build results contain files with the same name and the same modification timestamp but a different content. Not increasing the date breaks `rsync` without the `--checksum` option or indeed any transfer/sync/backup process that relies on the `mtime` of files to change to detect underlying content changes. While it is not generally safe to rely on modification times (and thus also not to backup systems without `--checksum`), we should not unnecessarily break things." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "OpenSUSE performs such rebuilds automatically and also uses something called \"build tree pruning\". Build tree pruning is to discard the output when it is the same and thus not trigger such rebuilds on packages that build depend on the discarded output. Normally this works, but if a build e.g. embeds `SOURCE_DATE_EPOCH` in its output, then the output changes every time such a rebuild happens, which can be very often. This is to be avoided as updating packages without necessity is too expensive. (The correct solution would, of course, be to never embed `SOURCE_DATE_EPOCH` as so far, no use-case was found were something else is not better, like instead embed a major version number. However convincing everyone and changing every instance of this is an impractical task.)" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "The following achieves both detecting rebuilds that did not change, despite a changed build dependency and having an incremented `mtime` on files in the output:" msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "Use the old `SOURCE_DATE_EPOCH` that was not incremented for the inner build script." msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "Use the incremented `SOURCE_DATE_EPOCH` for the outer build script which uses it to set the file date after the inner build script is done." msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "Instead of clamping the file date to `SOURCE_DATE_EPOCH`, set it exactly. This avoids bugs where one of the inner build scripts sets the file date to something earlier, causing two builds to output a file with same date and name, but different content." msgstr "" #. type: Bullet: '* ' #: _docs/source-date-epoch.md msgid "Ignore the file date when comparing build output to decide whether to discard for build tree pruning." msgstr "" #. type: Title ## #: _docs/source-date-epoch.md #, no-wrap msgid "History and alternative proposals" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "[1](https://lists.alioth.debian.org/pipermail/reproducible-builds/Week-of-Mon-20150608/001823.html) and the surrounding messages describe the initial motivation behind this, including an evaluation of how different programming languages handle date formats." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "We do not have a proposal that includes anything resembling a \"time zone\". Developing such a standard requires consideration of various issues:" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Intuitive and naive ways of handling human-readable dates, such as the POSIX date functions, are highly flawed and freely mix implicit not-well-defined calendars with absolute time. For example, they don't specify they mean the Gregorian calendar, and/or don't specify what to do with dates before when the Gregorian calendar was introduced, or use named time zones that require an up-to-date timezone database (e.g. with historical DST definitions) to parse properly." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "Since this is meant to be a universal standard that all tools and distributions can support, we need to keep things simple and precise, so that different groups of people cannot accidentally interpret it in different ways. So it is probably unwise to try to standardise anything that resembles a named time zone, since that is very very complex." msgstr "" #. type: Plain text #: _docs/source-date-epoch.md msgid "One likely candidate would be something similar to the git internal timestamp format, see `man git-commit`:" msgstr "" #. type: Plain text #: _docs/source-date-epoch.md #, no-wrap msgid " It is