#!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")" usage() { echo "usage: $0 --mode rs274ngc-pre|runtime [manifest]" >&2 } mode= manifest=linuxcnc-rs274-wasm-source-files.txt 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 link probe option: $1" >&2 exit 1 ;; *) manifest=$1 shift ;; esac done case "$mode" in rs274ngc-pre|runtime) ;; "") usage echo "missing --mode" >&2 exit 1 ;; *) usage echo "unknown wasm link 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_LINK_PROBE_CACHE_DIR-build/wasm-link-probe-cache} if [[ -z "$cache_dir" ]]; then echo "CNC_SIM_WASM_LINK_PROBE_CACHE_DIR must not be empty" >&2 exit 1 fi if [[ "$cache_dir" =~ [[:space:]] ]]; then echo "CNC_SIM_WASM_LINK_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_LINK_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"} object_mode=$mode main_source=core/wasm_shims/rs274ngc_pre_probe_main.cc target_name=rs274ngc_pre_probe common_flag_output=$(LINUXCNC_ROOT="$linuxcnc_root" ./list-linuxcnc-wasm-common-cxxflags.sh --profile core20-sections) mapfile -t common_flags <<<"$common_flag_output" case "$mode" in runtime) object_mode=runtime main_source=core/wasm_shims/cnc_sim_wasm_runtime_probe_main.cc target_name=cnc_sim_wasm_runtime_probe common_flags+=(-DCNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND) ;; esac object_output=$(CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" LINUXCNC_ROOT="$linuxcnc_root" ./build-linuxcnc-wasm-probe-objects.sh --mode "$object_mode" "$manifest") mapfile -t objects <<<"$object_output" manifest=$(cd "$(dirname "$manifest")" && pwd)/$(basename "$manifest") linuxcnc_root=$(cd "$linuxcnc_root" && pwd) mode_dir="$cache_dir/$mode" mkdir -p "$mode_dir" exec 8>"$mode_dir/link.lock" flock 8 main_object="$mode_dir/main.o" target="$mode_dir/$target_name" signature="$mode_dir/link.signature" next_signature="$mode_dir/link.signature.next" { printf 'CXX=%s\n' "$cxx" printf 'PWD=%s\n' "$PWD" printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root" printf 'MANIFEST=%s\n' "$manifest" printf 'MODE=%s\n' "$mode" printf 'BUILD_RULE_VERSION=1\n' printf 'COMMON_FLAGS=' printf ' %s' "${common_flags[@]}" printf '\n' printf 'MAIN_SOURCE=%s\n' "$main_source" printf 'OBJECTS:\n' printf '%s\n' "${objects[@]}" } > "$next_signature" if [[ ! -f "$signature" ]] || ! cmp -s "$signature" "$next_signature"; then rm -f "$main_object" "$main_object.d" "$target" "$mode_dir/runtime.symbols" fi mv "$next_signature" "$signature" makefile="$mode_dir/link.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 '.PHONY: all\n' printf 'all: %s\n\n' "$target" printf '%s: %s\n' "$main_object" "$main_source" printf '\t@$(CXX) $(COMMON_FLAGS) -MMD -MP -MF %s.d -c %s -o %s\n\n' "$main_object" "$main_source" "$main_object" printf '%s: $(OBJECTS) %s\n' "$target" "$main_object" printf '\t@$(CXX) $(OBJECTS) %s -Wl,--gc-sections -lfmt -o %s\n\n' "$main_object" "$target" printf '\n-include %s.d\n' "$main_object" } > "$makefile" make --output-sync=target -j"$build_jobs" -f "$makefile" >/dev/null printf '%s\n' "$target"