Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 5 additions & 3 deletions cross-js.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ let tool-version-map = (import ./tool-map.nix) self;
# add a trace helper. This will trace a message about disabling a component despite requesting it, if it's not supported in that compiler.
compiler-not-in = compiler-list: name: (if __elem compiler-nix-name compiler-list then __trace "No ${name}. Not yet compatible with ${compiler-nix-name}" false else true);

writers = import ./writers.nix { inherit pkgs; };

# * wrapped tools:
# A cabal-install wrapper that sets the appropriate static flags
wrapped-cabal = pkgs.writeShellApplication {
# A cabal-install wrapper that sets the appropriate static flags.
# See writers.nix for why writeShellApplicationWithRuntime is needed.
wrapped-cabal = writers.writeShellApplicationWithRuntime {
name = "cabal";
runtimeInputs = [ cabal-install pkgs.curl ];
text = with pkgs; ''
Expand Down Expand Up @@ -86,7 +89,6 @@ pkgs.mkShell ({
buildInputs = [];

nativeBuildInputs = [ wrapped-hsc2hs wrapped-cabal compiler ] ++ (with pkgs; [
curl
nodejs # helpful to evaluate output on the commandline.
cabal-install
(pkgs.pkg-config or pkgconfig)
Expand Down
9 changes: 7 additions & 2 deletions cross-windows.nix
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,14 @@ let tool-version-map = (import ./tool-map.nix) self;
kill $RISERV_PID
'';

# Use pkgsBuildBuild for the writers helper — cross-windows wrappers must be
# build-platform executables, not target-platform (which is Windows).
writers = import ./writers.nix { pkgs = pkgs.pkgsBuildBuild; };

# * wrapped tools:
# A cabal-install wrapper that sets the appropriate static flags
wrapped-cabal = pkgs.pkgsBuildBuild.writeShellApplication {
# A cabal-install wrapper that sets the appropriate static flags.
# See writers.nix for why writeShellApplicationWithRuntime is needed.
wrapped-cabal = writers.writeShellApplicationWithRuntime {
name = "cabal";
runtimeInputs = [ cabal-install curl ];
text = ''
Expand Down
7 changes: 5 additions & 2 deletions dynamic.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ let tool-version-map = (import ./tool-map.nix) self;
# add a trace helper. This will trace a message about disabling a component despite requesting it, if it's not supported in that compiler.
compiler-not-in = compiler-list: name: (if __elem compiler-nix-name compiler-list then __trace "No ${name}. Not yet compatible with ${compiler-nix-name}" false else true);

writers = import ./writers.nix { inherit pkgs; };

# * wrapped tools:
# fixup-nix-deps allows us to drop dylibs from macOS executables that can be
# linked directly.
Expand Down Expand Up @@ -40,7 +42,9 @@ let tool-version-map = (import ./tool-map.nix) self;
# have in the static configuration, and we may imagine needing to inject
# some flags into cabal (temporarily), hence we'll keep this functionality
# here.
wrapped-cabal = pkgs.writeShellApplication {
#
# See writers.nix for why writeShellApplicationWithRuntime is needed.
wrapped-cabal = writers.writeShellApplicationWithRuntime {
name = "cabal";
runtimeInputs = [ cabal-install pkgs.curl ];
text = ''
Expand Down Expand Up @@ -109,7 +113,6 @@ pkgs.mkShell {
stdenv.cc.cc.lib
]
++ (with pkgs; [
curl
openssl
pcre
pkg-config
Expand Down
8 changes: 5 additions & 3 deletions static.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ let tool-version-map = (import ./tool-map.nix) self;
# add a trace helper. This will trace a message about disabling a component despite requesting it, if it's not supported in that compiler.
compiler-not-in = compiler-list: name: (if __elem compiler-nix-name compiler-list then __trace "No ${name}. Not yet compatible with ${compiler-nix-name}" false else true);

writers = import ./writers.nix { inherit pkgs; };

# * wrapped tools:
# fixup-nix-deps allows us to drop dylibs from macOS executables that can be
# linked directly.
Expand All @@ -29,8 +31,9 @@ let tool-version-map = (import ./tool-map.nix) self;
done
'';
};
# A cabal-install wrapper that sets the appropriate static flags
wrapped-cabal = pkgs.writeShellApplication {
# A cabal-install wrapper that sets the appropriate static flags.
# See writers.nix for why writeShellApplicationWithRuntime is needed.
wrapped-cabal = writers.writeShellApplicationWithRuntime {
name = "cabal";
runtimeInputs = [ cabal-install pkgs.curl ];
text = with pkgs; ''
Expand Down Expand Up @@ -148,7 +151,6 @@ pkgs.mkShell (rec {
# products to be static.
(compiler.override { enableShared = true; })
] ++ (with pkgs; [
curl
(pkgs.pkg-config or pkgconfig)
stdenv.cc.cc.lib ]) ++ (with pkgs.buildPackages; [
])
Expand Down
71 changes: 71 additions & 0 deletions writers.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# writeShellApplicationWithRuntime — a drop-in replacement for writeShellApplication
# that also propagates runtimeInputs to dependent environments.
#
# ─── The problem ───────────────────────────────────────────────────────────────
#
# nixpkgs' writeShellApplication accepts a `runtimeInputs` parameter and
# compiles it into the wrapper script as:
#
# export PATH="${lib.makeBinPath runtimeInputs}:$PATH"
#
# This means the runtime inputs are only on PATH **inside the wrapper script
# itself**. They are NOT exposed as derivation attributes — not in
# propagatedNativeBuildInputs, not in passthru, nowhere.
#
# When a wrapper built this way is placed into a mkShell's buildInputs or
# nativeBuildInputs, `nix develop` reconstructs the environment by evaluating
# the shell derivation and walking all inputs. The Nix C++ evaluator (used by
# `nix develop` / `nix print-dev-env`) follows the full derivation closure, so
# it discovers everything transitively — including the runtimeInputs baked into
# wrapper scripts.
#
# However, devx generates `-env` container scripts at **evaluation time** using
# devShellTools. These scripts export raw derivation attributes and then
# `source "$stdenv/setup"` to reconstruct the environment. stdenv's setup.sh
# walks dependencies via the `findInputs` function (stdenv/setup lines 715-806),
# which reads `$pkg/nix-support/propagated-*` metadata files to discover
# transitive inputs. It does NOT look inside wrapper scripts.
#
# The result: any program in the -env container that is NOT the wrapper itself
# (e.g. GHC's stage0 bootstrap cabal, or any script that shells out to curl)
# cannot find the wrapper's runtimeInputs on PATH.
#
# ─── The fix ───────────────────────────────────────────────────────────────────
#
# We use overrideAttrs to add propagatedNativeBuildInputs to the wrapper
# derivation. When stdenv's setup.sh processes the wrapper from
# nativeBuildInputs, it:
#
# 1. Adds $wrapper/bin to PATH (the wrapper itself)
# 2. Reads $wrapper/nix-support/propagated-native-build-inputs
# 3. Recursively calls findInputs on each propagated input
# 4. Adds $curl/bin, $cabal-install/bin, etc. to PATH
#
# This makes runtimeInputs visible to the ENTIRE shell environment, not just
# inside the wrapper. The wrapper still has its own inline PATH injection
# (via writeShellApplication), so it works in both contexts.
#
# ─── Why not upstream? ─────────────────────────────────────────────────────────
#
# Ideally, nixpkgs' writeShellApplication would set propagatedNativeBuildInputs
# from runtimeInputs by default. Until that happens, this wrapper bridges
# the gap. If upstream adopts this, this file becomes a no-op passthrough
# and can be removed.
#
# ─── Usage ─────────────────────────────────────────────────────────────────────
#
# let writers = import ./writers.nix { inherit pkgs; };
# in writers.writeShellApplicationWithRuntime {
# name = "cabal";
# runtimeInputs = [ cabal-install pkgs.curl ];
# text = ''...'';
# }
#
{ pkgs }:
{
writeShellApplicationWithRuntime = args@{ runtimeInputs ? [], ... }:
(pkgs.writeShellApplication args).overrideAttrs (old: {
propagatedNativeBuildInputs =
(old.propagatedNativeBuildInputs or []) ++ runtimeInputs;
});
}
Loading