From 9005c67b8b882be6b59c9fda2ae8d0b590195962 Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 5 Oct 2026 09:27:11 +0200 Subject: [PATCH] Skip Windows DLL deployment when runtimes are present --- tools/chatgui/build.sh | 202 ++++++++++++++++++----------------------- 1 file changed, 89 insertions(+), 113 deletions(-) diff --git a/tools/chatgui/build.sh b/tools/chatgui/build.sh index 9d909e22..08f5a6d2 100755 --- a/tools/chatgui/build.sh +++ b/tools/chatgui/build.sh @@ -38,84 +38,82 @@ test ${PIPESTATUS[0]} -eq 0 || { log "Build FAILED"; exit 1; } log "" log "[3/4] Deploying runtime DLLs..." -WINDEPLOYQT="/ucrt64/bin/windeployqt" -if [ -x "$WINDEPLOYQT" ]; then - log " Running $WINDEPLOYQT..." - "$WINDEPLOYQT" --no-translations --no-compiler-runtime "$BUILD_DIR/vibechat.exe" 2>&1 | tee -a "$LOG_FILE" - RC=${PIPESTATUS[0]} - if [ $RC -eq 0 ]; then - log " OK: windeployqt completed" - else - log " WARN: windeployqt failed (exit $RC)" - fi -else - log " WARN: $WINDEPLOYQT not found (install: pacman -S mingw-w64-ucrt-x86_64-qt5-tools)" -fi - -# Резолвим НЕ-Qt зависимости (FFmpeg, mingw-runtime) всегда: windeployqt копирует только Qt. -# FFmpeg ищем ПЕРВЫМ в $FFMPEG_BIN: exe линкован именно под кастомный билд, -# а pacman-ffmpeg той же мажорной версии в /ucrt64/bin дал бы неверный набор кодеков. FFMPEG_BIN="$SRC_DIR/ffmpeg/ffmpeg_build/install/bin" -OBJDUMP="objdump"; [ -n "${MSYSTEM_PREFIX:-}" ] && OBJDUMP="$MSYSTEM_PREFIX/bin/objdump" -command -v "$OBJDUMP" >/dev/null 2>&1 || { log " ERROR: $OBJDUMP not found"; exit 1; } -shopt -s nocasematch nullglob -# Обновляем весь комплект FFmpeg, включая DLL, не импортируемые напрямую приложением. -for src in "$FFMPEG_BIN/"*.dll; do - cp "$src" "$BUILD_DIR/" || { log " ERROR: failed to copy $src"; exit 1; } - log " OK: $(basename "$src") (ffmpeg)" -done -log " Resolving non-Qt dependencies recursively..." -# Проверяем также уже скопированные DLL: наличие файла не гарантирует наличие его зависимостей. -todo=("$BUILD_DIR/vibechat.exe" "$BUILD_DIR/"*.dll) -declare -A scanned=() -MISSING=0 -CHECKED=0 -COPIED=0 -SCAN_STARTED=$SECONDS -log " Scanner: $OBJDUMP; initial files=${#todo[@]}" -log " Search directories: $FFMPEG_BIN; /ucrt64/bin; $SRC_DIR/rlottie_build" -# Большой вывод objdump передаём через файл, чтобы не зависеть от here-string и pipe в MSYS2. -if IMPORT_DUMP=$(mktemp); then - log " Temporary import dump: $IMPORT_DUMP" -else - log " ERROR: cannot create temporary file for DLL inspection" - exit 1 +MAIN_DLLS=( + "Qt[56]Core.dll" "Qt[56]Gui.dll" "Qt[56]Network.dll" "Qt[56]Widgets.dll" "platforms/qwindows.dll" + "libstdc++-6.dll" "libgcc_s_*.dll" "libwinpthread-1.dll" "librlottie.dll" "zlib1.dll" "libcrypto-*.dll" +) +if [ -d "$FFMPEG_BIN" ]; then + MAIN_DLLS+=("avcodec-*.dll" "avformat-*.dll" "avutil-*.dll" "swscale-*.dll" "swresample-*.dll") fi -trap 'rm -f -- "$IMPORT_DUMP" || log " WARN: cannot remove temporary import dump: $IMPORT_DUMP"' EXIT -for ((i = 0; i < ${#todo[@]}; i++)); do - src="${todo[i]}" - key="${src,,}" - [ -n "${scanned[$key]:-}" ] && continue - scanned[$key]=1 - CHECKED=$((CHECKED + 1)) - CHECK_STARTED=$SECONDS - log " Checking [$((i + 1))/${#todo[@]}]: $src (objdump starting)" - if "$OBJDUMP" -p "$src" > "$IMPORT_DUMP" 2>&1; then - IMPORT_BYTES=$(wc -c < "$IMPORT_DUMP") - log " Imports read: $src (objdump=$((SECONDS - CHECK_STARTED))s, output=$IMPORT_BYTES bytes; resolving dependencies)" - else - RC=$? - log " ERROR: cannot inspect $src (exit=$RC, elapsed=$((SECONDS - CHECK_STARTED))s): $(cat "$IMPORT_DUMP")" - MISSING=$((MISSING + 1)) - continue +DLLS_PRESENT=1 +for d in "${MAIN_DLLS[@]}"; do + if ! compgen -G "$BUILD_DIR/$d" >/dev/null; then + log " Main DLL missing: $d; deploying runtime DLLs" + DLLS_PRESENT=0 + break fi - IMPORT_COUNT=0 - SYSTEM_COUNT=0 - FILE_COPIED=0 - FILE_MISSING=0 - PARSE_STARTED=$SECONDS - log " Parsing import table: $src (awk starting)" - if import_list=$(awk '/DLL Name:/ {print $3}' "$IMPORT_DUMP" 2>&1); then - log " Import table parsed: $src (elapsed=$((SECONDS - PARSE_STARTED))s, names=${#import_list} chars)" +done +if [ "$DLLS_PRESENT" -eq 1 ]; then + log " SKIP: main runtime DLLs already present; copying and recursive dependency scan skipped" +else + WINDEPLOYQT="/ucrt64/bin/windeployqt" + if [ -x "$WINDEPLOYQT" ]; then + log " Running $WINDEPLOYQT..." + "$WINDEPLOYQT" --no-translations --no-compiler-runtime "$BUILD_DIR/vibechat.exe" 2>&1 | tee -a "$LOG_FILE" + RC=${PIPESTATUS[0]} + if [ $RC -eq 0 ]; then + log " OK: windeployqt completed" + else + log " WARN: windeployqt failed (exit $RC)" + fi else - RC=$? - log " ERROR: cannot parse imports for $src (exit=$RC, elapsed=$((SECONDS - PARSE_STARTED))s): $import_list" - MISSING=$((MISSING + 1)) - continue + log " WARN: $WINDEPLOYQT not found (install: pacman -S mingw-w64-ucrt-x86_64-qt5-tools)" fi - while read -r dep; do + + # Резолвим НЕ-Qt зависимости (FFmpeg, mingw-runtime): windeployqt копирует только Qt. + # FFmpeg ищем ПЕРВЫМ в $FFMPEG_BIN: exe линкован именно под кастомный билд, + # а pacman-ffmpeg той же мажорной версии в /ucrt64/bin дал бы неверный набор кодеков. + OBJDUMP="objdump"; [ -n "${MSYSTEM_PREFIX:-}" ] && OBJDUMP="$MSYSTEM_PREFIX/bin/objdump" + command -v "$OBJDUMP" >/dev/null 2>&1 || { log " ERROR: $OBJDUMP not found"; exit 1; } + shopt -s nocasematch nullglob + # Обновляем весь комплект FFmpeg, включая DLL, не импортируемые напрямую приложением. + for src in "$FFMPEG_BIN/"*.dll; do + cp "$src" "$BUILD_DIR/" || { log " ERROR: failed to copy $src"; exit 1; } + log " OK: $(basename "$src") (ffmpeg)" + done + log " Resolving non-Qt dependencies recursively..." + # Проверяем также уже скопированные DLL: наличие файла не гарантирует наличие его зависимостей. + todo=("$BUILD_DIR/vibechat.exe" "$BUILD_DIR/"*.dll) + declare -A scanned=() + MISSING=0 + # Большой вывод objdump передаём через файл, чтобы не зависеть от here-string и pipe в MSYS2. + IMPORT_DUMP=$(mktemp) || { + log " ERROR: cannot create temporary file for DLL inspection" + exit 1 + } + trap 'rm -f -- "$IMPORT_DUMP" || log " WARN: cannot remove temporary import dump: $IMPORT_DUMP"' EXIT + for ((i = 0; i < ${#todo[@]}; i++)); do + src="${todo[i]}" + key="${src,,}" + [ -n "${scanned[$key]:-}" ] && continue + scanned[$key]=1 + CHECK_STARTED=$SECONDS + "$OBJDUMP" -p "$src" > "$IMPORT_DUMP" 2>&1 || { + RC=$? + log " ERROR: cannot inspect $src (exit=$RC, elapsed=$((SECONDS - CHECK_STARTED))s): $(cat "$IMPORT_DUMP")" + MISSING=$((MISSING + 1)) + continue + } + PARSE_STARTED=$SECONDS + import_list=$(awk '/DLL Name:/ {print $3}' "$IMPORT_DUMP" 2>&1) || { + RC=$? + log " ERROR: cannot parse imports for $src (exit=$RC, elapsed=$((SECONDS - PARSE_STARTED))s): $import_list" + MISSING=$((MISSING + 1)) + continue + } + while read -r dep; do [ -z "$dep" ] && continue - IMPORT_COUNT=$((IMPORT_COUNT + 1)) case "$dep" in kernel32.dll|msvcrt.dll|msvcp140.dll|vcruntime140.dll|ucrtbase.dll|\ user32.dll|gdi32.dll|gdi32full.dll|shell32.dll|shlwapi.dll|advapi32.dll|\ @@ -126,15 +124,11 @@ for ((i = 0; i < ${#todo[@]}; i++)); do uxtheme.dll|dwmapi.dll|d3d11.dll|dxgi.dll|opengl32.dll|glu32.dll|\ wtsapi32.dll|mpr.dll|ntdll.dll|avicap32.dll|msimg32.dll|wldap32.dll|gdiplus.dll|usp10.dll|\ dwrite.dll|winspool.drv|api-ms-win-*) - SYSTEM_COUNT=$((SYSTEM_COUNT + 1)) continue ;; esac - DEP_STARTED=$SECONDS - log " Resolving import $IMPORT_COUNT: $dep (checking $BUILD_DIR/$dep)" if [ ! -f "$BUILD_DIR/$dep" ]; then dep_src="" for dir in "$FFMPEG_BIN" /ucrt64/bin "$SRC_DIR/rlottie_build"; do - log " Searching: $dir/$dep" if [ -f "$dir/$dep" ]; then dep_src="$dir/$dep" break @@ -143,54 +137,36 @@ for ((i = 0; i < ${#todo[@]}; i++)); do if [ -z "$dep_src" ]; then log " ERROR: $src requires $dep; not found in FFmpeg, UCRT64 or rlottie directories" MISSING=$((MISSING + 1)) - FILE_MISSING=$((FILE_MISSING + 1)) continue fi - log " Copying: $dep_src (required by $src)" cp "$dep_src" "$BUILD_DIR/" || { log " ERROR: failed to copy $dep_src"; exit 1; } - COPIED=$((COPIED + 1)) - FILE_COPIED=$((FILE_COPIED + 1)) log " OK: $dep (from $dep_src; required by $src)" fi todo+=("$BUILD_DIR/$dep") - log " Dependency ready: $dep (elapsed=$((SECONDS - DEP_STARTED))s, queue entries=${#todo[@]})" - done <<< "$import_list" - log " Checked: $src (elapsed=$((SECONDS - CHECK_STARTED))s, imports=$IMPORT_COUNT, system=$SYSTEM_COUNT)" - log " copied=$FILE_COPIED, missing=$FILE_MISSING, pending entries=$((${#todo[@]} - i - 1))" -done -log " DLL scan finished: checked=$CHECKED, copied=$COPIED, errors=$MISSING, elapsed=$((SECONDS - SCAN_STARTED))s" -shopt -u nocasematch nullglob -[ "$MISSING" -eq 0 ] || { log " ERROR: runtime DLL deployment incomplete"; exit 1; } -# Qt platform plugin (loaded dynamically, not in import table) -mkdir -p "$BUILD_DIR/platforms" -for d in /ucrt64/share/qt5/plugins /ucrt64/lib/qt5/plugins; do - cp "$d/platforms/qwindows.dll" "$BUILD_DIR/platforms/" 2>/dev/null && break -done -cp "$SRC_DIR/rlottie_build/librlottie.dll" "$BUILD_DIR/" 2>/dev/null && log " OK: librlottie.dll" || log " WARN: librlottie.dll not found" -cp "$SRC_DIR/setup_firewall.bat" "$BUILD_DIR/" 2>/dev/null && log " OK: setup_firewall.bat" || log " WARN: setup_firewall.bat not found" + done <<< "$import_list" + done + shopt -u nocasematch nullglob + [ "$MISSING" -eq 0 ] || { log " ERROR: runtime DLL deployment incomplete"; exit 1; } + # Qt platform plugin (loaded dynamically, not in import table) + mkdir -p "$BUILD_DIR/platforms" + for d in /ucrt64/share/qt5/plugins /ucrt64/lib/qt5/plugins; do + cp "$d/platforms/qwindows.dll" "$BUILD_DIR/platforms/" 2>/dev/null && break + done + cp "$SRC_DIR/rlottie_build/librlottie.dll" "$BUILD_DIR/" 2>/dev/null && log " OK: librlottie.dll" || log " WARN: librlottie.dll not found" -# Проверяем, что все ожидаемые не-Qt DLL на месте (FFmpeg + mingw-runtime + rlottie + zlib + OpenSSL) -log " Verifying required non-Qt DLLs..." -MISSING=0 -if [ -d "$FFMPEG_BIN" ]; then - for d in avcodec-*.dll avformat-*.dll avutil-*.dll swscale-*.dll swresample-*.dll; do - if compgen -G "$BUILD_DIR/$d" >/dev/null; then - log " OK: $d" - else + # Проверяем тот же основной комплект после копирования. + log " Verifying main runtime DLLs..." + MISSING=0 + for d in "${MAIN_DLLS[@]}"; do + if ! compgen -G "$BUILD_DIR/$d" >/dev/null; then log " WARN: $d MISSING in build dir"; MISSING=1 fi done -else - log " SKIP: FFmpeg not built — no FFmpeg DLLs expected" -fi -for d in libstdc++-6.dll libgcc_s_*.dll libwinpthread-1.dll librlottie.dll zlib1.dll libcrypto-*.dll; do - if compgen -G "$BUILD_DIR/$d" >/dev/null; then - log " OK: $d" - else - log " WARN: $d MISSING in build dir"; MISSING=1 + if [ "$MISSING" -eq 1 ]; then + log " WARN: some main runtime DLLs missing — app may not start" fi -done -[ "$MISSING" -eq 1 ] && log " WARN: some required non-Qt DLLs missing — app may not start" +fi +cp "$SRC_DIR/setup_firewall.bat" "$BUILD_DIR/" 2>/dev/null && log " OK: setup_firewall.bat" || log " WARN: setup_firewall.bat not found" log "" log "[4/4] Verifying..."