Files
media-player-server/build-dist-windows.sh
T
alexei.dolgolyov f80f6e9299
Lint & Test / test (push) Successful in 10s
Release / create-release (push) Successful in 2s
Release / build-linux (push) Successful in 35s
Release / build-windows (push) Successful in 1m28s
fix: correct ._pth path in Windows build script
..\..\app was resolving two levels up from python/ dir instead of one.
Changed to ..\app so embedded Python finds the media_server package.
2026-03-23 13:35:17 +03:00

152 lines
4.2 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
# Cross-build Windows distribution on Linux
# Usage: ./build-dist-windows.sh [VERSION]
# --- Version detection ---
VERSION="${1:-}"
if [ -z "$VERSION" ]; then
VERSION=$(git describe --tags --exact-match 2>/dev/null || true)
fi
if [ -z "$VERSION" ]; then
VERSION="${GITEA_REF_NAME:-${GITHUB_REF_NAME:-}}"
fi
if [ -z "$VERSION" ]; then
VERSION=$(grep -oP '__version__\s*=\s*"\K[^"]+' \
media_server/__init__.py 2>/dev/null || echo "0.0.0")
fi
VERSION_CLEAN="${VERSION#v}"
echo "Building Media Server v${VERSION_CLEAN} for Windows"
# --- Configuration ---
PYTHON_VERSION="3.11.9"
PYTHON_SHORT="311"
DIST_DIR="dist/media-server"
WHEEL_DIR="build/win-wheels"
SITE_PACKAGES="${DIST_DIR}/python/Lib/site-packages"
BUILD_OUTPUT="build/MediaServer-v${VERSION_CLEAN}-win-x64"
rm -rf dist build
mkdir -p "${DIST_DIR}" "${WHEEL_DIR}" "${SITE_PACKAGES}"
# --- Download embedded Python ---
echo "Downloading embedded Python ${PYTHON_VERSION}..."
curl -sL "https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-embed-amd64.zip" \
-o build/python-embed.zip
unzip -qo build/python-embed.zip -d "${DIST_DIR}/python"
# Patch ._pth to enable site-packages and app source
PTH_FILE=$(ls "${DIST_DIR}"/python/python*._pth | head -1)
sed -i 's/^#\s*import site/import site/' "$PTH_FILE"
echo 'Lib\site-packages' >> "$PTH_FILE"
echo '..\app' >> "$PTH_FILE"
# --- Download Windows wheels ---
echo "Downloading Windows wheels..."
# Core dependencies
CORE_DEPS=(
"fastapi>=0.109.0"
"uvicorn[standard]>=0.27.0"
"pydantic>=2.0"
"pydantic-settings>=2.0"
"pyyaml>=6.0"
"mutagen>=1.47.0"
"pillow>=10.0.0"
)
# Windows-specific dependencies
WIN_DEPS=(
"winsdk>=1.0.0b10"
"pywin32>=306"
"comtypes>=1.2.0"
"pycaw>=20230407"
"screen-brightness-control>=0.20.0"
"monitorcontrol>=3.0.0"
)
# Visualizer dependencies
VIS_DEPS=(
"soundcard>=0.4.0"
"numpy>=1.24.0"
)
ALL_DEPS=("${CORE_DEPS[@]}" "${WIN_DEPS[@]}" "${VIS_DEPS[@]}")
for dep in "${ALL_DEPS[@]}"; do
pip download --quiet --dest "$WHEEL_DIR" \
--platform win_amd64 --python-version "${PYTHON_SHORT}" \
--implementation cp --only-binary :all: \
"$dep" 2>/dev/null || \
pip download --quiet --dest "$WHEEL_DIR" "$dep"
done
# Install wheels into site-packages
echo "Installing wheels..."
for whl in "$WHEEL_DIR"/*.whl; do
unzip -qo "$whl" -d "$SITE_PACKAGES"
done
# --- Size optimization ---
echo "Optimizing size..."
find "$SITE_PACKAGES" -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
find "$SITE_PACKAGES" -type d -name tests -exec rm -rf {} + 2>/dev/null || true
find "$SITE_PACKAGES" -type d -name "*.dist-info" -exec rm -rf {} + 2>/dev/null || true
find "$SITE_PACKAGES" -name "*.pyi" -delete 2>/dev/null || true
rm -rf "$SITE_PACKAGES"/{pip,setuptools,pkg_resources}* 2>/dev/null || true
# Trim numpy if present
rm -rf "$SITE_PACKAGES"/numpy/{tests,f2py,typing} 2>/dev/null || true
# --- Verify frontend bundle ---
if [ ! -f "media_server/static/dist/app.bundle.js" ]; then
echo "ERROR: Frontend bundle not found. Run 'npm ci && npm run build' first."
exit 1
fi
# --- Copy application ---
echo "Copying application files..."
mkdir -p "${DIST_DIR}/app"
cp -r media_server "${DIST_DIR}/app/"
# Remove source JS (bundle is in dist/)
rm -rf "${DIST_DIR}/app/media_server/static/js"
# Remove source maps from release
rm -f "${DIST_DIR}/app/media_server/static/dist/"*.map
# Copy config example
cp config.example.yaml "${DIST_DIR}/"
# Copy scripts needed for auto-start
mkdir -p "${DIST_DIR}/scripts"
cp scripts/start-hidden.vbs "${DIST_DIR}/scripts/"
# --- Write version ---
echo "$VERSION_CLEAN" > "${DIST_DIR}/VERSION"
# --- Create launcher ---
cat > "${DIST_DIR}/media-server.bat" << 'LAUNCHER'
@echo off
setlocal
set "ROOT=%~dp0"
"%ROOT%python\python.exe" -m media_server.main %*
LAUNCHER
# --- Package ---
echo "Creating archives..."
mkdir -p build
# Portable ZIP
cp -r "${DIST_DIR}" "${BUILD_OUTPUT}"
cd build
zip -qr "MediaServer-v${VERSION_CLEAN}-win-x64.zip" "MediaServer-v${VERSION_CLEAN}-win-x64"
cd ..
echo "Build complete: build/MediaServer-v${VERSION_CLEAN}-win-x64.zip"
echo "Dist directory ready for NSIS: ${DIST_DIR}"