Files
negative-converter/scripts/build-windows.sh
2026-03-15 09:54:47 +01:00

157 lines
6.9 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# build-windows.sh
#
# Cross-compiles negative-converter for Windows (x86_64) using MinGW-w64.
# Produces a self-contained directory with negative-converter.exe and all
# required DLLs ready for distribution.
#
# Prerequisites (Ubuntu/Debian):
# sudo apt install mingw-w64 cmake ninja-build
# # Install MinGW-w64 cross builds of OpenCV, LibRaw, Qt6:
# # Option A compile from source with the MinGW toolchain.
# # Option B use an MXE (M cross environment) prefix.
# # https://mxe.cc/
# # Option C use pre-built MinGW packages from a provider such as
# # https://github.com/brechtsanders/winlibs_mingw
#
# Usage:
# bash scripts/build-windows.sh [BUILD_TYPE] [DEPS_PREFIX]
#
# BUILD_TYPE Release (default) | Debug | RelWithDebInfo
# DEPS_PREFIX Path to cross-compiled dependencies
# (default: /usr/x86_64-w64-mingw32)
#
# Example with a custom MXE prefix:
# bash scripts/build-windows.sh Release /opt/mxe/usr/x86_64-w64-mingw32.static
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
# ── Configuration ─────────────────────────────────────────────────────────────
BUILD_TYPE="${1:-Release}"
DEPS_PREFIX="${2:-/usr/x86_64-w64-mingw32}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
BUILD_DIR="${PROJECT_ROOT}/build-windows"
DIST_DIR="${PROJECT_ROOT}/dist-windows"
TOOLCHAIN="${PROJECT_ROOT}/cmake/toolchain-mingw64.cmake"
echo "========================================================"
echo " negative-converter Windows Cross-Compilation"
echo "========================================================"
echo " Project root : ${PROJECT_ROOT}"
echo " Build dir : ${BUILD_DIR}"
echo " Build type : ${BUILD_TYPE}"
echo " Deps prefix : ${DEPS_PREFIX}"
echo "========================================================"
# ── Verify prerequisites ──────────────────────────────────────────────────────
for tool in x86_64-w64-mingw32-g++ cmake ninja; do
if ! command -v "${tool}" &>/dev/null; then
echo "ERROR: '${tool}' not found in PATH." >&2
echo "Install with: sudo apt install mingw-w64 cmake ninja-build" >&2
exit 1
fi
done
# ── CMake configure ──────────────────────────────────────────────────────────
cmake \
-B "${BUILD_DIR}" \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN}" \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-DCMAKE_INSTALL_PREFIX="${DIST_DIR}" \
-DCMAKE_PREFIX_PATH="${DEPS_PREFIX}" \
-DBUILD_TESTS=OFF \
-DBUILD_GUI=ON \
"${PROJECT_ROOT}"
# ── Build ─────────────────────────────────────────────────────────────────────
cmake --build "${BUILD_DIR}" -- -j"$(nproc)"
# ── Install to dist dir ───────────────────────────────────────────────────────
cmake --install "${BUILD_DIR}"
# ── Collect runtime DLLs ─────────────────────────────────────────────────────
# MinGW runtime and dependency DLLs must ship alongside the .exe.
BIN_DIR="${DIST_DIR}/bin"
mkdir -p "${BIN_DIR}"
echo ""
echo "Collecting runtime DLLs..."
# Helper: copy a DLL if it exists in the sysroot.
copy_dll() {
local dll_name="$1"
local search_paths=(
"${DEPS_PREFIX}/bin"
"${DEPS_PREFIX}/lib"
"/usr/lib/gcc/x86_64-w64-mingw32"
"/usr/x86_64-w64-mingw32/lib"
)
for dir in "${search_paths[@]}"; do
if [[ -f "${dir}/${dll_name}" ]]; then
cp -v "${dir}/${dll_name}" "${BIN_DIR}/"
return 0
fi
done
echo " WARNING: ${dll_name} not found (may be statically linked)" >&2
return 0
}
# MinGW runtime DLLs (may be statically linked via -static-libgcc/-static-libstdc++)
copy_dll "libgcc_s_seh-1.dll" || true
copy_dll "libstdc++-6.dll" || true
copy_dll "libwinpthread-1.dll" || true
# OpenCV DLLs (names include version number use glob)
for dll in "${DEPS_PREFIX}/bin"/libopencv_*.dll; do
[[ -f "${dll}" ]] && cp -v "${dll}" "${BIN_DIR}/"
done
# LibRaw
copy_dll "libraw.dll" || true
copy_dll "libraw-23.dll" || true
# Qt6 DLLs
for qt_dll in Qt6Core Qt6Gui Qt6Widgets; do
copy_dll "${qt_dll}.dll" || true
done
# Qt platform plugin
QT_PLATFORMS_SRC="${DEPS_PREFIX}/share/qt6/plugins/platforms"
if [[ -d "${QT_PLATFORMS_SRC}" ]]; then
mkdir -p "${BIN_DIR}/platforms"
cp -v "${QT_PLATFORMS_SRC}/qwindows.dll" "${BIN_DIR}/platforms/" 2>/dev/null || true
fi
# ── Strip release binaries ────────────────────────────────────────────────────
if [[ "${BUILD_TYPE}" == "Release" ]]; then
echo ""
echo "Stripping debug symbols from release binaries..."
x86_64-w64-mingw32-strip --strip-all "${BIN_DIR}/negative-converter.exe" 2>/dev/null || true
find "${BIN_DIR}" -name "*.dll" -exec x86_64-w64-mingw32-strip --strip-unneeded {} \; 2>/dev/null || true
fi
# ── Copy example config ───────────────────────────────────────────────────────
cp -v "${PROJECT_ROOT}/config.ini" "${DIST_DIR}/config.ini.example"
# ── Create ZIP archive ────────────────────────────────────────────────────────
ARCHIVE="${PROJECT_ROOT}/negative-converter-windows-x64-${BUILD_TYPE}.zip"
if command -v zip &>/dev/null; then
(cd "${PROJECT_ROOT}" && zip -r "${ARCHIVE}" "dist-windows/")
echo ""
echo "Archive: ${ARCHIVE}"
else
echo "(zip not available; skipping archive creation)"
fi
echo ""
echo "========================================================"
echo " Build complete!"
echo " Output: ${DIST_DIR}"
echo " Run: wine ${BIN_DIR}/negative-converter.exe --help"
echo "========================================================"