Frustrations about splicing

A lot of this is actually in the nixpkgs manual, but I consider it really overwhelming due to too much prose and too many analogies. Let me try to summarise.

The three platforms are relevant when building a compiler:

  • buildPlatform = platform where the compiler is built
  • hostPlatform = platform where the compiler is run
  • targetPlatform = platform for which the compiler emits code, if the compiler has the limitation of only being able to emit code for a single platform

The word “compiler” here is relevant, because if you’re not building a compiler (i.e. runtime code-emitter), then targetPlatform is a bit nonsensical here and we should really just care about the first two platforms. (s/compiler/package/g, in that case…) Moreover, if you can choose the compiler’s target at runtime, then targetPlatform becomes irrelevant.

So, I’ll discuss for now the case of a non-compiler package, where we only care about build and host, because that’s really what us mere mortals are generally dealing with.

In such a case:

  • depsBuild*: things that should only be available at build-time, i.e. never get into the runtime closure!

    • depsBuildBuild: used to emit more build-time code (e.g. some executables/libs used to build build-time tooling)
    • depsBuildHost nativeBuildInputs: used to emit runtime code (e.g. build-systems for your package, like cmake, go here)
    • depsBuildTarget: used to just don’t.
  • depsHost*: things used at runtime

    In other words, depsHostHost and depsHostTarget buildInputs are the same, but we prefer calling the runtime deps buildInputs for no reason other than historical precedent.

    But for the sake of strictness in this summary, I will pretend that it is depsHostHost that refers to buildInputs in the non-compiler case since, again, target is nonsensical. (Btw, when packaging, we should still use buildInputs in most cases for runtime libs, especially because there are some things like fixup hooks that specifically check buildInputs and nothing else.)

  • depsTargetTarget: did you forget we don’t care about target?

To summarise: in a non-compiler package, we only use:

  • depsBuildBuild,
  • depsBuildHost nativeBuildInputs, and
  • depsHostHost buildInputs.

By this logic, to answer @anon20203487’s question:

extra-cmake-modules (ECM) is a KDE package which contains instructions for augmenting cmake to find various commonly-used binaries and libraries at build-time. In other words, cmake is using ECM at build-time, for build-time, i.e. you do not want ECM in the runtime closure!

So strictly speaking, cmake goes in depsBuildBuild, ECM goes in nativeBuildInputs.
If cmake is also used to build the actual package, then cmake will also go in nativeBuildInputs.
This duplication is fine, because the two uses of cmake in these lists mean two different things.
Finally, whatever libraries you’re linking against, including those mentioned by ECM, will go in buildInputs.

Do note that some packages might have some broken upstream code, so this approach may not work 100% of the time; this is just the most theoretically correct approach.

Technically runtime binaries could also go in buildInputs, but we don’t have any hooks to wrap the resulting package with binaries from buildInputs (we usually just use symlinkJoin or an explicit makeWrapper call), so it’d be kind of useless to put binaries in that list.

Maybe I’ll write a splicing essay tomorrow…

edit: proofread it a bit more

14 Likes