#!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")" # LinuxCNC source basis: standalone probe modes either compile LinuxCNC # rs274/tooldata sources directly or link wasm-safe shims whose source basis is # checked against LinuxCNC source comments before building. usage() { echo "usage: $0 --mode tooldata-link|tooldata-common-link|interp-base-link|python-plugin-link|python-plugin-inittab-link|rs274ngc-pre-object" >&2 } mode= while [[ "$#" -gt 0 ]]; do case "$1" in --mode) if [[ "$#" -lt 2 ]]; then echo "missing --mode value" >&2 exit 1 fi mode=$2 shift 2 ;; --help|-h) usage exit 0 ;; *) usage echo "unknown wasm standalone probe option: $1" >&2 exit 1 ;; esac done case "$mode" in tooldata-link|tooldata-common-link|interp-base-link|python-plugin-link|python-plugin-inittab-link|rs274ngc-pre-object) ;; "") usage echo "missing --mode" >&2 exit 1 ;; *) usage echo "unknown wasm standalone probe mode: $mode" >&2 exit 1 ;; esac linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc} cxx=${CXX:-g++} if [[ -z ${CXX:-} ]] && command -v ccache >/dev/null 2>&1; then cxx="ccache $cxx" fi build_jobs=${CNC_SIM_BUILD_JOBS:-8} if ! [[ "$build_jobs" =~ ^[1-9][0-9]*$ ]]; then echo "CNC_SIM_BUILD_JOBS must be a positive integer: $build_jobs" >&2 exit 1 fi cache_dir=${CNC_SIM_WASM_STANDALONE_PROBE_CACHE_DIR-build/wasm-standalone-probe-cache} if [[ -z "$cache_dir" ]]; then echo "CNC_SIM_WASM_STANDALONE_PROBE_CACHE_DIR must not be empty" >&2 exit 1 fi if [[ "$cache_dir" =~ [[:space:]] ]]; then echo "CNC_SIM_WASM_STANDALONE_PROBE_CACHE_DIR must not contain whitespace: $cache_dir" >&2 exit 1 fi mkdir -p "$cache_dir" cache_dir=$(cd "$cache_dir" && pwd) if [[ "$cache_dir" == "/" ]]; then echo "CNC_SIM_WASM_STANDALONE_PROBE_CACHE_DIR must not be the filesystem root" >&2 exit 1 fi preflight_cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-"$cache_dir/preflight-cache"} LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh --cache-dir "$preflight_cache_dir" --root-only linuxcnc_root=$(cd "$linuxcnc_root" && pwd) common_flag_args=() sources=() target_name= case "$mode" in tooldata-link|tooldata-common-link) if [[ "$mode" == "tooldata-common-link" ]]; then common_flag_args+=(--tooldata-include) fi tooldata_mmap_backend_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_mmap_backend.cc) tooldata_runtime_stubs_shim=$(./list-linuxcnc-wasm-safe-shims.sh tooldata_runtime_stubs.cc) tooldata_common_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/tooldata/tooldata_common.cc) grep -F 'LinuxCNC source basis: src/emc/tooldata/tooldata_common.cc provides' core/wasm_shims/tooldata/tooldata_common_probe_main.cc >/dev/null grep -F 'LinuxCNC source basis: src/emc/tooldata/tooldata_mmap.cc, tooldata_nml.cc,' core/wasm_shims/tooldata/tooldata_probe_main.cc >/dev/null sources+=( "$tooldata_common_source" "$tooldata_mmap_backend_shim" "$tooldata_runtime_stubs_shim" ) if [[ "$mode" == "tooldata-link" ]]; then sources+=(core/wasm_shims/tooldata/tooldata_probe_main.cc) target_name=tooldata_probe else sources+=(core/wasm_shims/tooldata/tooldata_common_probe_main.cc) target_name=tooldata_common_probe fi ;; interp-base-link) dlfcn_shim=$(./list-linuxcnc-wasm-safe-shims.sh dlfcn.cc) interp_base_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/rs274ngc/interp_base.cc) grep -F 'LinuxCNC source basis: src/emc/rs274ngc/interp_base.cc provides' core/wasm_shims/interp_base_probe_main.cc >/dev/null sources+=( "$dlfcn_shim" "$interp_base_source" core/wasm_shims/interp_base_probe_main.cc ) target_name=interp_base_probe ;; python-plugin-link|python-plugin-inittab-link) python_plugin_shim=$(./list-linuxcnc-wasm-safe-shims.sh python_plugin.cc) if [[ "$mode" == "python-plugin-link" ]]; then probe_source=core/wasm_shims/pythonplugin/python_plugin_probe_main.cc target_name=python_plugin_probe grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and' "$probe_source" >/dev/null else probe_source=core/wasm_shims/pythonplugin/python_plugin_inittab_probe_main.cc target_name=python_plugin_inittab_probe grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc' "$probe_source" >/dev/null fi sources+=( "$python_plugin_shim" "$probe_source" ) ;; rs274ngc-pre-object) rs274ngc_pre_source=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-source-files.sh src/emc/rs274ngc/rs274ngc_pre.cc) grep -F 'core:src/emc/rs274ngc/rs274ngc_pre.cc:Interp implementation covered by rs274ngc_pre link probe' linuxcnc-rs274-wasm-source-files.txt >/dev/null sources+=("$rs274ngc_pre_source") target_name=rs274ngc_pre.o ;; esac common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh "${common_flag_args[@]}") mapfile -t common_flags <<<"$common_flag_output" mode_dir="$cache_dir/$mode" mkdir -p "$mode_dir" exec 8>"$mode_dir/probe.lock" flock 8 objects=() object_index=0 for source in "${sources[@]}"; do objects+=("$mode_dir/source_${object_index}.o") object_index=$((object_index + 1)) done target="$mode_dir/$target_name" if [[ "$mode" == "rs274ngc-pre-object" ]]; then target=${objects[0]} fi signature="$mode_dir/probe.signature" next_signature="$mode_dir/probe.signature.next" { printf 'CXX=%s\n' "$cxx" printf 'PWD=%s\n' "$PWD" printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root" printf 'MODE=%s\n' "$mode" printf 'BUILD_RULE_VERSION=1\n' printf 'COMMON_FLAGS=' printf ' %s' "${common_flags[@]}" printf '\n' printf 'SOURCES:\n' printf '%s\n' "${sources[@]}" } > "$next_signature" if [[ ! -f "$signature" ]] || ! cmp -s "$signature" "$next_signature"; then rm -f "$mode_dir"/source_*.o "$mode_dir"/source_*.d "$target" fi mv "$next_signature" "$signature" makefile="$mode_dir/probe.mk" { printf 'CXX := %s\n' "$cxx" printf 'COMMON_FLAGS :=' printf ' %s' "${common_flags[@]}" printf '\n\n' printf 'OBJECTS :=' printf ' %s' "${objects[@]}" printf '\n\n' printf 'DEP_FILES :=\n' for object in "${objects[@]}"; do printf 'DEP_FILES += %s.d\n' "$object" done printf '\n.PHONY: all\n' printf 'all: %s\n\n' "$target" object_index=0 for source in "${sources[@]}"; do printf '%s: %s\n' "${objects[$object_index]}" "$source" printf '\t@$(CXX) $(COMMON_FLAGS) -MMD -MP -MF %s.d -c %s -o %s\n\n' \ "${objects[$object_index]}" "$source" "${objects[$object_index]}" object_index=$((object_index + 1)) done if [[ "$mode" != "rs274ngc-pre-object" ]]; then printf '%s: $(OBJECTS)\n' "$target" printf '\t@$(CXX) $(OBJECTS) -o %s\n\n' "$target" fi printf '\n-include $(DEP_FILES)\n' } > "$makefile" make --output-sync=target -j"$build_jobs" -f "$makefile" >/dev/null printf '%s\n' "$target"