summaryrefslogtreecommitdiffstats
path: root/documentation/dev-manual/multiconfig.rst
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/dev-manual/multiconfig.rst')
-rw-r--r--documentation/dev-manual/multiconfig.rst312
1 files changed, 312 insertions, 0 deletions
diff --git a/documentation/dev-manual/multiconfig.rst b/documentation/dev-manual/multiconfig.rst
new file mode 100644
index 0000000000..71fe542efb
--- /dev/null
+++ b/documentation/dev-manual/multiconfig.rst
@@ -0,0 +1,312 @@
1.. SPDX-License-Identifier: CC-BY-SA-2.0-UK
2
3Building Images for Multiple Targets With Multiconfig
4*****************************************************
5
6You can use a single ``bitbake`` command to build multiple images or
7packages for different targets where each image or package requires a
8different configuration (multiple configuration builds). The builds, in
9this scenario, are sometimes referred to as "multiconfigs", and this
10section uses that term throughout.
11
12This section describes how to set up for multiple configuration builds
13and how to account for cross-build dependencies between the
14multiconfigs.
15
16Setting Up and Running a Multiple Configuration Build
17=====================================================
18
19To accomplish a multiple configuration build, you must define each
20target's configuration separately using a parallel :term:`configuration file` in
21the :term:`Build Directory` or configuration directory within a layer, and you
22must follow a required file hierarchy. Additionally, you must enable the
23multiple configuration builds in your ``local.conf`` file.
24
25Follow these steps to set up and execute multiple configuration builds:
26
27- *Create Separate Configuration Files*: You need to create a single
28 :term:`Configuration File` for each build target (each multiconfig).
29 The configuration definitions are implementation dependent but often
30 each configuration file will define the :term:`MACHINE` and the
31 temporary directory (:term:`TMPDIR`) BitBake uses for the build.
32
33 .. note::
34
35 Whether the same temporary directory (:term:`TMPDIR`) can be shared will
36 depend on what is similar and what is different between the
37 configurations. Multiple :term:`MACHINE` targets can share the same
38 :term:`TMPDIR` as long as the rest of the configuration is the same,
39 multiple :term:`DISTRO` settings would need separate :term:`TMPDIR`
40 directories.
41
42 For example, consider a scenario with two different multiconfigs for the same
43 :term:`MACHINE`: "qemux86" built for two distributions such as "poky" and
44 "poky-lsb". In this case, you would need to use two different :term:`TMPDIR`.
45
46 In the general case, using separate :term:`TMPDIR` for the different
47 multiconfigs is strongly recommended.
48
49 The location for these multiconfig configuration files is specific.
50 They must reside in the current :term:`Build Directory` in a sub-directory of
51 ``conf`` named ``multiconfig`` or within a :term:`Layer`'s ``conf`` directory
52 under a directory named ``multiconfig``. Here is an example that defines
53 two configuration files for the "x86" and "arm" multiconfigs:
54
55 .. image:: figures/multiconfig_files.png
56 :align: center
57 :width: 50%
58
59 The usual :term:`BBPATH` search path is used to locate multiconfig files in
60 a similar way to other configuration files.
61
62 Here is an example showing the minimal statements needed in a
63 :term:`configuration file` named ``qemux86.conf`` for a ``qemux86`` target
64 whose temporary build directory is ``tmp-qemux86``::
65
66 MACHINE = "qemux86"
67 TMPDIR .= "-${BB_CURRENT_MC}"
68
69 BitBake will expand the :term:`BB_CURRENT_MC` variable to the value of the
70 current multiconfig in use. We append this value to :term:`TMPDIR` so that
71 any change on the definition of :term:`TMPDIR` will automatically affect the
72 value of :term:`TMPDIR` for each multiconfig.
73
74- *Add the BitBake Multi-configuration Variable to the Local
75 Configuration File*: Use the
76 :term:`BBMULTICONFIG`
77 variable in your ``conf/local.conf`` configuration file to specify
78 each multiconfig. Continuing with the example from the previous
79 figure, the :term:`BBMULTICONFIG` variable needs to enable two
80 multiconfigs: "x86" and "arm" by specifying each configuration file::
81
82 BBMULTICONFIG = "x86 arm"
83
84 .. note::
85
86 A "default" configuration already exists by definition. This
87 configuration is named: "" (i.e. empty string) and is defined by
88 the variables coming from your ``local.conf``
89 file. Consequently, the previous example actually adds two
90 additional configurations to your build: "arm" and "x86" along
91 with "".
92
93- *Launch BitBake*: Use the following BitBake command form to launch
94 the multiple configuration build::
95
96 $ bitbake [mc:multiconfigname:]target [[[mc:multiconfigname:]target] ... ]
97
98 For the example in this section, the following command applies::
99
100 $ bitbake mc:x86:core-image-minimal mc:arm:core-image-sato mc::core-image-base
101
102 The previous BitBake command builds several components:
103
104 - A ``core-image-minimal`` image that is configured through the ``x86.conf``
105 configuration file
106
107 - A ``core-image-sato`` image that is configured through the ``arm.conf``
108 configuration file
109
110 - A ``core-image-base`` that is configured through your ``local.conf``
111 configuration file
112
113.. note::
114
115 Support for multiple configuration builds in the Yocto Project &DISTRO;
116 (&DISTRO_NAME;) Release does not include Shared State (sstate)
117 optimizations. Consequently, if a build uses the same object twice
118 in, for example, two different :term:`TMPDIR`
119 directories, the build either loads from an existing sstate cache for
120 that build at the start or builds the object fresh.
121
122Enabling Multiple Configuration Build Dependencies
123==================================================
124
125Sometimes dependencies can exist between targets (multiconfigs) in a
126multiple configuration build. For example, suppose that in order to
127build a ``core-image-sato`` image for an "x86" multiconfig, the root
128filesystem of an "arm" multiconfig must exist. This dependency is
129essentially that the
130:ref:`ref-tasks-image` task in the
131``core-image-sato`` recipe depends on the completion of the
132:ref:`ref-tasks-rootfs` task of the
133``core-image-minimal`` recipe.
134
135To enable dependencies in a multiple configuration build, you must
136declare the dependencies in the recipe using the following statement
137form::
138
139 task_or_package[mcdepends] = "mc:from_multiconfig:to_multiconfig:recipe_name:task_on_which_to_depend"
140
141To better show how to use this statement, consider the example scenario
142from the first paragraph of this section. The following statement needs
143to be added to the recipe that builds the ``core-image-sato`` image::
144
145 do_image[mcdepends] = "mc:x86:arm:core-image-minimal:do_rootfs"
146
147In this example, the `from_multiconfig` is "x86". The `to_multiconfig` is "arm". The
148task on which the :ref:`ref-tasks-image` task in the recipe depends is the
149:ref:`ref-tasks-rootfs` task from the ``core-image-minimal`` recipe associated
150with the "arm" multiconfig.
151
152Once you set up this dependency, you can build the "x86" multiconfig
153using a BitBake command as follows::
154
155 $ bitbake mc:x86:core-image-sato
156
157This command executes all the tasks needed to create the
158``core-image-sato`` image for the "x86" multiconfig. Because of the
159dependency, BitBake also executes through the :ref:`ref-tasks-rootfs` task for the
160"arm" multiconfig build.
161
162Having a recipe depend on the root filesystem of another build might not
163seem that useful. Consider this change to the statement in the
164``core-image-sato`` recipe::
165
166 do_image[mcdepends] = "mc:x86:arm:core-image-minimal:do_image"
167
168In this case, BitBake must
169create the ``core-image-minimal`` image for the "arm" build since the
170"x86" build depends on it.
171
172Because "x86" and "arm" are enabled for multiple configuration builds
173and have separate configuration files, BitBake places the artifacts for
174each build in the respective temporary build directories (i.e.
175:term:`TMPDIR`).
176
177Suggested best practices
178========================
179
180- :term:`TMPDIR` (other than the default set in bitbake.conf) is only set in
181 ``local.conf`` by the user. This means that we should **not** manipulate
182 :term:`TMPDIR` in any way within the Machine or Distro :term:`configuration
183 file`.
184
185- A multiconfig should specify a :term:`TMPDIR`, and should specify it by
186 appending the multiconfig name with :term:`BB_CURRENT_MC`.
187
188- Recipes that are used to transfer the output from a multiconfig build to
189 another should use ``do_task[mcdepends]`` to trigger the build of the
190 component, and then transfer the item to the current configuration in
191 :ref:`ref-tasks-install` and :ref:`ref-tasks-deploy`, assuming the value of
192 the deployed item based on :term:`TMPDIR`.
193
194 The :ref:`ref-tasks-install` and :ref:`ref-tasks-deploy` tasks should look
195 like this::
196
197 do_install() {
198 install -m 0644 ${TMPDIR}-<multiconfig>/tmp/deploy/images/<machine>/somefile ${D}/some/path
199 }
200
201 do_deploy() {
202 install -m 0644 ${TMPDIR}-<multiconfig>/tmp/deploy/images/<machine>/somefile ${DEPLOYDIR}/somefile
203 }
204
205 In the example above:
206
207 - ``<multiconfig>`` is the multiconfig name as set by the multiconfig
208 :term:`configuration file` (see the :ref:`dev-manual/multiconfig:Setting
209 Up and Running a Multiple Configuration Build` section above).
210
211 - ``<machine>`` must be the :term:`MACHINE` for which ``somefile`` was built
212 and deployed. This value may differ from the current :term:`MACHINE` if
213 the multiconfig :term:`configuration file` overrides it.
214
215- Firmware recipes can set the :term:`INHIBIT_DEFAULT_DEPS` variable to ``1``
216 if they don't rely on default dependencies such as the standard C library.
217
218Common use case: building baremetal firmware alongside a Linux build
219====================================================================
220
221A common use case for multiconfig is to use the default configuration as the
222regular Linux build, while one or more multiconfigs can be used to build special
223components, such as baremetal firmware. It would also apply to a scenario where
224a microcontroller, for example, is companion to a main processor where Linux is
225running. This section details how one can achieve these kinds of scenarios with
226a multiconfig build.
227
228Adding a multiconfig configuration file and recipe for a baremetal firmware
229---------------------------------------------------------------------------
230
231As described in :ref:`dev-manual/multiconfig:Setting Up and Running a Multiple
232Configuration Build`, each multiconfig will require a separate
233:term:`Configuration File`. In addition, we will define a separate
234:term:`TMPDIR` for our baremetal firmware build configuration.
235
236For example, we will define a new ``conf/multiconfig/baremetal-firmware.conf``
237as follows::
238
239 TMPDIR .= "-${BB_CURRENT_MC}"
240 TCLIBC = "newlib"
241
242The ``baremetal-firmware.conf`` file configures a separate :term:`TMPDIR` for
243holding binaries compiled with the `newlib <https://sourceware.org/newlib/>`__
244toolchain (see :term:`TCLIBC`).
245
246.. note::
247
248 Here, the default :term:`MACHINE` is not overridden by the multiconfig
249 configuration file. As a consequence, the architecture of the built baremetal
250 binaries will be the same. In other cases, where the firmware runs on a
251 completely different architecture, the :term:`MACHINE` must be overridden.
252
253We then create a recipe ``my-firmware.bb`` that defines how the baremetal
254firmware is built. The recipe should contain enough information for the
255:term:`OpenEmbedded build system` to properly compile the firmware with our
256toolchain. The building tasks may vary depending on the nature of the firmware.
257However, the recipe should define a :ref:`ref-classes-deploy` task that deploys
258the output into the :term:`DEPLOYDIR` directory. We will consider in the
259following that the file is named ``my-firmware.elf``.
260
261Building the firmware
262---------------------
263
264The firmware can be built with BitBake with the following command::
265
266 $ bitbake mc:baremetal-firmware:my-firmware
267
268However, we would prefer for ``my-firmware`` to be automatically built when
269triggering a normal Linux build.
270
271Using a ``mcdepend``, a recipe belonging to the Linux build can trigger the
272build of ``my-firmware``. For example, let's consider that our Linux build needs
273to assemble a "special" firmware that uses the output of our ``my-firmware``
274recipe - let's call it ``my-parent-firmware.bb``. Then, we should specify this
275dependency in ``my-parent-firmware.bb`` with::
276
277 do_compile[mcdepends] = "mc::baremetal-firmware:my-firmware:do_deploy"
278
279The above will ensure that when the :ref:`ref-tasks-compile` task of
280``my-parent-firmware`` is triggered, the :ref:`ref-tasks-deploy` task of
281``my-firmware`` will already have run successfully.
282
283Using the output of ``my-firmware``
284-----------------------------------
285
286After ``my-firmware`` recipe has deployed ``my-firmware.elf``, we need to use
287the output in some way. We can make a series of assumptions, based on the
288default Yocto Project variables in order to get the binary for packaging.
289
290First, we can set the following in ``my-parent-firmware.bb``::
291
292 FIRMWARE_FILE ??= "${TMPDIR}-baremetal-firmware/deploy/images/<machine>/my-firmware.elf"
293 FIRMWARE_FILE[vardepsexclude] += "TMPDIR"
294
295The first assignment stores the value of the path to the firmware built and
296deployed by the ``my-firmware.bb`` recipe. The second assignment excludes the
297:term:`TMPDIR` variable from being part of ``FIRMWARE_FILE``'s dependencies ---
298meaning that changing the value of :term:`TMPDIR` (for example, changing the
299host on which the firmware is built) will not invalidate the :ref:`shared state
300cache <overview-manual/concepts:shared state cache>`.
301
302Additionally, ``<machine>`` should be replaced by the :term:`MACHINE` for which
303we are building in the baremetal-firmware context.
304
305We can then add a :ref:`ref-tasks-install` task to ``my-parent-firmware``::
306
307 do_install() {
308 install -Dm 0644 ${FIRMWARE_FILE} ${D}/lib/firmware/my-firmware.elf
309 }
310
311Doing the above will allow the firmware binary to be transferred and packaged
312into the Linux context and rootfs.