Hi all,

After a little bit of thinking about a conversation off list, and also Nathan's idea, I have a possible alternate approach for my use-case.

Each board could be its own distinct bst project (potentially in its own repo), that pulls in upstream GNOME OS through a junction. We can then use the junction's element replacement feature to inject whatever we need into the build pipeline. For example, we'd define some integration points:

```
# gnomeos/elements/board/kernel.bst
# This is a stub element
kind: stack

# We can't build GNOME OS without a kernel. So, if the board doesn't provide a kernel to use, make the build fail!
(!): "The board must define a kernel!"
```

```
# gnomeos/elements/board/extra-packages.bst
kind: stack
# This is a stub element, but it's a complete no-op. Does nothing unless overridden
```

Anyway, you'd have a ton of these stub elements. Then the rest of the build pipeline can be defined in terms of these stubs. For example, there might be an elements/board/_internal/uki.bst that depends on `board/kernel.bst` and `board/extra-kernel-cmdline.bst` and feeds their generated artifacts into ukify to make a bootable kernel UKI with a kernel command-line baked in. Ultimately you end up with an elements/image.bst, that depends on all the elements/board/_internal/ stuff, and spits out the final disk image. In the GNOME OS repo, if you try to `bst build image.bst` you'll get failures because of all the stub elements.

Then, each board gets a bst project. The microsoft-surface board I describe above, for instance, could look like:

- project.conf
- elements/
  - image.bst
  - gnome.bst
  - linux-surface.bst
  - kernel-cmdline.bst
  - extra-packages.bst
  - webcam-firmware.bst
  - extra-power-profiles.bst
  - detatchable-keyboard-daemon.bst

The important element here is gnome.bst, which is our junction:

```
# elements/gnome.bst
kind: junction

source:
- ...

config:
  options:
    arch: "%{arch}" # Selectable arch, because Surface devices come in x86_64 and aarch64
  replace:
    board/kernel.bst: linux-surface.bst
    board/extra-packages.bst: extra-packages.bst
    board/extra-kernel-cmdline.bst: kernel-cmdline.bst
```

Then, for CLI convenience, we could define `image.bst` as an alias:

```
kind: link
config:
   target: gnome.bst:image.bst
```

And that's that! `bst build image.bst` in the microsoft-surface bst project will give you a packaged up GNOME OS image for that device.

Pros of this approach:
- Works with existing buildstream
- We can pretty easily experiment with various board enablement out-of-tree (potentially privately) before upstreaming it
- Distinct per-device CI pipelines and rules
- You can replace arbitrary packages if necessary. Maybe some board needs a custom build of mesa, then we can package that in the board's own project and simply add it to our list of replacements

Cons of this approach:
- Requires an external project, which makes it kinda awkward to put in a monorepo - Lots of bst boilerplate: project.conf, aliases, plugins, mirrors, etc. Need to figure out a good way to share this. A lot of it can probably be pulled through the junction, but you still need the boilerplate to do that

I think this is a not-bad approach overall. Still, I believe that generator plugins would be pretty convenient and nice-to-have to address other usecases I mentioned (subpackages, for instance). Would love to hear your thoughts.

Best,
Adrian

Reply via email to