按规划持续工作

结论:WASM interpreter 已链接 vendored LinuxCNC interp_remap.cc,并通过 SDK C ABI 运行 vendored xyzac/xyzbc switchkins remap demo;Node/host/browser smoke 均通过,未新增 JavaScript M428/M429/M430 或运动学语义。
This commit is contained in:
2026-06-08 18:04:09 +08:00
parent 567f72d35f
commit 149095274c
7 changed files with 292 additions and 15 deletions

View File

@@ -107,7 +107,13 @@ and missing named-parameter lookup.
It also writes selected G-code fixtures into the It also writes selected G-code fixtures into the
Emscripten filesystem through the SDK and runs them through LinuxCNC Emscripten filesystem through the SDK and runs them through LinuxCNC
`Interp::open()`, `Interp::read()`, and `Interp::execute()` to validate the `Interp::open()`, `Interp::read()`, and `Interp::execute()` to validate the
file execution path. The same Node smoke writes LinuxCNC-format parameter file execution path. It also writes the vendored LinuxCNC `xyzac-trt` and
`xyzbc-trt` table-rotary-tilting sample machine INI, `remap_subs/*.ngc`, and
`xyzac_switchkins.ngc`/`xyzbc_switchkins.ngc` demo files into the Emscripten
filesystem, then validates the WASM C ABI/SDK path for vendored LinuxCNC
`REMAP` parsing, O-word remap execution, `M68`/`M66` HAL synchronization, and
file `open()`/`read()`/`execute()` completion without JavaScript M-code or
kinematics semantics. The same Node smoke writes LinuxCNC-format parameter
files into the Emscripten filesystem and validates vendored files into the Emscripten filesystem and validates vendored
`Interp::restore_parameters()` and `Interp::save_parameters()`, including the `Interp::restore_parameters()` and `Interp::save_parameters()`, including the
saved parameter values, missing required numeric parameter defaulting, and the saved parameter values, missing required numeric parameter defaulting, and the
@@ -238,7 +244,7 @@ The validation fails if:
| Harness | Purpose | | Harness | Purpose |
| --- | --- | | --- | --- |
| `tests/wasm/node/verify_ini_wasm.sh` | Validates the browser-facing INI WASM module can be built from vendored LinuxCNC `inifile.cc`, loaded through the JS SDK in Node, and queried through the exported C ABI, including LinuxCNC-backed boolean conversion and machine-session file-name string lookup. | | `tests/wasm/node/verify_ini_wasm.sh` | Validates the browser-facing INI WASM module can be built from vendored LinuxCNC `inifile.cc`, loaded through the JS SDK in Node, and queried through the exported C ABI, including LinuxCNC-backed boolean conversion and machine-session file-name string lookup. |
| `tests/wasm/node/verify_interp_wasm.sh` | Validates the initial interpreter-core WASM module can be built from vendored LinuxCNC interpreter source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. | | `tests/wasm/node/verify_interp_wasm.sh` | Validates the interpreter-core WASM module can be built from vendored LinuxCNC interpreter/remap source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, run vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo files through the WASM C ABI/SDK path, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
| `tests/wasm/node/verify_tp_wasm.sh` | Validates a standalone trajectory-planner WASM module can be built from vendored LinuxCNC TP/TC/Ruckig support source, loaded in Node, and run the same linear, arc, and queued-line planner probe paths covered by the native TP harness. | | `tests/wasm/node/verify_tp_wasm.sh` | Validates a standalone trajectory-planner WASM module can be built from vendored LinuxCNC TP/TC/Ruckig support source, loaded in Node, and run the same linear, arc, and queued-line planner probe paths covered by the native TP harness. |
| `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store including custom filenames and envelope/path rejection paths, machine file store, G-code text store including filename rejection paths, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. | | `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store including custom filenames and envelope/path rejection paths, machine file store, G-code text store including filename rejection paths, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. |
| `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, LinuxCNC-backed INI machine-session file-name string lookup, OPFS text-file round trip, generic session snapshot round trip plus custom filename and envelope/path rejection paths, machine file text round trip, G-code text round trip plus filename rejection paths, and the INI panel UI's machine-session load with default OPFS parameter/tool-table file mapping, G-code run, and canonical-event display paths in a real browser runtime. | | `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, LinuxCNC-backed INI machine-session file-name string lookup, OPFS text-file round trip, generic session snapshot round trip plus custom filename and envelope/path rejection paths, machine file text round trip, G-code text round trip plus filename rejection paths, and the INI panel UI's machine-session load with default OPFS parameter/tool-table file mapping, G-code run, and canonical-event display paths in a real browser runtime. |
@@ -603,5 +609,6 @@ standalone remap descriptor path. It reads the vendored `xyzac-trt` and
`xyzbc-trt` INI `REMAP` entries, resolves their `remap_subs/*.ngc` files `xyzbc-trt` INI `REMAP` entries, resolves their `remap_subs/*.ngc` files
through LinuxCNC `find_ngc_file()`, and validates the resulting through LinuxCNC `find_ngc_file()`, and validates the resulting
`_setup.m_remapped` descriptors for `M428`, `M429`, and `M430`. Python `_setup.m_remapped` descriptors for `M428`, `M429`, and `M430`. Python
callbacks, O-word remap execution, and HAL synchronization remain runtime callbacks remain runtime boundaries. Native and WASM validation now execute
boundaries. the NGC remap/file paths through vendored LinuxCNC O-word dispatch and the
standalone HAL adapter boundary.

View File

@@ -806,13 +806,17 @@ Current five-axis switchkins status:
`xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`,
`xyzac_switchkins_test_1.ngc`, and `xyzac_switchkins_test_3.ngc` through `xyzac_switchkins_test_1.ngc`, and `xyzac_switchkins_test_3.ngc` through
LinuxCNC remap/file execution paths. LinuxCNC remap/file execution paths.
7. The WASM interpreter core now links vendored `interp_remap.cc` plus the
Python-only runtime edge stub, and the Node WASM smoke runs vendored
`xyzac_switchkins.ngc` and `xyzbc_switchkins.ngc` through the SDK C ABI
without JavaScript M-code or kinematics semantics.
Next work: Next work:
1. Export the validated switchkins/remap status through the WASM SDK and INI 1. Add browser smoke/UI exposure for the validated switchkins/remap status
panel without adding JavaScript CNC semantics. without adding JavaScript CNC semantics.
2. Add browser/Node smoke coverage that runs the vendored 5-axis remap demo 2. Continue broadening five-axis fixture coverage after the browser path is
fixtures through the WASM interpreter boundary. stable.
Involved LinuxCNC source: Involved LinuxCNC source:

View File

@@ -74,10 +74,10 @@ Current validation is intentionally mechanical:
dual-rotary, and table-rotary-tilting LinuxCNC sample machines. NGC remap dual-rotary, and table-rotary-tilting LinuxCNC sample machines. NGC remap
descriptors for the TRT sample machines are parsed through vendored descriptors for the TRT sample machines are parsed through vendored
`Interp::parse_remap()` and `find_ngc_file()` by `Interp::parse_remap()` and `find_ngc_file()` by
`linuxcnc_remap_parse_harness`. Full standalone execution still needs `linuxcnc_remap_parse_harness`; native and WASM Node validation execute the
LinuxCNC O-word remap dispatch, the `M68`/`M66` synchronization path, and selected TRT switchkins demo files through vendored LinuxCNC O-word remap
`_hal[motion.switchkins-type]` readback connected through the standalone HAL dispatch, file `open()`/`read()`/`execute()`, and the standalone HAL adapter
boundary. boundary for `M68`/`M66` plus `_hal[motion.switchkins-type]` readback.
- Cutter compensation positive motion and negative interpreter paths are - Cutter compensation positive motion and negative interpreter paths are
fixture-covered through vendored `interp_convert.cc` and `interp_queue.cc`. fixture-covered through vendored `interp_convert.cc` and `interp_queue.cc`.
- Browser/WASM C ABI and JS SDK layers are now present for the INI parser, the - Browser/WASM C ABI and JS SDK layers are now present for the INI parser, the

View File

@@ -11,6 +11,7 @@
#include <emscripten/emscripten.h> #include <emscripten/emscripten.h>
#include "canon_event_sink.hh" #include "canon_event_sink.hh"
#include "emc/ini/inifile.hh"
#include "linuxcnc_hal_adapter.hh" #include "linuxcnc_hal_adapter.hh"
#include "linuxcnc_tool_adapter.hh" #include "linuxcnc_tool_adapter.hh"
#include "nml_intf/emc.hh" #include "nml_intf/emc.hh"
@@ -58,6 +59,19 @@ void seed_hal_values()
HAL_FLOAT, disconnected, false); HAL_FLOAT, disconnected, false);
} }
void seed_switchkins_hal()
{
standalone::reset_hal_adapter();
hal_data_u switchkins{};
switchkins.f = 0.0;
standalone::set_hal_value(standalone::HalValueKind::Pin, "motion.switchkins-type",
HAL_FLOAT, switchkins);
standalone::set_hal_value(standalone::HalValueKind::Pin, "motion.analog-out-03",
HAL_FLOAT, switchkins);
standalone::link_hal_pin_alias("motion.analog-out-03", "motion.switchkins-type");
}
void seed_tool_values() void seed_tool_values()
{ {
standalone::reset_tool_adapter(); standalone::reset_tool_adapter();
@@ -92,6 +106,29 @@ void initialize_minimal_interp(Interp &interp)
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers)); std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
} }
void initialize_fiveaxis_remap_interp(Interp &interp)
{
seed_switchkins_hal();
seed_tool_values();
interp._setup.length_units = CANON_UNITS_MM;
interp._setup.distance_mode = DISTANCE_MODE::ABSOLUTE;
interp._setup.ijk_distance_mode = DISTANCE_MODE::INCREMENTAL;
interp._setup.feed_mode = FEED_MODE::UNITS_PER_MINUTE;
interp._setup.plane = CANON_PLANE::XY;
interp._setup.motion_mode = G_0;
interp._setup.percent_flag = false;
interp._setup.sequence_number = 0;
interp._setup.parameter_occurrence = 0;
interp._setup.num_spindles = 1;
interp._setup.feature_set = FEATURE_INI_VARS | FEATURE_HAL_PIN_VARS;
interp._setup.parameter_g73_peck_clearance = 1.0;
interp._setup.parameter_g83_peck_clearance = 1.0;
interp._setup.parameters[5599] = 1.0;
interp.load_tool_table();
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
interp.init_named_parameters();
}
void initialize_indexer_interp(Interp &interp) void initialize_indexer_interp(Interp &interp)
{ {
standalone::reset_hal_adapter(); standalone::reset_hal_adapter();
@@ -220,6 +257,51 @@ void append_named_value(std::ostringstream &output, Interp &interp, const char *
output << name << ": rc=" << rc << " found=" << status << " value=" << value << "\n"; output << name << ": rc=" << rc << " found=" << status << " value=" << value << "\n";
} }
std::string parent_path(const char *path)
{
std::string value = path ? path : "";
const std::string::size_type slash = value.find_last_of('/');
if (slash == std::string::npos) {
return ".";
}
if (slash == 0) {
return "/";
}
return value.substr(0, slash);
}
bool parse_machine_remaps(Interp &interp, std::ostringstream &output, const char *ini_path)
{
const std::string machine_dir = parent_path(ini_path);
const std::string remap_dir = machine_dir + "/remap_subs";
linuxcnc::IniFile ini(ini_path ? ini_path : "");
const bool opened = static_cast<bool>(ini);
output << "fiveaxis_ini_open=" << (opened ? 1 : 0) << "\n";
if (!opened) {
return false;
}
std::snprintf(interp._setup.program_prefix, sizeof(interp._setup.program_prefix), "%s",
machine_dir.c_str());
interp._setup.subroutines[0] = strstore(remap_dir.c_str());
bool ok = true;
int remap_count = 0;
while (auto remap = ini.findString(++remap_count, "REMAP", "RS274NGC")) {
const int line_number = ini.lineOf(remap_count, "REMAP", "RS274NGC").second;
const int rc = interp.parse_remap(remap->c_str(), line_number);
output << "fiveaxis_parse_remap_" << remap_count << "=" << rc << "\n";
ok &= rc == INTERP_OK;
}
remap_count -= 1;
output << "fiveaxis_parsed_remap_count=" << remap_count << "\n";
ok &= remap_count == 3;
output << "fiveaxis_remaps_ready=" << (ok ? 1 : 0) << "\n";
return ok;
}
void apply_parameter_assignments(Interp &interp, const char *assignments) void apply_parameter_assignments(Interp &interp, const char *assignments)
{ {
std::istringstream input(assignments ? assignments : ""); std::istringstream input(assignments ? assignments : "");
@@ -368,6 +450,102 @@ char *lcinterp_run_file(const char *path)
return lcinterp_run_file_with_ini(path, nullptr); return lcinterp_run_file_with_ini(path, nullptr);
} }
EMSCRIPTEN_KEEPALIVE
char *lcinterp_run_fiveaxis_remap_file(const char *path, const char *ini_path)
{
if (ini_path && ini_path[0] != '\0') {
setenv("INI_FILE_NAME", ini_path, 1);
} else {
unsetenv("INI_FILE_NAME");
}
Interp interp;
standalone::reset_canon_events();
initialize_fiveaxis_remap_interp(interp);
std::ostringstream output;
bool ok = parse_machine_remaps(interp, output, ini_path);
const int open_rc = interp.open(path);
output << "fiveaxis_file_open=" << open_rc << "\n";
if (open_rc != INTERP_OK) {
append_error_text(output, interp, "fiveaxis_file_error_text=", open_rc);
output << "fiveaxis_linuxcnc_remap_file_execute=0\n";
unsetenv("INI_FILE_NAME");
return copy_result(output.str());
}
constexpr int max_file_steps = 4096;
int file_read_count = 0;
int file_execute_count = 0;
int file_finish_count = 0;
int final_rc = INTERP_OK;
bool reached_exit = false;
while ((file_read_count < max_file_steps) && (file_execute_count < max_file_steps)) {
const int read_rc = interp.read();
if (read_rc == INTERP_ENDFILE) {
output << "fiveaxis_file_read_eof=" << read_rc << "\n";
final_rc = read_rc;
break;
}
++file_read_count;
if ((read_rc != INTERP_OK) && (read_rc != INTERP_EXECUTE_FINISH)) {
output << "fiveaxis_file_read_" << file_read_count << "=" << read_rc << "\n";
append_error_text(output, interp, "fiveaxis_file_error_text=", read_rc);
final_rc = read_rc;
ok = false;
break;
}
const int execute_rc = interp.execute();
++file_execute_count;
final_rc = execute_rc;
if (execute_rc == INTERP_EXECUTE_FINISH) {
++file_finish_count;
}
if ((execute_rc != INTERP_OK) && (execute_rc != INTERP_EXIT) &&
(execute_rc != INTERP_EXECUTE_FINISH)) {
output << "fiveaxis_file_execute_" << file_execute_count << "="
<< execute_rc << "\n";
append_error_text(output, interp, "fiveaxis_file_error_text=", execute_rc);
ok = false;
break;
}
if (execute_rc == INTERP_EXIT) {
reached_exit = true;
break;
}
}
int hal_status = 0;
double switchkins_type = 0.0;
const int hal_rc =
interp.find_named_param("_hal[motion.switchkins-type]", &hal_status, &switchkins_type);
output << "fiveaxis_file_read_count=" << file_read_count << "\n";
output << "fiveaxis_file_execute_count=" << file_execute_count << "\n";
output << "fiveaxis_file_finish_count=" << file_finish_count << "\n";
output << "fiveaxis_file_final_rc=" << final_rc << "\n";
output << "fiveaxis_file_reached_exit=" << (reached_exit ? 1 : 0) << "\n";
output << "fiveaxis_hal_switchkins: rc=" << hal_rc << " found=" << hal_status
<< " value=" << switchkins_type << "\n";
ok &= reached_exit;
ok &= file_read_count > 0;
ok &= file_execute_count > 0;
ok &= file_read_count < max_file_steps;
ok &= file_execute_count < max_file_steps;
ok &= hal_rc == INTERP_OK && hal_status == 1 && switchkins_type == 0.0;
output << "fiveaxis_linuxcnc_remap_file_execute=" << (ok ? 1 : 0) << "\n";
unsetenv("INI_FILE_NAME");
return copy_result(output.str());
}
EMSCRIPTEN_KEEPALIVE EMSCRIPTEN_KEEPALIVE
char *lcinterp_restore_parameters(const char *path) char *lcinterp_restore_parameters(const char *path)
{ {

View File

@@ -74,6 +74,10 @@ export async function createLinuxCncInterpSdk(moduleOptions = {}) {
return callStringResult(mod, "lcinterp_run_file_with_ini", path, iniPath); return callStringResult(mod, "lcinterp_run_file_with_ini", path, iniPath);
}, },
runFiveAxisRemapFile(path, iniPath) {
return callStringResult(mod, "lcinterp_run_fiveaxis_remap_file", path, iniPath);
},
restoreParameters(path) { restoreParameters(path) {
return callStringResult(mod, "lcinterp_restore_parameters", path); return callStringResult(mod, "lcinterp_restore_parameters", path);
}, },

View File

@@ -1,4 +1,4 @@
import { readFileSync } from "node:fs"; import { readdirSync, readFileSync } from "node:fs";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path"; import { dirname, resolve } from "node:path";
import assert from "node:assert/strict"; import assert from "node:assert/strict";
@@ -88,6 +88,41 @@ const interp = await createLinuxCncInterpSdk({
}, },
}); });
function writeVendorTextFile(sourcePath, wasmPath) {
interp.writeTextFile(wasmPath, readFileSync(sourcePath, "utf8"));
}
function writeFiveAxisTrtMachineFiles() {
const sourceDir = resolve(
rootDir,
"vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting",
);
const wasmDir = "/work/fiveaxis/table-rotary-tilting";
writeVendorTextFile(resolve(sourceDir, "xyzac-trt.ini"), `${wasmDir}/xyzac-trt.ini`);
writeVendorTextFile(resolve(sourceDir, "xyzbc-trt.ini"), `${wasmDir}/xyzbc-trt.ini`);
for (const filename of readdirSync(resolve(sourceDir, "remap_subs"))) {
if (filename.endsWith(".ngc")) {
writeVendorTextFile(
resolve(sourceDir, "remap_subs", filename),
`${wasmDir}/remap_subs/${filename}`,
);
}
}
writeVendorTextFile(
resolve(sourceDir, "demos/xyzac_switchkins.ngc"),
`${wasmDir}/demos/xyzac_switchkins.ngc`,
);
writeVendorTextFile(
resolve(sourceDir, "demos/xyzbc_switchkins.ngc"),
`${wasmDir}/demos/xyzbc_switchkins.ngc`,
);
return wasmDir;
}
const namedParamIniPath = "/work/namedparams.ini"; const namedParamIniPath = "/work/namedparams.ini";
interp.writeTextFile( interp.writeTextFile(
namedParamIniPath, namedParamIniPath,
@@ -303,6 +338,54 @@ verifyExpectedOutput(
).trimEnd(), ).trimEnd(),
); );
const fiveAxisTrtDir = writeFiveAxisTrtMachineFiles();
verifyExpectedOutput(
"fiveaxis_xyzac_switchkins_wasm",
interp.runFiveAxisRemapFile(
`${fiveAxisTrtDir}/demos/xyzac_switchkins.ngc`,
`${fiveAxisTrtDir}/xyzac-trt.ini`,
),
[
"fiveaxis_ini_open=1",
"fiveaxis_parse_remap_1=0",
"fiveaxis_parse_remap_2=0",
"fiveaxis_parse_remap_3=0",
"fiveaxis_parsed_remap_count=3",
"fiveaxis_remaps_ready=1",
"fiveaxis_file_open=0",
"fiveaxis_file_read_count=620",
"fiveaxis_file_execute_count=620",
"fiveaxis_file_finish_count=21",
"fiveaxis_file_final_rc=1",
"fiveaxis_file_reached_exit=1",
"fiveaxis_hal_switchkins: rc=0 found=1 value=0",
"fiveaxis_linuxcnc_remap_file_execute=1",
].join("\n"),
);
verifyExpectedOutput(
"fiveaxis_xyzbc_switchkins_wasm",
interp.runFiveAxisRemapFile(
`${fiveAxisTrtDir}/demos/xyzbc_switchkins.ngc`,
`${fiveAxisTrtDir}/xyzbc-trt.ini`,
),
[
"fiveaxis_ini_open=1",
"fiveaxis_parse_remap_1=0",
"fiveaxis_parse_remap_2=0",
"fiveaxis_parse_remap_3=0",
"fiveaxis_parsed_remap_count=3",
"fiveaxis_remaps_ready=1",
"fiveaxis_file_open=0",
"fiveaxis_file_read_count=620",
"fiveaxis_file_execute_count=620",
"fiveaxis_file_finish_count=21",
"fiveaxis_file_final_rc=1",
"fiveaxis_file_reached_exit=1",
"fiveaxis_hal_switchkins: rc=0 found=1 value=0",
"fiveaxis_linuxcnc_remap_file_execute=1",
].join("\n"),
);
const parameterFilePath = "/work/rs274ngc.var"; const parameterFilePath = "/work/rs274ngc.var";
interp.writeTextFile( interp.writeTextFile(
parameterFilePath, parameterFilePath,

View File

@@ -59,11 +59,12 @@ INTERP_CORE_SOURCES=(
"$VENDOR_DIR/src/emc/rs274ngc/interp_namedparams.cc" "$VENDOR_DIR/src/emc/rs274ngc/interp_namedparams.cc"
"$VENDOR_DIR/src/emc/rs274ngc/interp_write.cc" "$VENDOR_DIR/src/emc/rs274ngc/interp_write.cc"
"$VENDOR_DIR/src/emc/rs274ngc/interp_o_word.cc" "$VENDOR_DIR/src/emc/rs274ngc/interp_o_word.cc"
"$VENDOR_DIR/src/emc/rs274ngc/interp_remap.cc"
"$VENDOR_DIR/src/emc/rs274ngc/rs274ngc_pre.cc" "$VENDOR_DIR/src/emc/rs274ngc/rs274ngc_pre.cc"
"$VENDOR_DIR/src/emc/tooldata/tooldata_common.cc" "$VENDOR_DIR/src/emc/tooldata/tooldata_common.cc"
"$WRAP_DIR/linuxcnc_hal_adapter.cpp" "$WRAP_DIR/linuxcnc_hal_adapter.cpp"
"$WRAP_DIR/linuxcnc_emc_status_runtime.cpp" "$WRAP_DIR/linuxcnc_emc_status_runtime.cpp"
"$WRAP_DIR/linuxcnc_interp_edge_stubs.cpp" "$WRAP_DIR/linuxcnc_interp_python_edge_stubs.cpp"
"$WRAP_DIR/linuxcnc_runtime_state_stubs.cpp" "$WRAP_DIR/linuxcnc_runtime_state_stubs.cpp"
"$WRAP_DIR/linuxcnc_tool_adapter.cpp" "$WRAP_DIR/linuxcnc_tool_adapter.cpp"
"$WRAP_DIR/linuxcnc_interp_minimal_runtime.cpp" "$WRAP_DIR/linuxcnc_interp_minimal_runtime.cpp"
@@ -96,5 +97,5 @@ link_wasm_module \
-s STACK_SIZE=2MB \ -s STACK_SIZE=2MB \
-s NO_EXIT_RUNTIME=1 \ -s NO_EXIT_RUNTIME=1 \
-s FORCE_FILESYSTEM=1 \ -s FORCE_FILESYSTEM=1 \
-s EXPORTED_FUNCTIONS='["_malloc","_free","_lcinterp_run_program","_lcinterp_run_program_with_ini","_lcinterp_run_file","_lcinterp_run_file_with_ini","_lcinterp_restore_parameters","_lcinterp_save_parameters","_lcinterp_load_tool_table","_lcinterp_load_tool_table_random","_lcinterp_save_tool_table","_lcinterp_probe_init_and_synch","_lcinterp_probe_indexer","_lcinterp_probe_named_parameters","_lcinterp_free_string"]' \ -s EXPORTED_FUNCTIONS='["_malloc","_free","_lcinterp_run_program","_lcinterp_run_program_with_ini","_lcinterp_run_file","_lcinterp_run_file_with_ini","_lcinterp_run_fiveaxis_remap_file","_lcinterp_restore_parameters","_lcinterp_save_parameters","_lcinterp_load_tool_table","_lcinterp_load_tool_table_random","_lcinterp_save_tool_table","_lcinterp_probe_init_and_synch","_lcinterp_probe_indexer","_lcinterp_probe_named_parameters","_lcinterp_free_string"]' \
-s EXPORTED_RUNTIME_METHODS='["FS","UTF8ToString","stringToUTF8","lengthBytesUTF8"]' -s EXPORTED_RUNTIME_METHODS='["FS","UTF8ToString","stringToUTF8","lengthBytesUTF8"]'