summary refs log tree commit diff
diff options
context:
space:
mode:
authorVladimír Čunát <vcunat@gmail.com>2016-02-10 21:18:34 +0100
committerVladimír Čunát <vcunat@gmail.com>2016-04-23 10:52:00 +0200
commit6e7787e666c50558b5aa10ffcca8e6c0c9bc1ba3 (patch)
tree0112b955ff093ab55a30f65c9017d6810876ab13
parent13df963c7eef2f2a6f469a881084bc5473d4cd88 (diff)
downloadnixpkgs-6e7787e666c50558b5aa10ffcca8e6c0c9bc1ba3.tar
nixpkgs-6e7787e666c50558b5aa10ffcca8e6c0c9bc1ba3.tar.gz
nixpkgs-6e7787e666c50558b5aa10ffcca8e6c0c9bc1ba3.tar.bz2
nixpkgs-6e7787e666c50558b5aa10ffcca8e6c0c9bc1ba3.tar.lz
nixpkgs-6e7787e666c50558b5aa10ffcca8e6c0c9bc1ba3.tar.xz
nixpkgs-6e7787e666c50558b5aa10ffcca8e6c0c9bc1ba3.tar.zst
nixpkgs-6e7787e666c50558b5aa10ffcca8e6c0c9bc1ba3.zip
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.
-rw-r--r--pkgs/build-support/setup-hooks/win-dll-link.sh45
-rw-r--r--pkgs/stdenv/generic/default.nix8
2 files changed, 52 insertions, 1 deletions
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 00000000000..be63f69ca10
--- /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 547541d2824..e01be369f42 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 {