Improve build system with debug symbols, clean modes, and parallel jobs

- Add build.md documentation for the WASM build system
- Default to debug builds with -gsource-map for WASM debugging
- Add --release flag to disable debug symbols
- Add --clean flag for full rebuild (deps + wxWidgets + KiCad)
- Add -j N flag for parallel compilation (default: 1 for sequential)
- Update Docker memory limit to 32GB
- Propagate DEBUG_BUILD and JOBS to all dependency scripts

Build modes:
- ./docker/build.sh --clean -j8  (full rebuild, parallel)
- ./docker/build.sh              (rebuild KiCad only)
- ./docker/build.sh --no-clean   (incremental)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Viktor Vaczi 2025-12-12 14:51:38 +01:00
commit af2adda002
16 changed files with 398 additions and 44 deletions

220
build.md Normal file
View file

@ -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/<dep>.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
```

View file

@ -5,12 +5,12 @@ services:
dockerfile: docker/Dockerfile dockerfile: docker/Dockerfile
container_name: kicad-wasm-builder container_name: kicad-wasm-builder
# Resource limits (M4 Max: 10 cores, 16GB) # Resource limits (adjust based on your machine)
deploy: deploy:
resources: resources:
limits: limits:
cpus: '10' cpus: '10'
memory: 16G memory: 32G
volumes: volumes:
# Source code (read-write for git operations) # Source code (read-write for git operations)

View file

@ -9,7 +9,8 @@
# --with-occ Enable OpenCASCADE (3D/STEP support) # --with-occ Enable OpenCASCADE (3D/STEP support)
# --with-ngspice Enable ngspice (simulation) # --with-ngspice Enable ngspice (simulation)
# --with-pthread Enable pthreads (multi-threading) # --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) # -j N Parallel jobs (default: nproc)
# --help Show this help # --help Show this help
@ -66,6 +67,10 @@ while [[ $# -gt 0 ]]; do
DEBUG_BUILD=1 DEBUG_BUILD=1
shift shift
;; ;;
--release)
DEBUG_BUILD=0
shift
;;
-j) -j)
PARALLEL_JOBS="$2" PARALLEL_JOBS="$2"
shift 2 shift 2
@ -83,7 +88,7 @@ done
# Set defaults if not set # Set defaults if not set
CLEAN_BUILD=${CLEAN_BUILD:-0} 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)} PARALLEL_JOBS=${PARALLEL_JOBS:-$(get_nproc)}
# Export for sub-scripts # Export for sub-scripts

View file

@ -22,6 +22,9 @@ PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
BUILD_DIR="$PROJECT_ROOT/build-wasm/wxwidgets-universal" BUILD_DIR="$PROJECT_ROOT/build-wasm/wxwidgets-universal"
WX_SOURCE="$PROJECT_ROOT/wxwidgets" 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 "=== Building wxWidgets wxUniversal for WASM ==="
echo "Project root: $PROJECT_ROOT" echo "Project root: $PROJECT_ROOT"
echo "Build dir: $BUILD_DIR" echo "Build dir: $BUILD_DIR"
@ -68,8 +71,20 @@ echo "=== Configuring ==="
# Z_HAVE_UNISTD_H ensures zlib includes <unistd.h> for read/write/lseek # Z_HAVE_UNISTD_H ensures zlib includes <unistd.h> for read/write/lseek
# Include pcre2 headers from the build directory (generated during configure) # Include pcre2 headers from the build directory (generated during configure)
PCRE2_INCLUDE="$BUILD_DIR/3rdparty/pcre/src" 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" \ emconfigure "$WX_SOURCE/configure" \
--host=emscripten \ --host=emscripten \
@ -82,7 +97,8 @@ emconfigure "$WX_SOURCE/configure" \
--without-libtiff \ --without-libtiff \
--disable-xlocale \ --disable-xlocale \
--with-cxx=17 \ --with-cxx=17 \
--enable-utf8 --enable-utf8 \
${WX_CONFIGURE_DEBUG}
# Build PCRE first to avoid race condition with parallel builds # Build PCRE first to avoid race condition with parallel builds
# PCRE headers (pcre2.h) must be generated before regex.cpp compiles # PCRE headers (pcre2.h) must be generated before regex.cpp compiles
@ -92,8 +108,8 @@ emmake make -C 3rdparty/pcre
# Build wxWidgets # Build wxWidgets
echo "" echo ""
echo "=== Building wxWidgets ===" echo "=== Building wxWidgets (using ${JOBS} parallel jobs) ==="
emmake make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu) emmake make -j${JOBS}
# Create library symlinks (remove -emscripten suffix for CMake compatibility) # Create library symlinks (remove -emscripten suffix for CMake compatibility)
echo "" echo ""

View file

@ -34,6 +34,32 @@ export EMSDK_QUIET=1
export EMCC_CFLAGS="-fPIC -DEMSCRIPTEN" export EMCC_CFLAGS="-fPIC -DEMSCRIPTEN"
export EMCC_CXXFLAGS="-fPIC -DEMSCRIPTEN -std=c++17" 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 # Common linker flags for WASM
export WASM_LDFLAGS="\ export WASM_LDFLAGS="\
-sALLOW_MEMORY_GROWTH=1 \ -sALLOW_MEMORY_GROWTH=1 \

View file

@ -226,7 +226,7 @@ get_nproc() {
# Parse common command line arguments # Parse common command line arguments
parse_common_args() { parse_common_args() {
CLEAN_BUILD=0 CLEAN_BUILD=0
DEBUG_BUILD=0 DEBUG_BUILD="${DEBUG_BUILD:-1}" # Default ON (use --release to disable)
PARALLEL_JOBS=$(get_nproc) PARALLEL_JOBS=$(get_nproc)
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
@ -239,6 +239,10 @@ parse_common_args() {
DEBUG_BUILD=1 DEBUG_BUILD=1
shift shift
;; ;;
--release)
DEBUG_BUILD=0
shift
;;
-j) -j)
PARALLEL_JOBS="$2" PARALLEL_JOBS="$2"
shift 2 shift 2

View file

@ -63,29 +63,38 @@ if [ ! -f "b2" ]; then
./bootstrap.sh --with-toolset=gcc ./bootstrap.sh --with-toolset=gcc
fi 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 # Create user-config.jam for Emscripten
cat > user-config.jam << 'EOF' cat > user-config.jam << EOF
using clang : emscripten using clang : emscripten
: em++ : em++
: <cxxflags>"-pthread" : <cxxflags>"${BOOST_DEBUG_FLAGS} -pthread"
<linkflags>"-pthread" <linkflags>"-pthread"
; ;
EOF EOF
# Build only the locale library (and its dependencies) # Build only the locale library (and its dependencies)
# Most of Boost is header-only, we just need locale built # Most of Boost is header-only, we just need locale built
log_info "Building Boost.Locale..." log_info "Building Boost.Locale (${BOOST_VARIANT})..."
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)
./b2 -j${JOBS} \ ./b2 -j${JOBS} \
--user-config=user-config.jam \ --user-config=user-config.jam \
--prefix="${SYSROOT}" \ --prefix="${SYSROOT}" \
--with-locale \ --with-locale \
toolset=clang-emscripten \ toolset=clang-emscripten \
variant=release \ variant=${BOOST_VARIANT} \
link=static \ link=static \
threading=multi \ threading=multi \
runtime-link=static \ runtime-link=static \
cxxflags="-pthread" \ cxxflags="${BOOST_DEBUG_FLAGS} -pthread" \
install install
create_stamp "${BOOST_STAMP}" create_stamp "${BOOST_STAMP}"

View file

@ -56,6 +56,15 @@ log_info "Building Cairo ${CAIRO_VERSION} for WASM..."
mkdir -p "${CAIRO_BUILD}" mkdir -p "${CAIRO_BUILD}"
cd "${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 # Cairo uses meson
cat > cross-file.txt << EOF cat > cross-file.txt << EOF
[binaries] [binaries]
@ -81,7 +90,7 @@ pkg_config_libdir = '${SYSROOT}/lib/pkgconfig'
default_library = 'static' default_library = 'static'
b_staticpic = false b_staticpic = false
b_pie = 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'] c_link_args = ['-pthread', '-L${SYSROOT}/lib']
pkg_config_path = '${SYSROOT}/lib/pkgconfig' pkg_config_path = '${SYSROOT}/lib/pkgconfig'
EOF EOF
@ -95,6 +104,7 @@ meson setup "${CAIRO_DIR}" \
--cross-file cross-file.txt \ --cross-file cross-file.txt \
--prefix="${SYSROOT}" \ --prefix="${SYSROOT}" \
--default-library=static \ --default-library=static \
--buildtype=${MESON_BUILD_TYPE} \
-Dfontconfig=disabled \ -Dfontconfig=disabled \
-Dfreetype=enabled \ -Dfreetype=enabled \
-Dglib=disabled \ -Dglib=disabled \
@ -108,7 +118,7 @@ meson setup "${CAIRO_DIR}" \
-Dfreetype2:default_library=static \ -Dfreetype2:default_library=static \
-Dlibpng: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 -j${JOBS}
ninja install ninja install

View file

@ -53,9 +53,11 @@ mkdir -p "${FREETYPE_BUILD}"
cd "${FREETYPE_BUILD}" cd "${FREETYPE_BUILD}"
emcmake cmake "${FREETYPE_DIR}" \ emcmake cmake "${FREETYPE_DIR}" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \
-DCMAKE_INSTALL_PREFIX="${SYSROOT}" \ -DCMAKE_INSTALL_PREFIX="${SYSROOT}" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -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_BZIP2=ON \
-DFT_DISABLE_BROTLI=ON \ -DFT_DISABLE_BROTLI=ON \
-DFT_DISABLE_HARFBUZZ=ON \ -DFT_DISABLE_HARFBUZZ=ON \

View file

@ -57,9 +57,11 @@ cd "${HARFBUZZ_BUILD}"
# HarfBuzz uses meson, but also has CMake support # HarfBuzz uses meson, but also has CMake support
emcmake cmake "${HARFBUZZ_DIR}" \ emcmake cmake "${HARFBUZZ_DIR}" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \
-DCMAKE_INSTALL_PREFIX="${SYSROOT}" \ -DCMAKE_INSTALL_PREFIX="${SYSROOT}" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -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_FREETYPE=ON \
-DHB_HAVE_GLIB=OFF \ -DHB_HAVE_GLIB=OFF \
-DHB_HAVE_ICU=OFF \ -DHB_HAVE_ICU=OFF \

View file

@ -53,9 +53,16 @@ mkdir -p "${NGSPICE_BUILD}"
cd "${NGSPICE_BUILD}" cd "${NGSPICE_BUILD}"
# ngspice uses autoconf # ngspice uses autoconf
# First we need to configure for shared library mode (libngspice) # Set compiler flags based on debug mode
export CFLAGS="-pthread" if [ "${DEBUG_BUILD:-1}" = "1" ]; then
export CXXFLAGS="-pthread" 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" export LDFLAGS="-pthread"
# Configure ngspice as a static library for WASM # Configure ngspice as a static library for WASM
@ -67,7 +74,7 @@ emconfigure "${NGSPICE_DIR}/configure" \
--build=$(uname -m)-linux-gnu \ --build=$(uname -m)-linux-gnu \
--disable-shared \ --disable-shared \
--enable-static \ --enable-static \
--disable-debug \ ${NGSPICE_DEBUG_FLAG} \
--disable-dependency-tracking \ --disable-dependency-tracking \
--disable-openmp \ --disable-openmp \
--enable-cider \ --enable-cider \

View file

@ -61,10 +61,10 @@ cd "${OCC_BUILD}"
# Enable core geometry and data exchange modules only # Enable core geometry and data exchange modules only
emcmake cmake "${OCC_DIR}" \ emcmake cmake "${OCC_DIR}" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \
-DCMAKE_INSTALL_PREFIX="${SYSROOT}" \ -DCMAKE_INSTALL_PREFIX="${SYSROOT}" \
-DCMAKE_CXX_FLAGS="-pthread -O2" \ -DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \
-DCMAKE_C_FLAGS="-pthread -O2" \ -DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \
-DBUILD_LIBRARY_TYPE=Static \ -DBUILD_LIBRARY_TYPE=Static \
-DBUILD_MODULE_ApplicationFramework=OFF \ -DBUILD_MODULE_ApplicationFramework=OFF \
-DBUILD_MODULE_Draw=OFF \ -DBUILD_MODULE_Draw=OFF \

View file

@ -52,6 +52,15 @@ log_info "Building Pixman ${PIXMAN_VERSION} for WASM..."
mkdir -p "${PIXMAN_BUILD}" mkdir -p "${PIXMAN_BUILD}"
cd "${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 # Pixman uses meson
cat > cross-file.txt << EOF cat > cross-file.txt << EOF
[binaries] [binaries]
@ -68,7 +77,7 @@ cpu = 'wasm32'
endian = 'little' endian = 'little'
[built-in options] [built-in options]
c_args = ['-pthread'] c_args = [${MESON_DEBUG_FLAGS}, '-pthread']
c_link_args = ['-pthread'] c_link_args = ['-pthread']
EOF EOF
@ -76,11 +85,12 @@ meson setup "${PIXMAN_DIR}" \
--cross-file cross-file.txt \ --cross-file cross-file.txt \
--prefix="${SYSROOT}" \ --prefix="${SYSROOT}" \
--default-library=static \ --default-library=static \
--buildtype=${MESON_BUILD_TYPE} \
-Dgtk=disabled \ -Dgtk=disabled \
-Dlibpng=disabled \ -Dlibpng=disabled \
-Dtests=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 -j${JOBS}
ninja install ninja install

View file

@ -55,9 +55,10 @@ mkdir -p "${PROTOBUF_BUILD}"
cd "${PROTOBUF_BUILD}" cd "${PROTOBUF_BUILD}"
emcmake cmake "${PROTOBUF_DIR}" \ emcmake cmake "${PROTOBUF_DIR}" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \
-DCMAKE_INSTALL_PREFIX="${SYSROOT}" \ -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_TESTS=OFF \
-Dprotobuf_BUILD_EXAMPLES=OFF \ -Dprotobuf_BUILD_EXAMPLES=OFF \
-Dprotobuf_BUILD_PROTOC_BINARIES=OFF \ -Dprotobuf_BUILD_PROTOC_BINARIES=OFF \

View file

@ -54,7 +54,7 @@ cd "${ZSTD_BUILD}"
# Zstd uses CMake in build/cmake directory # Zstd uses CMake in build/cmake directory
emcmake cmake "${ZSTD_DIR}/build/cmake" \ emcmake cmake "${ZSTD_DIR}/build/cmake" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \
-DCMAKE_INSTALL_PREFIX="${SYSROOT}" \ -DCMAKE_INSTALL_PREFIX="${SYSROOT}" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DZSTD_BUILD_PROGRAMS=OFF \ -DZSTD_BUILD_PROGRAMS=OFF \
@ -62,8 +62,8 @@ emcmake cmake "${ZSTD_DIR}/build/cmake" \
-DZSTD_BUILD_SHARED=OFF \ -DZSTD_BUILD_SHARED=OFF \
-DZSTD_BUILD_STATIC=ON \ -DZSTD_BUILD_STATIC=ON \
-DZSTD_MULTITHREAD_SUPPORT=ON \ -DZSTD_MULTITHREAD_SUPPORT=ON \
-DCMAKE_C_FLAGS="-pthread" \ -DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \
-DCMAKE_CXX_FLAGS="-pthread" -DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread"
emmake make -j${JOBS} emmake make -j${JOBS}
emmake make install emmake make install

View file

@ -6,9 +6,12 @@
# ./scripts/kicad/build-pcbnew.sh [options] # ./scripts/kicad/build-pcbnew.sh [options]
# #
# 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 # --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 set -e
@ -23,26 +26,60 @@ KICAD_STAMP="${BUILD_ROOT}/stamps/kicad-pcbnew.stamp"
WASM_LAYER="${PROJECT_ROOT}/wasm" WASM_LAYER="${PROJECT_ROOT}/wasm"
WX_BUILD="${BUILD_ROOT}/wxwidgets-universal" WX_BUILD="${BUILD_ROOT}/wxwidgets-universal"
# Parse arguments - clean by default # Parse arguments - clean KiCad by default
NO_CLEAN=0 NO_CLEAN=0
FULL_CLEAN=0
SKIP_DEPS=0 SKIP_DEPS=0
DEBUG=0 DEBUG=0
for arg in "$@"; do while [[ $# -gt 0 ]]; do
case $arg in case $1 in
--clean)
FULL_CLEAN=1
shift
;;
--no-clean) --no-clean)
NO_CLEAN=1 NO_CLEAN=1
shift
;; ;;
--skip-deps) --skip-deps)
SKIP_DEPS=1 SKIP_DEPS=1
shift
;; ;;
--debug) --debug)
DEBUG=1 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 esac
done done
# Step 1: Clean build directory (default behavior) log_info "Using ${JOBS} parallel jobs"
if [ $NO_CLEAN -eq 0 ]; then
# 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..." log_info "Cleaning KiCad PCBnew build directory..."
rm -rf "${KICAD_BUILD}" "${KICAD_STAMP}" rm -rf "${KICAD_BUILD}" "${KICAD_STAMP}"
else else
@ -73,12 +110,17 @@ fi
log_info "Building KiCad PCBnew ${KICAD_VERSION} for WASM..." log_info "Building KiCad PCBnew ${KICAD_VERSION} for WASM..."
# Step 5: Set build type # 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" BUILD_TYPE="Debug"
EXTRA_FLAGS="-g -O0" EXTRA_FLAGS="-g -O0"
LINKER_DEBUG_FLAGS="-g -gsource-map"
log_info "Building KiCad in DEBUG mode (with source maps)"
else else
BUILD_TYPE="Release" BUILD_TYPE="Release"
EXTRA_FLAGS="-O2" EXTRA_FLAGS="-O2"
LINKER_DEBUG_FLAGS=""
log_info "Building KiCad in RELEASE mode"
fi fi
# Step 6: Create build directory # Step 6: Create build directory
@ -128,7 +170,7 @@ emcmake cmake "${KICAD_DIR}" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DCMAKE_CXX_FLAGS="${EXTRA_FLAGS} -pthread -sUSE_ZLIB=1 -DKICAD_USE_PLATFORM_WASM=1 -I${SYSROOT}/include" \ -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_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}" \ -DCMAKE_PREFIX_PATH="${SYSROOT};${WX_BUILD}" \
-DwxWidgets_CONFIG_EXECUTABLE="${WX_BUILD}/wx-config" \ -DwxWidgets_CONFIG_EXECUTABLE="${WX_BUILD}/wx-config" \
\ \
@ -167,7 +209,7 @@ emcmake cmake "${KICAD_DIR}" \
# Step 8: Build pcbnew target # Step 8: Build pcbnew target
log_info "Building pcbnew..." 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 emmake make -j${JOBS} pcbnew
# Step 9: Create stamp file # Step 9: Create stamp file