siemens / kas

Setup tool for bitbake based projects
MIT License
353 stars 144 forks source link

bblayers order #36

Closed HerrMuellerluedenscheid closed 3 years ago

HerrMuellerluedenscheid commented 3 years ago

Hey, the order of layers in BBLAYERS in the generated build directory deviates from the order in my yml configuration.

After removing bblayers.conf (just to see that I'm not mistaken) I run kas build mconfig.yml. This is BBLAYERS:

BBLAYERS ?= " \
    /home/pyrocko/yocto/qs-kas/meta-mender/meta-mender-core \
    /home/pyrocko/yocto/qs-kas/meta-mender/meta-mender-raspberrypi \
    /home/pyrocko/yocto/qs-kas/meta-openembedded/meta-networking \
    /home/pyrocko/yocto/qs-kas/meta-openembedded/meta-oe \
    /home/pyrocko/yocto/qs-kas/meta-openembedded/meta-python \
    /home/pyrocko/yocto/qs-kas/meta-openembedded/meta-webserver \
    /home/pyrocko/yocto/qs-kas/meta-quakesaver/. \
    /home/pyrocko/yocto/qs-kas/meta-quakesaver/meta-qs-raspberrypi \
    /home/pyrocko/yocto/qs-kas/meta-scipy \
    /home/pyrocko/yocto/qs-kas/poky/meta \
    /home/pyrocko/yocto/qs-kas/poky/meta-poky \
    /home/pyrocko/yocto/qs-kas/poky/meta-yocto-bsp"

And this is the order of my yml file:

  meta-quakesaver:
    layers:
      .:
      meta-qs-raspberrypi:

  meta-scipy:

  meta-mender:
    layers:
      meta-mender-core:
      meta-mender-raspberrypi:
      meta-mender-core:

  meta-openembedded:
    layers:
      meta-oe:
      meta-python:
      meta-networking:
      meta-webserver:

  poky:
    layers:
       meta:
       meta-poky:
       meta-yocto-bsp:

As you can see it's not reversed but just different. The actual config includes another config.yml but that one doesn't define any layers or repos. Any idea why that happens?

HerrMuellerluedenscheid commented 3 years ago

BTW: I removed url and refspec to make the example a little more lightweight.

jan-kiszka commented 3 years ago

kas processes repos in parallel, plus repos and layers can come different include files. This made generated config files undeterministic, see c9326cc1edc9e84e950cdec7f0cecd4a520570ac. I'm open for a more user-controllable ordering algorithm, provided it's deterministic. But it's not a simple thing to solve I'm afraid.

Weren't layer prior invented for sorting out such ordering issues?

HerrMuellerluedenscheid commented 3 years ago

I'm not entirely sure and probably lack deeper understanding of how things are put together under the hood. I always thought that layer order actually matters. Given that two layers have identical priorities wouldn't assignments with e.g. ?= result in different settings dependent on the ordering of layers?

I asked in the yocto irc if order matters and basically got two replies:

Hey there: just to confirm: the order of the layers defined in BBLAYERS matters, right? mckoan: Yes mckoan: 1st priority, 2nd order qschulz: it's more complex than that, so if you have a precise question we can answer qschulz: bbclass and conf files are not handled the same way as bb or bbappends

If order matters, c9326cc1edc9e84e950cdec7f0cecd4a520570ac would be rather counterproductive.

jan-kiszka commented 3 years ago

That commit was needed as we were otherwise producing even random orders. But things seem to have changed since then, including dict becoming ordered by default. I think we can try reverting this. Can you check how far this gets us?

diff --git a/kas/config.py b/kas/config.py
index 0119f68..9b827fb 100644
--- a/kas/config.py
+++ b/kas/config.py
@@ -24,6 +24,7 @@
 """

 import os
+from collections import OrderedDict
 from .repos import Repo
 from .includehandler import IncludeHandler, IncludeException

@@ -87,7 +88,7 @@ class Config:
         """
         repo_config_dict = self._config.get('repos', {})
         repo_defaults = self._config.get('defaults', {}).get('repos', {})
-        repo_dict = {}
+        repo_dict = OrderedDict()
         repo_fallback_path = os.path.dirname(self.filenames[0])
         for repo in repo_config_dict:
             repo_config_dict[repo] = repo_config_dict[repo] or {}
@@ -128,7 +129,7 @@ class Config:
             Returns the local.conf header
         """
         header = ''
-        for key, value in sorted(self._config.get(header_name, {}).items()):
+        for key, value in self._config.get(header_name, {}).items():
             header += '# {}\n{}\n'.format(key, value)
         return header

diff --git a/kas/libcmds.py b/kas/libcmds.py
index d65048d..750c973 100644
--- a/kas/libcmds.py
+++ b/kas/libcmds.py
@@ -245,8 +245,8 @@ class WriteBBConfig(Command):
                 fds.write(ctx.config.get_bblayers_conf_header())
                 fds.write('BBLAYERS ?= " \\\n    ')
                 fds.write(' \\\n    '.join(
-                    sorted(layer for repo in ctx.config.get_repos()
-                           for layer in repo.layers)))
+                    layer for repo in ctx.config.get_repos()
+                    for layer in repo.layers))
                 fds.write('"\n')

         def _write_local_conf(ctx):

We may still have an undesired order of things across includes, simply because ordering was so far not checked. If that's the case, I suppose we can sort that out before the next release if folks with such workload provide feedback (our layering does not rely on ordering, thus cannot help).

jan-kiszka commented 3 years ago

Ping @HerrMuellerluedenscheid

HerrMuellerluedenscheid commented 3 years ago

Hey, sorry for the late reply. I did a quick test and can confirm that that patch preserves the layer order!

HerrMuellerluedenscheid commented 3 years ago

Let me know if I can help with anything else on that end. Feel free to close the issue.

jan-kiszka commented 3 years ago

Sorting by list order was discussed in https://groups.google.com/g/kas-devel/c/kbX_NAtQEMk, and we concluded to stick with ordering by name.

paweljonskim commented 3 years ago

@jan-kiszka Hello, unfortunately ordering layers by name makes kas unusable in our environment. We cannot really change that because of external yocto environment delivered from another company, but we still would like to use with kas. Is it closed matter or maybe we could find a way to maintain the yml layer order somehow?

jan-kiszka commented 3 years ago

Ordering is by layer key, as defined in the kas files. Is that external delivery providing you kas files as well? But even then: There is always a way to move a string before or after an existing set of stings.

paweljonskim commented 3 years ago

Can you please explain what do you mean by layer key? No, the provided repo does not contain kas config file. I will elaborate my case. Part of kas config yml file:

repos:
  repo_name:
    url: "git@github.com:org/repo_name.git"
    refspec: master
    layers:
      meta-c:
      meta-b:
      meta-a:

ends up creating bblayers.conf:

BBLAYERS ?= " \
    /home/pjonski/workspace/kasproject/repo_name/meta-a \
    /home/pjonski/workspace/kasproject/repo_name/meta-b \
    /home/pjonski/workspace/kasproject/repo_name/meta-c \

So repo names get sorted, which is not what I would expect. What do you mean by layer key?

jan-kiszka commented 3 years ago

Please read the email thread referenced in this issue, specifically https://groups.google.com/g/kas-devel/c/kbX_NAtQEMk/m/jYQzuz5VAgAJ.

90degs2infty commented 5 months ago

Sorry for resurrecting the dead. I've just stumbled upon a similar problem and wanted to add some thoughts on this.

From how I read this issue, kas relies on the layer ordering being specified by means of priorities (i.e. out of control of kas, as the layers themselves should set BBFILE_PRIORITY_... as needed). Consequently, the way kas orders the layers when writing BBLAYERS to conf/bblayers.conf should not matter. However, from how I understand Yocto's docs, the ordering in fact does matter:

Priority values control which layer takes precedence if there are recipe files with the same name in multiple layers. For these cases, the recipe file from the layer with a higher priority number takes precedence. Priority values also affect the order in which multiple .bbappend files for the same recipe are applied.

-- docs.yoctoproject.org

Note in the above, that the docs explicitly refer to recipes and append files. Quoting the docs some more:

Also, the layer priority does not currently affect the precedence order of .conf or .bbclass files. Future versions of BitBake might address this.

-- docs.yoctoproject.org

and

BitBake parses each conf/layer.conf file from the top down as specified in the BBLAYERS variable within the conf/bblayers.conf file. During the processing of each conf/layer.conf file, BitBake adds the recipes, classes and configurations contained within the particular layer to the source directory.

-- docs.yoctoproject.org

So to my understanding, bitbake respects priorities only in some context, while in others it falls back to the order in BBLAYERS.

In my specific use case, it was enough to employ the workaround referenced above. But I feel like this only works if there is a one-to-one mapping between git-repositories and layers. As soon as one maintains several layers within the same git repository,[^1] there is no way for the user to fully control the layers' ordering in BBLAYERS, right? So as long as bitbake in parts relies on the ordering in BBLAYERS, it might be beneficial to provide a fully user-controlled way to order layers from within kas?

[^1]: as is the case e.g. for meta-openembedded