Had some great ideas while sleeping, but... now I have even more questions. Feels like I'm overcomplicating the first steps again.
One of the questions I have is: what information should a derivation contain? What do I need to build it? And how do I serialize that in a sane way?
Previously, when I was doing KDL config + Fennel extensions, it was all nicely KDL, and I could conveniently encode the builder + its "arguments" as a KdlDocument.
That's probably not the right approach when using Fennel for the config language.
I think I'm overengineering this again, because I keep thinking about bootstrapping, and reproducibility from ~zero. Those are nice, but... probably not important right now.
All I need is to have a derivation, and some builders that can produce the desired output. For simplicity's sake, I'd even implement a fuck-provided builder that requires no external tools, that can copy some declared files to the store. But how do I encode that in the derivation?
Maybe I'd continue using KDL. I do need a serialization format for derivations, and Fennel's not it: I don't want a programming language in the derivations! It's 100% data, and KDL feels like a better fit than a Fennel table.
In which case, the internal builder could also be parameterized via KDL. But that means all other builders would receive their parameters that way too...
On second thought, that's not a bad thing.
Now, since I decided to use Fennel for the configuration too, that meant that I do not need to register handlers for the various KDL nodes, as there won't be any. I just point fuck to a configuration, tell it which derivation to work with, it picks out that function, runs it, and gets a derivation it then decides what to do with (build it, run it, display it, that kind of stuff).
No registration whatsoever necessary!
However, I need fetchers and builders too, and most of them should be on the Fennel side. How do I work with those?
In other words, the question in my head is this: can I turn fetchers and builders into derivations too?
...and that's pretty much how I ended up thinking about bootstrapping.
Lets consider an imaginary hello package, a single shell script that prints "Hello World", and the derivation is a directory with bin/hello as the main entry point.
derivation hello-0 {
source type=declarative-tree {
file path="bin/hello" mode=0o0555 "..."
}
build-system identity
system arch=x86-64 os=linux
output out {
path "..."
hash algo=blake3 "..."
}
}
This should be enough to build the hello package.
How do we get from here to something more useful with a fetcher?
derivation gnu.hello-2.12.3 {
source type=tarball {
fetch {
url "..."
}
path "..."
hash algo=blake3 "..."
}
build-system autotools
system arch=x86-64 os=linux
output out { ... }
}
Here, the tarball source type, the fetcher, and the build-system would all be derivations this depends on. And then we have a bootstrap problem.
Questions about laziness, macros, namespacing, parameters, and suchlike. Yes, very vague, but the questions themselves are more of a feeling in my head than questions I can actually describe or ask.
It's complicated.