结论:新增 compatibility-validation 与 drift-report,记录当前 native 验证链路、fixture 覆盖、无漂移规则和已知缺口,继续约束移植行为跟随 LinuxCNC 源程序。
29 KiB
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
linuxcnc/is upstream and read-only for the port effort.- Any source adaptation needed for WASM happens on copied or generated files under
wasm-port/. - No direct edits inside
linuxcnc/src,linuxcnc/lib,linuxcnc/tests, orlinuxcnc/webare part of the port workflow. - LinuxCNC GUI code is reference-only. The migrated UI is rebuilt in HTML + JavaScript.
- 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../linuxcncand 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:
- extract it into
vendor/linuxcnc/; - patch the vendored copy only;
- record the patch in
patches/; - 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:
tools/extracts upstream files intovendor/patches/are applied to vendored copiesruntime/core/compiles vendored files plus wrappersruntime/sdk/consumes the generated WASM moduleruntime/ui/consumes the SDKruntime/opfs/provides browser persistence servicestests/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:
- Record the exact upstream commit from
linuxcnc/.git. - Record local build assumptions:
- compiler version
- emscripten version
- python version
- node version
- Record the first supported LinuxCNC fixture set:
- one 3-axis machine
- one non-trivial kinematics case
- one 5-axis machine
- 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:
- 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/*
- G-code interpreter:
- For each file, classify it:
- copy unchanged
- copy plus shim
- copy plus light patch
- not included in phase 1
- For each file, record dependencies:
- HAL
- RTAPI
- NML
- native file IO
- Python
- GUI
- 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:
- Write extraction scripts in
wasm-port/tools/. - Copy selected upstream files into
wasm-port/vendor/linuxcnc/. - Preserve relative structure where useful, for example:
vendor/linuxcnc/src/emc/rs274ngc/...vendor/linuxcnc/src/emc/ini/...
- Store every modification as:
- a patch in
wasm-port/patches/, or - a thin wrapper outside the vendored file
- a patch in
- 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
../linuxcncdirectly.
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:
- Create
wasm-port/runtime/core/as the portable core layer. - Add wrapper translation units instead of editing vendored files where possible.
- Start with these subsystems in order:
- INI parser
- numeric parameter table
- named parameter logic
- interpreter core
- planner
- kinematics
- Build a native CLI harness first, before any WASM build.
- 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.shbuilds the INI parser probe, interpreter state probe, named-parameter harness, RS274 compile probe, and the minimal interpreter harness from the standalonewasm-port/workspace.tests/native/verify_native_probes.shvalidates that all native probe exit codes are zero and that the minimal interpreter harness emits aSTRAIGHT_TRAVERSEcanonical event forG0 X1.0 Y2.0, plusSET_FEED_RATEandSTRAIGHT_FEEDcanonical events forG1 X3.0 Y4.0 F120.0.- The same validation is now fixture-driven through
tests/fixtures/gcode/minimal_linear.ngcandtests/fixtures/canon/minimal_linear.events. tests/fixtures/gcode/modal_incremental.ngcandtests/fixtures/canon/modal_incremental.eventsaddG90/G91distance-mode switching plus modalG1carry-forward coverage. The temporary wrapper behavior is based on LinuxCNCinterp_convert.cc::convert_distance_mode()andinterp_convert.cc::convert_straight().tests/fixtures/gcode/position_params.ngcandtests/fixtures/canon/position_params.eventscover Z-axis motion plus current-position parameter visibility for#5420,#5421, and#5422. The parameter source basis is LinuxCNCinterp_parameter_def.hhandinterp_namedparams.cc.tests/fixtures/gcode/canned_cycles.ngcandtests/fixtures/canon/canned_cycles.eventscover LinuxCNC canned-cycle conversion through vendoredinterp_cycles.cc, includingG81,G82,G83,G80cancellation, dwell, peck drilling, and incrementalLrepeats.runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cppnow 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, andSELECT_PLANE.tests/fixtures/gcode/coordinate_offsets.ngcandtests/fixtures/canon/coordinate_offsets.eventspinG55, activeG10 L2,G92,G92.1, andG54behavior frominterp_convert.cc::convert_coordinate_system(),interp_convert.cc::convert_setup(), andinterp_convert.cc::convert_axis_offsets().runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cppnow 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, andSET_NAIVECAM_TOLERANCE.tests/fixtures/gcode/feed_control_modes.ngcandtests/fixtures/canon/feed_control_modes.eventspinG93,G94,G95,G61,G61.1, andG64 P/Qbehavior frominterp_convert.cc::convert_feed_mode(),interp_convert.cc::convert_control_mode(), andinterp_queue.cc.runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cppnow records probe canonical boundary calls emitted by vendoredinterp_convert.cc::convert_probe():TURN_PROBE_ON,STRAIGHT_PROBE, andTURN_PROBE_OFF.tests/fixtures/gcode/probe_semantics.ngcandtests/fixtures/canon/probe_semantics.eventspinG38.2,G38.3,G38.4, andG38.5probe type handling.runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cppnow records speed/feed synchronization and rigid-tap canonical boundary calls emitted by vendoredinterp_convert.cc::convert_straight():START_SPEED_FEED_SYNCH,STOP_SPEED_FEED_SYNCH, andRIGID_TAP.tests/fixtures/gcode/threading_sync.ngcandtests/fixtures/canon/threading_sync.eventspinG33spindle-synchronized straight feed andG33.1rigid tap behavior.runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cppnow records NURBS G5 canonical boundary calls emitted by vendoredinterp_convert.cc::convert_nurbs():NURBS_G5_FEED.tests/fixtures/gcode/nurbs_g5_semantics.ngcandtests/fixtures/canon/nurbs_g5_semantics.eventspinG5.2control-point collection andG5.3NURBS feed emission.runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cppnow records NURBS G6 canonical boundary calls emitted by vendoredinterp_convert.cc::convert_nurbs():NURBS_G6_FEED.tests/fixtures/gcode/nurbs_g6_semantics.ngcandtests/fixtures/canon/nurbs_g6_semantics.eventspinG6.2order, interpolation mode, control-point, weight, and K segment handling.runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cppnow records spindle-orient canonical boundary calls emitted by vendored LinuxCNC conversion and queue code:ORIENT_SPINDLEandWAIT_SPINDLE_ORIENT_COMPLETE.tests/fixtures/gcode/spindle_orient.ngcandtests/fixtures/canon/spindle_orient.eventspinM19 R/P/Qbehavior frominterp_convert.cc::convert_m()andinterp_queue.cc.runtime/core/linuxcnc_wrap/linuxcnc_interp_minimal_runtime.cppnow records tool-table canonical boundary calls emitted by vendoredinterp_convert.cc::convert_setup_tool():SET_TOOL_TABLE_ENTRY.tests/fixtures/gcode/tool_table_setup.ngcandtests/fixtures/canon/tool_table_setup.eventspinG10 L1tool offset, diameter, front/back angle, and orientation behavior.tests/fixtures/gcode_errors/g1_zero_feed.ngcandtests/fixtures/canon_errors/g1_zero_feed.expectedpin the negativeG1zero-feed case. The source basis is LinuxCNCinterp_convert.cc::convert_straight()andrs274ngc_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, andinterp_execute.cc. tools/build_native_probes.shnow includeslinuxcnc_interp_convert_source_probe, which directly compiles vendoredinterp_convert.cc. The requiredemcStatusshim is limited to the native status boundary used bytag_arc()for machine units; it is not a project-authored CNC behavior implementation.tools/build_native_probes.shnow also includes direct source compile probes for vendoredinterp_read.cc,interp_check.cc, andinterp_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
rs274ngcinterpreter 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, andrs274ngc_pre.cc.rs274ngc_pre.ccis compiled with the existing standaloneUNIT_TEST/LINUXCNC_STANDALONE_USE_RS274_PRE_STATEboundary that isolates Python runtime integration from the browser simulation core. tools/build_native_probes.shnow includes direct source compile probes for the vendored LinuxCNC trajectory-planner and posemath files used bylinuxcnc_tp_api_probe:tp.c,tc.c,tcq.c,spherical_arc.c,blendmath.c,sp_scurve.c,ruckig_wrapper.c, the selectedcruckig/*.csources,emcpose.c,posemath.cc,_posemath.c, andsincos.c. These probes use the sameTP_FLAGSas the standalone TP harness, including the existing-fpermissiveboundary required by upstream enum conversions intp.c.tools/verify_vendor_sync.shnow 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 undervendor/linuxcnc/and the matching file under../linuxcnc/.tools/source-manifest.txtwas also de-duplicated so the manifest is a single authoritative extraction list.- Direct source compile probes now also cover vendored
interp_base.ccandgomath.c.interp_base.ccuses a standaloneEMC2_HOMEcompile-time path boundary for LinuxCNC's dynamic interpreter lookup, andgomath.cis compiled as C withgccso its LinuxCNC C linkage is preserved. The standalonertapi.hshim was made C/C++ compatible for this C-source boundary without changing vendored LinuxCNC files. inifile.ccnow has its own direct source compile probe in addition to the existing INI parser harness. With this probe, every.cand.ccfile listed intools/source-manifest.txthas a native source-level compile check under the standalone build boundary.tools/build_native_probes.shnow emitsbuild/native/source-probes.tsvwhile compiling vendored*_source_probetargets. The native verification script compares that map against every.cand.ccentry intools/source-manifest.txt, so future LinuxCNC source additions fail validation unless they also get an explicit standalone source compile probe.tools/verify_no_standalone_cnc_semantics.shnow guards against reintroducing a standaloneInterp::convert_g()definition outsidevendor/linuxcnc/. This keeps G-code group conversion on the vendored LinuxCNCinterp_convert.ccpath instead of allowing the wrapper layer to grow another project-authored conversion implementation.docs/scope-and-baseline.mdrecords the current upstream LinuxCNC commit, local tool versions, and fixture baseline.tools/verify_upstream_baseline.shnow runs before vendor sync validation so extraction drift is checked against the intended upstream HEAD, not an accidental checkout change.docs/source-reuse-map.mdrecords the current vendored LinuxCNC source reuse matrix and dependency matrix, tying each extracted group to its standalone runtime boundary and validation path.docs/compatibility-validation.mdrecords the current validation chain, source coverage requirements, native harnesses, fixture coverage, and validation boundaries.docs/drift-report.mdrecords current no-drift enforcement, allowed standalone runtime boundaries, known gaps, and the current drift conclusion.
Phase 4: Port INI Parsing Without Editing Upstream
Purpose: Move LinuxCNC config parsing into the standalone runtime.
Steps:
- Vendor:
../linuxcnc/src/emc/ini/inifile.cc../linuxcnc/src/emc/ini/inifile.hh../linuxcnc/src/emc/ini/inifile.h
- Add shim headers under
wasm-port/runtime/core/shims/for small dependencies only. - Replace file loading through:
- wrapper-level adapter, preferred
- minimal vendored patch only if unavoidable
- Preserve:
#INCLUDE- relative includes
- recursion checks
- line continuation
- duplicate section merge behavior
- typed query behavior
- Add tests for INI semantics under
tests/native/.
Involved LinuxCNC source:
src/emc/ini/inifile.ccsrc/emc/ini/inifile.hhsrc/emc/ini/inifile.h
Phase 5: Port Parameter Tables and Variable Files
Purpose: Preserve LinuxCNC numeric parameter behavior exactly enough for simulation.
Steps:
- 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
- Extract:
setup.parameters[]required_parameters[]readonly_parameters[]- parameter file load/save logic
- Replace native file writes with a standalone file service abstraction.
- Keep LinuxCNC’s parameter text format in phase 1.
- 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.hhsrc/emc/rs274ngc/interp_array.ccsrc/emc/rs274ngc/interp_internal.hhsrc/emc/rs274ngc/rs274ngc_pre.cc
Phase 6: Port Named Parameters and Interpreter State
Purpose: Preserve LinuxCNC variable semantics and controller-visible state.
Steps:
- 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
- Preserve:
context.named_paramsPA_READONLYPA_GLOBALPA_USE_LOOKUPPA_FROM_INI- built-in named parameters from
init_named_parameters()
- Preserve lookup order:
- local
- global
_ini[...]_hal[...]- optional Python providers later
- Export state outward rather than redesigning it in JS.
- Add regression cases for:
- local/global scoping
- built-in state variables
_ini[...]_hal[...]- read-only errors
Involved LinuxCNC source:
src/emc/rs274ngc/interp_namedparams.ccsrc/emc/rs274ngc/interp_internal.hhsrc/emc/rs274ngc/interp_fwd.hhsrc/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:
- Do not vendor the whole HAL runtime as a target runtime dependency.
- 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
- Define a standalone HAL adapter interface:
- lookup by name
- typed numeric value
- connection/existence status
- Make
_hal[...]reads resolve through this adapter. - Seed the adapter from simulation config and runtime state.
- Add tests for:
- existing names
- missing names
- disconnected signals
- type conversion
Involved LinuxCNC source:
src/hal/hal.hsrc/hal/halmodule.ccsrc/emc/rs274ngc/interp_namedparams.ccsrc/emc/ini/inihal.cc
Phase 8: Port the Interpreter Core
Purpose: Build the standalone G-code execution engine without touching upstream files.
Steps:
- Vendor selected files from
../linuxcnc/src/emc/rs274ngc/. - Keep original source as intact as possible in
vendor/. - Add wrappers or minimal patches only in the standalone area.
- Replace these external edges:
- file open/read
- world sync
- HAL reads
- logging
- runtime callbacks
- Preserve:
- modal state
- subroutines
- offsets
- tool handling
- parameter interactions
- error semantics
- Add a canonical event sink interface in standalone code.
Involved LinuxCNC source:
src/emc/rs274ngc/interp_execute.ccsrc/emc/rs274ngc/interp_read.ccsrc/emc/rs274ngc/interp_check.ccsrc/emc/rs274ngc/interp_convert.ccsrc/emc/rs274ngc/interp_cycles.ccsrc/emc/rs274ngc/interp_find.ccsrc/emc/rs274ngc/interp_write.ccsrc/emc/rs274ngc/interp_o_word.ccsrc/emc/rs274ngc/rs274ngc_pre.ccsrc/emc/rs274ngc/rs274ngc_interp.hh
Phase 9: Port Planner and Kinematics
Purpose: Preserve LinuxCNC motion planning and 5-axis simulation behavior.
Steps:
- Vendor selected planner files from
../linuxcnc/src/emc/tp/. - Vendor selected kinematics files from:
../linuxcnc/src/emc/kinematics/- selected
.compsources mirrored into standalone code where needed
- Replace loadable-module assumptions with a registry in the standalone runtime.
- Keep original math and state logic intact as far as practical.
- Add tests for:
- planner outputs
- forward/inverse kinematics
- 5-axis world/joint transforms
Involved LinuxCNC source:
src/emc/tp/tp.csrc/emc/tp/tc.csrc/emc/tp/tcq.csrc/emc/tp/blendmath.csrc/emc/tp/sp_scurve.csrc/emc/tp/ruckig_wrapper.csrc/emc/kinematics/*.csrc/hal/components/xyzab_tdr_kins.compsrc/hal/components/xyzacb_trsrn.compsrc/hal/components/xyzbca_trsrn.comp
Phase 10: Build the Standalone WASM Program
Purpose: Keep the migrated program completely outside native LinuxCNC management.
Steps:
- Build the standalone native core first.
- Add a standalone WASM export layer under:
wasm-port/runtime/core/wasm-port/runtime/sdk/
- Use
vendor/sources plus standalone wrappers as build input. - Do not compile from
../linuxcncdirectly in the final WASM product build. - Emit:
wasmmodule- 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:
- Build frontend files under:
wasm-port/runtime/ui/wasm-port/runtime/opfs/
- Implement:
- HTML shell
- JavaScript control panel
- OPFS persistence
- file import/export
- machine/controller state views
- Keep LinuxCNC GUI code reference-only.
- 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:
- Use native LinuxCNC tests and fixtures as semantic baselines.
- Compare:
- LinuxCNC native behavior
- standalone native extracted core
- standalone WASM behavior
- Maintain a drift report.
- Re-run extraction if upstream source changes.
- Keep patches small and traceable.
Outputs:
- drift report
- compatibility regression suite
Management Rules For Daily Development
Use these rules continuously:
- Never edit files under
linuxcnc/as part of the port. - Any needed modification to upstream logic must be applied to vendored copies only.
- Any upstream sync must be script-driven and repeatable.
- Every shim must be documented.
- Every local patch against vendored source must be stored as a patch file or clearly isolated wrapper.
Recommended Document Set
Keep these documents under wasm-port/docs/:
scope-and-baseline.mdsource-reuse-map.mdstate-porting-strategy.mdwasm-build-strategy.mdfrontend-architecture.mdopfs-file-model.mdcompatibility-validation.mddrift-report.md
Immediate Next Step
Continue expanding the standalone interpreter core from the verified minimal traverse path:
- keep
convert_g()execution on vendored LinuxCNC interpreter conversion code and reject any new standaloneInterp::convert_g()implementation. - identify and shim the native runtime symbols blocking direct compilation of
interp_convert.cc,interp_execute.cc, and related interpreter files. - keep fixture coverage as regression protection while deleting temporary hand-written semantics.
- keep all source changes inside
wasm-port/and leave../linuxcnc/read-only.