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``. | ||