2025-11-27 15:30:10 +01:00
|
|
|
#!/bin/bash
|
2026-06-12 10:18:16 +02:00
|
|
|
# Build wxWidgets for WebAssembly (the DOM port: widgets are real HTML
|
|
|
|
|
# elements; owner-drawn widgets render into per-window canvas islands)
|
2026-01-03 11:55:54 +01:00
|
|
|
|
|
|
|
|
# Redirect all output to a log file (re-execs script with redirection)
|
|
|
|
|
source "$(dirname "$0")/common/logging.sh"
|
2026-01-09 14:48:23 +01:00
|
|
|
|
2026-03-13 12:26:48 +01:00
|
|
|
# Source common environment (sets up local emsdk)
|
2026-01-09 14:48:23 +01:00
|
|
|
source "$(dirname "$0")/common/env.sh"
|
2026-06-01 17:31:03 +02:00
|
|
|
# Build-progress markers (parsed by scripts/build-monitor.sh).
|
|
|
|
|
source "$(dirname "$0")/common/stages.sh"
|
2025-11-27 15:30:10 +01:00
|
|
|
# This builds the GUI-enabled wxWidgets needed for KiCad
|
2025-11-28 16:42:35 +01:00
|
|
|
#
|
|
|
|
|
# Prerequisites:
|
2026-03-13 12:26:48 +01:00
|
|
|
# - Emscripten SDK (auto-installed by env.sh via scripts/setup-emsdk.sh)
|
2025-11-28 16:42:35 +01:00
|
|
|
# - autoconf (for regenerating configure from configure.in)
|
|
|
|
|
#
|
|
|
|
|
# To regenerate Makefile.in from bakefiles (after modifying files.bkl):
|
|
|
|
|
# cd wxwidgets/build/bakefiles
|
|
|
|
|
# docker run --rm -v "$(pwd)/../..":"$(pwd)/../.." -w "$(pwd)" \
|
|
|
|
|
# ghcr.io/vslavik/bakefile:0.2 bakefile_gen
|
|
|
|
|
#
|
|
|
|
|
# Usage:
|
2026-06-12 10:18:16 +02:00
|
|
|
# ./build-wx-wasm.sh # Incremental build (default)
|
|
|
|
|
# ./build-wx-wasm.sh --clean # Clean build from scratch
|
2025-11-27 15:30:10 +01:00
|
|
|
|
|
|
|
|
set -e
|
|
|
|
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
|
|
|
WX_SOURCE="$PROJECT_ROOT/wxwidgets"
|
|
|
|
|
|
2026-06-12 10:18:16 +02:00
|
|
|
# Parse arguments: --clean or --no-clean (default; kept for the kicad
|
|
|
|
|
# pipeline's explicit call), in any order.
|
2026-06-10 17:17:57 +02:00
|
|
|
CLEAN_BUILD=0
|
|
|
|
|
for arg in "$@"; do
|
|
|
|
|
case "$arg" in
|
2026-06-11 00:19:53 +02:00
|
|
|
--clean) CLEAN_BUILD=1 ;;
|
|
|
|
|
--no-clean) CLEAN_BUILD=0 ;;
|
2026-06-10 17:17:57 +02:00
|
|
|
*) echo "Unknown argument: $arg"; exit 1 ;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
2026-06-12 10:18:16 +02:00
|
|
|
BUILD_DIR="$PROJECT_ROOT/build-wasm/wxwidgets"
|
|
|
|
|
WXLIB_PREFIX="libwx_wasmu"
|
2026-06-10 17:17:57 +02:00
|
|
|
|
2025-12-27 01:07:44 +01:00
|
|
|
# Use our config.sub wrapper for autoconf projects
|
|
|
|
|
# CONFIG_SHELL is critical: nested configures (pcre, etc.) do SHELL=${CONFIG_SHELL-/bin/sh}
|
|
|
|
|
# Without CONFIG_SHELL, nested configures would reset SHELL to /bin/sh and bypass our wrapper
|
|
|
|
|
export SHELL="$SCRIPT_DIR/config/config-sub-wrapper.sh"
|
|
|
|
|
export CONFIG_SHELL="$SCRIPT_DIR/config/config-sub-wrapper.sh"
|
|
|
|
|
|
2025-12-27 09:21:31 +01:00
|
|
|
# Disable autom4te cache to keep submodules clean
|
|
|
|
|
export AUTOM4TE="$SCRIPT_DIR/config/autom4te-wrapper.sh"
|
|
|
|
|
|
2025-12-15 15:59:23 +01:00
|
|
|
# Use JOBS from env.sh if set, otherwise use all available cores
|
|
|
|
|
JOBS="${JOBS:-$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)}"
|
2025-12-12 14:51:38 +01:00
|
|
|
|
2026-06-12 10:18:16 +02:00
|
|
|
echo "=== Building wxWidgets for WASM ==="
|
2025-11-27 15:30:10 +01:00
|
|
|
echo "Project root: $PROJECT_ROOT"
|
|
|
|
|
echo "Build dir: $BUILD_DIR"
|
|
|
|
|
echo "wxWidgets source: $WX_SOURCE"
|
|
|
|
|
|
|
|
|
|
# Verify we're in the right place
|
2025-11-28 16:42:35 +01:00
|
|
|
if [ ! -f "$WX_SOURCE/configure.in" ]; then
|
2025-11-27 15:30:10 +01:00
|
|
|
echo "ERROR: wxWidgets source not found at $WX_SOURCE"
|
|
|
|
|
echo "Make sure the wxwidgets submodule is initialized"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-06-10 17:17:57 +02:00
|
|
|
# Regenerate configure if configure.in or autoconf_inc.m4 is newer.
|
|
|
|
|
# (configure.in sincludes autoconf_inc.m4, which bakefile regenerates from
|
|
|
|
|
# build/bakefiles/files.bkl — new build conditions live there.)
|
|
|
|
|
if [ "$WX_SOURCE/configure.in" -nt "$WX_SOURCE/configure" ] || \
|
|
|
|
|
[ "$WX_SOURCE/autoconf_inc.m4" -nt "$WX_SOURCE/configure" ]; then
|
|
|
|
|
echo "configure inputs changed, regenerating configure..."
|
2025-11-28 16:42:35 +01:00
|
|
|
(cd "$WX_SOURCE" && autoconf)
|
|
|
|
|
fi
|
|
|
|
|
|
2025-12-27 11:26:25 +01:00
|
|
|
# Incremental build by default, use --clean for full rebuild
|
2026-06-10 17:17:57 +02:00
|
|
|
if [ "$CLEAN_BUILD" = "1" ]; then
|
2025-12-27 11:26:25 +01:00
|
|
|
echo "Cleaning build directory..."
|
2025-11-27 15:30:10 +01:00
|
|
|
rm -rf "$BUILD_DIR"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Create build directory
|
|
|
|
|
mkdir -p "$BUILD_DIR"
|
|
|
|
|
cd "$BUILD_DIR"
|
|
|
|
|
|
2025-12-26 20:51:58 +01:00
|
|
|
# Determine if we need to run configure
|
|
|
|
|
# Skip configure if:
|
|
|
|
|
# 1. Makefile exists (already configured)
|
|
|
|
|
# 2. configure.in hasn't changed since last configure
|
|
|
|
|
NEEDS_CONFIGURE=0
|
|
|
|
|
if [ ! -f "$BUILD_DIR/Makefile" ]; then
|
|
|
|
|
echo "Not configured yet, will run configure..."
|
|
|
|
|
NEEDS_CONFIGURE=1
|
|
|
|
|
elif [ "$WX_SOURCE/configure.in" -nt "$BUILD_DIR/Makefile" ]; then
|
|
|
|
|
echo "configure.in changed since last configure, will reconfigure..."
|
|
|
|
|
NEEDS_CONFIGURE=1
|
|
|
|
|
elif [ "$WX_SOURCE/configure" -nt "$BUILD_DIR/Makefile" ]; then
|
|
|
|
|
echo "configure script changed, will reconfigure..."
|
|
|
|
|
NEEDS_CONFIGURE=1
|
2026-06-10 17:17:57 +02:00
|
|
|
elif [ "$WX_SOURCE/Makefile.in" -nt "$BUILD_DIR/Makefile" ]; then
|
|
|
|
|
# Makefile.in is regenerated from build/bakefiles/files.bkl (see header);
|
|
|
|
|
# the build Makefile must be re-derived or new source files are ignored.
|
|
|
|
|
echo "Makefile.in changed since last configure, will reconfigure..."
|
|
|
|
|
NEEDS_CONFIGURE=1
|
2025-12-12 14:51:38 +01:00
|
|
|
else
|
2025-12-26 20:51:58 +01:00
|
|
|
echo "Already configured, skipping configure (use clean build to reconfigure)"
|
2025-12-12 14:51:38 +01:00
|
|
|
fi
|
|
|
|
|
|
2025-12-26 20:51:58 +01:00
|
|
|
if [ $NEEDS_CONFIGURE -eq 1 ]; then
|
|
|
|
|
# Configure with emconfigure
|
|
|
|
|
# Key flags based on wxWidgets-wasm:
|
|
|
|
|
# --host=emscripten Host system (detected via config.sub)
|
|
|
|
|
# --disable-shared Build static libraries
|
|
|
|
|
# --with-opengl Enable OpenGL/WebGL support
|
|
|
|
|
# --enable-exceptions Enable C++ exceptions (needed for KiCad debug builds)
|
|
|
|
|
# --disable-richtext Not needed for KiCad, simplifies build
|
|
|
|
|
# --without-libtiff Avoid external dependencies
|
|
|
|
|
# --disable-xlocale Browser environment handles locale
|
|
|
|
|
|
2026-06-01 17:31:03 +02:00
|
|
|
kw_stage wxwidgets-configure
|
2025-12-26 20:51:58 +01:00
|
|
|
echo ""
|
|
|
|
|
echo "=== Configuring ==="
|
|
|
|
|
|
2025-12-27 15:28:20 +01:00
|
|
|
# Regenerate autotools files in bundled PCRE to fix version mismatch
|
|
|
|
|
# The bundled PCRE was generated with automake 1.16.1 but build systems
|
|
|
|
|
# may have different versions. Running autoreconf ensures compatibility.
|
|
|
|
|
if command -v autoreconf &> /dev/null; then
|
|
|
|
|
echo "Regenerating autotools files for bundled PCRE..."
|
|
|
|
|
(cd "$WX_SOURCE/3rdparty/pcre" && autoreconf -fi 2>/dev/null || true)
|
|
|
|
|
fi
|
|
|
|
|
|
2025-12-26 20:51:58 +01:00
|
|
|
# Ensure Emscripten's zlib port is built (works in Docker and on host)
|
|
|
|
|
# This populates the cache sysroot with zlib.h and libz.a
|
|
|
|
|
echo "Building Emscripten zlib port..."
|
|
|
|
|
embuilder build zlib
|
|
|
|
|
|
|
|
|
|
# Get Emscripten cache sysroot path (portable across environments)
|
|
|
|
|
EM_CACHE_SYSROOT="$(em-config CACHE)/sysroot"
|
|
|
|
|
echo "Emscripten cache sysroot: $EM_CACHE_SYSROOT"
|
|
|
|
|
|
|
|
|
|
# Set flags for Emscripten compatibility
|
|
|
|
|
# Z_HAVE_UNISTD_H ensures zlib includes <unistd.h> for read/write/lseek
|
|
|
|
|
# Include pcre2 headers from the build directory (generated during configure)
|
|
|
|
|
PCRE2_INCLUDE="$BUILD_DIR/3rdparty/pcre/src"
|
|
|
|
|
|
|
|
|
|
# Configure debug/release flags based on DEBUG_BUILD environment variable
|
|
|
|
|
if [ "${DEBUG_BUILD:-1}" = "1" ]; then
|
|
|
|
|
WX_DEBUG_FLAGS="-g -O1"
|
|
|
|
|
WX_CONFIGURE_DEBUG="--enable-debug"
|
|
|
|
|
echo "Building wxWidgets in DEBUG mode"
|
|
|
|
|
else
|
|
|
|
|
WX_DEBUG_FLAGS="-O2"
|
|
|
|
|
WX_CONFIGURE_DEBUG=""
|
|
|
|
|
echo "Building wxWidgets in RELEASE mode"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Include emscripten cache sysroot for zlib headers
|
|
|
|
|
export CFLAGS="-DZ_HAVE_UNISTD_H=1 -I$EM_CACHE_SYSROOT/include ${WX_DEBUG_FLAGS} -fexceptions -pthread -matomics -mbulk-memory"
|
|
|
|
|
export CXXFLAGS="-DZ_HAVE_UNISTD_H=1 -I$EM_CACHE_SYSROOT/include -I$PCRE2_INCLUDE ${WX_DEBUG_FLAGS} -fexceptions -pthread -matomics -mbulk-memory"
|
|
|
|
|
export LDFLAGS="-L$EM_CACHE_SYSROOT/lib/wasm32-emscripten"
|
|
|
|
|
|
|
|
|
|
emconfigure "$WX_SOURCE/configure" \
|
|
|
|
|
--host=emscripten \
|
|
|
|
|
--without-subdirs \
|
|
|
|
|
--disable-shared \
|
|
|
|
|
--with-opengl \
|
|
|
|
|
--enable-exceptions \
|
|
|
|
|
--disable-richtext \
|
|
|
|
|
--without-libtiff \
|
|
|
|
|
--disable-xlocale \
|
|
|
|
|
--with-cxx=17 \
|
|
|
|
|
--enable-utf8 \
|
|
|
|
|
--with-zlib=sys \
|
|
|
|
|
${WX_CONFIGURE_DEBUG}
|
|
|
|
|
|
|
|
|
|
# Build PCRE first to avoid race condition with parallel builds
|
|
|
|
|
# PCRE headers (pcre2.h) must be generated before regex.cpp compiles
|
|
|
|
|
echo ""
|
|
|
|
|
echo "=== Building PCRE first (dependency) ==="
|
|
|
|
|
emmake make -C 3rdparty/pcre
|
|
|
|
|
fi
|
2025-11-28 16:42:35 +01:00
|
|
|
|
|
|
|
|
# Build wxWidgets
|
2026-06-01 17:31:03 +02:00
|
|
|
kw_stage wxwidgets-compile
|
2025-11-27 15:30:10 +01:00
|
|
|
echo ""
|
2025-12-12 14:51:38 +01:00
|
|
|
echo "=== Building wxWidgets (using ${JOBS} parallel jobs) ==="
|
|
|
|
|
emmake make -j${JOBS}
|
2025-11-27 15:30:10 +01:00
|
|
|
|
2025-12-08 18:26:57 +01:00
|
|
|
# Create library symlinks (remove -emscripten suffix for CMake compatibility)
|
|
|
|
|
echo ""
|
|
|
|
|
echo "=== Creating library symlinks ==="
|
|
|
|
|
cd "$BUILD_DIR/lib"
|
|
|
|
|
for lib in *-emscripten.a; do
|
2025-12-14 15:33:54 +01:00
|
|
|
# Skip symlinks - only process real files (stub symlinks are handled below)
|
|
|
|
|
if [ -f "$lib" ] && [ ! -L "$lib" ]; then
|
2025-12-08 18:26:57 +01:00
|
|
|
newname="${lib/-emscripten/}"
|
2025-12-14 15:33:54 +01:00
|
|
|
rm -f "$newname" # Remove existing symlink/file to avoid conflicts
|
2025-12-08 18:26:57 +01:00
|
|
|
ln -sf "$lib" "$newname"
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
# Create stub libraries for components wx-config reports but we didn't build
|
|
|
|
|
# KiCad doesn't use these directly
|
|
|
|
|
echo "Creating stub libraries..."
|
|
|
|
|
for stub in richtext webview; do
|
2025-12-14 15:33:54 +01:00
|
|
|
# Remove any existing symlinks first to avoid "same file" errors
|
2026-06-10 17:17:57 +02:00
|
|
|
rm -f "${WXLIB_PREFIX}_${stub}-3.2.a" "${WXLIB_PREFIX}_${stub}-3.2-emscripten.a"
|
|
|
|
|
emar rcs "${WXLIB_PREFIX}_${stub}-3.2.a"
|
|
|
|
|
ln -sf "${WXLIB_PREFIX}_${stub}-3.2.a" "${WXLIB_PREFIX}_${stub}-3.2-emscripten.a"
|
2025-12-08 18:26:57 +01:00
|
|
|
done
|
|
|
|
|
|
|
|
|
|
cd "$BUILD_DIR"
|
|
|
|
|
|
2025-11-27 15:30:10 +01:00
|
|
|
echo ""
|
|
|
|
|
echo "=== Build complete ==="
|
|
|
|
|
ls -lh "$BUILD_DIR"/lib/*.a 2>/dev/null || echo "Libraries built in $BUILD_DIR/lib"
|