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