diff --git a/build.md b/build.md new file mode 100644 index 0000000..4b358e9 --- /dev/null +++ b/build.md @@ -0,0 +1,220 @@ +# KiCad WASM Build System + +This document describes how to build KiCad for WebAssembly using the Docker-based build system. + +## Prerequisites + +- Docker Desktop with ARM64 support (for Apple Silicon) or x86_64 +- 10+ GB disk space for build cache +- Recommended: 10 CPUs, 16GB RAM allocated to Docker + +## Quick Start + +```bash +# Build KiCad WASM (with debug symbols by default, sequential compilation) +./docker/build.sh + +# Build with parallel compilation (faster, requires more RAM) +./docker/build.sh -j 4 + +# Build optimized release (smaller WASM, no debug symbols) +./docker/build.sh --release + +# Interactive shell for debugging +./docker/shell.sh +``` + +**Note:** Builds run sequentially by default (`-j 1`) to avoid memory exhaustion in Docker. Use `-j N` for parallel compilation if you have sufficient RAM (at least 16GB for `-j 4`). + +**Build outputs:** +- `build-wasm/kicad-pcbnew/pcbnew/pcbnew.js` - Main WASM loader +- `build-wasm/kicad-pcbnew/pcbnew/pcbnew.wasm` - WASM binary +- `build-wasm/kicad-pcbnew/pcbnew/pcbnew.wasm.map` - Source map (debug builds) + +## Docker Architecture + +**Base image:** `emscripten/emsdk:4.0.2-arm64` + +**Volumes:** +- Source code bind mount: Project root → `/workspace` +- Build cache (named volume): `kicad-build-cache` → `/workspace/build-wasm` +- Output bind mount: `./output` → `/workspace/output` + +**Entry scripts:** +| Script | Purpose | +|--------|---------| +| `docker/build.sh` | Run build from host | +| `docker/shell.sh` | Interactive shell in container | +| `docker/entrypoint.sh` | Sources Emscripten environment | + +## Dependencies + +| Dependency | Version | Build System | Purpose | +|-----------|---------|--------------|---------| +| GLM | 0.9.9.8 | Header-only | Math library | +| Zstd | 1.5.5 | CMake | Compression for project files | +| Protobuf | 3.21.12 | CMake | IPC serialization | +| FreeType | 2.13.2 | CMake | Font rendering | +| HarfBuzz | 8.3.0 | CMake | Text shaping | +| Pixman | 0.42.2 | Meson | Pixel manipulation | +| Cairo | 1.18.0 | Meson | 2D graphics rendering | +| Boost | 1.84.0 | B2 | Locale library | +| wxWidgets | 3.3.1 | Autoconf | GUI framework | +| OpenCASCADE | 7.8.0 | CMake | 3D geometry (optional) | +| ngspice | 45.2 | Autoconf | SPICE simulation (optional) | + +### Build Order + +1. **Header-only:** GLM +2. **Compression/serialization:** Zstd, Protobuf +3. **Font stack:** FreeType → HarfBuzz +4. **Graphics:** Pixman → Cairo +5. **Optional:** OpenCASCADE, ngspice +6. **GUI framework:** wxWidgets +7. **Application:** KiCad PCBnew + +## Build Flags + +| Flag | Description | +|------|-------------| +| `--clean` | Full clean rebuild (all deps + wxWidgets + KiCad) | +| `--no-clean` | Incremental build (don't clean anything) | +| `--skip-deps` | Skip dependency rebuild | +| `--release` | Disable debug symbols, enable optimizations | +| `--debug` | Enable debug symbols (default) | +| `-j N` | Parallel jobs (default: 1 for sequential builds) | + +### Clean Modes + +| Mode | Command | What gets cleaned | +|------|---------|-------------------| +| **Full clean** | `./docker/build.sh --clean` | All stamps, deps, wxWidgets, sysroot, KiCad | +| **Default** | `./docker/build.sh` | KiCad build only (reuses deps) | +| **Incremental** | `./docker/build.sh --no-clean` | Nothing (fastest for iteration) | + +**Full clean removes:** +- `build-wasm/stamps/*` - All build stamps +- `build-wasm/deps/*` - All dependency builds +- `build-wasm/wxwidgets-universal` - wxWidgets build +- `build-wasm/sysroot/*` - Installed headers/libraries +- `build-wasm/kicad-pcbnew` - KiCad build + +### Debug vs Release + +**Debug (default):** +- Compiler: `-g -O0` (DWARF symbols, no optimization) +- Linker: `-gsource-map` (JavaScript source maps) +- Output: `~30-50MB` WASM with `.wasm.map` file +- Use for: Development, debugging WASM exceptions + +**Release:** +- Compiler: `-O2` (optimized) +- Output: `~15MB` WASM +- Use for: Production deployment + +## Stamp-based Caching + +Build progress is tracked with stamp files in `build-wasm/stamps/`: + +``` +build-wasm/stamps/ +├── zstd.stamp +├── protobuf.stamp +├── freetype.stamp +├── harfbuzz.stamp +├── pixman.stamp +├── cairo.stamp +├── wxwidgets.stamp +└── kicad-pcbnew.stamp +``` + +**Clear specific component:** `rm build-wasm/stamps/zstd.stamp` +**Clear all stamps:** `rm -f build-wasm/stamps/*.stamp` + +After changing build flags (debug/release), clear stamps to force rebuild. + +## Build Scripts + +| Script | Purpose | +|--------|---------| +| `scripts/build-kicad-wasm.sh` | Master build orchestrator | +| `scripts/kicad/build-pcbnew.sh` | KiCad PCBnew build | +| `scripts/build-wxuniversal-wasm.sh` | wxWidgets GUI build | +| `scripts/deps/build-all-deps.sh` | All dependencies | +| `scripts/deps/build-*.sh` | Individual dependency builds | +| `scripts/common/env.sh` | Environment setup | +| `scripts/common/functions.sh` | Shared utilities | +| `scripts/common/versions.sh` | Dependency versions | + +## Build Times + +| Component | Approximate Time | +|-----------|-----------------| +| Dependencies (all) | 20-60 minutes | +| wxWidgets | 10-20 minutes | +| KiCad PCBnew | 5-15 minutes | +| **Total fresh build** | **1-2 hours** | + +OpenCASCADE is the longest dependency to build (~30 minutes). + +## Troubleshooting + +### Container freezes during build +- Check Docker resource allocation (increase CPU/memory) +- Reduce parallel jobs: `./docker/build.sh -j 4` +- OpenCASCADE is resource-intensive; consider skipping with separate builds + +### Build fails with missing dependency +- Clear the specific stamp: `rm build-wasm/stamps/.stamp` +- Re-run build + +### Incremental build not picking up changes +- Clear KiCad stamp: `rm build-wasm/stamps/kicad-pcbnew.stamp` +- Use `--no-clean` flag to avoid full rebuild + +### WASM exception with numeric error (e.g., `3788888`) +- Build with debug symbols (default): No `--release` flag +- Check for `.wasm.map` file +- Use Chrome DevTools to debug with source maps + +### Clear build cache completely +```bash +docker volume rm docker_kicad-build-cache +``` + +## WASM Compatibility Layer + +The WASM port requires compatibility layers for browser execution: + +| Directory | Purpose | +|-----------|---------| +| `wasm/kiplatform/` | Platform abstraction (app, UI, printing, etc.) | +| `wasm/libcontext/` | Coroutine/fiber implementation for Asyncify | +| `wasm/stubs/` | Stub implementations (libgit2, curl) | +| `wasm/config/` | Build configuration headers | +| `cmake/` | CMake find modules for dependencies | + +## Emscripten Flags + +Key flags used in the build: + +``` +-pthread -sUSE_PTHREADS=1 # Threading support +-sASYNCIFY=1 # Async coroutine support +-sALLOW_MEMORY_GROWTH=1 # Dynamic memory +-sINITIAL_MEMORY=256MB # Starting memory +-sMAXIMUM_MEMORY=4GB # Maximum memory +-sLEGACY_GL_EMULATION # OpenGL compatibility +-sMAX_WEBGL_VERSION=2 # WebGL 2.0 +``` + +## Testing + +After building, run the test suite: + +```bash +cd tests +npm install +npm run setup:kicad # Copy WASM from build +npm run test:kicad # Run Playwright tests +``` diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 8d68d41..6e4f34b 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -5,12 +5,12 @@ services: dockerfile: docker/Dockerfile container_name: kicad-wasm-builder - # Resource limits (M4 Max: 10 cores, 16GB) + # Resource limits (adjust based on your machine) deploy: resources: limits: cpus: '10' - memory: 16G + memory: 32G volumes: # Source code (read-write for git operations) diff --git a/scripts/build-kicad-wasm.sh b/scripts/build-kicad-wasm.sh index c2b3354..9fc1546 100755 --- a/scripts/build-kicad-wasm.sh +++ b/scripts/build-kicad-wasm.sh @@ -9,7 +9,8 @@ # --with-occ Enable OpenCASCADE (3D/STEP support) # --with-ngspice Enable ngspice (simulation) # --with-pthread Enable pthreads (multi-threading) -# --debug Debug build with symbols +# --release Release build (optimized, no debug symbols) +# --debug Debug build with symbols (default) # -j N Parallel jobs (default: nproc) # --help Show this help @@ -66,6 +67,10 @@ while [[ $# -gt 0 ]]; do DEBUG_BUILD=1 shift ;; + --release) + DEBUG_BUILD=0 + shift + ;; -j) PARALLEL_JOBS="$2" shift 2 @@ -83,7 +88,7 @@ done # Set defaults if not set CLEAN_BUILD=${CLEAN_BUILD:-0} -DEBUG_BUILD=${DEBUG_BUILD:-0} +DEBUG_BUILD=${DEBUG_BUILD:-1} # Debug mode by default (use --release for optimized builds) PARALLEL_JOBS=${PARALLEL_JOBS:-$(get_nproc)} # Export for sub-scripts diff --git a/scripts/build-wxuniversal-wasm.sh b/scripts/build-wxuniversal-wasm.sh index 9a5013d..8e702ec 100755 --- a/scripts/build-wxuniversal-wasm.sh +++ b/scripts/build-wxuniversal-wasm.sh @@ -22,6 +22,9 @@ PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" BUILD_DIR="$PROJECT_ROOT/build-wasm/wxwidgets-universal" WX_SOURCE="$PROJECT_ROOT/wxwidgets" +# Use JOBS from env.sh if set, otherwise default to 1 for sequential builds +JOBS="${JOBS:-1}" + echo "=== Building wxWidgets wxUniversal for WASM ===" echo "Project root: $PROJECT_ROOT" echo "Build dir: $BUILD_DIR" @@ -68,8 +71,20 @@ echo "=== Configuring ===" # Z_HAVE_UNISTD_H ensures zlib includes for read/write/lseek # Include pcre2 headers from the build directory (generated during configure) PCRE2_INCLUDE="$BUILD_DIR/3rdparty/pcre/src" -export CFLAGS="-DZ_HAVE_UNISTD_H=1" -export CXXFLAGS="-DZ_HAVE_UNISTD_H=1 -I$PCRE2_INCLUDE" + +# Configure debug/release flags based on DEBUG_BUILD environment variable +if [ "${DEBUG_BUILD:-1}" = "1" ]; then + WX_DEBUG_FLAGS="-g -O0" + 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 + +export CFLAGS="-DZ_HAVE_UNISTD_H=1 ${WX_DEBUG_FLAGS}" +export CXXFLAGS="-DZ_HAVE_UNISTD_H=1 -I$PCRE2_INCLUDE ${WX_DEBUG_FLAGS}" emconfigure "$WX_SOURCE/configure" \ --host=emscripten \ @@ -82,7 +97,8 @@ emconfigure "$WX_SOURCE/configure" \ --without-libtiff \ --disable-xlocale \ --with-cxx=17 \ - --enable-utf8 + --enable-utf8 \ + ${WX_CONFIGURE_DEBUG} # Build PCRE first to avoid race condition with parallel builds # PCRE headers (pcre2.h) must be generated before regex.cpp compiles @@ -92,8 +108,8 @@ emmake make -C 3rdparty/pcre # Build wxWidgets echo "" -echo "=== Building wxWidgets ===" -emmake make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu) +echo "=== Building wxWidgets (using ${JOBS} parallel jobs) ===" +emmake make -j${JOBS} # Create library symlinks (remove -emscripten suffix for CMake compatibility) echo "" diff --git a/scripts/common/env.sh b/scripts/common/env.sh index 82fa03c..3f28737 100755 --- a/scripts/common/env.sh +++ b/scripts/common/env.sh @@ -34,6 +34,32 @@ export EMSDK_QUIET=1 export EMCC_CFLAGS="-fPIC -DEMSCRIPTEN" export EMCC_CXXFLAGS="-fPIC -DEMSCRIPTEN -std=c++17" +# Debug mode (default: ON, use --release to disable) +# This can be overridden by setting DEBUG_BUILD=0 before sourcing this file +DEBUG_BUILD="${DEBUG_BUILD:-1}" + +if [ "$DEBUG_BUILD" = "1" ]; then + export BUILD_TYPE="Debug" + export DEBUG_CFLAGS="-g -O0" + export DEBUG_LDFLAGS="-g -gsource-map" +else + export BUILD_TYPE="Release" + export DEBUG_CFLAGS="-O2" + export DEBUG_LDFLAGS="" +fi + +export DEBUG_BUILD BUILD_TYPE DEBUG_CFLAGS DEBUG_LDFLAGS + +# Parallel jobs (default to 1 for memory-constrained environments like Docker) +# Can be overridden with -j N flag or by setting JOBS/PARALLEL_JOBS env vars +if [ -n "$PARALLEL_JOBS" ]; then + export JOBS="$PARALLEL_JOBS" +elif [ -z "$JOBS" ]; then + # Default to 1 for sequential builds (safer for memory) + # Use -j N to override for faster builds on machines with more RAM + export JOBS=1 +fi + # Common linker flags for WASM export WASM_LDFLAGS="\ -sALLOW_MEMORY_GROWTH=1 \ diff --git a/scripts/common/functions.sh b/scripts/common/functions.sh index ed66799..36e8b76 100755 --- a/scripts/common/functions.sh +++ b/scripts/common/functions.sh @@ -226,7 +226,7 @@ get_nproc() { # Parse common command line arguments parse_common_args() { CLEAN_BUILD=0 - DEBUG_BUILD=0 + DEBUG_BUILD="${DEBUG_BUILD:-1}" # Default ON (use --release to disable) PARALLEL_JOBS=$(get_nproc) while [[ $# -gt 0 ]]; do @@ -239,6 +239,10 @@ parse_common_args() { DEBUG_BUILD=1 shift ;; + --release) + DEBUG_BUILD=0 + shift + ;; -j) PARALLEL_JOBS="$2" shift 2 diff --git a/scripts/deps/build-boost.sh b/scripts/deps/build-boost.sh index d40d54f..95e1e65 100755 --- a/scripts/deps/build-boost.sh +++ b/scripts/deps/build-boost.sh @@ -63,29 +63,38 @@ if [ ! -f "b2" ]; then ./bootstrap.sh --with-toolset=gcc fi +# Determine boost variant based on DEBUG_BUILD +if [ "${DEBUG_BUILD:-1}" = "1" ]; then + BOOST_VARIANT="debug" + BOOST_DEBUG_FLAGS="-g -O0" +else + BOOST_VARIANT="release" + BOOST_DEBUG_FLAGS="-O2" +fi + # Create user-config.jam for Emscripten -cat > user-config.jam << 'EOF' +cat > user-config.jam << EOF using clang : emscripten : em++ - : "-pthread" + : "${BOOST_DEBUG_FLAGS} -pthread" "-pthread" ; EOF # Build only the locale library (and its dependencies) # Most of Boost is header-only, we just need locale built -log_info "Building Boost.Locale..." -JOBS=${JOBS:-$(sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 4)} +log_info "Building Boost.Locale (${BOOST_VARIANT})..." +# JOBS is set in env.sh (default: 1 for sequential builds, use -j N to override) ./b2 -j${JOBS} \ --user-config=user-config.jam \ --prefix="${SYSROOT}" \ --with-locale \ toolset=clang-emscripten \ - variant=release \ + variant=${BOOST_VARIANT} \ link=static \ threading=multi \ runtime-link=static \ - cxxflags="-pthread" \ + cxxflags="${BOOST_DEBUG_FLAGS} -pthread" \ install create_stamp "${BOOST_STAMP}" diff --git a/scripts/deps/build-cairo.sh b/scripts/deps/build-cairo.sh index 15f52ea..e0721c3 100755 --- a/scripts/deps/build-cairo.sh +++ b/scripts/deps/build-cairo.sh @@ -56,6 +56,15 @@ log_info "Building Cairo ${CAIRO_VERSION} for WASM..." mkdir -p "${CAIRO_BUILD}" cd "${CAIRO_BUILD}" +# Determine meson build type based on DEBUG_BUILD +if [ "${DEBUG_BUILD:-1}" = "1" ]; then + MESON_BUILD_TYPE="debug" + MESON_DEBUG_FLAGS="'-g', '-O0'" +else + MESON_BUILD_TYPE="release" + MESON_DEBUG_FLAGS="'-O2'" +fi + # Cairo uses meson cat > cross-file.txt << EOF [binaries] @@ -81,7 +90,7 @@ pkg_config_libdir = '${SYSROOT}/lib/pkgconfig' default_library = 'static' b_staticpic = false b_pie = false -c_args = ['-pthread', '-I${SYSROOT}/include', '-I${SYSROOT}/include/freetype2', '-I${SYSROOT}/include/pixman-1'] +c_args = [${MESON_DEBUG_FLAGS}, '-pthread', '-I${SYSROOT}/include', '-I${SYSROOT}/include/freetype2', '-I${SYSROOT}/include/pixman-1'] c_link_args = ['-pthread', '-L${SYSROOT}/lib'] pkg_config_path = '${SYSROOT}/lib/pkgconfig' EOF @@ -95,6 +104,7 @@ meson setup "${CAIRO_DIR}" \ --cross-file cross-file.txt \ --prefix="${SYSROOT}" \ --default-library=static \ + --buildtype=${MESON_BUILD_TYPE} \ -Dfontconfig=disabled \ -Dfreetype=enabled \ -Dglib=disabled \ @@ -108,7 +118,7 @@ meson setup "${CAIRO_DIR}" \ -Dfreetype2:default_library=static \ -Dlibpng:default_library=static -JOBS=${JOBS:-$(sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 4)} +# JOBS is set in env.sh (default: 1 for sequential builds, use -j N to override) ninja -j${JOBS} ninja install diff --git a/scripts/deps/build-freetype.sh b/scripts/deps/build-freetype.sh index 7c68fa4..6a433bc 100755 --- a/scripts/deps/build-freetype.sh +++ b/scripts/deps/build-freetype.sh @@ -53,9 +53,11 @@ mkdir -p "${FREETYPE_BUILD}" cd "${FREETYPE_BUILD}" emcmake cmake "${FREETYPE_DIR}" \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \ -DCMAKE_INSTALL_PREFIX="${SYSROOT}" \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ + -DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0}" \ + -DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0}" \ -DFT_DISABLE_BZIP2=ON \ -DFT_DISABLE_BROTLI=ON \ -DFT_DISABLE_HARFBUZZ=ON \ diff --git a/scripts/deps/build-harfbuzz.sh b/scripts/deps/build-harfbuzz.sh index fe26ff1..165116d 100755 --- a/scripts/deps/build-harfbuzz.sh +++ b/scripts/deps/build-harfbuzz.sh @@ -57,9 +57,11 @@ cd "${HARFBUZZ_BUILD}" # HarfBuzz uses meson, but also has CMake support emcmake cmake "${HARFBUZZ_DIR}" \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \ -DCMAKE_INSTALL_PREFIX="${SYSROOT}" \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ + -DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0}" \ + -DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0}" \ -DHB_HAVE_FREETYPE=ON \ -DHB_HAVE_GLIB=OFF \ -DHB_HAVE_ICU=OFF \ diff --git a/scripts/deps/build-ngspice.sh b/scripts/deps/build-ngspice.sh index 2a5e5dc..051811a 100755 --- a/scripts/deps/build-ngspice.sh +++ b/scripts/deps/build-ngspice.sh @@ -53,9 +53,16 @@ mkdir -p "${NGSPICE_BUILD}" cd "${NGSPICE_BUILD}" # ngspice uses autoconf -# First we need to configure for shared library mode (libngspice) -export CFLAGS="-pthread" -export CXXFLAGS="-pthread" +# Set compiler flags based on debug mode +if [ "${DEBUG_BUILD:-1}" = "1" ]; then + export CFLAGS="-g -O0 -pthread" + export CXXFLAGS="-g -O0 -pthread" + NGSPICE_DEBUG_FLAG="--enable-debug" +else + export CFLAGS="-O2 -pthread" + export CXXFLAGS="-O2 -pthread" + NGSPICE_DEBUG_FLAG="--disable-debug" +fi export LDFLAGS="-pthread" # Configure ngspice as a static library for WASM @@ -67,7 +74,7 @@ emconfigure "${NGSPICE_DIR}/configure" \ --build=$(uname -m)-linux-gnu \ --disable-shared \ --enable-static \ - --disable-debug \ + ${NGSPICE_DEBUG_FLAG} \ --disable-dependency-tracking \ --disable-openmp \ --enable-cider \ diff --git a/scripts/deps/build-opencascade.sh b/scripts/deps/build-opencascade.sh index 3b15d04..fa6dec8 100755 --- a/scripts/deps/build-opencascade.sh +++ b/scripts/deps/build-opencascade.sh @@ -61,10 +61,10 @@ cd "${OCC_BUILD}" # Enable core geometry and data exchange modules only emcmake cmake "${OCC_DIR}" \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \ -DCMAKE_INSTALL_PREFIX="${SYSROOT}" \ - -DCMAKE_CXX_FLAGS="-pthread -O2" \ - -DCMAKE_C_FLAGS="-pthread -O2" \ + -DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \ + -DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \ -DBUILD_LIBRARY_TYPE=Static \ -DBUILD_MODULE_ApplicationFramework=OFF \ -DBUILD_MODULE_Draw=OFF \ diff --git a/scripts/deps/build-pixman.sh b/scripts/deps/build-pixman.sh index 7f4c815..06e9c60 100755 --- a/scripts/deps/build-pixman.sh +++ b/scripts/deps/build-pixman.sh @@ -52,6 +52,15 @@ log_info "Building Pixman ${PIXMAN_VERSION} for WASM..." mkdir -p "${PIXMAN_BUILD}" cd "${PIXMAN_BUILD}" +# Determine meson build type based on DEBUG_BUILD +if [ "${DEBUG_BUILD:-1}" = "1" ]; then + MESON_BUILD_TYPE="debug" + MESON_DEBUG_FLAGS="'-g', '-O0'" +else + MESON_BUILD_TYPE="release" + MESON_DEBUG_FLAGS="'-O2'" +fi + # Pixman uses meson cat > cross-file.txt << EOF [binaries] @@ -68,7 +77,7 @@ cpu = 'wasm32' endian = 'little' [built-in options] -c_args = ['-pthread'] +c_args = [${MESON_DEBUG_FLAGS}, '-pthread'] c_link_args = ['-pthread'] EOF @@ -76,11 +85,12 @@ meson setup "${PIXMAN_DIR}" \ --cross-file cross-file.txt \ --prefix="${SYSROOT}" \ --default-library=static \ + --buildtype=${MESON_BUILD_TYPE} \ -Dgtk=disabled \ -Dlibpng=disabled \ -Dtests=disabled -JOBS=${JOBS:-$(sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 4)} +# JOBS is set in env.sh (default: 1 for sequential builds, use -j N to override) ninja -j${JOBS} ninja install diff --git a/scripts/deps/build-protobuf.sh b/scripts/deps/build-protobuf.sh index 3650913..85cf856 100755 --- a/scripts/deps/build-protobuf.sh +++ b/scripts/deps/build-protobuf.sh @@ -55,9 +55,10 @@ mkdir -p "${PROTOBUF_BUILD}" cd "${PROTOBUF_BUILD}" emcmake cmake "${PROTOBUF_DIR}" \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \ -DCMAKE_INSTALL_PREFIX="${SYSROOT}" \ - -DCMAKE_CXX_FLAGS="-pthread" \ + -DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \ + -DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \ -Dprotobuf_BUILD_TESTS=OFF \ -Dprotobuf_BUILD_EXAMPLES=OFF \ -Dprotobuf_BUILD_PROTOC_BINARIES=OFF \ diff --git a/scripts/deps/build-zstd.sh b/scripts/deps/build-zstd.sh index 828da64..0c1d4f5 100755 --- a/scripts/deps/build-zstd.sh +++ b/scripts/deps/build-zstd.sh @@ -54,7 +54,7 @@ cd "${ZSTD_BUILD}" # Zstd uses CMake in build/cmake directory emcmake cmake "${ZSTD_DIR}/build/cmake" \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \ -DCMAKE_INSTALL_PREFIX="${SYSROOT}" \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DZSTD_BUILD_PROGRAMS=OFF \ @@ -62,8 +62,8 @@ emcmake cmake "${ZSTD_DIR}/build/cmake" \ -DZSTD_BUILD_SHARED=OFF \ -DZSTD_BUILD_STATIC=ON \ -DZSTD_MULTITHREAD_SUPPORT=ON \ - -DCMAKE_C_FLAGS="-pthread" \ - -DCMAKE_CXX_FLAGS="-pthread" + -DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \ + -DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" emmake make -j${JOBS} emmake make install diff --git a/scripts/kicad/build-pcbnew.sh b/scripts/kicad/build-pcbnew.sh index 2ebd7a8..b7fff72 100755 --- a/scripts/kicad/build-pcbnew.sh +++ b/scripts/kicad/build-pcbnew.sh @@ -6,9 +6,12 @@ # ./scripts/kicad/build-pcbnew.sh [options] # # Options: -# --no-clean Skip cleaning the build directory (default: clean before build) +# --clean Full clean rebuild (dependencies + KiCad) +# --no-clean Skip cleaning the build directory (default: clean KiCad only) # --skip-deps Skip building dependencies -# --debug Build with debug symbols +# --debug Build with debug symbols (default) +# --release Build optimized without debug symbols +# -j N Parallel compilation jobs (default: 1) set -e @@ -23,26 +26,60 @@ KICAD_STAMP="${BUILD_ROOT}/stamps/kicad-pcbnew.stamp" WASM_LAYER="${PROJECT_ROOT}/wasm" WX_BUILD="${BUILD_ROOT}/wxwidgets-universal" -# Parse arguments - clean by default +# Parse arguments - clean KiCad by default NO_CLEAN=0 +FULL_CLEAN=0 SKIP_DEPS=0 DEBUG=0 -for arg in "$@"; do - case $arg in +while [[ $# -gt 0 ]]; do + case $1 in + --clean) + FULL_CLEAN=1 + shift + ;; --no-clean) NO_CLEAN=1 + shift ;; --skip-deps) SKIP_DEPS=1 + shift ;; --debug) DEBUG=1 + shift + ;; + --release) + DEBUG_BUILD=0 + export DEBUG_BUILD + shift + ;; + -j) + export JOBS="$2" + shift 2 + ;; + -j*) + export JOBS="${1#-j}" + shift + ;; + *) + shift ;; esac done -# Step 1: Clean build directory (default behavior) -if [ $NO_CLEAN -eq 0 ]; then +log_info "Using ${JOBS} parallel jobs" + +# Step 1: Clean build directories +if [ $FULL_CLEAN -eq 1 ]; then + log_info "Full clean: removing all stamps and build directories..." + rm -rf "${STAMPS_DIR}"/* + rm -rf "${BUILD_ROOT}/deps"/* + rm -rf "${BUILD_ROOT}/wxwidgets-universal" + rm -rf "${BUILD_ROOT}/stubs" + rm -rf "${KICAD_BUILD}" + rm -rf "${SYSROOT}"/* +elif [ $NO_CLEAN -eq 0 ]; then log_info "Cleaning KiCad PCBnew build directory..." rm -rf "${KICAD_BUILD}" "${KICAD_STAMP}" else @@ -73,12 +110,17 @@ fi log_info "Building KiCad PCBnew ${KICAD_VERSION} for WASM..." # Step 5: Set build type -if [ $DEBUG -eq 1 ]; then +# Use environment DEBUG_BUILD if set, otherwise check local --debug flag +if [ "${DEBUG_BUILD:-0}" = "1" ] || [ $DEBUG -eq 1 ]; then BUILD_TYPE="Debug" EXTRA_FLAGS="-g -O0" + LINKER_DEBUG_FLAGS="-g -gsource-map" + log_info "Building KiCad in DEBUG mode (with source maps)" else BUILD_TYPE="Release" EXTRA_FLAGS="-O2" + LINKER_DEBUG_FLAGS="" + log_info "Building KiCad in RELEASE mode" fi # Step 6: Create build directory @@ -128,7 +170,7 @@ emcmake cmake "${KICAD_DIR}" \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_CXX_FLAGS="${EXTRA_FLAGS} -pthread -sUSE_ZLIB=1 -DKICAD_USE_PLATFORM_WASM=1 -I${SYSROOT}/include" \ -DCMAKE_C_FLAGS="${EXTRA_FLAGS} -pthread -sUSE_ZLIB=1 -I${SYSROOT}/include" \ - -DCMAKE_EXE_LINKER_FLAGS="-pthread -sUSE_ZLIB=1 -sASYNCIFY=1 -sASYNCIFY_STACK_SIZE=65536 -sUSE_PTHREADS=1 -sPTHREAD_POOL_SIZE=4 -sALLOW_MEMORY_GROWTH=1 -sINITIAL_MEMORY=256MB -sMAXIMUM_MEMORY=4GB -L${SYSROOT}/lib ${STUBS_BUILD}/libgit2_stub.a ${STUBS_BUILD}/libcurl_stub.a" \ + -DCMAKE_EXE_LINKER_FLAGS="${LINKER_DEBUG_FLAGS} -pthread -sUSE_ZLIB=1 -sASYNCIFY=1 -sASYNCIFY_STACK_SIZE=65536 -sUSE_PTHREADS=1 -sPTHREAD_POOL_SIZE=4 -sALLOW_MEMORY_GROWTH=1 -sINITIAL_MEMORY=256MB -sMAXIMUM_MEMORY=4GB -L${SYSROOT}/lib ${STUBS_BUILD}/libgit2_stub.a ${STUBS_BUILD}/libcurl_stub.a" \ -DCMAKE_PREFIX_PATH="${SYSROOT};${WX_BUILD}" \ -DwxWidgets_CONFIG_EXECUTABLE="${WX_BUILD}/wx-config" \ \ @@ -167,7 +209,7 @@ emcmake cmake "${KICAD_DIR}" \ # Step 8: Build pcbnew target log_info "Building pcbnew..." -JOBS=${JOBS:-$(sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 4)} +# JOBS is set in env.sh (default: 1 for sequential builds, use -j N to override) emmake make -j${JOBS} pcbnew # Step 9: Create stamp file