Packaging custom assets for another program/package

I want to create a nix package containing custom assets for another program. The program expects to find the assets in a particular place relative to the executable, or in a directory under ${XDG_DATA_HOME} (which defaults to ~/.local/share). Alternatively, there is a command line option to specify the location of the assets.

The program in this case is Pandoc, and the assets are templates, but I think this is a general use-case.

Here are the approaches I’m considering. Are there any good approaches I’ve overlooked?

  1. Create an ordinary (separate) derivation for these custom assets, except there’s no executable.

PRO: People could choose to install it, or run it in a shell (which is especially nice if they want different versions for different projects).

CON: The user has to find out where in the nix store the assets ended up, and supply that path in the command line option every time they invoke the program. Or they could create an alias or script to invoke the program for them, or create a link under ${XDG_DATA_HOME} to the nix store. But they’ll have to change this every time they install a new version of the assets.

  1. Create a derivation that installs both the program and the assets.

PRO: Users don’t need to know where the assets are.

CON: Probably best if users don’t install the derivation because it would hide their “ordinary” Pandoc binary.

CON: Duplication of effort, since the program has already been packaged in nixpkgs.

  1. Create a derivation that links the assets under ${XDG_DATA_HOME}/pandoc/defaults.

Is this even possible? I wrote the assets to $out/share/pandoc, and they end up in the nix store, but they don’t seem to be linked anywhere.

  1. Create a derivation that also sets an environment variable to the location of the assets in the nix store.

Is this even possible?

You’re on the right track. One way to handle something like this is by making a derivation that builds an executable wrapper that will set some environment variables and then exec some other executable.

Some packages have this functionality in the form of a passthru function, often named something like withPlugins, withExtensions, withLibraries, and so on. Here’s an example in nixpkgs:

If you wanted the bare tflint, you could just use tflint, but if you needed something else you could build a wrapper with something like:

tflint.withPlugins (cp: [ cp.tflint-ruleset-aws ])

This is just for convenience; you can do the same thing by building one derivation for the template files, and another (you can use runCommand as above) that builds a wrapper that will run pandoc and either specify your templates via arguments or environment variables.