Enable exceptions and pthreads atomics for KiCad WASM build
Build fixes: - Enable C++ exceptions in wxWidgets (--enable-exceptions, -fexceptions) Required for KiCad's OnExceptionInMainLoop override in debug builds - Add -matomics -mbulk-memory to all dependency builds for shared memory Required for pthreads support with Emscripten - Fix docker/build.sh output copy path (pcbnew/ not bin/) - Make workspace mount read-only in docker-compose.yml Updated dependency scripts: - build-freetype.sh, build-harfbuzz.sh, build-protobuf.sh - build-zstd.sh, build-opencascade.sh, build-boost.sh - build-pixman.sh, build-cairo.sh (meson cross-file) - build-wxuniversal-wasm.sh, build-pcbnew.sh 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
71f800d6a5
commit
d8d934ffca
13 changed files with 100 additions and 34 deletions
|
|
@ -14,6 +14,6 @@ docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
|
|||
# Copy output to host-accessible directory
|
||||
echo "Copying build output to ./output/..."
|
||||
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
|
||||
bash -c "mkdir -p /workspace/output && cp -r /workspace/build-wasm/kicad-pcbnew/bin/* /workspace/output/ 2>/dev/null || true"
|
||||
bash -c "mkdir -p /workspace/output && cp /workspace/build-wasm/kicad-pcbnew/pcbnew/pcbnew.{js,wasm,wasm.map,worker.js} /workspace/output/ 2>/dev/null || cp /workspace/build-wasm/kicad-pcbnew/pcbnew/pcbnew.{js,wasm} /workspace/output/"
|
||||
|
||||
echo "Build complete. Output files in ./output/"
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ services:
|
|||
memory: 32G
|
||||
|
||||
volumes:
|
||||
# Source code (read-write for git operations)
|
||||
- ..:/workspace:cached
|
||||
# Source code (read-only - all modifications happen in build-wasm volume)
|
||||
- ..:/workspace:ro
|
||||
# Named volume for build cache (faster than bind mount on macOS)
|
||||
- kicad-build-cache:/workspace/build-wasm
|
||||
# Output directory for easy access to final WASM files
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ cd "$BUILD_DIR"
|
|||
# --enable-universal Use wxUniversal (draws widgets directly)
|
||||
# --disable-shared Build static libraries
|
||||
# --with-opengl Enable OpenGL/WebGL support
|
||||
# --disable-exceptions Emscripten doesn't support C++ exceptions well
|
||||
# --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
|
||||
|
|
@ -83,8 +83,8 @@ else
|
|||
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}"
|
||||
export CFLAGS="-DZ_HAVE_UNISTD_H=1 ${WX_DEBUG_FLAGS} -fexceptions -pthread -matomics -mbulk-memory"
|
||||
export CXXFLAGS="-DZ_HAVE_UNISTD_H=1 -I$PCRE2_INCLUDE ${WX_DEBUG_FLAGS} -fexceptions -pthread -matomics -mbulk-memory"
|
||||
|
||||
emconfigure "$WX_SOURCE/configure" \
|
||||
--host=emscripten \
|
||||
|
|
@ -92,7 +92,7 @@ emconfigure "$WX_SOURCE/configure" \
|
|||
--enable-universal \
|
||||
--disable-shared \
|
||||
--with-opengl \
|
||||
--disable-exceptions \
|
||||
--enable-exceptions \
|
||||
--disable-richtext \
|
||||
--without-libtiff \
|
||||
--disable-xlocale \
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ log_info "=== Phase 1: Header-only libraries ==="
|
|||
log_info "=== Phase 2: Basic compression/serialization ==="
|
||||
"${SCRIPT_DIR}/build-zstd.sh" ${CLEAN}
|
||||
"${SCRIPT_DIR}/build-protobuf.sh" ${CLEAN}
|
||||
"${SCRIPT_DIR}/build-boost.sh" ${CLEAN}
|
||||
|
||||
# 3. Font rendering stack
|
||||
log_info "=== Phase 3: Font rendering ==="
|
||||
|
|
@ -54,6 +55,11 @@ log_info "=== Phase 4: Graphics libraries ==="
|
|||
"${SCRIPT_DIR}/build-pixman.sh" ${CLEAN}
|
||||
"${SCRIPT_DIR}/build-cairo.sh" ${CLEAN}
|
||||
|
||||
# 4b. Stub headers (needed for KiCad compilation but functionality is stubbed)
|
||||
log_info "=== Phase 4b: Stub dependencies (headers only) ==="
|
||||
"${SCRIPT_DIR}/build-curl-headers.sh" ${CLEAN}
|
||||
"${SCRIPT_DIR}/build-libgit2-headers.sh" ${CLEAN}
|
||||
|
||||
# 5. Optional heavy dependencies
|
||||
if [ $WITH_OCC -eq 1 ]; then
|
||||
log_info "=== Phase 5a: OpenCASCADE (3D/STEP support) ==="
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ fi
|
|||
cat > user-config.jam << EOF
|
||||
using clang : emscripten
|
||||
: em++
|
||||
: <cxxflags>"${BOOST_DEBUG_FLAGS} -pthread"
|
||||
: <cxxflags>"${BOOST_DEBUG_FLAGS} -pthread -matomics -mbulk-memory"
|
||||
<linkflags>"-pthread"
|
||||
;
|
||||
EOF
|
||||
|
|
@ -94,7 +94,7 @@ log_info "Building Boost.Locale (${BOOST_VARIANT})..."
|
|||
link=static \
|
||||
threading=multi \
|
||||
runtime-link=static \
|
||||
cxxflags="${BOOST_DEBUG_FLAGS} -pthread" \
|
||||
cxxflags="${BOOST_DEBUG_FLAGS} -pthread -matomics -mbulk-memory" \
|
||||
install
|
||||
|
||||
create_stamp "${BOOST_STAMP}"
|
||||
|
|
|
|||
|
|
@ -82,15 +82,19 @@ cpu = 'wasm32'
|
|||
endian = 'little'
|
||||
|
||||
[properties]
|
||||
# Prevent finding system libraries when cross-compiling
|
||||
sys_root = '${SYSROOT}'
|
||||
# Don't set sys_root - it gets prepended to pkg-config paths which are already absolute
|
||||
# Just use pkg_config_libdir to control where we find .pc files
|
||||
pkg_config_libdir = '${SYSROOT}/lib/pkgconfig'
|
||||
|
||||
[built-in options]
|
||||
default_library = 'static'
|
||||
b_staticpic = false
|
||||
b_pie = false
|
||||
c_args = [${MESON_DEBUG_FLAGS}, '-pthread', '-I${SYSROOT}/include', '-I${SYSROOT}/include/freetype2', '-I${SYSROOT}/include/pixman-1']
|
||||
# Emscripten has these functions but meson checks fail - provide HAVE_ defines
|
||||
# to prevent Cairo from defining its own conflicting implementations
|
||||
# Include ft2build.h and ftcolor.h to fix FT_Color forward declaration bug in cairo-ft-private.h
|
||||
# (the forward declaration is inside HAVE_FT_SVG_DOCUMENT but used in HAVE_FT_COLR_V1)
|
||||
c_args = [${MESON_DEBUG_FLAGS}, '-pthread', '-matomics', '-mbulk-memory', '-I${SYSROOT}/include', '-I${SYSROOT}/include/freetype2', '-I${SYSROOT}/include/pixman-1', '-DHAVE_CTIME_R=1', '-DHAVE_LOCALTIME_R=1', '-DHAVE_GMTIME_R=1', '-DHAVE_STRNDUP=1', '-include', 'ft2build.h', '-include', 'freetype/ftcolor.h']
|
||||
c_link_args = ['-pthread', '-L${SYSROOT}/lib']
|
||||
pkg_config_path = '${SYSROOT}/lib/pkgconfig'
|
||||
EOF
|
||||
|
|
@ -119,8 +123,38 @@ meson setup "${CAIRO_DIR}" \
|
|||
-Dlibpng:default_library=static
|
||||
|
||||
# JOBS is set in env.sh (default: 1 for sequential builds, use -j N to override)
|
||||
ninja -j${JOBS}
|
||||
ninja install
|
||||
# Build only the library targets we need - utility executables fail to link and aren't needed
|
||||
ninja -j${JOBS} src/libcairo.a
|
||||
|
||||
# Manual installation - ninja install tries to build everything including utilities
|
||||
# which fail due to freetype atomics issues
|
||||
log_info "Installing Cairo library and headers..."
|
||||
mkdir -p "${SYSROOT}/lib" "${SYSROOT}/include/cairo" "${SYSROOT}/lib/pkgconfig"
|
||||
cp src/libcairo.a "${SYSROOT}/lib/"
|
||||
cp "${CAIRO_DIR}/src/cairo.h" "${SYSROOT}/include/cairo/"
|
||||
cp "${CAIRO_DIR}/src/cairo-deprecated.h" "${SYSROOT}/include/cairo/"
|
||||
cp "${CAIRO_DIR}/src/cairo-version.h" "${SYSROOT}/include/cairo/"
|
||||
# cairo-features.h is generated during configure in the build directory
|
||||
cp src/cairo-features.h "${SYSROOT}/include/cairo/"
|
||||
cp "${CAIRO_DIR}/src/cairo-ft.h" "${SYSROOT}/include/cairo/"
|
||||
cp "${CAIRO_DIR}/src/cairo-pdf.h" "${SYSROOT}/include/cairo/"
|
||||
cp "${CAIRO_DIR}/src/cairo-ps.h" "${SYSROOT}/include/cairo/"
|
||||
cp "${CAIRO_DIR}/src/cairo-script.h" "${SYSROOT}/include/cairo/"
|
||||
|
||||
# Create pkg-config file
|
||||
cat > "${SYSROOT}/lib/pkgconfig/cairo.pc" << PKGEOF
|
||||
prefix=${SYSROOT}
|
||||
exec_prefix=\${prefix}
|
||||
libdir=\${prefix}/lib
|
||||
includedir=\${prefix}/include
|
||||
|
||||
Name: cairo
|
||||
Description: Multi-platform 2D graphics library
|
||||
Version: 1.18.0
|
||||
Libs: -L\${libdir} -lcairo
|
||||
Cflags: -I\${includedir}/cairo
|
||||
Requires.private: freetype2 pixman-1
|
||||
PKGEOF
|
||||
|
||||
create_stamp "${CAIRO_STAMP}"
|
||||
log_info "Cairo build complete!"
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ emcmake cmake "${FREETYPE_DIR}" \
|
|||
-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}" \
|
||||
-DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread -matomics -mbulk-memory" \
|
||||
-DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread -matomics -mbulk-memory" \
|
||||
-DFT_DISABLE_BZIP2=ON \
|
||||
-DFT_DISABLE_BROTLI=ON \
|
||||
-DFT_DISABLE_HARFBUZZ=ON \
|
||||
|
|
@ -68,5 +68,12 @@ emcmake cmake "${FREETYPE_DIR}" \
|
|||
emmake make -j${JOBS}
|
||||
emmake make install
|
||||
|
||||
# Create symlink without debug suffix for pkg-config compatibility
|
||||
# FreeType CMake adds 'd' suffix for Debug builds but pkg-config expects 'libfreetype'
|
||||
if [ -f "${SYSROOT}/lib/libfreetyped.a" ] && [ ! -f "${SYSROOT}/lib/libfreetype.a" ]; then
|
||||
ln -sf libfreetyped.a "${SYSROOT}/lib/libfreetype.a"
|
||||
log_info "Created libfreetype.a symlink for pkg-config"
|
||||
fi
|
||||
|
||||
create_stamp "${FREETYPE_STAMP}"
|
||||
log_info "FreeType build complete!"
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ emcmake cmake "${HARFBUZZ_DIR}" \
|
|||
-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}" \
|
||||
-DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread -matomics -mbulk-memory" \
|
||||
-DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread -matomics -mbulk-memory" \
|
||||
-DHB_HAVE_FREETYPE=ON \
|
||||
-DHB_HAVE_GLIB=OFF \
|
||||
-DHB_HAVE_ICU=OFF \
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ emcmake cmake "${OCC_DIR}" \
|
|||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \
|
||||
-DCMAKE_INSTALL_PREFIX="${SYSROOT}" \
|
||||
-DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \
|
||||
-DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \
|
||||
-DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread -matomics -mbulk-memory" \
|
||||
-DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread -matomics -mbulk-memory" \
|
||||
-DBUILD_LIBRARY_TYPE=Static \
|
||||
-DBUILD_MODULE_ApplicationFramework=OFF \
|
||||
-DBUILD_MODULE_Draw=OFF \
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ cpu = 'wasm32'
|
|||
endian = 'little'
|
||||
|
||||
[built-in options]
|
||||
c_args = [${MESON_DEBUG_FLAGS}, '-pthread']
|
||||
c_args = [${MESON_DEBUG_FLAGS}, '-pthread', '-matomics', '-mbulk-memory']
|
||||
c_link_args = ['-pthread']
|
||||
EOF
|
||||
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ cd "${PROTOBUF_BUILD}"
|
|||
emcmake cmake "${PROTOBUF_DIR}" \
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE:-Debug} \
|
||||
-DCMAKE_INSTALL_PREFIX="${SYSROOT}" \
|
||||
-DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \
|
||||
-DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread" \
|
||||
-DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread -matomics -mbulk-memory" \
|
||||
-DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread -matomics -mbulk-memory" \
|
||||
-Dprotobuf_BUILD_TESTS=OFF \
|
||||
-Dprotobuf_BUILD_EXAMPLES=OFF \
|
||||
-Dprotobuf_BUILD_PROTOC_BINARIES=OFF \
|
||||
|
|
@ -68,5 +68,16 @@ emcmake cmake "${PROTOBUF_DIR}" \
|
|||
emmake make -j${JOBS}
|
||||
emmake make install
|
||||
|
||||
# Create symlinks without debug suffix for pkg-config compatibility
|
||||
# Protobuf CMake adds 'd' suffix for Debug builds but pkg-config expects 'libprotobuf'
|
||||
if [ -f "${SYSROOT}/lib/libprotobufd.a" ] && [ ! -f "${SYSROOT}/lib/libprotobuf.a" ]; then
|
||||
ln -sf libprotobufd.a "${SYSROOT}/lib/libprotobuf.a"
|
||||
log_info "Created libprotobuf.a symlink for pkg-config"
|
||||
fi
|
||||
if [ -f "${SYSROOT}/lib/libprotobuf-lited.a" ] && [ ! -f "${SYSROOT}/lib/libprotobuf-lite.a" ]; then
|
||||
ln -sf libprotobuf-lited.a "${SYSROOT}/lib/libprotobuf-lite.a"
|
||||
log_info "Created libprotobuf-lite.a symlink for pkg-config"
|
||||
fi
|
||||
|
||||
create_stamp "${PROTOBUF_STAMP}"
|
||||
log_info "Protobuf build complete!"
|
||||
|
|
|
|||
|
|
@ -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="${DEBUG_CFLAGS:--g -O0} -pthread" \
|
||||
-DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread"
|
||||
-DCMAKE_C_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread -matomics -mbulk-memory" \
|
||||
-DCMAKE_CXX_FLAGS="${DEBUG_CFLAGS:--g -O0} -pthread -matomics -mbulk-memory"
|
||||
|
||||
emmake make -j${JOBS}
|
||||
emmake make install
|
||||
|
|
|
|||
|
|
@ -87,9 +87,10 @@ else
|
|||
fi
|
||||
|
||||
# Step 2: Build dependencies
|
||||
# Note: --with-occ for OpenCASCADE, but NOT ngspice since KICAD_SPICE=OFF
|
||||
if [ $SKIP_DEPS -eq 0 ]; then
|
||||
log_info "Building dependencies..."
|
||||
"${SCRIPT_DIR}/../deps/build-all-deps.sh" --all
|
||||
"${SCRIPT_DIR}/../deps/build-all-deps.sh" --with-occ
|
||||
else
|
||||
log_info "Skipping dependencies (--skip-deps specified)"
|
||||
fi
|
||||
|
|
@ -100,26 +101,33 @@ if [ $NO_CLEAN -eq 1 ] && check_stamp "${KICAD_STAMP}"; then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
# Step 4: Verify wxWidgets is built
|
||||
# Step 4: Build wxWidgets if not present
|
||||
WXWIDGETS_STAMP="${BUILD_ROOT}/stamps/wxwidgets.stamp"
|
||||
if [ ! -f "${WX_BUILD}/lib/libwx_baseu-3.2.a" ]; then
|
||||
log_error "wxWidgets not found. Please build wxWidgets first with:"
|
||||
log_error " ./scripts/build-wxuniversal-wasm.sh"
|
||||
exit 1
|
||||
log_info "Building wxWidgets..."
|
||||
"${SCRIPT_DIR}/../build-wxuniversal-wasm.sh" --no-clean
|
||||
# Create stamp after successful build
|
||||
touch "${WXWIDGETS_STAMP}"
|
||||
elif [ ! -f "${WXWIDGETS_STAMP}" ]; then
|
||||
# Library exists but no stamp - create one
|
||||
touch "${WXWIDGETS_STAMP}"
|
||||
fi
|
||||
|
||||
log_info "Building KiCad PCBnew ${KICAD_VERSION} for WASM..."
|
||||
|
||||
# Step 5: Set build type
|
||||
# Use environment DEBUG_BUILD if set, otherwise check local --debug flag
|
||||
# -fexceptions is required because wxWidgets is built with exceptions enabled
|
||||
# -matomics -mbulk-memory are required for shared memory (pthreads)
|
||||
if [ "${DEBUG_BUILD:-0}" = "1" ] || [ $DEBUG -eq 1 ]; then
|
||||
BUILD_TYPE="Debug"
|
||||
EXTRA_FLAGS="-g -O0"
|
||||
LINKER_DEBUG_FLAGS="-g -gsource-map"
|
||||
EXTRA_FLAGS="-g -O0 -fexceptions -matomics -mbulk-memory"
|
||||
LINKER_DEBUG_FLAGS="-g -gsource-map -fexceptions"
|
||||
log_info "Building KiCad in DEBUG mode (with source maps)"
|
||||
else
|
||||
BUILD_TYPE="Release"
|
||||
EXTRA_FLAGS="-O2"
|
||||
LINKER_DEBUG_FLAGS=""
|
||||
EXTRA_FLAGS="-O2 -fexceptions -matomics -mbulk-memory"
|
||||
LINKER_DEBUG_FLAGS="-fexceptions"
|
||||
log_info "Building KiCad in RELEASE mode"
|
||||
fi
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue