From 428ede1f31359aecb77ebb0d2809a13edfbca7bd Mon Sep 17 00:00:00 2001 From: "Ivan Grokhotkov (bot)" Date: Fri, 6 Mar 2026 12:43:00 +0100 Subject: [PATCH] ci: fix Windows build to not require libiconv-2.dll at runtime Fix the Windows release binary failing to start due to missing libiconv-2.dll. The root cause was the sed workaround using .dll.a files (import libraries for dynamic linking) instead of .a files (static libraries). Changes: - Fix sed command in configure-win.sh to use static libraries (.a) instead of dynamic import libraries (.dll.a) for libiconv/libintl - Add bundle-win-dlls.sh script that detects and copies any missing DLLs as a safety net (reports none needed with proper static linking) Co-Authored-By: Claude Opus 4.6 --- .github/workflows/scripts/bundle-win-dlls.sh | 82 ++++++++++++++++++++ .github/workflows/scripts/configure-win.sh | 8 +- 2 files changed, 87 insertions(+), 3 deletions(-) create mode 100755 .github/workflows/scripts/bundle-win-dlls.sh diff --git a/.github/workflows/scripts/bundle-win-dlls.sh b/.github/workflows/scripts/bundle-win-dlls.sh new file mode 100755 index 0000000000..c02d483dcd --- /dev/null +++ b/.github/workflows/scripts/bundle-win-dlls.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +# +# Bundle required DLLs for Windows builds (if any are needed) +# +# This script detects missing DLLs for the QEMU binaries and copies them +# from the MinGW64 bin directory. With proper static linking, no DLLs +# should be needed, but this provides a safety net. +# + +set -euo pipefail + +INSTALL_BIN_DIR="${1:-install/qemu/bin}" +MINGW_BIN_DIR="/mingw64/bin" + +echo "Checking for missing DLLs in ${INSTALL_BIN_DIR}..." + +# Collect all missing DLLs from all executables +missing_dlls=() + +for exe in "${INSTALL_BIN_DIR}"/*.exe; do + if [[ -f "${exe}" ]]; then + echo "Analyzing: $(basename "${exe}")" + # Use ldd to find dependencies marked as "not found" + # Also filter for DLLs that exist in mingw64/bin (our responsibility) + while IFS= read -r line; do + # Extract the DLL name from lines like "libfoo.dll => not found" + if [[ "${line}" =~ ^[[:space:]]*([^[:space:]]+\.dll)[[:space:]]*'=>'[[:space:]]*'not found' ]]; then + dll="${BASH_REMATCH[1]}" + # Check if this DLL exists in our MinGW bin dir + if [[ -f "${MINGW_BIN_DIR}/${dll}" ]]; then + missing_dlls+=("${dll}") + fi + fi + done < <(ldd "${exe}" 2>/dev/null || true) + fi +done + +# Remove duplicates +if [[ ${#missing_dlls[@]} -gt 0 ]]; then + readarray -t missing_dlls < <(printf '%s\n' "${missing_dlls[@]}" | sort -u) +fi + +# Copy missing DLLs +if [[ ${#missing_dlls[@]} -eq 0 ]]; then + echo "" + echo "No missing DLLs found - static linking appears to be working correctly." + echo "" +else + echo "" + echo "Found ${#missing_dlls[@]} missing DLLs. Copying from ${MINGW_BIN_DIR}..." + + for dll in "${missing_dlls[@]}"; do + src="${MINGW_BIN_DIR}/${dll}" + if [[ -f "${src}" ]]; then + cp -v "${src}" "${INSTALL_BIN_DIR}/" + else + echo "WARNING: ${dll} not found in ${MINGW_BIN_DIR}" + fi + done + + echo "" + echo "DLL bundling complete." + + # Re-check for any still-missing dependencies (recursive deps) + echo "" + echo "Re-checking dependencies after bundling..." + still_missing=0 + for exe in "${INSTALL_BIN_DIR}"/*.exe; do + if [[ -f "${exe}" ]]; then + missing=$(ldd "${exe}" 2>/dev/null | grep -i "not found" || true) + if [[ -n "${missing}" ]]; then + echo "WARNING: Still missing deps for $(basename "${exe}"):" + echo "${missing}" + still_missing=1 + fi + fi + done + + if [[ ${still_missing} -eq 0 ]]; then + echo "All dependencies resolved." + fi +fi diff --git a/.github/workflows/scripts/configure-win.sh b/.github/workflows/scripts/configure-win.sh index f5b62ecf33..b27632cbcd 100755 --- a/.github/workflows/scripts/configure-win.sh +++ b/.github/workflows/scripts/configure-win.sh @@ -26,7 +26,9 @@ echo DBG || { cat meson-logs/meson-log.txt && false; } -# This fixes the issue that for some reason, meson is not able to determine correct -# paths for libiconv and libintl libraries from 'pkg-config --libs --static libgcrypt'. +# Fix: pkg-config for libgcrypt outputs incorrect paths for libiconv and libintl: +# - Unix-style paths (/mingw64/lib/...) instead of Windows paths (D:/a/_temp/msys64/mingw64/lib/...) +# - Dynamic import libraries (.dll.a) instead of static libraries (.a) +# We need to fix both issues in build.ninja for the static build to work correctly. MSYS_BASE=$(cygpath -w / | sed 's/\\/\//g') -sed -i "s|/mingw64/lib/libintl.dll.a|${MSYS_BASE}/mingw64/lib/libintl.dll.a|g; s|/mingw64/lib/libiconv.dll.a|${MSYS_BASE}/mingw64/lib/libiconv.dll.a|g" build/build.ninja +sed -i "s|/mingw64/lib/libintl.dll.a|${MSYS_BASE}/mingw64/lib/libintl.a|g; s|/mingw64/lib/libiconv.dll.a|${MSYS_BASE}/mingw64/lib/libiconv.a|g" build/build.ninja