multiconfig.rst 14 KB

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