Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC 0075] Declarative wrappers #75

Draft
wants to merge 38 commits into
base: master
Choose a base branch
from
Draft
Changes from 15 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ef81400
[RFC 55]: Declarative Wrappers
doronbehar May 10, 2020
b780229
Declarative wrappers
doronbehar Aug 15, 2020
d09a058
Finish motivation
doronbehar Aug 16, 2020
37c7a8c
Remove old RFC file
doronbehar Aug 16, 2020
2a0a630
Add more relevant issues regarding compiling wrappers
doronbehar Aug 16, 2020
c9d7055
Write most of the design and more
doronbehar Aug 16, 2020
abb7609
Small improvements to summary vs motivation
doronbehar Aug 16, 2020
d1cadb6
Rephrase a bit orchestrating motivation section
doronbehar Aug 16, 2020
a570b1a
Add small ()
doronbehar Aug 16, 2020
8db3605
More rephrasings and additions
doronbehar Aug 16, 2020
5ddd60b
Fix possibly fixable title
doronbehar Aug 16, 2020
778bc99
Design sec improvements
doronbehar Aug 16, 2020
44a3b87
Improve examples
doronbehar Aug 16, 2020
0b259fa
Improve ending
doronbehar Aug 16, 2020
d75c73e
Last (?) rephrasings
doronbehar Aug 16, 2020
94038bd
75: Introduction on run-time dependencies and wrappers.
FRidh Aug 20, 2020
0fa64ab
Merge pull request #1 from FRidh/75-intro
doronbehar Aug 25, 2020
ffacf5f
Add SANE_CONFIG_DIR issue to motivation
doronbehar Aug 30, 2020
f754ad7
Mark @nmattia's idea as unsuitable because of IFD.
doronbehar Sep 8, 2020
4ab0448
Revert "Mark @nmattia's idea as unsuitable because of IFD."
doronbehar Sep 11, 2020
60d3825
Add shepherds
edolstra Nov 19, 2020
f3416a0
Remove out scope Nixpkgs issue #32790 from motivation
doronbehar Feb 24, 2021
c092848
Add date to header
doronbehar Feb 24, 2021
732246d
Mention a new hplip wrapping issue
doronbehar Feb 24, 2021
67b002b
Update link to gnome docs
doronbehar Feb 24, 2021
cac0cbb
Better explain Nixpkgs issue #86369
doronbehar Feb 24, 2021
7b0c9e1
Remove some not directly related issues to wrapping
doronbehar Feb 24, 2021
034a13e
Rewrite most of RFC after 1st meeting
doronbehar Feb 24, 2021
edbf315
Small rephrasings
doronbehar Mar 19, 2021
48f9118
Add shepherd leader metadata
lheckemann Jun 10, 2021
73421fd
Apply suggestions by @lheckermann
doronbehar Jul 18, 2021
f0c2533
Rename wrappersInfo -> combineWrappersInfo
doronbehar Jul 18, 2021
391f5d0
Add subtitles for the motivation categories
doronbehar Jul 18, 2021
fb0dd98
Small rephrasings
doronbehar Aug 6, 2021
c51c9c0
Use a list of glob patterns for the wrapping
doronbehar Aug 6, 2021
31a24a0
Small rephrasings
doronbehar Aug 14, 2021
a6123b9
Explain default behaviour of order and separators
doronbehar Aug 14, 2021
a65ac77
Make combineWrappersInfo a nix function that returns a shell command
doronbehar Aug 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
353 changes: 353 additions & 0 deletions rfcs/0075-declarative-wrappers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,353 @@
---
feature: Declarative Wrappers
start-date: (fill me in with today's date, YYYY-MM-DD)
author: Doron Behar <[email protected]>
co-authors: (find a buddy later to help out with the RFC)
shepherd-team: (names, to be nominated and accepted by RFC steering committee)
shepherd-leader: (name to be appointed by RFC steering committee)
lheckemann marked this conversation as resolved.
Show resolved Hide resolved
related-issues: POC Implementation at [#85103](https://github.com/NixOS/nixpkgs/pull/85103).
---

# Summary
[summary]: #summary

Manage the environment of wrappers declaratively and deprecate shell based
methods for calculating runtime environment of packages. Make wrappers a
separate derivation so that mere changes to the environment will not trigger a
rebuild. Make it easier to debug why env vars are added to an executable, by
using Nix as the language to evaluate what env vars are needed, instead of not
documented good enough and not easily debug-able shell hooks.

# Motivation
[motivation]: #motivation

We have numerous issues regarding wrappers and our wrapper shell hooks. Here's
a list of them, sorted to categories.
doronbehar marked this conversation as resolved.
Show resolved Hide resolved

## Closure related

- [issue 95027](https://github.com/NixOS/nixpkgs/issues/95027)

@jtojnar & @yegortimoshenko How
hard would it be to test all of our wrapped `gobject-introspection` using
packages that the equivalent, `GI_GIR_PATH` environment should work? If our
wrappers were declarative, and they were a separate derivation, at least we
wouldn't have to rebuild tons of packages to do so - we'd have to rebuild only
the wrappers. Plus, since all of the environment is available to us via
`builtins.toJSON`, it should be possible to write a script that will compare
the environments to make the transition easier to review.

## Missing environment

- [pull 83321](https://github.com/NixOS/nixpkgs/pull/83321)
- [pull 53816](https://github.com/NixOS/nixpkgs/pull/53816)

@rnhmjoj & @timokau How unfortunate it is that Python's `buildEnv` doesn't know
to do anything besides setting `NIX_PYTHONPATH` - it knows nothing about other
env vars, which some deps rely upon when eventually used. Declarative wrappers
don't care about the meaning of env vars - all of them are treated equally,
considering all of the inputs of a derivation equally.

- [pull 75851](https://github.com/NixOS/nixpkgs/pull/75851)
- [issue 87667](https://github.com/NixOS/nixpkgs/issues/87667)

Fixable with our current wrapping tools (I guess?) but it's unfortunate that we
have to trigger a rebuild of VLC and potentially increase it's closure size,
just because of a missing env var for only _some_ users. If only our wrapping
requirements were accessible via Nix attrsets, we could have instructed our
modules to consider this information when building the wrappers of the packages
in `environment.systemPackages`.

- [issue 87883](https://github.com/NixOS/nixpkgs/issues/87883) (Fixed)

@jtojnar wouldn't it be wonderful if the wrapper of gimp would have known
exactly what `NIX_PYTHONPATH` to use when wrapping gimp, just because `pygtk`
was in it's inputs? Declarative wrappers would also allow us to merge the
wrappings of such derivation to reduce double wrappings, as currently done at
[`wrapper.nix`](https://github.com/NixOS/nixpkgs/blob/b7be00ad5ed0cdbba73fa7fd7fadcb842831f137/pkgs/applications/graphics/gimp/wrapper.nix#L16-L28)
and
[`default.nix`](https://github.com/NixOS/nixpkgs/blob/b7be00ad5ed0cdbba73fa7fd7fadcb842831f137/pkgs/applications/graphics/gimp/default.nix#L142-L145).

- [issue 85306](https://github.com/NixOS/nixpkgs/issues/85306)
- [issue 84249](https://github.com/NixOS/nixpkgs/issues/84249)

`git-remote-hg` and `qttools` are not wrapped properly.

- [issue 86048](https://github.com/NixOS/nixpkgs/issues/86048)

I guess we don't wrap HPLIP because not everybody want to use these binaries
and hence want these GUI deps in their closure (if they were wrapped with a
setup hook)? Declarative wrappers would allow _some_ users to use the wrapped
binaries and others not to need this wrapping. Via an override or a NixOS
config flag, without triggering a rebuild of HPLIP itself, these users would be
easily satisfied.

## Orchestrating wrapping hooks

- [issue 78792](https://github.com/NixOS/nixpkgs/issues/78792)

@worldofpeace you are correct. All of these setup-hooks are a mess. At least we
have documented, (yet not totally implemented) this section of the manual
https://nixos.org/nixpkgs/manual/#ssec-gnome-common-issues-double-wrapped

Declarative wrappers will deprecate the usage of our shell based hooks and will
wrap all executables automatically according to their needs, without requiring
the contributor a lot of knowledge of the wrapping system. Also, double
wrappings will become a problem of the past.

- [issue 86369](https://github.com/NixOS/nixpkgs/issues/86369)

@ttuegel I get the sense [you support this idea of declarative
wrappers](https://github.com/NixOS/nixpkgs/issues/86369#issuecomment-626732191).
For anyone else interested in a summary, the issue is a bit complex, so once
you'll read the design of this RFC, and see examples of what the POC
implementation of declarative wrappers [is capable
of](https://github.com/NixOS/nixpkgs/pull/85103#issuecomment-614195666), I hope
you'll see how declarative wrappers will solve this issue.


## Issues _possibly_ fixable by declarative wrappers (?)

- [pull 61213](https://github.com/NixOS/nixpkgs/pull/61213)

I'm not sure what's the issue there. But, I'm sure that a declarative, Nix
based builder of a Python environment, even if this environment is used only
for a build, should make it easier to control and alter it's e.g `$PATH`.

- [issue 83667](https://github.com/NixOS/nixpkgs/issues/83667)

@FRidh I see no reason for Python deps of Python packages to need to be in
`propagatedBuildInputs` and not regular `buildInputs` but please correct me if
I'm wrong. I think this was done so in the past so it'd be easy to know how to
wrap them? Declarative wrappers won't require runtime-env-requiring deps to be
only in `propagatedBuildInputs` or `buildInputs` - it should pick such deps
from both lists. Hence, (I think) it should be possible to make Python's static
builds consistent with other ecosystems.

- [issue 86054](https://github.com/NixOS/nixpkgs/issues/86054)

@ttuegel TBH I can't tell if declarative wrappers might help, but I'm linking
this issue here because @worldofpeace wrote it might be related to wrappers?
Feel free to suggest removing this in the RFC review.

- [issue 49132](https://github.com/NixOS/nixpkgs/issues/49132)
- [issue 54278](https://github.com/NixOS/nixpkgs/issues/54278)
- [issue 39493](https://github.com/NixOS/nixpkgs/issues/39493)

`GDK_PIXBUF` compatibilities? I haven't investigated them to the details, so feel
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both of the issues related to gdk-pixbuf only happened for non-wrapped derivations and current wrapGAppsHook would already fix them.

The issue was, IIRC, that gdk-pixbuf NixOS module sets GDK_PIXBUF_MODULE_FILE environment variable, which was enabling binary gdk-pixbuf modules with ABI incompatible with the gdk-pixbuf the programs linked against. In one case it was caused by a bug that slipped through the ABI stability guarantees, in the other by running a program for i686 on x86_64.

Either way, it is somewhat orthogonal to wrappers. Only that we might want to always wrap graphical applications with librsvg gdk-pixbuf module.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though there is one concern around GDK_PIXBUF_MODULE_FILE – the environment variable supports only a single path so we need to build the cache containing all the modules using gdk-pixbuf-query-loaders – the current hook actually does not actually do that! but it is required for some image formats to work in e.g. eog. We will need to take inspiration in the module.

free @jtojnar to review me and tell me that declarative wrappers won't help.

## Unreported issues (AFAIK)

Issues that bother me personally, but I haven't bothered to open an issue since
I doubt it would be feasible to fix with our current wrapping ecosystem, excuse
my pessimism `wrap{G,Qt}AppsHook` authors.

`kdeconnect` has `kdoctools` in it's closure because it's wrapper has
`kdoctools` due to it picked by `wrapQtAppsHook`:

```
$ nix why-depends -f. kdeconnect kdoctools
/nix/store/sh42k6cz4j48br4cxi2qn173rys4japp-kdeconnect-1.3.5
╚═══bin/kdeconnect-cli: …xport XDG_DATA_DIRS='/nix/store/m16681i5dhhkhszi9w42ir037jvbnab9-kdoctools-5.71.0/share'${XDG_DA…
=> /nix/store/m16681i5dhhkhszi9w42ir037jvbnab9-kdoctools-5.71.0
```

A similar issue is with `kconfigwidgets.dev` and `kdeconnect`:

```
$ nix why-depends -f. kdeconnect kdeframeworks.kconfigwidgets.dev
/nix/store/sh42k6cz4j48br4cxi2qn173rys4japp-kdeconnect-1.3.5
╚═══bin/kdeconnect-cli: …port QT_PLUGIN_PATH='/nix/store/qssjj6ki7jiskw2kfygvfiy8fxrclwrl-kconfigwidgets-5.71.0-dev/lib/q…
=> /nix/store/qssjj6ki7jiskw2kfygvfiy8fxrclwrl-kconfigwidgets-5.71.0-dev
```

Also similar (but possibly fixable by moving `gobject-introspection` to a
different inputs list?):

```
$ nix why-depends -f. beets gobject-introspection.dev
/nix/store/93lfrhm8vp17m8ziqi8vp6v4cff67wkb-beets-1.4.9
╚═══bin/beet: …-expat-2.2.8-dev/bin:/nix/store/y3ym76wrak3300vsjyf3klr52cnzmxwd-gobject-introspection-1.64.1-de…
=> /nix/store/y3ym76wrak3300vsjyf3klr52cnzmxwd-gobject-introspection-1.64.1-dev
```

## Other issues
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More related issues with wrappers NixOS/nixpkgs#160923 and the ones linked at NixOS/nixpkgs#160923 (comment)


- [issue 60260](https://github.com/NixOS/nixpkgs/issues/60260)

General, justified complaint about wrappers.

- [issue 95027](https://github.com/NixOS/nixpkgs/issues/95027)
- [issue 23018](https://github.com/NixOS/nixpkgs/issues/23018)
- [issue 11133](https://github.com/NixOS/nixpkgs/issues/11133)
- [pull 95569](https://github.com/NixOS/nixpkgs/pull/95569)

Since our wrappers are shell scripts, `gdb` can't run them. What if we had
written a C based wrapper, that perhaps would read what environment it needs to
set from a JSON file, and it will call the unwrapped original executable? I
need feedback regarding whether `gdb` will play nice with this.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative to this is the libtool approach, which still allow you to use strace,gdb etc: https://www.gnu.org/software/libtool/manual/html_node/Invoking-libtool.html
If a binary wrapper is used than it should be compiled for every target as this increases package size/build time. Instead having the wrapper reading its actual configuration from the same directory might work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compiling a binary wrapper for each target is probably a small overhead. All it needs to do is modify the environment and exec the target. This should be a trivial C program. I think I would rather it be something trivial like that then needing to read config files which is somewhat more complicated. Although if we really want to optimize we would need some proper profiling about build time and execution time (including cache effects).

But either way I think this proposal enables us to solve this problem, we can figure out the details when start to tackle it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Mic92 do you mean it should not be compiled for each package?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worked a bit on a wrapper tool some time ago: svep. Maybe there are some useful ideas there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worked a bit on a wrapper tool some time ago: svep. Maybe there are some useful ideas there?

That's a nice tool :), but I'm not sure it helps a lot, it seems it only supplies an alternative to makeCWrapper, but that depends on rust, and not pure C99.

We won't be able for example to use it to save the wrapping information of a package, as we want to access that information independently, from ${pkg}/nix-support/, and not from the binaries that the package may distribute.


This issue may not directly relate to declarative wrappers, and it is already
addressed in @FRidh's [pull 95569](https://github.com/NixOS/nixpkgs/pull/95569), but perhaps
both ideas could be integrated into an alternative, simpler creation method of
binary wrappers. See [my
comment](https://github.com/NixOS/nixpkgs/pull/95569#issuecomment-674508806).

# Detailed design
[design]: #detailed-design

The current design is roughly implemented at
[pull 85103](https://github.com/NixOS/nixpkgs/pull/85103) .

The idea is to have a Nix function, let us call it `wrapGeneric`, with an
interface similar to
[`wrapMpv`](https://github.com/NixOS/nixpkgs/blob/a5985162e31587ae04ddc65c4e06146c2aff104c/pkgs/applications/video/mpv/wrapper.nix#L9-L23)
and
[`wrapNeovim`](https://github.com/NixOS/nixpkgs/blob/a5985162e31587ae04ddc65c4e06146c2aff104c/pkgs/applications/editors/neovim/wrapper.nix#L11-L24)
which will accept a single derivation or an array of them and will wrap all of
their executables with the proper environment, based on their inputs.

`wrapGeneric` should iterate recursively all `buildInputs` and
`propagatedBuildInputs` of the input derivation(s), and construct an attrset with
which it'll calculate the necessary environment of the executables. Then either
via `wrapProgram` or a better method, it'll create the wrappers.

A contributor using `wrapGeneric` shouldn't _care_ what type of wrapping needs
to be performed on his derivation's executables - whether these are Qt related
wrappings or a Gtk / gobject related. `wrapGeneric` should know all there is to
know about environment variables every library / input may need during runtime,
and with this information at hand, construct the necessary wrapper.

In order for `wrapGenric` to know all of this information about our packaged
libraries - the information about runtime env, we need to write in the
`passthru`s of these libraries, what env vars they need. Such information was
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Limiting ourselves to environment variables is at times too limiting. Also, environment variables should be the implementation detail, although the variable names could be used as identifier.

Python example.

If you have a closure of packages, and there happens to be a Python application with Python libraries as dependencies, then that group of packages needs to be composed. If there is another Python application depending on other libraries, then that needs to be composed separately. At least, they are not allowed to share the same *PYTHONPATH. (Note one also should not use PYTHONPATH but that's a different discussion.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is another Python application depending on other libraries, then that needs to be composed separately. At least, they are not allowed to share the same *PYTHONPATH

I see this is all about ABI compatibility, and I understand the issue while I remember you mentioned this in NixOS/nixpkgs#85103 . I'm still unsure whether it's possible it'd happen, assuming our libraries are composed OK. @FRidh could you perhaps give a situation (with perhaps some rough code examples) to a situation where say Python2's and Python3's libraries will share the same *PYTHONPATH? It's important to note that the current design counts upon buildInputs and propagatedBuildInputs only.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Different Python version is one case, the other is simply applications requiring different versions of a dependency.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can happen for example when you have a python3 application that shells out to an python2 application.

Copy link
Member

@FRidh FRidh Aug 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently we prevent some of these effects by unsetting NIX_PYTHONPATH when a Python program starts, thereby avoiding leakage. This problem with wrappers and environment variables should also be noted clearly in the RFC.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I think I start to understand better the concerns. But still, this is not a "Drawback" of the idea, I mean, we still need to workaround such edge cases specifically in our current methods right? I agree though that it might be more complicated if someone is obliged to use wrapGeneric and not a wrap hook.

As an implementation detail, it may be worth noting that it'd be nice to make wrapGeneric able to "catch" such incompatible values in an environment variable.

added in the POC pull at [commit
@6283f15](https://github.com/NixOS/nixpkgs/pull/85103/commits/6283f15bb9b65af64571a78b039115807dcc2958).

Additional features / improvements are [already
available](https://github.com/NixOS/nixpkgs/pull/85103#issuecomment-614195666)
in the POC pull. For example:

- It should be **impossible** for multi-value env vars to have duplicates, as
that's guaranteed by Nix' behavior when constructing arrays / attrsets.
- Asking the wrapper creator to use more links and less colon-separated values
in env vars - should help avoid what [pull
84689](https://github.com/NixOS/nixpkgs/pull/84689) fixed.

# Examples and Interactions
[examples-and-interactions]: #examples-and-interactions

All examples are copied from and based on the [POC
pull](https://github.com/NixOS/nixpkgs/pull/85103).

Here's a new method of creating a python environment:

```nix
my-python-env = wrapGeneric python3 {
linkByEnv = {
# you can use "link" here and that will link only the necessary files
# to the runtime environment.
PYTHONPATH = "linkPkg";
};
extraPkgs = with python3.pkgs; [
matplotlib
];
wrapOut = {
# tells wrapGeneric to add to the wrappers this value for PYTHONPATH.
# Naturally, this should play along with the values given in
# linkByEnv.PYTHONPATH.
PYTHONPATH = "$out/${python3.sitePackages}";
};
};
```

Consider a package is wrapped without directly making accessible the unwrapped
derivation. Meaning, say `all-packages.nix` has:

```nix
my-awesome-pkg = wrapGeneric (callPackage ../applications/my-awesome-pkg { }) { };
```

Assuming the user knows `my-awesome-pkg` is wrapped with `wrapGeneric`, they would
need to use an overlay like this, to override the unwrapped derivation:

```nix
self: super:

{
my-awesome-pkg = super.wrapGeneric (
super.my-awesome-pkg.unwrapped.overrideAttrs(oldAttrs: {
preFixup = ''
overriding preFixup from an overlay!!
'';
})
) {};
}
```

And to override the wrapper derivation, e.g to add new optional features not
strictly necessary (as in [pull
83482](https://github.com/NixOS/nixpkgs/pull/83482)), it should be possible
using:

```nix
self: super:

{
my-awesome-pkg = super.wrapGeneric super.my-awesome-pkg.unwrapped {
extraPkgs = [
super.qt5.certain-qt-plugin
];
};
}
```

# Drawbacks
[drawbacks]: #drawbacks

The current design is heavily based on Nix, and knowing how to write and debug
Nix expressions is a skill not everyone are akin to learn. Also, overriding a
wrapped derivation is somewhat more awkward, due to this. Perhaps this
interface could be improved, and for sure proper documentation written should
help.

# Alternatives
[alternatives]: #alternatives

Perhaps our shell hooks _can_ be fixed / improved, and we could help make it
easier to debug them via `NIX_DEBUG`. Then it might help us track down e.g why
environment variables are added twice etc. Still though, this wouldn't solve
half of the other issues presented here. Most importantly, the shell hooks rely
upon being in the inputs during build of the original derivation. Hence, mere
requests for changes to an environment a wrapper sets, trigger rebuilds that
take a lot of time and resources from average users. See [this
comment](https://github.com/NixOS/nixpkgs/pull/88136#issuecomment-632674653).

# Unresolved questions
[unresolved]: #unresolved-questions

The POC implementation does 1 thing which I'm most sure could be done better,
and that's iterating **recursively** all `buildInputs` and
`propagatedBuildInputs` of the given derivations. This is currently implemented
with a recursive (Nix) function, prone to reach a state of infinite recursion.
This risk is currently mitigated using an array of packages we know don't need
any env vars at runtime, and for sure are very much at the bottom of the list
of all Nixpkgs' dependency graph. This part is implemented
[here](https://github.com/NixOS/nixpkgs/pull/85103/files#diff-44c2102a355f50131eb8f69fb7e7c18bR75-R131).

There are other methods of doing this recursive search, but I haven't yet
investigated all of them. For reference and hopefully for an advice, this need
was requested by others and discussed at:

- [nix issue 1245](https://github.com/NixOS/nix/issues/1245).
- [Interesting idea by @aszlig at nix issue
1245](https://github.com/NixOS/nix/issues/1245#issuecomment-401642781).
- [@nmattia's
post](https://www.nmattia.com/posts/2019-10-08-runtime-dependencies.html).
- [Discourse thread](https://discourse.nixos.org/t/any-way-to-get-a-derivations-inputdrvs-from-within-nix/7212/3).

# Future work
[future]: #future-work

Not that I can think of.