{"id":5948,"date":"2022-01-20T09:00:00","date_gmt":"2022-01-20T08:00:00","guid":{"rendered":"https:\/\/www.blaess.fr\/christophe\/?p=5948"},"modified":"2022-01-27T14:43:56","modified_gmt":"2022-01-27T13:43:56","slug":"yocto-cooker-2-3","status":"publish","type":"post","link":"https:\/\/www.blaess.fr\/christophe\/2022\/01\/20\/yocto-cooker-2-3\/","title":{"rendered":"Yocto Cooker (2\/3)"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"alignright size-full\"><a href=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2022\/01\/cooker-logo-small-size.png\"><img loading=\"lazy\" decoding=\"async\" width=\"128\" height=\"160\" src=\"https:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2022\/01\/cooker-logo-small-size.png\" alt=\"\" class=\"wp-image-5898\"\/><\/a><\/figure><\/div>\n\n\n\n<p>Dans le <a rel=\"noreferrer noopener\" href=\"https:\/\/www.blaess.fr\/christophe\/2022\/01\/13\/yocto-cooker-1-3\/\" data-type=\"post\" data-id=\"5897\" target=\"_blank\">premier article<\/a> de cette s\u00e9rie nous avons vu comment utiliser <code>cooker<\/code> pour produire une image avec Yocto Project en ne renseignant qu&rsquo;un seul fichier&nbsp;: le menu.<\/p>\n\n\n\n<p>Dans cet article nous allons voir comment compl\u00e9ter ce menu pour produire plusieurs <em>builds<\/em> en une seule commande, certains d&rsquo;entre-eux pouvant partager divers \u00e9l\u00e9ments de configuration.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Pour m\u00e9moire le fichier que nous avions utilis\u00e9 \u00e9tait le suivant&nbsp;: <a href=\"https:\/\/www.blaess.fr\/christophe\/files\/yocto-cooker\/menu-001.json\">menu-001.json<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ <strong>cat menu-001.json<\/strong>\n\n{\n  \"sources\" : &#91;\n    { \"url\": \"git:\/\/git.yoctoproject.org\/poky\", \"branch\": \"dunfell\", \"rev\": \"yocto-3.1.13\" } \n  ],\n\n  \"layers\" : &#91;\n    \"poky\/meta\",\n    \"poky\/meta-poky\",\n    \"poky\/meta-yocto-bsp\"\n  ],\n\n  \"builds\" : {\n\n    \"qemuarm\": {\n\n      \"target\" : \"core-image-base\",\n\n      \"local.conf\": &#91;\n        \"MACHINE = 'qemuarm' \",\n        \"IMAGE_FEATURES += 'empty-root-password' \"\n      ]\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Ajout d&rsquo;un <em>build<\/em><\/h2>\n\n\n\n<p>Commen\u00e7ons par ajouter un autre <em>build<\/em> dans notre menu. Par exemple la production d&rsquo;une image pour une autre cible \u00e9mul\u00e9e par Qemu&nbsp;: <code>qemux86<\/code>. Pour cela nous ajoutons un deuxi\u00e8me couple cl\u00e9\/valeur dans l&rsquo;attribut <code>builds<\/code> du menu.<\/p>\n\n\n\n<p>Voici le nouveau menu&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"sources\" : &#91;\n    { \"url\": \"git:\/\/git.yoctoproject.org\/poky\", \"branch\": \"dunfell\", \"rev\": \"yocto-3.1.13\" }\n  ],\n\n  \"layers\" : &#91;\n    \"poky\/meta\",\n    \"poky\/meta-poky\",\n    \"poky\/meta-yocto-bsp\"\n  ],\n\n  \"builds\" : {\n\n    \"qemuarm\": {\n\n      \"target\" : \"core-image-base\",\n\n      \"local.conf\": &#91;\n        \"MACHINE = 'qemuarm' \",\n        \"IMAGE_FEATURES += 'empty-root-password' \"\n      ]\n    },\n\n    \"<strong>qemux86<\/strong>\": {\n\n      \"target\" : \"core-image-base\",\n\n      \"local.conf\": &#91;\n        \"MACHINE = 'qemux86' \",\n        \"IMAGE_FEATURES += 'empty-root-password' \"\n      ]\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>\u00c0 pr\u00e9sent, si nous lan\u00e7ons <code>cooker<\/code> ainsi&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ <strong>cooker  cook  menu-002.json<\/strong>\n<\/code><\/pre>\n\n\n\n<p>il va compiler successivement les deux images pour les deux machines voulues. Sauf si nous pr\u00e9cisons explicitement quelle image produire en indiquant le nom du <em>build<\/em> sur la ligne de commande, par exemple&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ <strong>cooker  cook  menu-002.json  qemux86<\/strong><\/code><\/pre>\n\n\n\n<p>Avant de produire v\u00e9ritablement l&rsquo;image, nous pouvons encore am\u00e9liorer et enrichir un peu notre menu.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Attribut <code>local.conf<\/code> global<\/h2>\n\n\n\n<p>Nous observons que la ligne<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\" IMAGE_FEATURES += 'empty-root-password' \"<\/code><\/pre>\n\n\n\n<p>est commune \u00e0 nos deux <em>builds<\/em>. Nous pouvons la factoriser en l&rsquo;extrayant de leurs propri\u00e9t\u00e9s <code>local.conf<\/code> et en la  pla\u00e7ant dans un attribut <code>local.conf<\/code> global \u00e0 tout le menu. Bien s\u00fbr il faut s&rsquo;assurer auparavant que cette ligne soit souhaitable pour tous les <em>builds<\/em> envisag\u00e9s. Voici le menu modifi\u00e9.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"sources\" : &#91;\n    { \"url\": \"git:\/\/git.yoctoproject.org\/poky\", \"branch\": \"dunfell\", \"rev\": \"yocto-3.1.13\" }\n  ],\n\n  \"layers\" : &#91;\n    \"poky\/meta\",\n    \"poky\/meta-poky\",\n    \"poky\/meta-yocto-bsp\"\n  ],\n\n  <strong>\"local.conf\": &#91;\n    \"IMAGE_FEATURES += 'empty-root-password' \"\n  ],<\/strong>\n\n  \"builds\" : {\n\n    \"qemuarm\": {\n\n      \"target\" : \"core-image-base\",\n\n      \"local.conf\": &#91;\n        \"MACHINE = 'qemuarm' \"\n      ]\n    },\n\n    \"qemux86\": {\n\n      \"target\" : \"core-image-base\",\n\n      \"local.conf\": &#91;\n        \"MACHINE = 'qemux86' \"\n      ]\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>Dans les projets de mes clients, j&rsquo;utilise surtout l&rsquo;attribut <code>local.conf<\/code> au niveau du menu pour d\u00e9finir des variables de configuration qui sont employ\u00e9es ensuite dans des recettes pour le code m\u00e9tier. Une autre variable que j&rsquo;indique souvent ici est <code>\"OE_TERMINAL = 'screen' \"<\/code> pour faciliter la configuration du <em>kernel<\/em> lorsque je me connecte \u00e0 distance sur la machine de compilation.<\/p>\n\n\n\n<p>Pour l&rsquo;instant nous n&rsquo;utilisons que le d\u00e9p\u00f4t Poky comme source, avec ses trois <em>layers<\/em> incontournables. Mais nous pouvons en ajouter d&rsquo;autres.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Layer suppl\u00e9mentaire<\/h2>\n\n\n\n<p>Supposons que dans l&rsquo;image pour <code>qemux86<\/code> nous souhaitions installer l&rsquo;utilitaire <code>nano<\/code> (\u00e9diteur de texte). Pour cela nous devons inclure un <em>layer<\/em> suppl\u00e9mentaire (<code>meta-oe<\/code>) pr\u00e9sent dans le d\u00e9p\u00f4t <code>meta-openembedded<\/code>.<\/p>\n\n\n\n<p>Cela implique plusieurs choses pour notre menu. Tout d&rsquo;abord nous devons ajouter le d\u00e9p\u00f4t <code>meta-openembedded<\/code> \u00e0 la liste des <code>sources<\/code> \u00e0 t\u00e9l\u00e9charger. Contrairement \u00e0 Poky, <code>meta-openembedded<\/code> ne g\u00e8re pas les <em>tags<\/em>, aussi devrons-nous indiquer un num\u00e9ro de <em>commit<\/em> pour garantir la reproductibilit\u00e9 de la compilation.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \"sources\" : &#91;\n    { \"url\": \"git:\/\/git.yoctoproject.org\/poky\", \"branch\": \"dunfell\", \"rev\": \"yocto-3.1.13\" },\n    { \"url\": \"git:\/\/git.openembedded.org\/meta-openembedded\", \"branch\": \"dunfell\", \"rev\": \"ab9fca48\" }\n  ],<\/code><\/pre>\n\n\n\n<p>Ensuite, il faut indiquer que le <em>layer<\/em> <code>meta-oe<\/code> est n\u00e9cessaire pour le <em>build<\/em> <code>qemux86<\/code>. Mais uniquement pour lui. Pas pour <code>qemuarm<\/code>. <\/p>\n\n\n\n<p>Pour cela, nous allons ajouter un attribut <code>layers<\/code> \u00e0 l&rsquo;objet <code>build<\/code> concern\u00e9. Cet attribut indiquera les <em>layers<\/em>  suppl\u00e9mentaires \u00e0 prendre en compte en plus de ceux de la propri\u00e9t\u00e9 <code>layers<\/code> du menu.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \"qemux86\": {\n\n    \"target\" : \"core-image-base\",\n\n    <strong>\"layers\" : &#91;\n      \"meta-openembedded\/meta-oe\"\n    ],<\/strong>\n    &#91;...]\n  }<\/code><\/pre>\n\n\n\n<p>Enfin, il faut indiquer que l&rsquo;on veut inclure la recette <code>nano<\/code> lors de la g\u00e9n\u00e9ration de l&rsquo;image pour <code>qemux86<\/code>, ce que nous pouvons faire directement dans son attribut <code>local.conf<\/code>. Dans un projet r\u00e9el on d\u00e9finirait plut\u00f4t une recette d&rsquo;image sp\u00e9cifique dans un <em>layer<\/em> personnalis\u00e9 <\/p>\n\n\n\n<p>Voici donc le contenu du  <a href=\"https:\/\/www.blaess.fr\/christophe\/files\/yocto-cooker\/menu-002.json\">menu-002.json<\/a> complet.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"sources\" : &#91;\n    { \"url\": \"git:\/\/git.yoctoproject.org\/poky\", \"branch\": \"dunfell\", \"rev\": \"yocto-3.1.13\" },\n    { \"url\": \"git:\/\/git.openembedded.org\/meta-openembedded\", \"branch\": \"dunfell\", \"rev\": \"ab9fca48\" }\n  ],\n\n  \"layers\" : &#91;\n    \"poky\/meta\",\n    \"poky\/meta-poky\",\n    \"poky\/meta-yocto-bsp\"\n  ],\n\n  \"local.conf\": &#91;\n    \"IMAGE_FEATURES += 'empty-root-password' \"\n  ],\n\n  \"builds\" : {\n\n    \"qemuarm\": {\n\n      \"target\" : \"core-image-base\",\n\n      \"local.conf\": &#91;\n        \"MACHINE = 'qemuarm' \"\n      ]\n    },\n\n    \"qemux86\": {\n\n      \"target\" : \"core-image-base\",\n\n      \"layers\" : &#91;\n        \"meta-openembedded\/meta-oe\"\n      ],\n\n      \"local.conf\": &#91;\n        \"MACHINE = 'qemux86' \",\n        <strong>\"IMAGE_INSTALL:append = ' nano' \"<\/strong>\n      ]\n    }\n  }\n}\n\n<\/code><\/pre>\n\n\n\n<p>Note&nbsp;: l&rsquo;ajout de la recette <code>nano<\/code> dans la variable <code>IMAGE_INSTALL<\/code> se fait avec la notation <code>:append<\/code>. Cette extension remplace,  depuis la mi-2021 la pr\u00e9c\u00e9dente notation <code>_append<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">H\u00e9ritage<\/h2>\n\n\n\n<p>Nous avons donc deux <em>builds<\/em> distincts dans le m\u00eame menu, chacun pour une cible sp\u00e9cifique. L&rsquo;un deux utilise un <em>layer<\/em> particulier. Bien s\u00fbr, dans l&rsquo;exemple ci-dessus le <em>layer<\/em> en question est l&rsquo;ultra-courant <code>meta-oe<\/code>, mais il pourrait s&rsquo;agir d&rsquo;un support sp\u00e9cifique pour une plateforme mat\u00e9rielle ou un ensemble de recettes pour le code applicatif m\u00e9tier.<\/p>\n\n\n\n<p>Approfondissons encore cet exemple avec deux nouveaux <em>builds<\/em>. L&rsquo;un pour Raspberry Pi 3 et l&rsquo;autre pour Raspberry Pi 4.<\/p>\n\n\n\n<p>Il nous faut d&rsquo;abord indiquer le d\u00e9p\u00f4t sp\u00e9cifique \u00e0 t\u00e9l\u00e9charger pour l&rsquo;architecture Raspberry Pi.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \"sources\" : &#91;\n    { \"url\": \"git:\/\/git.yoctoproject.org\/poky\", \"branch\": \"dunfell\", \"rev\": \"yocto-3.1.13\" },\n    { \"url\": \"git:\/\/git.openembedded.org\/meta-openembedded\", \"branch\": \"dunfell\", \"rev\": \"ab9fca48\" },\n    { \"url\": \"git:\/\/git.yoctoproject.org\/meta-raspberrypi\", \"branch\": \"dunfell\", \"rev\": \"934064a0\" }\n  ],<\/code><\/pre>\n\n\n\n<p>Puis nous cr\u00e9ons les deux <em>builds<\/em> n\u00e9cessaires. Ils devront inclure ce nouveau layer. Et dans l&rsquo;attribut <code>local.conf<\/code>, nous ajoutons quelques lignes de configuration mat\u00e9rielle propre \u00e0 ces cartes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \"builds\" : {\n     &#91;...]\n\n    \"<strong>rpi3<\/strong>\" : {\n      \"target\": \"core-image-base\",\n      \"layers\" : &#91;\n        \"meta-raspberrypi\n      ],\n      \"local.conf\" : &#91;\n        \"MACHINE = 'raspberrypi3'  \",\n        \"ENABLE_UART = '1'         \",\n        \"ENABLE_SPI_BUS =  '1'     \",\n        \"ENABLE_I2C =  '1'         \",\n        \"HDMI_FORCE_HOTPLUG = '1'  \",\n        \"CONFIG_HDMI_BOOST = '1'   \"\n      ],\n    },\n\n    \"<strong>rpi4<\/strong>\" : {\n      \"target\": \"core-image-base\",\n      \"layers\" : &#91;\n        \"meta-raspberrypi\n      ],\n      \"local.conf\" : &#91;\n        \"MACHINE = 'raspberrypi4'  \",\n        \"ENABLE_UART = '1'         \",\n        \"ENABLE_SPI_BUS =  '1'     \",\n        \"ENABLE_I2C =  '1'         \",\n        \"HDMI_FORCE_HOTPLUG = '1'  \",\n        \"CONFIG_HDMI_BOOST = '1'   \"\n      ],\n    }\n  }<\/code><\/pre>\n\n\n\n<p>J&rsquo;ai peut-\u00eatre un peu forc\u00e9 le trait, mais je suppose que vous comprenez le probl\u00e8me&nbsp;: ces deux <em>builds<\/em> qui ne diff\u00e8rent que par leurs noms et les  variables <code>MACHINES<\/code> sont oblig\u00e9s de r\u00e9p\u00e9ter une grosse poign\u00e9e de lignes identiques.<\/p>\n\n\n\n<p>Contrairement \u00e0 la ligne <code>IMAGE_FEATURES += 'empty-root-password'<\/code> que nous avons pr\u00e9c\u00e9demment inscrite dans l&rsquo;attribut <code>local.conf<\/code> global \u00e0 tout le menu, les lignes de configuration ci-dessus ne concernent que les deux <em>builds<\/em> pour Raspberry Pi 3 et 4, pas les autres <em>builds<\/em>. Il n&rsquo;est donc pas possible de rajouter ces \u00e9l\u00e9ments dans la propri\u00e9t\u00e9 <code>local.conf<\/code> du menu.<\/p>\n\n\n\n<p>Pour simplifier le menu et le rendre plus maintenable en \u00e9vitant les r\u00e9p\u00e9titions, il est possible d&rsquo;utiliser un m\u00e9canisme d&rsquo;<strong>h\u00e9ritage<\/strong>.<\/p>\n\n\n\n<p>Nous pouvons d\u00e9finir un objet dans l&rsquo;ensemble des <em>builds<\/em> qui ne sera pas compil\u00e9 par lui-meme mais dont les attributs seront ajout\u00e9s aux <em>builds<\/em> qui demandent \u00e0 en h\u00e9riter.<\/p>\n\n\n\n<p>Pour rendre un <em>build<\/em> non compilable, deux possibilit\u00e9s s&rsquo;offrent \u00e0 nous&nbsp;:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>ne pas lui d\u00e9finir d&rsquo;attribut <code>target<\/code> ;<\/li><li>lui donner un nom qui commence par un point. On dit qu&rsquo;il agit alors d&rsquo;un <em>template<\/em>.<\/li><\/ul>\n\n\n\n<p>C&rsquo;est la seconde option que j&rsquo;ai choisie ici. Le <em>build<\/em> g\u00e9n\u00e9rique <code>.raspberrypi<\/code> ne sera pas compil\u00e9, mais ses attributs  seront h\u00e9rit\u00e9s par les deux autres <em>builds<\/em>.<\/p>\n\n\n\n<p>Pour indiquer qu&rsquo;un <em>build<\/em> h\u00e9rite d&rsquo;un autre, il suffit de lui ajouter un attribut <code>inherit<\/code> indiquant le <em>template<\/em> de base.<\/p>\n\n\n\n<p>Voici donc le fichier <code><a rel=\"noreferrer noopener\" href=\"https:\/\/www.blaess.fr\/christophe\/files\/yocto-cooker\/menu-003.json\" data-type=\"URL\" data-id=\"https:\/\/www.blaess.fr\/christophe\/files\/yocto-cooker\/menu-003.json\" target=\"_blank\">menu-003.json<\/a><\/code> d\u00e9finitif. Je n&rsquo;ai pas reproduit les <em>builds<\/em> <code>qemux86 et<\/code>qemuarm` d\u00e9j\u00e0 pr\u00e9sents pr\u00e9c\u00e9demment.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cat menu-003.json\n\n{\n  \"sources\" : &#91;\n    { \"url\": \"git:\/\/git.yoctoproject.org\/poky\", \"branch\": \"dunfell\", \"rev\": \"yocto-3.1.13\" },\n    { \"url\": \"git:\/\/git.openembedded.org\/meta-openembedded\", \"branch\": \"dunfell\", \"rev\": \"ab9fca48\" },\n    { \"url\": \"git:\/\/git.yoctoproject.org\/meta-raspberrypi\", \"branch\": \"dunfell\", \"rev\": \"934064a0\" }\n  ],\n\n  \"layers\" : &#91;\n    \"poky\/meta\",\n    \"poky\/meta-poky\",\n    \"poky\/meta-yocto-bsp\"\n  ],\n\n  \"local.conf\": &#91;\n    \"IMAGE_FEATURES += 'empty-root-password' \"\n  ],\n\n  \"builds\" : {\n\n    \"qemuarm\": {\n      &#91;...]\n    },\n\n    \"qemux86\": {\n      &#91;...]\n    },\n\n    \"<strong>.raspberrypi<\/strong>\" : {\n\n      \"target\": \"core-image-base\",\n\n      \"layers\" : &#91;\n        \"meta-raspberrypi\"\n      ],\n\n      \"local.conf\" : &#91;\n        \"ENABLE_UART = '1'         \",\n         \"ENABLE_SPI_BUS =  '1'     \",\n         \"ENABLE_I2C =  '1'         \",\n         \"HDMI_FORCE_HOTPLUG = '1'  \",\n         \"CONFIG_HDMI_BOOST = '1'   \"\n      ]\n    },\n\n    \"rpi3\" : {\n      <strong>\"inherit\": &#91; \".raspberrypi\" ],<\/strong>\n      \"local.conf\": &#91;\n        \"MACHINE = 'raspberrypi3'  \"\n      ]\n    },\n\n    \"rpi4\" : {\n      <strong>\"inherit\": &#91; \".raspberrypi\" ],<\/strong>\n      \"local.conf\": &#91;\n        \"MACHINE = 'raspberrypi4'  \"\n      ]\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>La structure du menu est ainsi assez \u00e9l\u00e9gante, tout ce qui concerne le <em>template<\/em> de base est regroup\u00e9 en un seul point, et des <em>builds<\/em> d\u00e9riv\u00e9s peuvent en h\u00e9riter pour compl\u00e9ter les param\u00e8tres.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">H\u00e9ritage multiple<\/h2>\n\n\n\n<p>Comme vous l&rsquo;avez peut-\u00eatre remarqu\u00e9, l&rsquo;attribut <code>inherit<\/code> d&rsquo;un objet <em>build<\/em> est un ensemble. Il peut donc contenir le nom de plusieurs <em>templates<\/em> de base.<\/p>\n\n\n\n<p>Cette notion d&rsquo;h\u00e9ritage peut s&rsquo;appliquer, comme ci-dessus au support mat\u00e9riel, mais \u00e9galement aux options du code m\u00e9tier.<\/p>\n\n\n\n<p>Supposons par exemple, que notre code applicatif soit ajout\u00e9 par une recette nomm\u00e9e <code>custom-app<\/code> et que cette derni\u00e8re puisse \u00eatre compil\u00e9e au choix en versions \u00ab\u00a0all\u00e9g\u00e9e\u00a0\u00bb (<code>lite<\/code>), \u00ab\u00a0normal\u00a0\u00bb (<code>base<\/code>) et \u00ab\u00a0compl\u00e8te\u00a0\u00bb (<code>ff<\/code> pour <em>full featured<\/em>).<\/p>\n\n\n\n<p>On pourra donc d\u00e9finir des <em>templates<\/em> de base sp\u00e9cifiques comme&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \"<strong>.lite<\/strong>\" : {\n    \"local.conf\": &#91;\n      \"PACKAGECONFIG:append:pn-custom-app = ' lite' \"\n    ]\n  },\n\n  \"<strong>.normal<\/strong>\" : {\n    \"local.conf\": &#91;\n      \"PACKAGECONFIG:append:pn-custom-app = ' normal' \"\n    ]\n  },\n\n  \"<strong>.ff<\/strong>\" : {\n    \"local.conf\": &#91;\n      \"PACKAGECONFIG:append:pn-custom-app = ' ff' \"\n    ]\n  }<\/code><\/pre>\n\n\n\n<p>Il sera alors possible de combiner des <em>builds<\/em> h\u00e9ritant de plusieurs <em>templates<\/em>, par exemple on pourrait d\u00e9finir&nbsp;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \"rpi3-lt\" : {\n    <strong>\"inherit\": &#91; \".raspberrypi\", \".lite\" ],<\/strong>\n    \"local.conf\": &#91; \"MACHINE = 'raspberrypi3'  \" ]\n  },\n\n  \"rpi3\" : {\n    <strong>\"inherit\": &#91; \".raspberrypi\", \".normal\" ],<\/strong>\n    \"local.conf\": &#91; \"MACHINE = 'raspberrypi3'  \" ]\n  },\n\n  \"rpi3-ff\" : {\n    <strong>\"inherit\": &#91; \".raspberrypi\", \".ff\" ],<\/strong>\n    \"local.conf\": &#91; \"MACHINE = 'raspberrypi3'  \" ]\n  },\n\n  \"rpi4-lt\" : {\n    <strong>\"inherit\": &#91; \".raspberrypi\", \".lt\" ],<\/strong>\n    \"local.conf\": &#91; \"MACHINE = 'raspberrypi4'  \" ]\n  },\n\n  \"rpi4\" : {\n    <strong>\"inherit\": &#91; \".raspberrypi\", \".normal\" ],<\/strong>\n    \"local.conf\": &#91; \"MACHINE = 'raspberrypi4'  \" ]\n  },\n\n  \"rpi4-ff\" : {\n    <strong>\"inherit\": &#91; \".raspberrypi\", \".ff\" ],<\/strong>\n    \"local.conf\": &#91; \"MACHINE = 'raspberrypi4'  \" ]\n  },<\/code><\/pre>\n\n\n\n<p>\u00c0 titre d&rsquo;exemple, j&rsquo;ai utilis\u00e9 cette approche pour un projet client o\u00f9 il fallait g\u00e9rer plusieurs plateformes mat\u00e9rielles et plusieurs tailles d&rsquo;\u00e9cran (ce qui jouait sur les fichiers <em>bitmaps<\/em> \u00e0 utiliser pendant le <em>boot<\/em>).<\/p>\n\n\n\n<p>Bien s\u00fbr on \u00e9vitera de trop multiplier le nombre de <em>builds<\/em> \u00e0 produire, pour limiter la complexit\u00e9 du travail \u00e0 la production et \u00e0 la maintenance.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Commentaires<\/h2>\n\n\n\n<p>L&rsquo;encha\u00eenement des diff\u00e9rents <em>builds<\/em> peut \u00eatre parfois un peu compliqu\u00e9 \u00e0 suivre.<\/p>\n\n\n\n<p>On peut regretter que le format JSON n&rsquo;accepte pas de commentaires permettant d&rsquo;expliquer un choix de <em>package<\/em>, la n\u00e9cessit\u00e9 d&rsquo;un <em>layer<\/em> ou une option de configuration d&rsquo;un <em>package<\/em>.<\/p>\n\n\n\n<p>Pour pallier ce probl\u00e8me, nous avons choisi d&rsquo;ajouter un attribut facultatif <code>notes<\/code> que l&rsquo;on peut ajouter au niveau du menu global ou au niveau d&rsquo;un objet <em>build<\/em>.<\/p>\n\n\n\n<p>\u00c0 titre d&rsquo;exemple nous pouvons observer des extraits d&rsquo;un fichier-menu fourni en exemple avec Yocto Cooker (r\u00e9pertoire <code>sample-menus<\/code>)\/<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  <strong>\"notes\" : &#91;<\/strong>\n    \"This is a standard menu for Raspberry Pi 3.\",\n    \"Please refer to the README file for instruction on how to build the image\"\n  <strong>],<\/strong>\n\n  \"sources\" : &#91;\n    { \"url\": \"git:\/\/git.yoctoproject.org\/poky\", \"branch\": \"zeus\", \"rev\": \"yocto-3.0.1\" },\n\n&#91;...]\n\n  \"builds\" : {\n\n    \"pi3\": {\n\n      <strong>\"notes\" : &#91;<\/strong>\n        \"The default `core-image-base` image is used for bitbake.\"\n      <strong>],<\/strong>\n      \"target\" : \"core-image-base\",\n\n&#91;...]<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Nous avons vu que le fichier-menu utilis\u00e9 par Yocto Cooker reste assez simple et lisible, m\u00eame s&rsquo;il offre des possibilit\u00e9s plut\u00f4t avanc\u00e9es, comme l&rsquo;h\u00e9ritage multiple.<\/p>\n\n\n\n<p>Dans l&rsquo;<a rel=\"noreferrer noopener\" href=\"https:\/\/www.blaess.fr\/christophe\/2022\/01\/13\/yocto-cooker-1-3\/\" data-type=\"post\" data-id=\"5897\" target=\"_blank\">article pr\u00e9c\u00e9dent<\/a> nous n&rsquo;avons utilis\u00e9 que les actions <code>cooker cook<\/code> et <code>cooker shell<\/code>. Il existe plusieurs autres actions possibles pour g\u00e9n\u00e9rer les images ou s&rsquo;assurer du fonctionnement de <code>cooker<\/code>. Nous les examinerons dans<br>le <a href=\"https:\/\/www.blaess.fr\/christophe\/2022\/01\/27\/yocto-cooker-3-3\/\" data-type=\"post\" data-id=\"5961\">prochain article<\/a>. <\/p>","protected":false},"excerpt":{"rendered":"<p>Dans le premier article de cette s&eacute;rie nous avons vu comment utiliser cooker pour produire une image avec Yocto Project en ne renseignant qu&rsquo;un seul fichier&nbsp;: le menu. Dans cet article nous allons voir comment compl&eacute;ter ce menu pour produire plusieurs builds en une seule commande, certains d&rsquo;entre-eux pouvant partager divers &eacute;l&eacute;ments de configuration.<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,8,21],"tags":[],"class_list":["post-5948","post","type-post","status-publish","format-standard","hentry","category-embarque","category-linux-2","category-yocto-project"],"_links":{"self":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/5948","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/comments?post=5948"}],"version-history":[{"count":5,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/5948\/revisions"}],"predecessor-version":[{"id":5971,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/5948\/revisions\/5971"}],"wp:attachment":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/media?parent=5948"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/categories?post=5948"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/tags?post=5948"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}