diff options
| author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-06-07 17:59:20 +0100 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-06-14 22:45:33 +0100 |
| commit | 1a1941cc489190b8d4d604cdddb8d3e355990709 (patch) | |
| tree | c1bd8c759fc2f433129baf72151dded16cab9a87 /documentation/test-manual | |
| parent | b32f1ad8798fda46ec598d29a0ac9e2fb11d5e2a (diff) | |
| download | poky-1a1941cc489190b8d4d604cdddb8d3e355990709.tar.gz | |
test-manual: add initial reproducible builds documentation
(From yocto-docs rev: a4ec469042ccb2487c1d076a2c005f33f8021816)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Michael Opdenacker <michael.opdenacker@bootlin.com>
Reviewed-by: Quentin Schulz <foss@0leil.net>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'documentation/test-manual')
| -rw-r--r-- | documentation/test-manual/index.rst | 1 | ||||
| -rw-r--r-- | documentation/test-manual/reproducible-builds.rst | 135 |
2 files changed, 136 insertions, 0 deletions
diff --git a/documentation/test-manual/index.rst b/documentation/test-manual/index.rst index e2198c4c39..d122b5e270 100644 --- a/documentation/test-manual/index.rst +++ b/documentation/test-manual/index.rst | |||
| @@ -13,6 +13,7 @@ Yocto Project Test Environment Manual | |||
| 13 | intro | 13 | intro |
| 14 | test-process | 14 | test-process |
| 15 | understand-autobuilder | 15 | understand-autobuilder |
| 16 | reproducible-builds | ||
| 16 | history | 17 | history |
| 17 | 18 | ||
| 18 | .. include:: /boilerplate.rst | 19 | .. include:: /boilerplate.rst |
diff --git a/documentation/test-manual/reproducible-builds.rst b/documentation/test-manual/reproducible-builds.rst new file mode 100644 index 0000000000..e13583c0bf --- /dev/null +++ b/documentation/test-manual/reproducible-builds.rst | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | .. SPDX-License-Identifier: CC-BY-SA-2.0-UK | ||
| 2 | |||
| 3 | ******************* | ||
| 4 | Reproducible Builds | ||
| 5 | ******************* | ||
| 6 | |||
| 7 | ================ | ||
| 8 | How we define it | ||
| 9 | ================ | ||
| 10 | |||
| 11 | The Yocto Project defines reproducibility as where a given input build | ||
| 12 | configuration will give the same binary output regardless of when it is built | ||
| 13 | (now or in 5 years time), regardless of the path on the filesystem the build is | ||
| 14 | run in, and regardless of the distro and tools on the underlying host system the | ||
| 15 | build is running on. | ||
| 16 | |||
| 17 | ============== | ||
| 18 | Why it matters | ||
| 19 | ============== | ||
| 20 | |||
| 21 | The project aligns with the `Reproducible Builds project | ||
| 22 | <https://reproducible-builds.org/>`_, which shares information about why | ||
| 23 | reproducibility matters. The primary focus of the project is the ability to | ||
| 24 | detect security issues being introduced. However, from a Yocto Project | ||
| 25 | perspective, it is also hugely important that our builds are deterministic. When | ||
| 26 | you build a given input set of metadata, we expect you to get consistent output. | ||
| 27 | This has always been a key focus but, :yocto_docs:`since release 3.1 ("dunfell") | ||
| 28 | </ref-manual/migration-3.1.html#reproducible-builds-now-enabled-by-default>`, | ||
| 29 | it is now true down to the binary level including timestamps. | ||
| 30 | |||
| 31 | For example, at some point in the future life of a product, you find that you | ||
| 32 | need to rebuild to add a security fix. If this happens, only the components that | ||
| 33 | have been modified should change at the binary level. This would lead to much | ||
| 34 | easier and clearer bounds on where validation is needed. | ||
| 35 | |||
| 36 | This also gives an additional benefit to the project builds themselves, our hash | ||
| 37 | equivalence for :ref:`Shared State <overview-manual/concepts:Shared State>` | ||
| 38 | object reuse works much more effectively when the binary output remains the | ||
| 39 | same. | ||
| 40 | |||
| 41 | .. note:: | ||
| 42 | |||
| 43 | We strongly advise you to make sure your project builds reproducibly | ||
| 44 | before finalizing your production images. It would be too late if you | ||
| 45 | only address this issue when the first updates are required. | ||
| 46 | |||
| 47 | =================== | ||
| 48 | How we implement it | ||
| 49 | =================== | ||
| 50 | |||
| 51 | There are many different aspects to build reproducibility, but some particular | ||
| 52 | things we do within the build system to ensure reproducibility include: | ||
| 53 | |||
| 54 | - Adding mappings to the compiler options to ensure debug filepaths are mapped | ||
| 55 | to consistent target compatible paths. This is done through the | ||
| 56 | ``DEBUG_PREFIX_MAP`` variable which sets the ``-fmacro-prefix-map`` and | ||
| 57 | ``-fdebug-prefix-map`` compiler options correctly to map to target paths. | ||
| 58 | - Being explicit about recipe dependencies and their configuration (no floating | ||
| 59 | configure options or host dependencies creeping in). In particular this means | ||
| 60 | making sure :term:`PACKAGECONFIG` coverage covers configure options which may | ||
| 61 | otherwise try and auto-detect host dependencies. | ||
| 62 | - Using recipe specific sysroots to isolate recipes so they only see their | ||
| 63 | dependencies. These are visible as ``recipe-sysroot`` and | ||
| 64 | ``recipe-sysroot-native`` directories within the :term:`WORKDIR` of a given | ||
| 65 | recipe and are populated only with the dependencies a recipe has. | ||
| 66 | - Build images from a reduced package set: only packages from recipes the image | ||
| 67 | depends upon. | ||
| 68 | - Filtering the tools available from the host's ``PATH`` to only a specific set | ||
| 69 | of tools, set using the :term:`HOSTTOOLS` variable. | ||
| 70 | |||
| 71 | ========================================= | ||
| 72 | Can we prove the project is reproducible? | ||
| 73 | ========================================= | ||
| 74 | |||
| 75 | Yes, we can prove it and we regularly test this on the Autobuilder. At the | ||
| 76 | time of writing (release 3.3, "hardknott"), :term:`OpenEmbedded-Core (OE-Core)` | ||
| 77 | is 100% reproducible for all its recipes (i.e. world builds) apart from the Go | ||
| 78 | language and Ruby documentation packages. Unfortunately, the current | ||
| 79 | implementation of the Go language has fundamental reproducibility problems as | ||
| 80 | it always depends upon the paths it is built in. | ||
| 81 | |||
| 82 | .. note:: | ||
| 83 | |||
| 84 | Only BitBake and :term:`OpenEmbedded-Core (OE-Core)`, which is the ``meta`` | ||
| 85 | layer in Poky, guarantee complete reproducibility. The moment you add | ||
| 86 | another layer, this warranty is voided, because of additional configuration | ||
| 87 | files, ``bbappend`` files, overridden classes, etc. | ||
| 88 | |||
| 89 | To run our automated selftest, as we use in our CI on the Autobuilder, you can | ||
| 90 | run:: | ||
| 91 | |||
| 92 | oe-selftest -r reproducible.ReproducibleTests.test_reproducible_builds | ||
| 93 | |||
| 94 | This defaults to including a ``world`` build so, if other layers are added, it would | ||
| 95 | also run the tests for recipes in the additional layers. The first build will be | ||
| 96 | run using :ref:`Shared State <overview-manual/concepts:Shared State>` if | ||
| 97 | available, the second build explicitly disables | ||
| 98 | :ref:`Shared State <overview-manual/concepts:Shared State>` and builds on the | ||
| 99 | specific host the build is running on. This means we can test reproducibility | ||
| 100 | builds between different host distributions over time on the Autobuilder. | ||
| 101 | |||
| 102 | If ``OEQA_DEBUGGING_SAVED_OUTPUT`` is set, any differing packages will be saved | ||
| 103 | here. The test is also able to run the ``diffoscope`` command on the output to | ||
| 104 | generate HTML files showing the differences between the packages, to aid | ||
| 105 | debugging. On the Autobuilder, these appear under | ||
| 106 | https://autobuilder.yocto.io/pub/repro-fail/ in the form ``oe-reproducible + | ||
| 107 | <date> + <random ID>``, e.g. ``oe-reproducible-20200202-1lm8o1th``. | ||
| 108 | |||
| 109 | The project's current reproducibility status can be seen at | ||
| 110 | :yocto_home:`/reproducible-build-results/` | ||
| 111 | |||
| 112 | You can also check the reproducibility status on supported host distributions: | ||
| 113 | |||
| 114 | - CentOS: :yocto_ab:`/typhoon/#/builders/reproducible-centos` | ||
| 115 | - Debian: :yocto_ab:`/typhoon/#/builders/reproducible-debian` | ||
| 116 | - Fedora: :yocto_ab:`/typhoon/#/builders/reproducible-fedora` | ||
| 117 | - Ubuntu: :yocto_ab:`/typhoon/#/builders/reproducible-ubuntu` | ||
| 118 | |||
| 119 | =============================== | ||
| 120 | Can I test my layer or recipes? | ||
| 121 | =============================== | ||
| 122 | |||
| 123 | Once again, you can run a ``world`` test using the | ||
| 124 | :ref:`oe-selftest <ref-manual/release-process:Testing and Quality Assurance>` | ||
| 125 | command provided above. This functionality is implemented | ||
| 126 | in :oe_git:`meta/lib/oeqa/selftest/cases/reproducible.py | ||
| 127 | </openembedded-core/tree/meta/lib/oeqa/selftest/cases/reproducible.py>`. | ||
| 128 | |||
| 129 | You could subclass the test and change ``targets`` to a different target. | ||
| 130 | |||
| 131 | You may also change ``sstate_targets`` which would allow you to "pre-cache" some | ||
| 132 | set of recipes before the test, meaning they are excluded from reproducibility | ||
| 133 | testing. As a practical example, you could set ``sstate_targets`` to | ||
| 134 | ``core-image-sato``, then setting ``targets`` to ``core-image-sato-sdk`` would | ||
| 135 | run reproducibility tests only on the targets belonging only to ``core-image-sato-sdk``. | ||
