强制WASM增量构建
结论:INI和解释器WASM构建已改为对象、依赖和命令指纹驱动的增量编译,并将所有构建必须增量写入项目规则。
This commit is contained in:
@@ -70,6 +70,9 @@ expanded into a separate implementation of G-code behavior.
|
||||
- GUI.
|
||||
7. Frontend code must be implemented with web technology, not migrated from
|
||||
native GUI code.
|
||||
8. All build scripts must be incremental. Native and WASM builds must reuse
|
||||
object files, dependency files, and command fingerprints, and must not
|
||||
unconditionally recompile unchanged source files.
|
||||
|
||||
## Required Layout
|
||||
|
||||
|
||||
@@ -3,17 +3,44 @@ set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
OUT_DIR="$ROOT_DIR/runtime/ui/ini-panel"
|
||||
BUILD_DIR="$ROOT_DIR/build/wasm/ini-panel"
|
||||
OBJ_DIR="$BUILD_DIR/obj"
|
||||
|
||||
emcc \
|
||||
-std=c++20 \
|
||||
source "$ROOT_DIR/tools/wasm_incremental_build_lib.sh"
|
||||
|
||||
mkdir -p "$OUT_DIR" "$BUILD_DIR" "$OBJ_DIR"
|
||||
|
||||
TARGET="linuxcnc_ini_wasm"
|
||||
: > "$BUILD_DIR/$TARGET.stdout.log"
|
||||
: > "$BUILD_DIR/$TARGET.stderr.log"
|
||||
|
||||
COMMON_FLAGS=(
|
||||
-std=c++20
|
||||
-O2
|
||||
-I"$ROOT_DIR/runtime/core/shims"
|
||||
-I"$ROOT_DIR/vendor/linuxcnc/src"
|
||||
-I"$ROOT_DIR/vendor/linuxcnc/src/rtapi"
|
||||
-I"$ROOT_DIR/vendor/linuxcnc/src/emc"
|
||||
)
|
||||
|
||||
SOURCES=(
|
||||
"$ROOT_DIR/vendor/linuxcnc/src/emc/ini/inifile.cc"
|
||||
"$ROOT_DIR/runtime/core/linuxcnc_wrap/linuxcnc_ini_wasm.cpp"
|
||||
)
|
||||
|
||||
OBJECTS=()
|
||||
for source in "${SOURCES[@]}"; do
|
||||
obj="$(source_object_path "$source" "$ROOT_DIR" "$OBJ_DIR")"
|
||||
OBJECTS+=("$obj")
|
||||
compile_wasm_object "$TARGET" "$source" "$obj" "$BUILD_DIR" "${COMMON_FLAGS[@]}"
|
||||
done
|
||||
|
||||
link_wasm_module \
|
||||
"$TARGET" \
|
||||
"$OUT_DIR/linuxcnc_ini.js" \
|
||||
"$BUILD_DIR" \
|
||||
-O2 \
|
||||
-I"$ROOT_DIR/runtime/core/shims" \
|
||||
-I"$ROOT_DIR/vendor/linuxcnc/src" \
|
||||
-I"$ROOT_DIR/vendor/linuxcnc/src/rtapi" \
|
||||
-I"$ROOT_DIR/vendor/linuxcnc/src/emc" \
|
||||
"$ROOT_DIR/vendor/linuxcnc/src/emc/ini/inifile.cc" \
|
||||
"$ROOT_DIR/runtime/core/linuxcnc_wrap/linuxcnc_ini_wasm.cpp" \
|
||||
-o "$OUT_DIR/linuxcnc_ini.js" \
|
||||
"${OBJECTS[@]}" \
|
||||
-s MODULARIZE=1 \
|
||||
-s EXPORT_ES6=1 \
|
||||
-s ENVIRONMENT=web,node \
|
||||
|
||||
@@ -7,8 +7,16 @@ WRAP_DIR="$ROOT_DIR/runtime/core/linuxcnc_wrap"
|
||||
SHIM_DIR="$ROOT_DIR/runtime/core/shims"
|
||||
INCLUDE_DIR="$ROOT_DIR/runtime/core/include"
|
||||
OUT_DIR="$ROOT_DIR/build/wasm/core"
|
||||
BUILD_DIR="$OUT_DIR"
|
||||
OBJ_DIR="$BUILD_DIR/obj"
|
||||
|
||||
mkdir -p "$OUT_DIR"
|
||||
source "$ROOT_DIR/tools/wasm_incremental_build_lib.sh"
|
||||
|
||||
mkdir -p "$OUT_DIR" "$OBJ_DIR"
|
||||
|
||||
TARGET="linuxcnc_interp_wasm"
|
||||
: > "$BUILD_DIR/$TARGET.stdout.log"
|
||||
: > "$BUILD_DIR/$TARGET.stderr.log"
|
||||
|
||||
COMMON_FLAGS=(
|
||||
-std=c++20
|
||||
@@ -62,11 +70,24 @@ INTERP_CORE_SOURCES=(
|
||||
"$VENDOR_DIR/src/emc/ini/inifile.cc"
|
||||
)
|
||||
|
||||
emcc \
|
||||
"${COMMON_FLAGS[@]}" \
|
||||
SOURCES=(
|
||||
"${INTERP_CORE_SOURCES[@]}" \
|
||||
"$WRAP_DIR/linuxcnc_interp_wasm.cpp" \
|
||||
-o "$OUT_DIR/linuxcnc_interp.js" \
|
||||
)
|
||||
|
||||
OBJECTS=()
|
||||
for source in "${SOURCES[@]}"; do
|
||||
obj="$(source_object_path "$source" "$ROOT_DIR" "$OBJ_DIR")"
|
||||
OBJECTS+=("$obj")
|
||||
compile_wasm_object "$TARGET" "$source" "$obj" "$BUILD_DIR" "${COMMON_FLAGS[@]}"
|
||||
done
|
||||
|
||||
link_wasm_module \
|
||||
"$TARGET" \
|
||||
"$OUT_DIR/linuxcnc_interp.js" \
|
||||
"$BUILD_DIR" \
|
||||
-O2 \
|
||||
"${OBJECTS[@]}" \
|
||||
-s MODULARIZE=1 \
|
||||
-s EXPORT_ES6=1 \
|
||||
-s ENVIRONMENT=web,node \
|
||||
|
||||
139
wasm-port/tools/wasm_incremental_build_lib.sh
Normal file
139
wasm-port/tools/wasm_incremental_build_lib.sh
Normal file
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
write_command_file() {
|
||||
local file="$1"
|
||||
shift
|
||||
printf '%q\n' "$@" > "$file"
|
||||
}
|
||||
|
||||
command_matches() {
|
||||
local file="$1"
|
||||
shift
|
||||
|
||||
local tmp
|
||||
tmp="$(mktemp)"
|
||||
write_command_file "$tmp" "$@"
|
||||
if [[ -f "$file" ]] && cmp -s "$tmp" "$file"; then
|
||||
rm -f "$tmp"
|
||||
return 0
|
||||
fi
|
||||
rm -f "$tmp"
|
||||
return 1
|
||||
}
|
||||
|
||||
depfile_newer_than() {
|
||||
local depfile="$1"
|
||||
local output="$2"
|
||||
|
||||
[[ -f "$depfile" ]] || return 0
|
||||
|
||||
local deps
|
||||
deps="$(tr '\\\n' ' ' < "$depfile" | sed -e 's/^[^:]*://')"
|
||||
local dep
|
||||
for dep in $deps; do
|
||||
if [[ -f "$dep" && "$dep" -nt "$output" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
object_needs_rebuild() {
|
||||
local obj="$1"
|
||||
local depfile="$2"
|
||||
local cmdfile="$3"
|
||||
shift 3
|
||||
|
||||
[[ -f "$obj" ]] || return 0
|
||||
command_matches "$cmdfile" "$@" || return 0
|
||||
depfile_newer_than "$depfile" "$obj" && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
link_needs_rebuild() {
|
||||
local output="$1"
|
||||
local cmdfile="$2"
|
||||
shift 2
|
||||
|
||||
[[ -f "$output" ]] || return 0
|
||||
command_matches "$cmdfile" "$@" || return 0
|
||||
|
||||
local arg
|
||||
for arg in "$@"; do
|
||||
if [[ -f "$arg" && "$arg" -nt "$output" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
source_object_path() {
|
||||
local source="$1"
|
||||
local root_dir="$2"
|
||||
local obj_dir="$3"
|
||||
local relative="${source#"$root_dir"/}"
|
||||
|
||||
if [[ "$relative" == "$source" ]]; then
|
||||
relative="$(basename "$source")"
|
||||
fi
|
||||
|
||||
relative="${relative//\//__}"
|
||||
printf '%s/%s.o' "$obj_dir" "${relative%.*}"
|
||||
}
|
||||
|
||||
compile_wasm_object() {
|
||||
local target="$1"
|
||||
local source="$2"
|
||||
local obj="$3"
|
||||
local build_dir="$4"
|
||||
shift 4
|
||||
|
||||
local stdout_log="$build_dir/$target.stdout.log"
|
||||
local stderr_log="$build_dir/$target.stderr.log"
|
||||
local depfile="$obj.d"
|
||||
local cmdfile="$obj.cmd"
|
||||
local cmd=(emcc "$@" -MMD -MP -MF "$depfile" -c "$source" -o "$obj")
|
||||
|
||||
mkdir -p "$(dirname "$obj")"
|
||||
if ! object_needs_rebuild "$obj" "$depfile" "$cmdfile" "${cmd[@]}"; then
|
||||
printf 'up to date: %s\n' "$source" >> "$stdout_log"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf 'compile: %s\n' "$source" >> "$stdout_log"
|
||||
if "${cmd[@]}" >> "$stdout_log" 2>> "$stderr_log"; then
|
||||
write_command_file "$cmdfile" "${cmd[@]}"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
link_wasm_module() {
|
||||
local target="$1"
|
||||
local output="$2"
|
||||
local build_dir="$3"
|
||||
shift 3
|
||||
|
||||
local stdout_log="$build_dir/$target.stdout.log"
|
||||
local stderr_log="$build_dir/$target.stderr.log"
|
||||
local cmdfile="$build_dir/$(basename "$output").cmd"
|
||||
local wasm_output="${output%.js}.wasm"
|
||||
local cmd=(emcc "$@" -o "$output")
|
||||
|
||||
if [[ -f "$output" && ! -f "$wasm_output" ]]; then
|
||||
printf 'missing paired wasm output: %s\n' "$wasm_output" >> "$stdout_log"
|
||||
rm -f "$output"
|
||||
fi
|
||||
|
||||
if ! link_needs_rebuild "$output" "$cmdfile" "${cmd[@]}"; then
|
||||
printf 'up to date: %s\n' "$output" >> "$stdout_log"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf 'link: %s\n' "$output" >> "$stdout_log"
|
||||
if "${cmd[@]}" >> "$stdout_log" 2>> "$stderr_log"; then
|
||||
write_command_file "$cmdfile" "${cmd[@]}"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
Reference in New Issue
Block a user