From e17554758868023857adce0cf4736787416ca5f8 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 14 Aug 2026 15:32:25 -0400 Subject: [PATCH 1/2] curl: do not ask for a host shell where there is none `wcurl` is a shell script, so a cross build rewrites its shebang to the host's `runtimeShell` and forbids the build one from being referenced. But for platforms that don't *have* a shell (e.g. MinGW, where `bash` needs Cygwin or similar) we still want to build curl. See the comments for details, but the short version is: - Don't even temporarily patch the installed script to the build shell --- that would be wrong. - Make the runtime dep conditional on a shell being available for the host at all. `patchShebangs --host` gracefully does nothing when it is not, so the call site needs no condition of its own. - Leave the disallowed references unconditional for cross: we never want to pollute the runtime closure with build tools, whether or not we patched anything. Assisted-by: Claude Code (Claude Opus 5) (cherry picked from commit 30cf6b6a9aac3880509dd3f407c1fd62a3935bdf) --- pkgs/by-name/cu/curlMinimal/package.nix | 58 ++++++++++++++++++++----- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/pkgs/by-name/cu/curlMinimal/package.nix b/pkgs/by-name/cu/curlMinimal/package.nix index 41cd5bfad64d..739610d7ae3f 100644 --- a/pkgs/by-name/cu/curlMinimal/package.nix +++ b/pkgs/by-name/cu/curlMinimal/package.nix @@ -105,8 +105,36 @@ stdenv.mkDerivation (finalAttrs: { # necessary for FreeBSD code path in configure postPatch = '' substituteInPlace ./config.guess --replace-fail /usr/bin/uname uname - patchShebangs scripts - ''; + '' + # `wcurl` is the one thing in `scripts` that is installed, so it is the one + # whose shebang has to suit the host platform. The rest are only used during + # the build, and want this platform's shell. Say which is which rather than + # patch them all one way and correct it afterwards. + # + # Where the host has no shell at all, `patchShebangs --host` finds nothing + # and leaves the shebang as shipped, which is the best available answer. + # + # TODO: take the first branch unconditionally --- in the spirit of strictDeps, + # it is good to always be defensive rather than do something unnecessarily + # that we can only get away with when build == host. + + ( + if isCross then + '' + local f flag + for f in scripts/*; do + if [[ "$f" == scripts/wcurl ]]; then + flag=--host + else + flag=--build + fi + patchShebangs "$flag" "$f" + done + '' + else + '' + patchShebangs scripts + '' + ); outputs = [ "bin" @@ -247,19 +275,27 @@ stdenv.mkDerivation (finalAttrs: { ln $out/lib/libcurl${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/libcurl-gnutls${stdenv.hostPlatform.extensions.sharedLibrary}.4 ln $out/lib/libcurl${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/libcurl-gnutls${stdenv.hostPlatform.extensions.sharedLibrary}.4.4.0 '' - # The wcurl shell script found in `''${!outputBin}/bin`, is located in the - # source along with all the scripts patched in `postPatch` above. - # `patchShebangs` at that stage causes the host intended wcurl script to get - # the buildPlatform's runtimeShell shebang, instead of the hostPlatform's. To - # make sure this doesn't happen we disallow it, and fix it above in the - # postInstall, and also with the conditional hostPlatform's - # runtimeShellPackage added in buildInputs. + # `postPatch` above should have pointed everything installed at the host's + # shell already. Do it again over what was installed, defensively. + lib.optionalString isCross '' - patchShebangs --update --host "''${!outputBin}/bin" + patchShebangs --host "''${!outputBin}/bin" ''; + + # Whether we patch the shebangs in the installed script or not, we should not + # have build platform software in the final runtime closure. outputChecks.bin.disallowedReferences = lib.optional isCross buildPackages.runtimeShellPackage; outputChecks.out.disallowedReferences = lib.optional isCross buildPackages.runtimeShellPackage; - buildInputs = lib.optional isCross runtimeShellPackage; + + # Some hosts have no shell for the scripts to point at: MinGW is the one in + # tree, where `bash` is marked unsupported because it needs a POSIX layer. We + # cannot patch shebangs in that case. + # + # TODO: drop the isCross part of the condition --- in the spirit of + # `strictDeps` it is good to have the dep (when it is available), even if it + # is gratuitous in the `build = host` case. + buildInputs = lib.optional ( + isCross && lib.meta.availableOn stdenv.hostPlatform runtimeShellPackage + ) runtimeShellPackage; passthru = let From d7e1c663a30ba63cfe980ceb31a88b4b6dbaa1dd Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 26 Aug 2026 11:40:22 -0400 Subject: [PATCH 2/2] curl: Fix TODOs from #553075 That PR left two TODOs for a later mass-rebuild. Now that PR is in staging, we can fix those TODOs. The diff should be self-explanatory, as the now-deleted TODOs said what is supposed to happen. Assisted-by: Claude Code (Claude Opus 5) (cherry picked from commit 3b5068f0b6647cf740e92828c4890ef6e373e66b) --- pkgs/by-name/cu/curlMinimal/package.nix | 41 ++++++++----------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/pkgs/by-name/cu/curlMinimal/package.nix b/pkgs/by-name/cu/curlMinimal/package.nix index 739610d7ae3f..a58bfb134608 100644 --- a/pkgs/by-name/cu/curlMinimal/package.nix +++ b/pkgs/by-name/cu/curlMinimal/package.nix @@ -113,28 +113,17 @@ stdenv.mkDerivation (finalAttrs: { # # Where the host has no shell at all, `patchShebangs --host` finds nothing # and leaves the shebang as shipped, which is the best available answer. - # - # TODO: take the first branch unconditionally --- in the spirit of strictDeps, - # it is good to always be defensive rather than do something unnecessarily - # that we can only get away with when build == host. - + ( - if isCross then - '' - local f flag - for f in scripts/*; do - if [[ "$f" == scripts/wcurl ]]; then - flag=--host - else - flag=--build - fi - patchShebangs "$flag" "$f" - done - '' - else - '' - patchShebangs scripts - '' - ); + + '' + local f flag + for f in scripts/*; do + if [[ "$f" == scripts/wcurl ]]; then + flag=--host + else + flag=--build + fi + patchShebangs "$flag" "$f" + done + ''; outputs = [ "bin" @@ -289,13 +278,7 @@ stdenv.mkDerivation (finalAttrs: { # Some hosts have no shell for the scripts to point at: MinGW is the one in # tree, where `bash` is marked unsupported because it needs a POSIX layer. We # cannot patch shebangs in that case. - # - # TODO: drop the isCross part of the condition --- in the spirit of - # `strictDeps` it is good to have the dep (when it is available), even if it - # is gratuitous in the `build = host` case. - buildInputs = lib.optional ( - isCross && lib.meta.availableOn stdenv.hostPlatform runtimeShellPackage - ) runtimeShellPackage; + buildInputs = lib.optional (lib.meta.availableOn stdenv.hostPlatform runtimeShellPackage) runtimeShellPackage; passthru = let