Javier has been doing some excellent work in tidying up our graphics stack. One of the things he's had to do is split the strata up to be smaller, resulting in more strata over-all.

This is in-general a good thing, since it results in fewer superfluous dependencies, meaning fewer rebuilds after things are changed.

It has the unfortunate side-effect of requiring our system morphologies to need to list many strata to get a functional system.

This is because we don't currently have the concept of runtime-dependencies in morph, beyond what gets listed in the system artifact.

Some software will cope with optional runtime-dependencies, but it's no big loss in functionality to remove an optional dependency by conditionalising it via some tag from the system, compared to omitting it from the stratum list.

Format

So to include the new runtime-dependency information, we would change the gtk3 stratum to include this:

name: gtk3
kind: stratum
description: the gtk3 stratum
build-depends:
- morph: strata/gtk-deps.morph
- morph: strata/wayland-generic.morph
run-depends:
  gtk3-runtime:
  - morph: strata/gtk-deps.morph
    artifacts:
    - gtk-deps-runtime
  - morph: strata/wayland-generic.morph
    artifacts:
    - wayland-generic-runtime
  gtk3-devel:
  - morph: strata/gtk-deps.morph
    artifacts:
    - gtk-deps-runtime
    - gtk-deps-devel
  - morph: strata/wayland-generic.morph
    artifacts:
    - wayland-generic-runtime
    - wayland-generic-devel
chunks:
- name: libepoxy
  repo: upstream:libepoxy
  ref: 7422de5b4be7b19d789136b3bb5f932de42db27c
  unpetrify-ref: v1.2
  build-depends: []
- name: gtk3
  morph: strata/gtk3/gtk3.morph
  repo: upstream:gtk+
  ref: 911f3fb6d29f1570a2d30db6f2085d0202e7ad2a
  unpetrify-ref: 3.15.0
  build-depends:
  - libepoxy

I welcome suggestions on how to make the run-depends shorter while still handling split strata. Similarly it would be handy to have a way to specify runtime dependencies of artifacts you produce on each other.

An alternative idea might be to have run-depends look like:

run-depends:
  gtk3-runtime:
  - gtk-deps-runtime
  - wayland-generic-runtime
  gtk3-devel:
  - gtk3-runtime
  - gtk-deps-devel
  - wayland-generic-devel

This would work out which artifacts are meant from which strata are built-depended on and which artifacts are produced by building the sources of this morphology.

However, this precludes the possibility of runtime depending on a stratum you didn't build-depend on. This is possible for things like python modules, which tend to use libraries that they don't need to be present at "build" time.

Also, we don't currently allow referring to artifacts without also referring to the source they came from, so we could get conflicts where multiple sources produced an artifact called gtk3-runtime.

We could solve both by requiring the morphology and artifact be specified, at which point it looks more like this:

run-depends:
  gtk3-runtime:
  - morph: strata/gtk-deps.morph
    artifact: gtk-deps-runtime
  - morph: strata/wayland-generic.morph
    artifact: wayland-generic-runtime
  gtk3-devel:
  - artifact: gtk3-runtime
  - morph: strata/gtk-deps.morph
    artifact: gtk-deps-devel
  - morph: strata/wayland-generic.morph
    artifact: wayland-generic-devel

However, at that point we're back to the previous form, except if you want to depend on multiple artifacts produced by the sources of a morphology, you have to list the morph: line multiple times.

"metapackage"-like functionality

If we slacken the validation of morphologies to allow a stratum morphology to be entirely runtime depends, then we can define helpful strata for collecting functionality together.

name: gnome-desktop
kind: stratum
run-depends:
  gnome-desktop-runtime:
  - morph: strata/gnome-shell.morph
    artifact: gnome-shell-runtime
  - morph: strata/gnome-terminal.morph
    artifact: gnome-terminal-runtime
  - morph: strata/gedit.morph
    artifact: gedit-runtime
  gnome-desktop-devel:
  - artifact: gnome-desktop-runtime
  - morph: strata/gnome-shell.morph
    artifact: gnome-shell-devel
  - morph: strata/gnome-terminal.morph
    artifact: gnome-terminal-devel
  - morph: strata/gedit.morph
    artifact: gedit-devel

Semantics at system artifact construction time

We'll continue to include all the chunk artifacts the specified stratum artifact includes, and not treat the absence of runtime dependencies as a build failure, as this provides a migration path.

If a stratum artifact has runtime dependencies listed, then we'll include them in the system artifact, and all the runtime dependencies of those dependencies recursively.

Semantics at staging area population time

We can either include runtime dependencies of artifacts we build-depend on, or leave runtime dependencies to being purely for system artifact construction time.

There's arguments for either.

It makes some amount of sense for runtime dependencies of an artifact you build-depend on to be included in the staging area, as it saves having to define these build-only-runtime-depends as build-depends, which would cause unnecessary build-time dependencies for python modules.

However, if you don't include this, then you only need to rebuild the system artifact when build-dependencies change, which has some appeal.

The important thing is that you don't depend on your runtime dependencies at build-time, but people who depend on you end up depending on your runtime dependencies.

This is sufficiently odd that it bakes my noodle a little.

Cache key changes

No explicit changes need to be made, but the dependencies of a source get extended.

If we're not using the runtime dependencies of our build-depends, then we just change the system morphology dependency graphing to make it depend on all the runtime dependencies of the strata we list as well.

It's the same idea if we want to include the runtime dependencies at build time, but it's applied to every type of produced artifact, which implies rebuilds when you change runtime-depends.