From 6e7787e666c50558b5aa10ffcca8e6c0c9bc1ba3 Mon Sep 17 00:00:00 2001 From: Vladimír Čunát Date: Wed, 10 Feb 2016 21:18:34 +0100 Subject: stdenv for windows: auto-link dependency DLLs For every *.{exe,dll} in $output/bin/ we try to find all (potential) transitive dependencies and symlink those DLLs into $output/bin so they are found on invocation. (DLLs are first searched in the directory of the running exe file.) The links are relative, so relocating whole /nix/store won't break them. The hook is activated on cygwin and when cross-compiling to mingw. --- pkgs/build-support/setup-hooks/win-dll-link.sh | 45 ++++++++++++++++++++++++++ pkgs/stdenv/generic/default.nix | 8 ++++- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 pkgs/build-support/setup-hooks/win-dll-link.sh diff --git a/pkgs/build-support/setup-hooks/win-dll-link.sh b/pkgs/build-support/setup-hooks/win-dll-link.sh new file mode 100644 index 000000000000..be63f69ca10b --- /dev/null +++ b/pkgs/build-support/setup-hooks/win-dll-link.sh @@ -0,0 +1,45 @@ + +fixupOutputHooks+=(_linkDLLs) + +# For every *.{exe,dll} in $output/bin/ we try to find all (potential) +# transitive dependencies and symlink those DLLs into $output/bin +# so they are found on invocation. +# (DLLs are first searched in the directory of the running exe file.) +# The links are relative, so relocating whole /nix/store won't break them. +_linkDLLs() { +( + if [ ! -d "$prefix/bin" ]; then exit; fi + cd "$prefix/bin" + + # Compose path list where DLLs should be located: + # prefix $PATH by currently-built outputs + local DLLPATH="" + local outName + for outName in $outputs; do + addToSearchPath DLLPATH "${!outName}/bin" + done + DLLPATH="$DLLPATH:$PATH" + + echo DLLPATH="'$DLLPATH'" + + linkCount=0 + # Iterate over any DLL that we depend on. + local dll + for dll in $(objdump -p *.{exe,dll} | sed -n 's/.*DLL Name: \(.*\)/\1/p' | sort -u); do + if [ -e "./$dll" ]; then continue; fi + # Locate the DLL - it should be an *executable* file on $DLLPATH. + local dllPath="$(PATH="$DLLPATH" type -P "$dll")" + if [ -z "$dllPath" ]; then continue; fi + # That DLL might have its own (transitive) dependencies, + # so add also all DLLs from its directory to be sure. + local dllPath2 + for dllPath2 in "$dllPath" "$(dirname "$dllPath")"/*.dll; do + if [ -e ./"$(basename "$dllPath2")" ]; then continue; fi + ln -sr "$dllPath2" . + linkCount=$(($linkCount+1)) + done + done + echo "Created $linkCount DLL link(s) in $prefix/bin" +) +} + diff --git a/pkgs/stdenv/generic/default.nix b/pkgs/stdenv/generic/default.nix index 547541d28246..e01be369f423 100644 --- a/pkgs/stdenv/generic/default.nix +++ b/pkgs/stdenv/generic/default.nix @@ -196,7 +196,13 @@ let buildInputs = if crossConfig != null then buildInputs' else []; propagatedBuildInputs = if crossConfig != null then propagatedBuildInputs else []; # Inputs built by the usual native compiler. - nativeBuildInputs = nativeBuildInputs ++ (if crossConfig == null then buildInputs' else []); + nativeBuildInputs = nativeBuildInputs + ++ lib.optionals (crossConfig == null) buildInputs' + ++ lib.optional + (result.isCygwin + || (crossConfig != null && lib.hasSuffix "mingw32" crossConfig)) + ../../build-support/setup-hooks/win-dll-link.sh + ; propagatedNativeBuildInputs = propagatedNativeBuildInputs ++ (if crossConfig == null then propagatedBuildInputs else []); } // ifDarwin { -- cgit 1.4.1