Add runtime resource loading and fix Docker incremental builds

- Build images.tar.gz bitmap archive for KiCad icons
- Fetch resources at runtime via HTTP instead of bundling in WASM
- Write to Emscripten virtual FS at compile-time KICAD_DATA path
- Fix rsync timestamp handling for correct make change detection
- Update kicad submodule with WASM settings manager fix

🤖 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-27 20:09:26 +01:00
commit b5d379fe70
7 changed files with 64 additions and 7 deletions

1
.gitignore vendored
View file

@ -47,6 +47,7 @@ wxwidgets-clean/
/tests/apps/standalone/*/*.wasm
/tests/apps/kicad/*.js
/tests/apps/kicad/*.wasm
/tests/apps/kicad/*.tar.gz
!tests/apps/kicad/pcbnew.html
/temp/
*.log

View file

@ -21,10 +21,15 @@ fi
docker compose -f docker/docker-compose.yml up -d
# Sync source code to container volume (fixes macOS Docker timestamp issues)
# This ensures timestamps are consistent within the container filesystem
# rsync -a preserves host timestamps, but make needs container timestamps to
# correctly detect changes against cached object files. We touch transferred
# files to set their mtime to container's current time.
echo "Syncing source code to container..."
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
rsync -a --delete --exclude='build-wasm' --exclude='output' /workspace-host/ /workspace/
bash -c 'rsync -ai --delete --exclude="build-wasm" --exclude="output" /workspace-host/ /workspace/ | \
grep "^>f" | \
sed "s/^[^ ]* //" | \
while read f; do touch "/workspace/$f" 2>/dev/null; done'
# Run build command (without asyncify - handled on host due to memory requirements)
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
@ -34,7 +39,10 @@ docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
# Note: pcbnew.wasm.debug.wasm contains DWARF debug info (generated with -gseparate-dwarf)
echo "Copying build output to ./output/..."
docker compose -f docker/docker-compose.yml exec kicad-wasm-builder \
bash -c "mkdir -p /workspace/output && cp /workspace/build-wasm/kicad-pcbnew/pcbnew/pcbnew.{js,wasm,wasm.debug.wasm,wasm.map,worker.js} /workspace/output/ 2>/dev/null || cp /workspace/build-wasm/kicad-pcbnew/pcbnew/pcbnew.{js,wasm} /workspace/output/"
bash -c "mkdir -p /workspace/output && \
cp /workspace/build-wasm/kicad-pcbnew/pcbnew/pcbnew.{js,wasm,wasm.debug.wasm,wasm.map,worker.js} /workspace/output/ 2>/dev/null || \
cp /workspace/build-wasm/kicad-pcbnew/pcbnew/pcbnew.{js,wasm} /workspace/output/; \
cp /workspace/build-wasm/kicad-pcbnew/resources/images.tar.gz /workspace/output/ 2>/dev/null || true"
# Inject dynCall shims into pcbnew.js
# This fixes "dynCall_* is not defined" errors in Emscripten 4.x

View file

@ -7,12 +7,16 @@ source /emsdk/emsdk_env.sh 2>/dev/null
# Sync source from host to workspace volume
# This fixes macOS Docker timestamp issues with bind mounts
# (autoconf sanity checks fail when timestamps appear inconsistent)
# Touch transferred files to set container timestamps for correct make detection
if [[ -d /workspace-host ]]; then
echo "Syncing source code to container volume..."
rsync -a --delete \
rsync -ai --delete \
--exclude='build-wasm' \
--exclude='output' \
/workspace-host/ /workspace/
/workspace-host/ /workspace/ | \
grep "^>f" | \
sed "s/^[^ ]* //" | \
while read f; do touch "/workspace/$f" 2>/dev/null; done
echo "Sync complete."
fi

2
kicad

@ -1 +1 @@
Subproject commit 2532a4682eb4a6a862d8bdf7baf700f58c4cc5fe
Subproject commit 279f2f1a84dc07a831496334a12373d5454f1d38

View file

@ -306,6 +306,11 @@ fi
log_info "Building pcbnew..."
emmake make -j${JOBS} pcbnew
# Step 8.1: Build bitmap resources (images.tar.gz)
# This creates the icon archive that KiCad loads at runtime
log_info "Building bitmap resources..."
emmake make bitmap_archive_build
# Step 9: Create stamp file
create_stamp "${KICAD_STAMP}"
log_info "KiCad PCBnew build complete!"

View file

@ -105,9 +105,43 @@
document.getElementById('status').style.display = 'none';
};
// Pre-fetched resource data (fetched before pcbnew.js loads)
var resourceData = null;
// Start fetching images.tar.gz immediately (runs in parallel with WASM loading)
fetch('images.tar.gz')
.then(function(response) {
if (!response.ok) throw new Error('HTTP ' + response.status);
return response.arrayBuffer();
})
.then(function(buffer) {
resourceData = new Uint8Array(buffer);
console.log('[KICAD] Prefetched images.tar.gz (' + resourceData.length + ' bytes)');
})
.catch(function(err) {
console.warn('[KICAD] Could not prefetch images.tar.gz:', err.message);
});
// Write pre-fetched resources to FS (called in preRun after FS is available)
var writeResources = function() {
// Create directory structure matching KiCad's compiled-in KICAD_DATA path
// This path is baked in during CMake configuration
var resourcePath = '/workspace/build-wasm/sysroot/share/kicad/resources';
FS.mkdirTree(resourcePath);
// Write pre-fetched data if available
if (resourceData) {
FS.writeFile(resourcePath + '/images.tar.gz', resourceData);
console.log('[KICAD] Wrote images.tar.gz to ' + resourcePath);
} else {
console.warn('[KICAD] images.tar.gz not ready yet (WASM loaded faster than fetch)');
}
};
var Module = {
thisProgram: '/usr/bin/pcbnew', // Fake absolute path for argv[0] (KiCad DEBUG check)
preRun: [createCanvas],
preRun: [createCanvas, writeResources],
postRun: [],
print: function(text) {

View file

@ -22,6 +22,8 @@ if [ -f "$OUTPUT_DIR/pcbnew.js" ] && [ -f "$OUTPUT_DIR/pcbnew.wasm" ]; then
cp "$OUTPUT_DIR/pcbnew.wasm.map" "$KICAD_TEST/" 2>/dev/null || true
# Worker file for pthreads (optional)
cp "$OUTPUT_DIR/pcbnew.worker.js" "$KICAD_TEST/" 2>/dev/null || true
# Bitmap resources for KiCad icons (optional)
cp "$OUTPUT_DIR/images.tar.gz" "$KICAD_TEST/" 2>/dev/null || true
else
echo "Output directory not found, copying from Docker build..."
docker compose -f "$PROJECT_ROOT/docker/docker-compose.yml" cp \
@ -34,6 +36,9 @@ else
# Worker file for pthreads (optional)
docker compose -f "$PROJECT_ROOT/docker/docker-compose.yml" cp \
kicad-wasm-builder:/workspace/build-wasm/kicad-pcbnew/pcbnew/pcbnew.worker.js "$KICAD_TEST/" 2>/dev/null || true
# Bitmap resources for KiCad icons (optional)
docker compose -f "$PROJECT_ROOT/docker/docker-compose.yml" cp \
kicad-wasm-builder:/workspace/build-wasm/kicad-pcbnew/resources/images.tar.gz "$KICAD_TEST/" 2>/dev/null || true
fi
# wxWidgets WASM JavaScript glue code (defines JS functions called from WASM)