#!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")" linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc} build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_cmake_safe_probe.XXXXXX") manifest=${1:-linuxcnc-rs274-wasm-source-files.txt} if [[ ! -f "$manifest" ]]; then echo "missing manifest: $manifest" >&2 exit 1 fi if [[ ! -d "$linuxcnc_root" ]]; then echo "missing LinuxCNC root: $linuxcnc_root" >&2 exit 1 fi trap 'rm -rf "$build_dir"' EXIT missing_root=/tmp/does-not-exist-linuxcnc missing_root_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_build_wasm_missing_root.XXXXXX.log") if LINUXCNC_ROOT="$missing_root" ./build-wasm.sh >"$missing_root_log" 2>&1; then echo "build-wasm accepted missing LinuxCNC root: $missing_root" >&2 exit 1 fi if ! grep -F "missing LinuxCNC root: $missing_root" "$missing_root_log" >/dev/null; then echo "build-wasm did not report missing LinuxCNC root clearly" >&2 sed -n '1,20p' "$missing_root_log" >&2 exit 1 fi grep -F 'exec 9>"${TMPDIR:-/tmp}/cnc_sim_build_wasm.lock"' build-wasm.sh >/dev/null grep -F "flock 9" build-wasm.sh >/dev/null rm -f "$missing_root_log" missing_root_scripts=( test-linuxcnc-wasm-interp-base-link.sh test-linuxcnc-wasm-interp-find-link.sh test-linuxcnc-wasm-python-plugin-link.sh test-linuxcnc-wasm-rs274ngc-pre-object.sh test-linuxcnc-wasm-tooldata-common-link.sh test-linuxcnc-wasm-tooldata-link.sh test-linuxcnc-wasm-tooldata-mmap-symbols.sh test-linuxcnc-wasm-tooldata-runtime-symbols.sh ) for script in "${missing_root_scripts[@]}"; do if LINUXCNC_ROOT="$missing_root" "./$script" >"$missing_root_log" 2>&1; then echo "$script accepted missing LinuxCNC root: $missing_root" >&2 exit 1 fi if ! grep -F "missing LinuxCNC root: $missing_root" "$missing_root_log" >/dev/null; then echo "$script did not report missing LinuxCNC root clearly" >&2 sed -n '1,20p' "$missing_root_log" >&2 exit 1 fi done rm -f "$missing_root_log" missing_source_root=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_missing_linuxcnc_source_root.XXXXXX") missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_linuxcnc_source.XXXXXX.log") mkdir -p "$missing_source_root/src" "$missing_source_root/include" fixed_source_scripts=( "test-linuxcnc-wasm-interp-base-link.sh:src/emc/rs274ngc/interp_base.cc" "test-linuxcnc-wasm-interp-find-link.sh:src/emc/tooldata/tooldata_common.cc" "test-linuxcnc-wasm-rs274ngc-pre-object.sh:src/emc/rs274ngc/rs274ngc_pre.cc" "test-linuxcnc-wasm-tooldata-common-link.sh:src/emc/tooldata/tooldata_common.cc" "test-linuxcnc-wasm-tooldata-link.sh:src/emc/tooldata/tooldata_common.cc" ) for script_and_path in "${fixed_source_scripts[@]}"; do script=${script_and_path%%:*} source_path=${script_and_path#*:} if LINUXCNC_ROOT="$missing_source_root" "./$script" >"$missing_source_log" 2>&1; then echo "$script accepted missing LinuxCNC source: $source_path" >&2 exit 1 fi if ! grep -F "missing LinuxCNC source: $source_path" "$missing_source_log" >/dev/null; then echo "$script did not report missing LinuxCNC source clearly" >&2 sed -n '1,20p' "$missing_source_log" >&2 exit 1 fi done rm -rf "$missing_source_root" rm -f "$missing_source_log" unknown_group_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_unknown_wasm_manifest_group.XXXXXX.txt") unknown_group_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_unknown_wasm_manifest_group.XXXXXX.log") printf 'bogus:src/emc/rs274ngc/interp_arc.cc:test unknown group\n' >"$unknown_group_manifest" for script in \ analyze-linuxcnc-wasm-blockers.sh \ test-linuxcnc-wasm-source-syntax.sh \ test-linuxcnc-wasm-source-objects.sh \ test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh \ test-linuxcnc-wasm-rs274ngc-pre-link.sh; do if "./$script" "$unknown_group_manifest" >"$unknown_group_log" 2>&1; then echo "$script accepted unknown manifest group" >&2 exit 1 fi if ! grep -F "unknown manifest group: bogus" "$unknown_group_log" >/dev/null; then echo "$script did not report unknown manifest group clearly" >&2 sed -n '1,20p' "$unknown_group_log" >&2 exit 1 fi done rm -f "$unknown_group_manifest" "$unknown_group_log" blocker_scan_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_blocker_scan.XXXXXX.log") ./test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh >"$blocker_scan_log" 2>&1 blocker_report_file=$(awk '/^wrote / { print $2 }' "$blocker_scan_log") if [[ -z "$blocker_report_file" || ! -f "$blocker_report_file" ]]; then echo "wasm rs274ngc_pre blocker scan did not preserve its report file" >&2 sed -n '1,20p' "$blocker_scan_log" >&2 exit 1 fi rm -f "$blocker_report_file" "$blocker_scan_log" missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_manifest_source.XXXXXX.txt") missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_manifest_source.XXXXXX.log") printf 'core:src/emc/rs274ngc/does_not_exist.cc:test missing source\n' >"$missing_source_manifest" if ./test-linuxcnc-wasm-source-syntax.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then echo "wasm source syntax probe accepted missing manifest source" >&2 exit 1 fi if ! grep -F "missing manifest source: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then echo "wasm source syntax probe did not report missing manifest source clearly" >&2 sed -n '1,20p' "$missing_source_log" >&2 exit 1 fi if ./test-linuxcnc-wasm-source-objects.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then echo "wasm source object probe accepted missing manifest source" >&2 exit 1 fi if ! grep -F "missing manifest source: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then echo "wasm source object probe did not report missing manifest source clearly" >&2 sed -n '1,20p' "$missing_source_log" >&2 exit 1 fi if ./test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then echo "wasm rs274ngc_pre blocker scan accepted missing manifest source" >&2 exit 1 fi if ! grep -F "missing manifest source: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then echo "wasm rs274ngc_pre blocker scan did not report missing manifest source clearly" >&2 sed -n '1,20p' "$missing_source_log" >&2 exit 1 fi if ./test-linuxcnc-wasm-rs274ngc-pre-link.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then echo "wasm rs274ngc_pre link probe accepted missing manifest source" >&2 exit 1 fi if ! grep -F "missing manifest source: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then echo "wasm rs274ngc_pre link probe did not report missing manifest source clearly" >&2 sed -n '1,20p' "$missing_source_log" >&2 exit 1 fi rm -f "$missing_source_manifest" "$missing_source_log" linuxcnc_root=$(cd "$linuxcnc_root" && pwd) default_manifest="$PWD/linuxcnc-rs274-wasm-source-files.txt" manifest_core_count=0 manifest_blocked_count=0 while IFS=: read -r group path note; do case "$group" in core) manifest_core_count=$((manifest_core_count + 1)) ;; blocked) manifest_blocked_count=$((manifest_blocked_count + 1)) ;; ""|\#*) continue ;; *) echo "unknown manifest group: $group" >&2 exit 1 ;; esac if [[ ! -f "$linuxcnc_root/$path" ]]; then echo "missing manifest source: $path" >&2 exit 1 fi done < "$manifest" required_shims=( wasm_shims/dlfcn.cc wasm_shims/emc_status_shim.cc wasm_shims/gettext_shim.cc wasm_shims/linuxcnc_runtime_shim.cc wasm_shims/python_c_api_shim.cc wasm_shims/rtapi_compat.cc wasm_shims/tooldata/tooldata_mmap_backend.cc wasm_shims/tooldata/tooldata_runtime_stubs.cc wasm_shims/pythonplugin/python_plugin.cc ) required_project_sources=( src/canon_event_sink.cpp src/linuxcnc_canon_bridge.cpp src/linuxcnc_tooldata_fixture.cpp src/rtcp_kinematics.cpp ) if [[ "$manifest" == "$default_manifest" ]] && [[ "$manifest_core_count" -ne 25 || "$manifest_blocked_count" -ne 1 ]]; then echo "unexpected wasm manifest partition: core=$manifest_core_count blocked=$manifest_blocked_count" >&2 exit 1 fi if [[ "$manifest_core_count" -eq 0 || "$manifest_blocked_count" -eq 0 ]]; then echo "unexpected wasm manifest partition: core=$manifest_core_count blocked=$manifest_blocked_count" >&2 exit 1 fi for shim in "${required_shims[@]}"; do if ! grep -F "$shim" core/CMakeLists.txt >/dev/null; then echo "missing CMake wasm-safe shim: $shim" >&2 exit 1 fi done for source in "${required_project_sources[@]}"; do if ! grep -F "$source" core/CMakeLists.txt >/dev/null; then echo "missing CMake wasm-safe project source: $source" >&2 exit 1 fi done grep -F "add_executable(linuxcnc_rs274_wasm_safe_probe EXCLUDE_FROM_ALL" core/CMakeLists.txt >/dev/null grep -F "wasm_shims/rs274ngc_pre_probe_main.cc" core/CMakeLists.txt >/dev/null grep -F "target_link_libraries(linuxcnc_rs274_wasm_safe_probe PRIVATE fmt)" core/CMakeLists.txt >/dev/null grep -F "add_custom_target(linuxcnc_rs274_wasm_blocked_sources" core/CMakeLists.txt >/dev/null grep -F "LinuxCNC source root does not exist" core/CMakeLists.txt >/dev/null grep -F 'if(NOT IS_DIRECTORY "${CNC_SIM_LINUXCNC_ROOT_ABS}")' core/CMakeLists.txt >/dev/null grep -F "LinuxCNC wasm source manifest is not a file" core/CMakeLists.txt >/dev/null grep -F 'if(IS_DIRECTORY "${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}")' core/CMakeLists.txt >/dev/null grep -F "LinuxCNC wasm manifest source does not exist" core/CMakeLists.txt >/dev/null grep -F 'if(NOT EXISTS "${manifest_source}")' core/CMakeLists.txt >/dev/null grep -F "LinuxCNC wasm manifest source is not a file" core/CMakeLists.txt >/dev/null grep -F 'if(IS_DIRECTORY "${manifest_source}")' core/CMakeLists.txt >/dev/null awk ' /set\(manifest_source/ { manifest_source = NR } /Unknown LinuxCNC wasm source manifest group/ { unknown_group = NR } END { exit !(unknown_group && manifest_source && unknown_group < manifest_source) } ' core/CMakeLists.txt grep -F "LinuxCNC wasm source manifest has no blocked entries" core/CMakeLists.txt >/dev/null if ! command -v cmake >/dev/null 2>&1; then echo "cmake not found; skipping linuxcnc wasm-safe CMake probe target" exit 0 fi cmake -S core -B "$build_dir" \ -DCMAKE_BUILD_TYPE=Release \ -DCNC_SIM_LINUXCNC_ROOT="$linuxcnc_root" \ -DCNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST="$manifest" \ -DCNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE=ON cmake --build "$build_dir" --target linuxcnc_rs274_wasm_safe_probe_objects cmake --build "$build_dir" --target linuxcnc_rs274_wasm_safe_probe "$build_dir/linuxcnc_rs274_wasm_safe_probe" echo "linuxcnc wasm-safe CMake probe target passed"