From a2f34149ca99f0029601a1745f2decb7c5ce7c55 Mon Sep 17 00:00:00 2001 From: Dario Gabriel Lipicar Date: Fri, 14 Aug 2026 10:29:11 -0300 Subject: [PATCH] feat(windows): stage an external library's DLL from /bin externalLibCopies flattens each external library into the module's ./lib so CMake's find_library can see it, but it only ever reads /lib. A library that follows the WINDOWS convention ships its runtime half in bin/ -- that is CMake's own RUNTIME destination, and what openssl, postgres and every autotools port in nixpkgs do. For those, the staged lib/ ends up holding the import library or the static archive but no .dll, and LogosModule.cmake then hard-fails with "found no companion DLL in .../lib" -- or, worse, silently links the static archive instead. Take that library's own .dll from bin/ as well. Matching only *.dll keeps this inherently Windows-only (no native package ships one in bin/), so no platform flag has to be threaded in and a native build provably cannot pick up a stray executable. Only THIS library's files are copied, never all of bin/: the dependency DLLs that nixpkgs' win-dll-link hook stages there must stay symlinks, created by the postFixup pass below. Copying them as real files would make $out/lib look complete while leaving the Nix closure empty again -- a PE embeds no store paths, so those symlinks are the only thing the reference scanner can see. Verified by cross-building logos-delivery-module for x86_64-windows against a logos-delivery that installs its .dll to bin/: the plugin links the import library, and loads and dispatches on real Windows. Co-Authored-By: Claude Opus 5 --- lib/buildPlugin.nix | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/buildPlugin.nix b/lib/buildPlugin.nix index 9a776ef..6cbb6c1 100644 --- a/lib/buildPlugin.nix +++ b/lib/buildPlugin.nix @@ -97,6 +97,27 @@ let if [ -d "${libInfo}/lib" ]; then cp -r "${libInfo}/lib"/* lib/ 2>/dev/null || true fi + # A library that follows the WINDOWS convention ships its runtime half + # in bin/ -- that is CMake's RUNTIME destination, and what openssl, + # postgres and every autotools port in nixpkgs do. Without this the + # staged lib/ holds the import library or the static archive but no + # .dll, and LogosModule.cmake then hard-fails with "found no companion + # DLL in .../lib" (or links the static archive by accident). + # + # Only THIS library's own files are taken, never all of bin/: the + # dependency DLLs that nixpkgs' win-dll-link hook stages there must stay + # symlinks, created by the postFixup pass below. Copying them as real + # files would make $out/lib look complete while leaving the Nix closure + # empty again -- a PE embeds no store paths, so those symlinks are the + # only thing the reference scanner can see. + # Matching only *.dll keeps this inherently Windows-only -- no native + # package ships one in bin/ -- so no platform flag has to be threaded + # in, and a native build provably cannot pick up a stray executable. + if [ -d "${libInfo}/bin" ]; then + for f in "${libInfo}"/bin/lib${extLib.name}.dll "${libInfo}"/bin/${extLib.name}.dll; do + [ -f "$f" ] && cp -fL "$f" lib/ 2>/dev/null || true + done + fi if [ -f "${libInfo}" ]; then cp "${libInfo}" lib/ 2>/dev/null || true fi