| .. SPDX-License-Identifier: CC-BY-SA-2.0-UK | 
|   | 
| ******************* | 
| Reproducible Builds | 
| ******************* | 
|   | 
| ================ | 
| How we define it | 
| ================ | 
|   | 
| The Yocto Project defines reproducibility as where a given input build | 
| configuration will give the same binary output regardless of when it is built | 
| (now or in 5 years time), regardless of the path on the filesystem the build is | 
| run in, and regardless of the distro and tools on the underlying host system the | 
| build is running on. | 
|   | 
| ============== | 
| Why it matters | 
| ============== | 
|   | 
| The project aligns with the `Reproducible Builds project | 
| <https://reproducible-builds.org/>`_, which shares information about why | 
| reproducibility matters. The primary focus of the project is the ability to | 
| detect security issues being introduced. However, from a Yocto Project | 
| perspective, it is also hugely important that our builds are deterministic. When | 
| you build a given input set of metadata, we expect you to get consistent output. | 
| This has always been a key focus but, :yocto_docs:`since release 3.1 ("dunfell") | 
| </ref-manual/migration-3.1.html#reproducible-builds-now-enabled-by-default>`, | 
| it is now true down to the binary level including timestamps. | 
|   | 
| For example, at some point in the future life of a product, you find that you | 
| need to rebuild to add a security fix. If this happens, only the components that | 
| have been modified should change at the binary level. This would lead to much | 
| easier and clearer bounds on where validation is needed. | 
|   | 
| This also gives an additional benefit to the project builds themselves, our hash | 
| equivalence for :ref:`Shared State <overview-manual/concepts:Shared State>` | 
| object reuse works much more effectively when the binary output remains the | 
| same. | 
|   | 
| .. note:: | 
|   | 
|    We strongly advise you to make sure your project builds reproducibly | 
|    before finalizing your production images. It would be too late if you | 
|    only address this issue when the first updates are required. | 
|   | 
| ================ | 
| How to enable it | 
| ================ | 
|   | 
| You can enable build reproducibility by inheriting the | 
| :ref:`reproducible-build <ref-classes-reproducible-build>` class | 
| in the configuration for your distribution. | 
|   | 
| This is what the Poky reference distribution does:: | 
|   | 
|    INHERIT += "reproducible_build" | 
|   | 
| =================== | 
| How we implement it | 
| =================== | 
|   | 
| There are many different aspects to build reproducibility, but some particular | 
| things we do within the build system to ensure reproducibility include: | 
|   | 
| -  Adding mappings to the compiler options to ensure debug filepaths are mapped | 
|    to consistent target compatible paths. This is done through the | 
|    :term:`DEBUG_PREFIX_MAP` variable which sets the ``-fmacro-prefix-map`` and | 
|    ``-fdebug-prefix-map`` compiler options correctly to map to target paths. | 
| -  Being explicit about recipe dependencies and their configuration (no floating | 
|    configure options or host dependencies creeping in). In particular this means | 
|    making sure :term:`PACKAGECONFIG` coverage covers configure options which may | 
|    otherwise try and auto-detect host dependencies. | 
| -  Using recipe specific sysroots to isolate recipes so they only see their | 
|    dependencies. These are visible as ``recipe-sysroot`` and | 
|    ``recipe-sysroot-native`` directories within the :term:`WORKDIR` of a given | 
|    recipe and are populated only with the dependencies a recipe has. | 
| -  Build images from a reduced package set: only packages from recipes the image | 
|    depends upon. | 
| -  Filtering the tools available from the host's ``PATH`` to only a specific set | 
|    of tools, set using the :term:`HOSTTOOLS` variable. | 
|   | 
| .. note:: | 
|   | 
|    Because of an open bug in GCC, using ``DISTRO_FEATURES:append = " lto"`` or | 
|    adding ``-flto`` (Link Time Optimization) to ``CFLAGS`` makes the resulting | 
|    binary non-reproducible, in that it depends on the full absolute build path | 
|    to ``recipe-sysroot-native``, so installing the Yocto Project in a different | 
|    directory results in a different binary. | 
|   | 
|    This issue is addressed by | 
|    :yocto_bugs:`bug 14481 -  Programs built with -flto are not reproducible</show_bug.cgi?id=14481>`. | 
|   | 
| ========================================= | 
| Can we prove the project is reproducible? | 
| ========================================= | 
|   | 
| Yes, we can prove it and we regularly test this on the Autobuilder. At the | 
| time of writing (release 3.3, "hardknott"), :term:`OpenEmbedded-Core (OE-Core)` | 
| is 100% reproducible for all its recipes (i.e. world builds) apart from the Go | 
| language and Ruby documentation packages. Unfortunately, the current | 
| implementation of the Go language has fundamental reproducibility problems as | 
| it always depends upon the paths it is built in. | 
|   | 
| .. note:: | 
|   | 
|    Only BitBake and :term:`OpenEmbedded-Core (OE-Core)`, which is the ``meta`` | 
|    layer in Poky, guarantee complete reproducibility. The moment you add | 
|    another layer, this warranty is voided, because of additional configuration | 
|    files, ``bbappend`` files, overridden classes, etc. | 
|   | 
| To run our automated selftest, as we use in our CI on the Autobuilder, you can | 
| run:: | 
|   | 
|    oe-selftest -r reproducible.ReproducibleTests.test_reproducible_builds | 
|   | 
| This defaults to including a ``world`` build so, if other layers are added, it would | 
| also run the tests for recipes in the additional layers. The first build will be | 
| run using :ref:`Shared State <overview-manual/concepts:Shared State>` if | 
| available, the second build explicitly disables | 
| :ref:`Shared State <overview-manual/concepts:Shared State>` and builds on the | 
| specific host the build is running on. This means we can test reproducibility | 
| builds between different host distributions over time on the Autobuilder. | 
|   | 
| If ``OEQA_DEBUGGING_SAVED_OUTPUT`` is set, any differing packages will be saved | 
| here. The test is also able to run the ``diffoscope`` command on the output to | 
| generate HTML files showing the differences between the packages, to aid | 
| debugging. On the Autobuilder, these appear under | 
| https://autobuilder.yocto.io/pub/repro-fail/ in the form ``oe-reproducible + | 
| <date> + <random ID>``, e.g. ``oe-reproducible-20200202-1lm8o1th``. | 
|   | 
| The project's current reproducibility status can be seen at | 
| :yocto_home:`/reproducible-build-results/` | 
|   | 
| You can also check the reproducibility status on supported host distributions: | 
|   | 
| -  CentOS: :yocto_ab:`/typhoon/#/builders/reproducible-centos` | 
| -  Debian: :yocto_ab:`/typhoon/#/builders/reproducible-debian` | 
| -  Fedora: :yocto_ab:`/typhoon/#/builders/reproducible-fedora` | 
| -  Ubuntu: :yocto_ab:`/typhoon/#/builders/reproducible-ubuntu` | 
|   | 
| =============================== | 
| Can I test my layer or recipes? | 
| =============================== | 
|   | 
| Once again, you can run a ``world`` test using the | 
| :ref:`oe-selftest <ref-manual/release-process:Testing and Quality Assurance>` | 
| command provided above. This functionality is implemented | 
| in :oe_git:`meta/lib/oeqa/selftest/cases/reproducible.py | 
| </openembedded-core/tree/meta/lib/oeqa/selftest/cases/reproducible.py>`. | 
|   | 
| You could subclass the test and change ``targets`` to a different target. | 
|   | 
| You may also change ``sstate_targets`` which would allow you to "pre-cache" some | 
| set of recipes before the test, meaning they are excluded from reproducibility | 
| testing. As a practical example, you could set ``sstate_targets`` to | 
| ``core-image-sato``, then setting ``targets`` to ``core-image-sato-sdk`` would | 
| run reproducibility tests only on the targets belonging only to ``core-image-sato-sdk``. |