Files
cnc_wams/wasm-port/docs/porting-steps-standalone.md
wangdequan 4158a78760 按推荐建议,继续执行
结论:新增 vendored LinuxCNC 源码同步验证脚本,去重 source-manifest,并在 native 验证前检查 vendor 与上游源文件字节一致,强化功能来源于 LinuxCNC 源程序的纪律。
2026-06-07 17:06:02 +08:00

26 KiB
Raw Blame History

LinuxCNC WASM Porting Steps

Goal

Build a separate WASM-based CNC simulation program that:

  • uses LinuxCNC source as the semantic source of truth,
  • does not modify the original linuxcnc/ source tree,
  • is managed independently from native LinuxCNC,
  • provides HTML + JavaScript frontend plus OPFS persistence,
  • matches LinuxCNC software behavior as closely as practical except for realtime hardware driving.

Non-Negotiable Constraints

  1. linuxcnc/ is upstream and read-only for the port effort.
  2. Any source adaptation needed for WASM happens on copied or generated files under wasm-port/.
  3. No direct edits inside linuxcnc/src, linuxcnc/lib, linuxcnc/tests, or linuxcnc/web are part of the port workflow.
  4. LinuxCNC GUI code is reference-only. The migrated UI is rebuilt in HTML + JavaScript.
  5. LinuxCNC compute logic should be reused before any reimplementation is considered.

Workspace Structure

Create and keep these directories under wasm-port/:

  • docs/ Planning, architecture, and validation documents.
  • vendor/linuxcnc/ Copied source files selected for the port.
  • patches/ Patch files against the vendored copies.
  • tools/ Scripts that extract files from ../linuxcnc, apply patches, and verify drift.
  • runtime/core/ WASM-targeted C/C++ code and wrappers.
  • runtime/sdk/ JavaScript/TypeScript wrapper over the WASM module.
  • runtime/ui/ HTML + JavaScript frontend.
  • runtime/opfs/ Browser file adapter.
  • tests/native/ Native extracted-core regression tests.
  • tests/browser/ Browser/WASM regression and smoke tests.

Ported Program Directory Structure

The migrated program itself should be managed as a standalone product under wasm-port/, with LinuxCNC acting as an upstream source provider.

The recommended final structure is:

wasm-port/
├── docs/
├── vendor/
│   └── linuxcnc/
│       └── src/
│           ├── emc/
│           │   ├── ini/
│           │   ├── kinematics/
│           │   ├── rs274ngc/
│           │   └── tp/
│           ├── hal/
│           │   └── components/
│           └── libnml/
│               └── posemath/
├── patches/
├── tools/
├── runtime/
│   ├── core/
│   │   ├── include/
│   │   ├── shims/
│   │   ├── adapters/
│   │   ├── canon/
│   │   ├── session/
│   │   ├── simulation/
│   │   ├── linuxcnc_wrap/
│   │   └── c_api/
│   ├── sdk/
│   │   └── src/
│   ├── ui/
│   │   ├── public/
│   │   └── src/
│   │       ├── panels/
│   │       ├── preview/
│   │       ├── state/
│   │       ├── machine/
│   │       └── files/
│   └── opfs/
├── tests/
│   ├── native/
│   ├── wasm/
│   └── fixtures/
├── build/
│   ├── native/
│   └── wasm/
└── dist/
    ├── sdk/
    └── web/

Directory Responsibilities

  • vendor/linuxcnc/ Holds extracted upstream LinuxCNC source files. These are copied or generated from ../linuxcnc and are the only place where source-level port patches are applied.
  • patches/ Stores every patch applied to vendored LinuxCNC files. Patches are tracked here instead of being mixed into the original source tree.
  • tools/ Holds extraction, sync, verification, manifest generation, and compatibility-check scripts.
  • runtime/core/ The standalone simulation runtime. This is where vendored LinuxCNC source is wrapped, adapted, and exposed to the rest of the ported program.
  • runtime/core/include/ Public internal headers for the standalone runtime.
  • runtime/core/shims/ Small compatibility headers and implementation stubs required to compile vendored LinuxCNC code outside the native runtime.
  • runtime/core/adapters/ Host boundary adapters such as file IO, logging, simulation HAL, and runtime-state providers.
  • runtime/core/canon/ Canonical motion event collection and serialization.
  • runtime/core/session/ Per-simulation session ownership for interpreter state, planner state, machine state, and controller state.
  • runtime/core/simulation/ Higher-level simulation orchestration built on top of reused LinuxCNC compute modules.
  • runtime/core/linuxcnc_wrap/ Thin wrappers around vendored LinuxCNC entry points. Prefer wrappers here over editing vendored source directly.
  • runtime/core/c_api/ Stable C ABI exported to the WASM layer.
  • runtime/sdk/ JavaScript/TypeScript SDK that calls the WASM module and hides memory management and ABI details from the frontend.
  • runtime/ui/ The actual CNC simulation web application built with HTML + JavaScript.
  • runtime/ui/src/panels/ Operator panels, machine configuration panels, parameter editors, and controller-status panels.
  • runtime/ui/src/preview/ 2D/3D path preview, 5-axis visualization, joint/world overlays, and playback views.
  • runtime/ui/src/state/ Browser-side state management for session lifecycle and UI coordination.
  • runtime/ui/src/machine/ Machine-model-specific UI logic.
  • runtime/ui/src/files/ File import/export and project/session handling UI logic.
  • runtime/opfs/ OPFS-backed file services, snapshot persistence, and path mapping.
  • tests/native/ Native extracted-core regression tests run before WASM build validation.
  • tests/wasm/ WASM tests for Node and browser environments.
  • tests/fixtures/ Shared INI, G-code, parameter, tool-table, and machine fixtures.
  • build/ Intermediate build output. This is disposable.
  • dist/ Deliverable artifacts such as generated web bundles and SDK packages.

Source Ownership Rule

The ported program's own source code is expected to live under:

  • runtime/core/
  • runtime/sdk/
  • runtime/ui/
  • runtime/opfs/
  • tests/
  • tools/
  • docs/

Vendored LinuxCNC code must live under:

  • vendor/linuxcnc/

The original upstream tree must remain outside the ported program's source ownership boundary:

  • ../linuxcnc/

Patch Placement Rule

If a LinuxCNC source file needs adaptation:

  1. extract it into vendor/linuxcnc/;
  2. patch the vendored copy only;
  3. record the patch in patches/;
  4. document why the patch exists in docs/ or in the patch header.

Do not place LinuxCNC source patches under runtime/.

Build Graph Rule

The standalone build should flow like this:

  1. tools/ extracts upstream files into vendor/
  2. patches/ are applied to vendored copies
  3. runtime/core/ compiles vendored files plus wrappers
  4. runtime/sdk/ consumes the generated WASM module
  5. runtime/ui/ consumes the SDK
  6. runtime/opfs/ provides browser persistence services
  7. tests/ validate native and browser behavior

This ensures the ported program remains independently buildable while still tracking LinuxCNC as the semantic source of truth.

Phase 0: Freeze Upstream Reference

Purpose: Make the LinuxCNC source baseline explicit before extraction starts.

Steps:

  1. Record the exact upstream commit from linuxcnc/.git.
  2. Record local build assumptions:
    • compiler version
    • emscripten version
    • python version
    • node version
  3. Record the first supported LinuxCNC fixture set:
    • one 3-axis machine
    • one non-trivial kinematics case
    • one 5-axis machine
  4. Record the first G-code feature set:
    • linear motion
    • arc motion
    • canned cycles
    • offsets and coordinate systems
    • subroutines
    • numeric and named variables
    • representative 5-axis programs

Outputs:

  • upstream revision note
  • supported feature baseline
  • supported machine baseline

Phase 1: Build the Source Reuse Map

Purpose: Identify exactly which LinuxCNC source files are needed.

Steps:

  1. Map each required capability to LinuxCNC files:
    • G-code interpreter: ../linuxcnc/src/emc/rs274ngc/*
    • parameter tables and named variables: ../linuxcnc/src/emc/rs274ngc/interp_*
    • INI parsing: ../linuxcnc/src/emc/ini/inifile.*
    • planner: ../linuxcnc/src/emc/tp/*
    • kinematics: ../linuxcnc/src/emc/kinematics/* and selected files from ../linuxcnc/src/hal/components/*.comp
    • posemath: ../linuxcnc/src/libnml/posemath/*
  2. For each file, classify it:
    • copy unchanged
    • copy plus shim
    • copy plus light patch
    • not included in phase 1
  3. For each file, record dependencies:
    • HAL
    • RTAPI
    • NML
    • native file IO
    • Python
    • GUI
  4. Save the mapping as a table under wasm-port/docs/.

Outputs:

  • file-level reuse matrix
  • dependency matrix

Phase 2: Build the Extraction Pipeline

Purpose: Keep LinuxCNC source untouched while making port-specific copies available.

Steps:

  1. Write extraction scripts in wasm-port/tools/.
  2. Copy selected upstream files into wasm-port/vendor/linuxcnc/.
  3. Preserve relative structure where useful, for example:
    • vendor/linuxcnc/src/emc/rs274ngc/...
    • vendor/linuxcnc/src/emc/ini/...
  4. Store every modification as:
    • a patch in wasm-port/patches/, or
    • a thin wrapper outside the vendored file
  5. Add a verification script that compares upstream file hashes against the vendored source list.

Rules:

  • if upstream changes, re-run extraction;
  • reapply patches only in the standalone workspace;
  • never patch ../linuxcnc directly.

Outputs:

  • reproducible extraction pipeline
  • vendored source tree

Phase 3: Build the Native Extracted Core

Purpose: Prove the reusable LinuxCNC compute code works outside the full runtime.

Steps:

  1. Create wasm-port/runtime/core/ as the portable core layer.
  2. Add wrapper translation units instead of editing vendored files where possible.
  3. Start with these subsystems in order:
    • INI parser
    • numeric parameter table
    • named parameter logic
    • interpreter core
    • planner
    • kinematics
  4. Build a native CLI harness first, before any WASM build.
  5. Replace host edges with abstractions:
    • file provider
    • HAL adapter
    • runtime state provider
    • logging adapter

Outputs:

  • portable native core
  • native harness executable

Current verified progress:

  • tools/build_native_probes.sh builds the INI parser probe, interpreter state probe, named-parameter harness, RS274 compile probe, and the minimal interpreter harness from the standalone wasm-port/ workspace.
  • tests/native/verify_native_probes.sh validates that all native probe exit codes are zero and that the minimal interpreter harness emits a STRAIGHT_TRAVERSE canonical event for G0 X1.0 Y2.0, plus SET_FEED_RATE and STRAIGHT_FEED canonical events for G1 X3.0 Y4.0 F120.0.
  • The same validation is now fixture-driven through tests/fixtures/gcode/minimal_linear.ngc and tests/fixtures/canon/minimal_linear.events.
  • tests/fixtures/gcode/modal_incremental.ngc and tests/fixtures/canon/modal_incremental.events add G90/G91 distance-mode switching plus modal G1 carry-forward coverage. The temporary wrapper behavior is based on LinuxCNC interp_convert.cc::convert_distance_mode() and interp_convert.cc::convert_straight().
  • tests/fixtures/gcode/position_params.ngc and tests/fixtures/canon/position_params.events cover Z-axis motion plus current-position parameter visibility for #5420, #5421, and #5422. The parameter source basis is LinuxCNC interp_parameter_def.hh and interp_namedparams.cc.
  • tests/fixtures/gcode/canned_cycles.ngc and tests/fixtures/canon/canned_cycles.events cover LinuxCNC canned-cycle conversion through vendored interp_cycles.cc, including G81, G82, G83, G80 cancellation, dwell, peck drilling, and incremental L repeats.
  • runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp now records coordinate-system canonical boundary calls emitted by vendored LinuxCNC conversion code: SET_G5X_OFFSET, SET_G92_OFFSET, SET_XY_ROTATION, CANON_UPDATE_END_POINT, USE_LENGTH_UNITS, and SELECT_PLANE. tests/fixtures/gcode/coordinate_offsets.ngc and tests/fixtures/canon/coordinate_offsets.events pin G55, active G10 L2, G92, G92.1, and G54 behavior from interp_convert.cc::convert_coordinate_system(), interp_convert.cc::convert_setup(), and interp_convert.cc::convert_axis_offsets().
  • runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp now records feed/control canonical boundary calls emitted by vendored LinuxCNC conversion and queue code: SET_TRAVERSE_RATE, SET_FEED_REFERENCE, SET_FEED_MODE, SET_MOTION_CONTROL_MODE, and SET_NAIVECAM_TOLERANCE. tests/fixtures/gcode/feed_control_modes.ngc and tests/fixtures/canon/feed_control_modes.events pin G93, G94, G95, G61, G61.1, and G64 P/Q behavior from interp_convert.cc::convert_feed_mode(), interp_convert.cc::convert_control_mode(), and interp_queue.cc.
  • runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp now records probe canonical boundary calls emitted by vendored interp_convert.cc::convert_probe(): TURN_PROBE_ON, STRAIGHT_PROBE, and TURN_PROBE_OFF. tests/fixtures/gcode/probe_semantics.ngc and tests/fixtures/canon/probe_semantics.events pin G38.2, G38.3, G38.4, and G38.5 probe type handling.
  • runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp now records speed/feed synchronization and rigid-tap canonical boundary calls emitted by vendored interp_convert.cc::convert_straight(): START_SPEED_FEED_SYNCH, STOP_SPEED_FEED_SYNCH, and RIGID_TAP. tests/fixtures/gcode/threading_sync.ngc and tests/fixtures/canon/threading_sync.events pin G33 spindle-synchronized straight feed and G33.1 rigid tap behavior.
  • runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp now records NURBS G5 canonical boundary calls emitted by vendored interp_convert.cc::convert_nurbs(): NURBS_G5_FEED. tests/fixtures/gcode/nurbs_g5_semantics.ngc and tests/fixtures/canon/nurbs_g5_semantics.events pin G5.2 control-point collection and G5.3 NURBS feed emission.
  • runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp now records NURBS G6 canonical boundary calls emitted by vendored interp_convert.cc::convert_nurbs(): NURBS_G6_FEED. tests/fixtures/gcode/nurbs_g6_semantics.ngc and tests/fixtures/canon/nurbs_g6_semantics.events pin G6.2 order, interpolation mode, control-point, weight, and K segment handling.
  • runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp now records spindle-orient canonical boundary calls emitted by vendored LinuxCNC conversion and queue code: ORIENT_SPINDLE and WAIT_SPINDLE_ORIENT_COMPLETE. tests/fixtures/gcode/spindle_orient.ngc and tests/fixtures/canon/spindle_orient.events pin M19 R/P/Q behavior from interp_convert.cc::convert_m() and interp_queue.cc.
  • runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cpp now records tool-table canonical boundary calls emitted by vendored interp_convert.cc::convert_setup_tool(): SET_TOOL_TABLE_ENTRY. tests/fixtures/gcode/tool_table_setup.ngc and tests/fixtures/canon/tool_table_setup.events pin G10 L1 tool offset, diameter, front/back angle, and orientation behavior.
  • tests/fixtures/gcode_errors/g1_zero_feed.ngc and tests/fixtures/canon_errors/g1_zero_feed.expected pin the negative G1 zero-feed case. The source basis is LinuxCNC interp_convert.cc::convert_straight() and rs274ngc_return.hh::NCE_CANNOT_DO_G1_WITH_ZERO_FEED_RATE.
  • This proves the current extracted interpreter slice can parse and execute a small fixture set through a standalone canonical event sink.
  • Important direction change: the minimal wrapper behavior is a migration probe, not the program body. Do not expand it into a separate CNC implementation. The next work must retire hand-written wrapper semantics and move execution through vendored LinuxCNC interpreter source such as interp_convert.cc, interp_read.cc, interp_check.cc, and interp_execute.cc.
  • tools/build_native_probes.sh now includes linuxcnc_interp_convert_source_probe, which directly compiles vendored interp_convert.cc. The required emcStatus shim is limited to the native status boundary used by tag_arc() for machine units; it is not a project-authored CNC behavior implementation.
  • tools/build_native_probes.sh now also includes direct source compile probes for vendored interp_read.cc, interp_check.cc, and interp_execute.cc. These probes keep the next interpreter-core migration work focused on LinuxCNC source entry points and expose missing standalone runtime shims before wrapper behavior is expanded.
  • The direct source compile probes now cover the remaining vendored rs274ngc interpreter core files used by the standalone harness: modal_state.cc, interp_array.cc, interp_internal.cc, interp_arc.cc, interp_inverse.cc, interp_cycles.cc, interp_g7x.cc, interp_queue.cc, interp_find.cc, interp_namedparams.cc, interp_write.cc, interp_o_word.cc, and rs274ngc_pre.cc. rs274ngc_pre.cc is compiled with the existing standalone UNIT_TEST/LINUXCNC_STANDALONE_USE_RS274_PRE_STATE boundary that isolates Python runtime integration from the browser simulation core.
  • tools/build_native_probes.sh now includes direct source compile probes for the vendored LinuxCNC trajectory-planner and posemath files used by linuxcnc_tp_api_probe: tp.c, tc.c, tcq.c, spherical_arc.c, blendmath.c, sp_scurve.c, ruckig_wrapper.c, the selected cruckig/*.c sources, emcpose.c, posemath.cc, _posemath.c, and sincos.c. These probes use the same TP_FLAGS as the standalone TP harness, including the existing -fpermissive boundary required by upstream enum conversions in tp.c.
  • tools/verify_vendor_sync.sh now validates the LinuxCNC source extraction boundary before native probes run. It rejects duplicate manifest entries, missing or extra vendored files, and byte-level drift between each manifest file under vendor/linuxcnc/ and the matching file under ../linuxcnc/. tools/source-manifest.txt was also de-duplicated so the manifest is a single authoritative extraction list.

Phase 4: Port INI Parsing Without Editing Upstream

Purpose: Move LinuxCNC config parsing into the standalone runtime.

Steps:

  1. Vendor:
    • ../linuxcnc/src/emc/ini/inifile.cc
    • ../linuxcnc/src/emc/ini/inifile.hh
    • ../linuxcnc/src/emc/ini/inifile.h
  2. Add shim headers under wasm-port/runtime/core/shims/ for small dependencies only.
  3. Replace file loading through:
    • wrapper-level adapter, preferred
    • minimal vendored patch only if unavoidable
  4. Preserve:
    • #INCLUDE
    • relative includes
    • recursion checks
    • line continuation
    • duplicate section merge behavior
    • typed query behavior
  5. Add tests for INI semantics under tests/native/.

Involved LinuxCNC source:

  • src/emc/ini/inifile.cc
  • src/emc/ini/inifile.hh
  • src/emc/ini/inifile.h

Phase 5: Port Parameter Tables and Variable Files

Purpose: Preserve LinuxCNC numeric parameter behavior exactly enough for simulation.

Steps:

  1. Vendor:
    • ../linuxcnc/src/emc/rs274ngc/interp_parameter_def.hh
    • ../linuxcnc/src/emc/rs274ngc/interp_array.cc
    • ../linuxcnc/src/emc/rs274ngc/interp_internal.hh
    • ../linuxcnc/src/emc/rs274ngc/rs274ngc_pre.cc
  2. Extract:
    • setup.parameters[]
    • required_parameters[]
    • readonly_parameters[]
    • parameter file load/save logic
  3. Replace native file writes with a standalone file service abstraction.
  4. Keep LinuxCNCs parameter text format in phase 1.
  5. Add regression tests for:
    • missing file
    • out-of-order parameters
    • zero-fill behavior
    • required parameter persistence
    • read-only protection

Involved LinuxCNC source:

  • src/emc/rs274ngc/interp_parameter_def.hh
  • src/emc/rs274ngc/interp_array.cc
  • src/emc/rs274ngc/interp_internal.hh
  • src/emc/rs274ngc/rs274ngc_pre.cc

Phase 6: Port Named Parameters and Interpreter State

Purpose: Preserve LinuxCNC variable semantics and controller-visible state.

Steps:

  1. Vendor:
    • ../linuxcnc/src/emc/rs274ngc/interp_namedparams.cc
    • ../linuxcnc/src/emc/rs274ngc/interp_internal.hh
    • ../linuxcnc/src/emc/rs274ngc/interp_fwd.hh
    • selected interpreter files needed by setup/state handling
  2. Preserve:
    • context.named_params
    • PA_READONLY
    • PA_GLOBAL
    • PA_USE_LOOKUP
    • PA_FROM_INI
    • built-in named parameters from init_named_parameters()
  3. Preserve lookup order:
    • local
    • global
    • _ini[...]
    • _hal[...]
    • optional Python providers later
  4. Export state outward rather than redesigning it in JS.
  5. Add regression cases for:
    • local/global scoping
    • built-in state variables
    • _ini[...]
    • _hal[...]
    • read-only errors

Involved LinuxCNC source:

  • src/emc/rs274ngc/interp_namedparams.cc
  • src/emc/rs274ngc/interp_internal.hh
  • src/emc/rs274ngc/interp_fwd.hh
  • src/emc/rs274ngc/interpmodule.cc

Phase 7: Replace HAL Runtime With a Simulation HAL Adapter

Purpose: Keep LinuxCNC interpreter-visible HAL behavior without migrating HAL itself.

Steps:

  1. Do not vendor the whole HAL runtime as a target runtime dependency.
  2. Use LinuxCNC HAL source as reference only for interface semantics:
    • ../linuxcnc/src/hal/hal.h
    • ../linuxcnc/src/hal/halmodule.cc
    • ../linuxcnc/src/emc/ini/inihal.cc
  3. Define a standalone HAL adapter interface:
    • lookup by name
    • typed numeric value
    • connection/existence status
  4. Make _hal[...] reads resolve through this adapter.
  5. Seed the adapter from simulation config and runtime state.
  6. Add tests for:
    • existing names
    • missing names
    • disconnected signals
    • type conversion

Involved LinuxCNC source:

  • src/hal/hal.h
  • src/hal/halmodule.cc
  • src/emc/rs274ngc/interp_namedparams.cc
  • src/emc/ini/inihal.cc

Phase 8: Port the Interpreter Core

Purpose: Build the standalone G-code execution engine without touching upstream files.

Steps:

  1. Vendor selected files from ../linuxcnc/src/emc/rs274ngc/.
  2. Keep original source as intact as possible in vendor/.
  3. Add wrappers or minimal patches only in the standalone area.
  4. Replace these external edges:
    • file open/read
    • world sync
    • HAL reads
    • logging
    • runtime callbacks
  5. Preserve:
    • modal state
    • subroutines
    • offsets
    • tool handling
    • parameter interactions
    • error semantics
  6. Add a canonical event sink interface in standalone code.

Involved LinuxCNC source:

  • src/emc/rs274ngc/interp_execute.cc
  • src/emc/rs274ngc/interp_read.cc
  • src/emc/rs274ngc/interp_check.cc
  • src/emc/rs274ngc/interp_convert.cc
  • src/emc/rs274ngc/interp_cycles.cc
  • src/emc/rs274ngc/interp_find.cc
  • src/emc/rs274ngc/interp_write.cc
  • src/emc/rs274ngc/interp_o_word.cc
  • src/emc/rs274ngc/rs274ngc_pre.cc
  • src/emc/rs274ngc/rs274ngc_interp.hh

Phase 9: Port Planner and Kinematics

Purpose: Preserve LinuxCNC motion planning and 5-axis simulation behavior.

Steps:

  1. Vendor selected planner files from ../linuxcnc/src/emc/tp/.
  2. Vendor selected kinematics files from:
    • ../linuxcnc/src/emc/kinematics/
    • selected .comp sources mirrored into standalone code where needed
  3. Replace loadable-module assumptions with a registry in the standalone runtime.
  4. Keep original math and state logic intact as far as practical.
  5. Add tests for:
    • planner outputs
    • forward/inverse kinematics
    • 5-axis world/joint transforms

Involved LinuxCNC source:

  • src/emc/tp/tp.c
  • src/emc/tp/tc.c
  • src/emc/tp/tcq.c
  • src/emc/tp/blendmath.c
  • src/emc/tp/sp_scurve.c
  • src/emc/tp/ruckig_wrapper.c
  • src/emc/kinematics/*.c
  • src/hal/components/xyzab_tdr_kins.comp
  • src/hal/components/xyzacb_trsrn.comp
  • src/hal/components/xyzbca_trsrn.comp

Phase 10: Build the Standalone WASM Program

Purpose: Keep the migrated program completely outside native LinuxCNC management.

Steps:

  1. Build the standalone native core first.
  2. Add a standalone WASM export layer under:
    • wasm-port/runtime/core/
    • wasm-port/runtime/sdk/
  3. Use vendor/ sources plus standalone wrappers as build input.
  4. Do not compile from ../linuxcnc directly in the final WASM product build.
  5. Emit:
    • wasm module
    • JS loader
    • standalone SDK

Outputs:

  • independently managed WASM simulation core

Phase 11: Build the Frontend and OPFS Layer

Purpose: Keep the standalone port program separate from LinuxCNC GUI code and storage.

Steps:

  1. Build frontend files under:
    • wasm-port/runtime/ui/
    • wasm-port/runtime/opfs/
  2. Implement:
    • HTML shell
    • JavaScript control panel
    • OPFS persistence
    • file import/export
    • machine/controller state views
  3. Keep LinuxCNC GUI code reference-only.
  4. Ensure the frontend depends only on the standalone SDK, not on native LinuxCNC binaries.

Outputs:

  • standalone browser program

Phase 12: Validate Drift Against Upstream

Purpose: Prove the standalone port still tracks LinuxCNC behavior.

Steps:

  1. Use native LinuxCNC tests and fixtures as semantic baselines.
  2. Compare:
    • LinuxCNC native behavior
    • standalone native extracted core
    • standalone WASM behavior
  3. Maintain a drift report.
  4. Re-run extraction if upstream source changes.
  5. Keep patches small and traceable.

Outputs:

  • drift report
  • compatibility regression suite

Management Rules For Daily Development

Use these rules continuously:

  1. Never edit files under linuxcnc/ as part of the port.
  2. Any needed modification to upstream logic must be applied to vendored copies only.
  3. Any upstream sync must be script-driven and repeatable.
  4. Every shim must be documented.
  5. Every local patch against vendored source must be stored as a patch file or clearly isolated wrapper.

Keep these documents under wasm-port/docs/:

  • scope-and-baseline.md
  • source-reuse-map.md
  • state-porting-strategy.md
  • wasm-build-strategy.md
  • frontend-architecture.md
  • opfs-file-model.md
  • compatibility-validation.md
  • drift-report.md

Immediate Next Step

Continue expanding the standalone interpreter core from the verified minimal traverse path:

  1. replace the temporary minimal convert_g() implementation with calls into vendored LinuxCNC interpreter conversion code.
  2. identify and shim the native runtime symbols blocking direct compilation of interp_convert.cc, interp_execute.cc, and related interpreter files.
  3. keep fixture coverage as regression protection while deleting temporary hand-written semantics.
  4. keep all source changes inside wasm-port/ and leave ../linuxcnc/ read-only.