diff options
author | Antonin Godard <antonin.godard@bootlin.com> | 2025-02-17 15:50:25 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2025-02-26 14:49:28 +0000 |
commit | dcfbb14ad38aa31eab9f51c4af21b6f85667963c (patch) | |
tree | 806b3c45782deb3a6f708b5123f7657cf1117db6 | |
parent | 705966c54623b85775ba540acbd6941c91e23e40 (diff) | |
download | poky-dcfbb14ad38aa31eab9f51c4af21b6f85667963c.tar.gz |
dev-manual/multiconfig: add suggested best practices and baremetal sections
After the suggestions from Mark Hatle on the list
(https://lists.yoctoproject.org/g/docs/topic/110487932), add two
sections to the multiconfig doc:
- Suggested best practices: suggestion for better design of multiconfig
builds.
- Common use case: baremetal build.
This section applies the guidelines from the first sections and apply
it to a real-life example of how to use multiconfig. This one to build
some baremetal firmware alongside a regular Linux build.
Suggested-by: Mark Hatle <mark.hatle@kernel.crashing.org>
Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
(From yocto-docs rev: 36fb1e9e5099aa0d858d5478530143e9bac39588)
Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | documentation/dev-manual/multiconfig.rst | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/documentation/dev-manual/multiconfig.rst b/documentation/dev-manual/multiconfig.rst index 8371cf0e46..71fe542efb 100644 --- a/documentation/dev-manual/multiconfig.rst +++ b/documentation/dev-manual/multiconfig.rst | |||
@@ -174,3 +174,139 @@ and have separate configuration files, BitBake places the artifacts for | |||
174 | each build in the respective temporary build directories (i.e. | 174 | each build in the respective temporary build directories (i.e. |
175 | :term:`TMPDIR`). | 175 | :term:`TMPDIR`). |
176 | 176 | ||
177 | Suggested 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 | |||
218 | Common use case: building baremetal firmware alongside a Linux build | ||
219 | ==================================================================== | ||
220 | |||
221 | A common use case for multiconfig is to use the default configuration as the | ||
222 | regular Linux build, while one or more multiconfigs can be used to build special | ||
223 | components, such as baremetal firmware. It would also apply to a scenario where | ||
224 | a microcontroller, for example, is companion to a main processor where Linux is | ||
225 | running. This section details how one can achieve these kinds of scenarios with | ||
226 | a multiconfig build. | ||
227 | |||
228 | Adding a multiconfig configuration file and recipe for a baremetal firmware | ||
229 | --------------------------------------------------------------------------- | ||
230 | |||
231 | As described in :ref:`dev-manual/multiconfig:Setting Up and Running a Multiple | ||
232 | Configuration 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 | |||
236 | For example, we will define a new ``conf/multiconfig/baremetal-firmware.conf`` | ||
237 | as follows:: | ||
238 | |||
239 | TMPDIR .= "-${BB_CURRENT_MC}" | ||
240 | TCLIBC = "newlib" | ||
241 | |||
242 | The ``baremetal-firmware.conf`` file configures a separate :term:`TMPDIR` for | ||
243 | holding binaries compiled with the `newlib <https://sourceware.org/newlib/>`__ | ||
244 | toolchain (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 | |||
253 | We then create a recipe ``my-firmware.bb`` that defines how the baremetal | ||
254 | firmware is built. The recipe should contain enough information for the | ||
255 | :term:`OpenEmbedded build system` to properly compile the firmware with our | ||
256 | toolchain. The building tasks may vary depending on the nature of the firmware. | ||
257 | However, the recipe should define a :ref:`ref-classes-deploy` task that deploys | ||
258 | the output into the :term:`DEPLOYDIR` directory. We will consider in the | ||
259 | following that the file is named ``my-firmware.elf``. | ||
260 | |||
261 | Building the firmware | ||
262 | --------------------- | ||
263 | |||
264 | The firmware can be built with BitBake with the following command:: | ||
265 | |||
266 | $ bitbake mc:baremetal-firmware:my-firmware | ||
267 | |||
268 | However, we would prefer for ``my-firmware`` to be automatically built when | ||
269 | triggering a normal Linux build. | ||
270 | |||
271 | Using a ``mcdepend``, a recipe belonging to the Linux build can trigger the | ||
272 | build of ``my-firmware``. For example, let's consider that our Linux build needs | ||
273 | to assemble a "special" firmware that uses the output of our ``my-firmware`` | ||
274 | recipe - let's call it ``my-parent-firmware.bb``. Then, we should specify this | ||
275 | dependency in ``my-parent-firmware.bb`` with:: | ||
276 | |||
277 | do_compile[mcdepends] = "mc::baremetal-firmware:my-firmware:do_deploy" | ||
278 | |||
279 | The 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 | |||
283 | Using the output of ``my-firmware`` | ||
284 | ----------------------------------- | ||
285 | |||
286 | After ``my-firmware`` recipe has deployed ``my-firmware.elf``, we need to use | ||
287 | the output in some way. We can make a series of assumptions, based on the | ||
288 | default Yocto Project variables in order to get the binary for packaging. | ||
289 | |||
290 | First, 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 | |||
295 | The first assignment stores the value of the path to the firmware built and | ||
296 | deployed by the ``my-firmware.bb`` recipe. The second assignment excludes the | ||
297 | :term:`TMPDIR` variable from being part of ``FIRMWARE_FILE``'s dependencies --- | ||
298 | meaning that changing the value of :term:`TMPDIR` (for example, changing the | ||
299 | host on which the firmware is built) will not invalidate the :ref:`shared state | ||
300 | cache <overview-manual/concepts:shared state cache>`. | ||
301 | |||
302 | Additionally, ``<machine>`` should be replaced by the :term:`MACHINE` for which | ||
303 | we are building in the baremetal-firmware context. | ||
304 | |||
305 | We 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 | |||
311 | Doing the above will allow the firmware binary to be transferred and packaged | ||
312 | into the Linux context and rootfs. | ||