Harden LinuxCNC wasm and native probe workflows
This commit is contained in:
88
analyze-linuxcnc-wasm-blockers.sh
Executable file
88
analyze-linuxcnc-wasm-blockers.sh
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
python_blockers=()
|
||||
dlopen_blockers=()
|
||||
tooldata_blockers=()
|
||||
shimmed_tooldata_users=()
|
||||
native_backend_blockers=()
|
||||
native_fs_blockers=()
|
||||
|
||||
while IFS=: read -r group path note; do
|
||||
[[ -z "$group" || "$group" == \#* ]] && continue
|
||||
case "$group" in
|
||||
core)
|
||||
continue
|
||||
;;
|
||||
blocked)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest group: $group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
full_path="$linuxcnc_root/$path"
|
||||
if [[ ! -f "$full_path" ]]; then
|
||||
echo "missing manifest source: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$path" == src/emc/tooldata/* ]]; then
|
||||
tooldata_blockers+=("$path")
|
||||
fi
|
||||
|
||||
if [[ "$path" == "src/emc/tooldata/tooldata_mmap.cc" ]]; then
|
||||
native_backend_blockers+=("$path")
|
||||
fi
|
||||
|
||||
if grep -Eq 'Python\.h|boost/python|pythonplugin|PyObject|PyInit_' "$full_path"; then
|
||||
python_blockers+=("$path")
|
||||
fi
|
||||
|
||||
if grep -Eq 'dlopen|dlsym|RTLD_' "$full_path"; then
|
||||
dlopen_blockers+=("$path")
|
||||
fi
|
||||
|
||||
if grep -Eq 'mkstemp|mkstemps|dirent\.h|opendir|readdir|unistd\.h' "$full_path"; then
|
||||
native_fs_blockers+=("$path")
|
||||
fi
|
||||
|
||||
if [[ "$path" != src/emc/tooldata/* ]] && grep -Eq 'tooldata/tooldata.hh|tooldata_' "$full_path"; then
|
||||
shimmed_tooldata_users+=("$path")
|
||||
fi
|
||||
done < "$manifest"
|
||||
|
||||
print_group() {
|
||||
local title=$1
|
||||
shift
|
||||
echo "[$title]"
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "(none)"
|
||||
else
|
||||
printf '%s\n' "$@" | LC_ALL=C sort -u
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
print_group "python" "${python_blockers[@]}"
|
||||
print_group "dlopen" "${dlopen_blockers[@]}"
|
||||
print_group "tooldata" "${tooldata_blockers[@]}"
|
||||
print_group "tooldata-users" "${shimmed_tooldata_users[@]}"
|
||||
print_group "native-backend" "${native_backend_blockers[@]}"
|
||||
print_group "native-fs" "${native_fs_blockers[@]}"
|
||||
@@ -3,12 +3,68 @@ set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||
|
||||
# This script writes fixed build and public artifact paths, so serialize it.
|
||||
exec 9>"${TMPDIR:-/tmp}/cnc_sim_build_wasm.lock"
|
||||
flock 9
|
||||
|
||||
echo "LinuxCNC wasm blocker scan"
|
||||
./test-linuxcnc-wasm-blockers.sh
|
||||
|
||||
echo "LinuxCNC wasm-safe source syntax probe"
|
||||
./test-linuxcnc-wasm-source-syntax.sh
|
||||
|
||||
echo "LinuxCNC wasm-safe source object probe"
|
||||
./test-linuxcnc-wasm-source-objects.sh
|
||||
|
||||
echo "LinuxCNC wasm-safe CMake probe target"
|
||||
./test-linuxcnc-wasm-cmake-safe-probe.sh
|
||||
|
||||
echo "LinuxCNC wasm tooldata shim link probe"
|
||||
./test-linuxcnc-wasm-tooldata-link.sh
|
||||
|
||||
echo "LinuxCNC wasm tooldata_common link probe"
|
||||
./test-linuxcnc-wasm-tooldata-common-link.sh
|
||||
|
||||
echo "LinuxCNC wasm tooldata_mmap symbol probe"
|
||||
./test-linuxcnc-wasm-tooldata-mmap-symbols.sh
|
||||
|
||||
echo "LinuxCNC wasm tooldata runtime symbol probe"
|
||||
./test-linuxcnc-wasm-tooldata-runtime-symbols.sh
|
||||
|
||||
echo "LinuxCNC wasm interp_base link probe"
|
||||
./test-linuxcnc-wasm-interp-base-link.sh
|
||||
|
||||
echo "LinuxCNC wasm interp_find link probe"
|
||||
./test-linuxcnc-wasm-interp-find-link.sh
|
||||
|
||||
echo "LinuxCNC wasm python_plugin link probe"
|
||||
./test-linuxcnc-wasm-python-plugin-link.sh
|
||||
|
||||
echo "LinuxCNC wasm rs274ngc_pre object probe"
|
||||
./test-linuxcnc-wasm-rs274ngc-pre-object.sh
|
||||
|
||||
echo "LinuxCNC wasm rs274ngc_pre link blocker scan"
|
||||
./test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh
|
||||
|
||||
echo "LinuxCNC wasm rs274ngc_pre link probe"
|
||||
./test-linuxcnc-wasm-rs274ngc-pre-link.sh
|
||||
|
||||
if ! command -v emcmake >/dev/null 2>&1; then
|
||||
echo "Emscripten is required. Install/activate emsdk so emcmake and emcc are in PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
emcmake cmake -S core -B build/wasm -DCMAKE_BUILD_TYPE=Release
|
||||
emcmake cmake -S core -B build/wasm \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCNC_SIM_LINUXCNC_ROOT="$linuxcnc_root" \
|
||||
-DCNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE=ON
|
||||
cmake --build build/wasm
|
||||
|
||||
mkdir -p web/public
|
||||
|
||||
@@ -3,7 +3,13 @@ project(cnc_sim_wasm_core LANGUAGES CXX)
|
||||
|
||||
option(CNC_SIM_ENABLE_LINUXCNC_BRIDGE "Build the experimental LinuxCNC canon bridge" OFF)
|
||||
option(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND "Build the native LinuxCNC librs274 backend" OFF)
|
||||
option(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE "Compile the browser-safe subset of LinuxCNC rs274 sources" OFF)
|
||||
set(CNC_SIM_LINUXCNC_ROOT "" CACHE PATH "LinuxCNC source root for the experimental bridge")
|
||||
set(CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../linuxcnc-rs274-wasm-source-files.txt"
|
||||
CACHE FILEPATH
|
||||
"Manifest that partitions LinuxCNC rs274 sources into wasm-safe core and blocked groups"
|
||||
)
|
||||
|
||||
set(cnc_sim_core_sources
|
||||
src/canon_event_sink.cpp
|
||||
@@ -28,6 +34,137 @@ if(CNC_SIM_ENABLE_LINUXCNC_RS274_BACKEND)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE)
|
||||
if(NOT CNC_SIM_LINUXCNC_ROOT)
|
||||
message(FATAL_ERROR "Set CNC_SIM_LINUXCNC_ROOT to the LinuxCNC source root")
|
||||
endif()
|
||||
get_filename_component(CNC_SIM_LINUXCNC_ROOT_ABS
|
||||
"${CNC_SIM_LINUXCNC_ROOT}"
|
||||
ABSOLUTE
|
||||
BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.."
|
||||
)
|
||||
if(NOT IS_DIRECTORY "${CNC_SIM_LINUXCNC_ROOT_ABS}")
|
||||
message(FATAL_ERROR "LinuxCNC source root does not exist: ${CNC_SIM_LINUXCNC_ROOT_ABS}")
|
||||
endif()
|
||||
if(NOT EXISTS "${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}")
|
||||
message(FATAL_ERROR "Missing LinuxCNC wasm source manifest: ${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}")
|
||||
endif()
|
||||
if(IS_DIRECTORY "${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}")
|
||||
message(FATAL_ERROR "LinuxCNC wasm source manifest is not a file: ${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}")
|
||||
endif()
|
||||
|
||||
set(linuxcnc_wasm_safe_probe_sources)
|
||||
set(linuxcnc_wasm_blocked_sources)
|
||||
file(STRINGS "${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}" linuxcnc_wasm_manifest_lines)
|
||||
foreach(manifest_line IN LISTS linuxcnc_wasm_manifest_lines)
|
||||
string(STRIP "${manifest_line}" manifest_line)
|
||||
if(manifest_line STREQUAL "" OR manifest_line MATCHES "^#")
|
||||
continue()
|
||||
endif()
|
||||
if(NOT manifest_line MATCHES "^([^:]+):([^:]+):(.*)$")
|
||||
message(FATAL_ERROR "Bad LinuxCNC wasm source manifest line: ${manifest_line}")
|
||||
endif()
|
||||
|
||||
set(manifest_group "${CMAKE_MATCH_1}")
|
||||
set(manifest_path "${CMAKE_MATCH_2}")
|
||||
if(NOT manifest_group STREQUAL "core" AND NOT manifest_group STREQUAL "blocked")
|
||||
message(FATAL_ERROR "Unknown LinuxCNC wasm source manifest group: ${manifest_group}")
|
||||
endif()
|
||||
|
||||
set(manifest_source "${CNC_SIM_LINUXCNC_ROOT_ABS}/${manifest_path}")
|
||||
if(NOT EXISTS "${manifest_source}")
|
||||
message(FATAL_ERROR "LinuxCNC wasm manifest source does not exist: ${manifest_source}")
|
||||
endif()
|
||||
if(IS_DIRECTORY "${manifest_source}")
|
||||
message(FATAL_ERROR "LinuxCNC wasm manifest source is not a file: ${manifest_source}")
|
||||
endif()
|
||||
|
||||
if(manifest_group STREQUAL "core")
|
||||
list(APPEND linuxcnc_wasm_safe_probe_sources "${manifest_source}")
|
||||
else()
|
||||
list(APPEND linuxcnc_wasm_blocked_sources "${manifest_source}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(LENGTH linuxcnc_wasm_safe_probe_sources linuxcnc_wasm_safe_probe_source_count)
|
||||
list(LENGTH linuxcnc_wasm_blocked_sources linuxcnc_wasm_blocked_source_count)
|
||||
if(linuxcnc_wasm_safe_probe_source_count EQUAL 0)
|
||||
message(FATAL_ERROR "LinuxCNC wasm source manifest has no core entries")
|
||||
endif()
|
||||
if(linuxcnc_wasm_blocked_source_count EQUAL 0)
|
||||
message(FATAL_ERROR "LinuxCNC wasm source manifest has no blocked entries")
|
||||
endif()
|
||||
message(STATUS "LinuxCNC wasm-safe core sources: ${linuxcnc_wasm_safe_probe_source_count}")
|
||||
message(STATUS "LinuxCNC wasm blocked sources: ${linuxcnc_wasm_blocked_source_count}")
|
||||
|
||||
set(linuxcnc_wasm_safe_probe_shims
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/dlfcn.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/emc_status_shim.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/gettext_shim.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/linuxcnc_runtime_shim.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/python_c_api_shim.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/rtapi_compat.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/tooldata/tooldata_mmap_backend.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/tooldata/tooldata_runtime_stubs.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/pythonplugin/python_plugin.cc
|
||||
)
|
||||
|
||||
add_library(linuxcnc_rs274_wasm_safe_probe_objects OBJECT
|
||||
${linuxcnc_wasm_safe_probe_shims}
|
||||
${linuxcnc_wasm_safe_probe_sources}
|
||||
)
|
||||
target_compile_features(linuxcnc_rs274_wasm_safe_probe_objects PUBLIC cxx_std_20)
|
||||
target_compile_definitions(linuxcnc_rs274_wasm_safe_probe_objects PRIVATE ULAPI)
|
||||
target_compile_options(linuxcnc_rs274_wasm_safe_probe_objects PRIVATE -include wctype.h)
|
||||
target_include_directories(linuxcnc_rs274_wasm_safe_probe_objects
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/nml_intf
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/rs274ngc
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/motion
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/include
|
||||
)
|
||||
|
||||
set(linuxcnc_rs274_wasm_safe_probe_project_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/canon_event_sink.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_canon_bridge.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/linuxcnc_tooldata_fixture.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/rtcp_kinematics.cpp
|
||||
)
|
||||
|
||||
add_executable(linuxcnc_rs274_wasm_safe_probe EXCLUDE_FROM_ALL
|
||||
$<TARGET_OBJECTS:linuxcnc_rs274_wasm_safe_probe_objects>
|
||||
${linuxcnc_rs274_wasm_safe_probe_project_sources}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims/rs274ngc_pre_probe_main.cc
|
||||
)
|
||||
target_compile_features(linuxcnc_rs274_wasm_safe_probe PRIVATE cxx_std_20)
|
||||
target_compile_definitions(linuxcnc_rs274_wasm_safe_probe PRIVATE ULAPI)
|
||||
target_compile_options(linuxcnc_rs274_wasm_safe_probe PRIVATE -include wctype.h)
|
||||
target_include_directories(linuxcnc_rs274_wasm_safe_probe
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wasm_shims
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/nml_intf
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/rs274ngc
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/src/emc/motion
|
||||
${CNC_SIM_LINUXCNC_ROOT_ABS}/include
|
||||
)
|
||||
target_link_libraries(linuxcnc_rs274_wasm_safe_probe PRIVATE fmt)
|
||||
|
||||
if(linuxcnc_wasm_blocked_sources)
|
||||
add_custom_target(linuxcnc_rs274_wasm_blocked_sources
|
||||
SOURCES ${linuxcnc_wasm_blocked_sources}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(cnc_sim_objects OBJECT
|
||||
${cnc_sim_core_sources}
|
||||
)
|
||||
|
||||
@@ -39,6 +39,8 @@ void CanonEventSink::reset() {
|
||||
feed_hold_ = false;
|
||||
mist_on_ = false;
|
||||
flood_on_ = false;
|
||||
has_pending_motion_start_ = false;
|
||||
pending_motion_start_ = {};
|
||||
}
|
||||
|
||||
void CanonEventSink::set_callback(CncSimEventCallback callback, void *user_data) {
|
||||
@@ -55,6 +57,10 @@ bool CanonEventSink::callback_aborted() const {
|
||||
return callback_status_ != 0;
|
||||
}
|
||||
|
||||
void CanonEventSink::set_block_delete(bool enabled) {
|
||||
block_delete_ = enabled;
|
||||
}
|
||||
|
||||
void CanonEventSink::configure_rtcp(bool enabled, double tool_length) {
|
||||
rtcp_enabled_ = enabled;
|
||||
default_rtcp_tool_length_ = tool_length;
|
||||
@@ -80,6 +86,10 @@ void CanonEventSink::set_tool_length_offset(const CncSimPose &offset) {
|
||||
}
|
||||
|
||||
void CanonEventSink::apply_tool_length_offset(const CncSimPose &offset) {
|
||||
if (!has_pending_motion_start_) {
|
||||
pending_motion_start_ = position_;
|
||||
has_pending_motion_start_ = true;
|
||||
}
|
||||
double dx = tool_length_offset_.x - offset.x;
|
||||
double dy = tool_length_offset_.y - offset.y;
|
||||
rotate_xy(&dx, &dy, -xy_rotation_degrees_);
|
||||
@@ -305,41 +315,45 @@ void CanonEventSink::change_tool(int line) {
|
||||
|
||||
void CanonEventSink::straight_traverse(int line, const CncSimPose &end) {
|
||||
CncSimEvent event = base_event(CNC_SIM_EVENT_RAPID, line);
|
||||
event.start = position_;
|
||||
event.start = has_pending_motion_start_ ? pending_motion_start_ : position_;
|
||||
event.end = end;
|
||||
emit(event);
|
||||
emit_rtcp_pivot(line, position_, end);
|
||||
emit_rtcp_pivot(line, event.start, end);
|
||||
has_pending_motion_start_ = false;
|
||||
position_ = end;
|
||||
}
|
||||
|
||||
void CanonEventSink::straight_feed(int line, const CncSimPose &end) {
|
||||
CncSimEvent event = base_event(CNC_SIM_EVENT_LINEAR_FEED, line);
|
||||
event.start = position_;
|
||||
event.start = has_pending_motion_start_ ? pending_motion_start_ : position_;
|
||||
event.end = end;
|
||||
emit(event);
|
||||
emit_rtcp_pivot(line, position_, end);
|
||||
emit_rtcp_pivot(line, event.start, end);
|
||||
has_pending_motion_start_ = false;
|
||||
position_ = end;
|
||||
}
|
||||
|
||||
void CanonEventSink::arc_feed(int line, const CncSimPose &end, const CncSimPose ¢er, int turns) {
|
||||
CncSimEvent event = base_event(CNC_SIM_EVENT_ARC_FEED, line);
|
||||
event.start = position_;
|
||||
event.start = has_pending_motion_start_ ? pending_motion_start_ : position_;
|
||||
event.end = end;
|
||||
event.center = center;
|
||||
event.arc_turns = turns;
|
||||
emit(event);
|
||||
emit_rtcp_pivot(line, position_, end);
|
||||
emit_rtcp_pivot(line, event.start, end);
|
||||
has_pending_motion_start_ = false;
|
||||
position_ = end;
|
||||
}
|
||||
|
||||
void CanonEventSink::straight_probe(int line, const CncSimPose &end, int probe_type) {
|
||||
CncSimEvent event = base_event(CNC_SIM_EVENT_PROBE, line);
|
||||
event.start = position_;
|
||||
event.start = has_pending_motion_start_ ? pending_motion_start_ : position_;
|
||||
event.end = end;
|
||||
event.reserved = probe_type;
|
||||
emit(event);
|
||||
probe_position_ = end;
|
||||
probe_tripped_ = (probe_type & 2) == 0;
|
||||
has_pending_motion_start_ = false;
|
||||
position_ = end;
|
||||
}
|
||||
|
||||
@@ -446,6 +460,10 @@ bool CanonEventSink::flood_on() const {
|
||||
return flood_on_;
|
||||
}
|
||||
|
||||
bool CanonEventSink::block_delete() const {
|
||||
return block_delete_;
|
||||
}
|
||||
|
||||
void CanonEventSink::set_mist_on(bool enabled) {
|
||||
mist_on_ = enabled;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ public:
|
||||
void set_callback(CncSimEventCallback callback, void *user_data);
|
||||
void clear_callback_status();
|
||||
bool callback_aborted() const;
|
||||
void set_block_delete(bool enabled);
|
||||
void configure_rtcp(bool enabled, double tool_length);
|
||||
void set_tool_length(int h_code, double tool_length);
|
||||
void set_tool_length_offset(const CncSimPose &offset);
|
||||
@@ -70,6 +71,7 @@ public:
|
||||
bool feed_hold() const;
|
||||
bool mist_on() const;
|
||||
bool flood_on() const;
|
||||
bool block_delete() const;
|
||||
void set_mist_on(bool enabled);
|
||||
void set_flood_on(bool enabled);
|
||||
|
||||
@@ -104,5 +106,8 @@ private:
|
||||
bool feed_hold_ = false;
|
||||
bool mist_on_ = false;
|
||||
bool flood_on_ = false;
|
||||
bool block_delete_ = false;
|
||||
std::unordered_map<int, double> tool_lengths_;
|
||||
bool has_pending_motion_start_ = false;
|
||||
CncSimPose pending_motion_start_{};
|
||||
};
|
||||
|
||||
@@ -152,6 +152,11 @@ int apply_config(CncSimHandle *handle, const std::string &json) {
|
||||
if (has_rtcp_enabled || has_tool_length) {
|
||||
handle->sink.configure_rtcp(rtcp_enabled, tool_length);
|
||||
}
|
||||
bool block_delete = false;
|
||||
if (contains_bool_value(compact, "blockdelete", &block_delete) ||
|
||||
contains_bool_value(compact, "block_delete", &block_delete)) {
|
||||
handle->sink.set_block_delete(block_delete);
|
||||
}
|
||||
apply_tool_length_table(handle->sink, compact);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -77,8 +77,12 @@ bool write_temp_program(const char *program,
|
||||
size_t program_len,
|
||||
std::string *path,
|
||||
std::string *error) {
|
||||
char tmpl[] = "/tmp/cnc_sim_api_XXXXXX.ngc";
|
||||
const int fd = mkstemps(tmpl, 4);
|
||||
const char *tmpdir = std::getenv("TMPDIR");
|
||||
std::string tmpl = std::string(tmpdir ? tmpdir : "/tmp") + "/cnc_sim_api_XXXXXX.ngc";
|
||||
std::vector<char> tmpl_buffer(tmpl.begin(), tmpl.end());
|
||||
tmpl_buffer.push_back('\0');
|
||||
|
||||
const int fd = mkstemps(tmpl_buffer.data(), 4);
|
||||
if (fd < 0) {
|
||||
if (error) {
|
||||
*error = "failed to create temporary ngc file";
|
||||
@@ -100,13 +104,13 @@ bool write_temp_program(const char *program,
|
||||
ok = false;
|
||||
}
|
||||
if (!ok) {
|
||||
unlink(tmpl);
|
||||
unlink(tmpl_buffer.data());
|
||||
if (error) {
|
||||
*error = "failed to write temporary ngc file";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*path = tmpl;
|
||||
*path = tmpl_buffer.data();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -185,6 +189,7 @@ int parse_linuxcnc_rs274_backend(CanonEventSink &sink,
|
||||
cnc_sim_linuxcnc_set_canon_sink(nullptr);
|
||||
return -1;
|
||||
}
|
||||
SET_BLOCK_DELETE(sink.block_delete());
|
||||
|
||||
if (file_mode_enabled()) {
|
||||
std::string temp_path;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@
|
||||
#include "canon_event_sink.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
class SmokeGcodeParser {
|
||||
@@ -12,6 +13,14 @@ public:
|
||||
int parse(const char *program, size_t program_len, std::string *error);
|
||||
|
||||
private:
|
||||
struct SmokeToolTableEntry {
|
||||
CncSimPose offset{};
|
||||
double diameter = 0.0;
|
||||
double frontangle = 0.0;
|
||||
double backangle = 0.0;
|
||||
double orientation = 0.0;
|
||||
};
|
||||
|
||||
CanonEventSink &sink_;
|
||||
bool absolute_ = true;
|
||||
bool arc_absolute_ = false;
|
||||
@@ -55,4 +64,5 @@ private:
|
||||
double oword_return_value_ = 0.0;
|
||||
bool oword_value_returned_ = false;
|
||||
int selected_tool_id_ = 0;
|
||||
std::unordered_map<int, SmokeToolTableEntry> tool_table_;
|
||||
};
|
||||
|
||||
@@ -1200,6 +1200,47 @@ int main() {
|
||||
ok &= expect(saw_g52_restore, "expected LinuxCNC G52/G92 shared offset to restore with G92.3");
|
||||
ok &= expect(saw_g52_end_line, "expected LinuxCNC G52 program end line number");
|
||||
|
||||
const char block_delete_program[] =
|
||||
"G21 G90 G17 F100\n"
|
||||
" /N10 G1 X5\n"
|
||||
"G1 X2\n"
|
||||
"M30\n";
|
||||
const char block_delete_on_config[] = "{\"backend\":\"linuxcnc-rs274\",\"blockDelete\":true}";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_load_config_json(sim, block_delete_on_config, sizeof(block_delete_on_config) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
ok &= expect(cnc_sim_parse_program(sim, block_delete_program, sizeof(block_delete_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_block_delete_skipped_line = false;
|
||||
bool saw_block_delete_followup_line = false;
|
||||
for (const auto &event : events) {
|
||||
saw_block_delete_skipped_line = saw_block_delete_skipped_line ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 2 &&
|
||||
event.end.x == 5.0);
|
||||
saw_block_delete_followup_line = saw_block_delete_followup_line ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 3 &&
|
||||
event.end.x == 2.0);
|
||||
}
|
||||
ok &= expect(!saw_block_delete_skipped_line, "expected LinuxCNC block-delete line to be skipped");
|
||||
ok &= expect(saw_block_delete_followup_line, "expected LinuxCNC block-delete followup line to execute");
|
||||
|
||||
const char block_delete_off_config[] = "{\"backend\":\"linuxcnc-rs274\",\"blockDelete\":false}";
|
||||
events.clear();
|
||||
ok &= expect(cnc_sim_load_config_json(sim, block_delete_off_config, sizeof(block_delete_off_config) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
ok &= expect(cnc_sim_parse_program(sim, block_delete_program, sizeof(block_delete_program) - 1) == 0,
|
||||
cnc_sim_last_error(sim));
|
||||
bool saw_block_delete_disabled_line = false;
|
||||
for (const auto &event : events) {
|
||||
saw_block_delete_disabled_line = saw_block_delete_disabled_line ||
|
||||
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||
event.line == 2 &&
|
||||
event.end.x == 5.0);
|
||||
}
|
||||
ok &= expect(saw_block_delete_disabled_line, "expected LinuxCNC disabled block-delete line to execute");
|
||||
|
||||
cnc_sim_destroy(sim);
|
||||
|
||||
int abort_count = 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -128,6 +128,11 @@ bool trace_enabled() {
|
||||
return std::getenv("CNC_SIM_TRACE_RS274") != nullptr;
|
||||
}
|
||||
|
||||
bool block_delete_enabled() {
|
||||
const char *value = std::getenv("CNC_SIM_BLOCK_DELETE");
|
||||
return value && std::string(value) != "0" && std::string(value) != "false";
|
||||
}
|
||||
|
||||
bool execute_line(InterpBase *interp,
|
||||
CanonEventSink &sink,
|
||||
const std::string &line,
|
||||
@@ -251,6 +256,7 @@ int main(int argc, char **argv) {
|
||||
cnc_sim_init_minimal_linuxcnc_tooldata();
|
||||
|
||||
CanonEventSink sink;
|
||||
sink.set_block_delete(block_delete_enabled());
|
||||
bool first = true;
|
||||
sink.set_callback(print_event, &first);
|
||||
cnc_sim_linuxcnc_set_canon_sink(&sink);
|
||||
@@ -271,6 +277,7 @@ int main(int argc, char **argv) {
|
||||
if (trace_enabled()) {
|
||||
std::cerr << "rs274:init done\n";
|
||||
}
|
||||
SET_BLOCK_DELETE(sink.block_delete());
|
||||
|
||||
bool ok = true;
|
||||
if (use_file_mode) {
|
||||
|
||||
4
core/wasm_shims/boost/python/dict.hpp
Normal file
4
core/wasm_shims/boost/python/dict.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
4
core/wasm_shims/boost/python/extract.hpp
Normal file
4
core/wasm_shims/boost/python/extract.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
4
core/wasm_shims/boost/python/import.hpp
Normal file
4
core/wasm_shims/boost/python/import.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
4
core/wasm_shims/boost/python/list.hpp
Normal file
4
core/wasm_shims/boost/python/list.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
211
core/wasm_shims/boost/python/object.hpp
Normal file
211
core/wasm_shims/boost/python/object.hpp
Normal file
@@ -0,0 +1,211 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct _typeobject {
|
||||
const char *tp_name;
|
||||
};
|
||||
using PyTypeObject = _typeobject;
|
||||
|
||||
struct _object {
|
||||
PyTypeObject *ob_type;
|
||||
};
|
||||
using PyObject = _object;
|
||||
|
||||
struct _inittab {
|
||||
const char *name;
|
||||
PyObject *(*initfunc)(void);
|
||||
};
|
||||
|
||||
int Py_IsInitialized(void);
|
||||
PyObject *PyErr_Occurred(void);
|
||||
void PyErr_Clear(void);
|
||||
int PyErr_ExceptionMatches(PyObject *);
|
||||
int PyCallable_Check(PyObject *);
|
||||
void PyErr_Fetch(PyObject **, PyObject **, PyObject **);
|
||||
void PyErr_NormalizeException(PyObject **, PyObject **, PyObject **);
|
||||
void PyErr_Print(void);
|
||||
int PyUnicode_Check(PyObject *);
|
||||
int PyLong_Check(PyObject *);
|
||||
int PyFloat_Check(PyObject *);
|
||||
int PyGen_Check(PyObject *);
|
||||
PyObject *PyObject_Str(PyObject *);
|
||||
const char *PyUnicode_AsUTF8(PyObject *);
|
||||
void Py_DecRef(PyObject *);
|
||||
extern PyObject *PyExc_KeyError;
|
||||
extern PyObject *PyExc_StopIteration;
|
||||
extern PyObject *_Py_NoneStructPtr;
|
||||
|
||||
#define Py_None (_Py_NoneStructPtr)
|
||||
#define Py_TYPE(ob) ((ob)->ob_type)
|
||||
#define Py_XDECREF(ob) \
|
||||
do { \
|
||||
if (ob) { \
|
||||
Py_DecRef(ob); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
}
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename T>
|
||||
const T &cref(const T &value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
namespace python {
|
||||
|
||||
class error_already_set {};
|
||||
|
||||
class object {
|
||||
public:
|
||||
object() = default;
|
||||
template <typename T>
|
||||
object(const T &) {
|
||||
}
|
||||
~object() = default;
|
||||
|
||||
class attr_proxy {
|
||||
public:
|
||||
template <typename T>
|
||||
attr_proxy &operator=(const T &) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator object() const {
|
||||
return object();
|
||||
}
|
||||
};
|
||||
|
||||
attr_proxy attr(const char *) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
object operator[](const char *) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
object operator[](const std::string &) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
object operator[](int) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
PyObject *ptr() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
object operator()(Args &&...) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
inline object getattr(const object &, const char *) {
|
||||
return {};
|
||||
}
|
||||
|
||||
class list : public object {
|
||||
public:
|
||||
template <typename T>
|
||||
void append(const T &) {
|
||||
}
|
||||
};
|
||||
|
||||
class dict : public object {
|
||||
public:
|
||||
list keys() const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
class tuple : public object {
|
||||
public:
|
||||
tuple() = default;
|
||||
tuple(const list &) {
|
||||
}
|
||||
};
|
||||
|
||||
class scope {
|
||||
public:
|
||||
explicit scope(const object &) {
|
||||
}
|
||||
|
||||
object::attr_proxy attr(const char *) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract {
|
||||
explicit extract(const object &) {
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
inline object import(const char *) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline int len(const list &) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void handle_exception() {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct borrowed_result {
|
||||
explicit borrowed_result(T *) {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct allow_null_result {
|
||||
explicit allow_null_result(T *) {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
borrowed_result<T> borrowed(T *value) {
|
||||
return borrowed_result<T>(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
allow_null_result<T> allow_null(T *value) {
|
||||
return allow_null_result<T>(value);
|
||||
}
|
||||
|
||||
template <typename T = void>
|
||||
class handle {
|
||||
public:
|
||||
template <typename U>
|
||||
explicit handle(const U &) {
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class str : public object {
|
||||
public:
|
||||
template <typename T>
|
||||
explicit str(const T &) {
|
||||
}
|
||||
|
||||
object join(const object &) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
10
core/wasm_shims/boost/python/object_fwd.hpp
Normal file
10
core/wasm_shims/boost/python/object_fwd.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
class object;
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
|
||||
4
core/wasm_shims/boost/python/scope.hpp
Normal file
4
core/wasm_shims/boost/python/scope.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
3
core/wasm_shims/boost/python/str.hpp
Normal file
3
core/wasm_shims/boost/python/str.hpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
3
core/wasm_shims/boost/python/tuple.hpp
Normal file
3
core/wasm_shims/boost/python/tuple.hpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
30
core/wasm_shims/dlfcn.cc
Normal file
30
core/wasm_shims/dlfcn.cc
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "dlfcn.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
|
||||
thread_local char last_error[128] = "dynamic loading is unavailable in wasm-safe probe";
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
void *dlopen(const char *, int) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *dlsym(void *, const char *) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char *dlerror(void) {
|
||||
return last_error;
|
||||
}
|
||||
|
||||
int dlclose(void *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
18
core/wasm_shims/dlfcn.h
Normal file
18
core/wasm_shims/dlfcn.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RTLD_GLOBAL 0x00100
|
||||
#define RTLD_NOW 0x00002
|
||||
|
||||
void *dlopen(const char *filename, int flags);
|
||||
void *dlsym(void *handle, const char *symbol);
|
||||
char *dlerror(void);
|
||||
int dlclose(void *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
4
core/wasm_shims/emc_status_shim.cc
Normal file
4
core/wasm_shims/emc_status_shim.cc
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "nml_intf/emc_nml.hh"
|
||||
|
||||
EMC_STAT *emcStatus = nullptr;
|
||||
|
||||
6
core/wasm_shims/gettext_shim.cc
Normal file
6
core/wasm_shims/gettext_shim.cc
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <cstddef>
|
||||
|
||||
extern "C" char *gettext(const char *msgid) {
|
||||
return const_cast<char *>(msgid ? msgid : "");
|
||||
}
|
||||
|
||||
7
core/wasm_shims/interp_base_probe_main.cc
Normal file
7
core/wasm_shims/interp_base_probe_main.cc
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "interp_base.hh"
|
||||
|
||||
int main() {
|
||||
InterpBase *interp = interp_from_shlib("nonexistent-interpreter.so");
|
||||
return interp == nullptr ? 0 : 1;
|
||||
}
|
||||
|
||||
40
core/wasm_shims/interp_find_probe_main.cc
Normal file
40
core/wasm_shims/interp_find_probe_main.cc
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "tooldata/tooldata.hh"
|
||||
#include "rs274ngc/rs274ngc_interp.hh"
|
||||
|
||||
int main() {
|
||||
if (tool_mmap_creator(nullptr, 1) != 0) {
|
||||
return 7;
|
||||
}
|
||||
tooldata_reset();
|
||||
|
||||
CANON_TOOL_TABLE spindle = tooldata_entry_init();
|
||||
spindle.toolno = 0;
|
||||
spindle.pocketno = 0;
|
||||
if (tooldata_put(spindle, 0) != IDX_OK) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
CANON_TOOL_TABLE tool = tooldata_entry_init();
|
||||
tool.toolno = 7;
|
||||
tool.pocketno = 12;
|
||||
if (tooldata_put(tool, 12) != IDX_NEW) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
int idx = -1;
|
||||
int pocket = -1;
|
||||
auto *interp = reinterpret_cast<Interp *>(0x1);
|
||||
if (interp->find_tool_index(nullptr, 7, &idx) != INTERP_OK) {
|
||||
return 3;
|
||||
}
|
||||
if (idx != 12) {
|
||||
return 4;
|
||||
}
|
||||
if (interp->find_tool_pocket(nullptr, 7, &pocket) != INTERP_OK) {
|
||||
return 5;
|
||||
}
|
||||
if (pocket != 12) {
|
||||
return 6;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
7
core/wasm_shims/interp_find_probe_stubs.cc
Normal file
7
core/wasm_shims/interp_find_probe_stubs.cc
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "rs274ngc/rs274ngc_interp.hh"
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
void Interp::setError(const char *, ...) {
|
||||
}
|
||||
|
||||
72
core/wasm_shims/linuxcnc_runtime_shim.cc
Normal file
72
core/wasm_shims/linuxcnc_runtime_shim.cc
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "boost/python/object.hpp"
|
||||
#include "hal.h"
|
||||
|
||||
int _task = 0;
|
||||
|
||||
extern "C" PyObject *PyInit_interpreter(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" PyObject *PyInit_emccanon(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
struct _inittab builtin_modules[] = {
|
||||
{"interpreter", PyInit_interpreter},
|
||||
{"emccanon", PyInit_emccanon},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
}
|
||||
|
||||
extern "C" int hal_init(const char *) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" int hal_ready(int) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int hal_get_pin_value_by_name(const char *,
|
||||
hal_type_t *type,
|
||||
hal_data_u **data,
|
||||
bool *connected) {
|
||||
if (type) {
|
||||
*type = HAL_TYPE_UNINITIALIZED;
|
||||
}
|
||||
if (data) {
|
||||
*data = nullptr;
|
||||
}
|
||||
if (connected) {
|
||||
*connected = false;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int hal_get_signal_value_by_name(const char *,
|
||||
hal_type_t *type,
|
||||
hal_data_u **data,
|
||||
bool *has_writers) {
|
||||
if (type) {
|
||||
*type = HAL_TYPE_UNINITIALIZED;
|
||||
}
|
||||
if (data) {
|
||||
*data = nullptr;
|
||||
}
|
||||
if (has_writers) {
|
||||
*has_writers = false;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int hal_get_param_value_by_name(const char *,
|
||||
hal_type_t *type,
|
||||
hal_data_u **data) {
|
||||
if (type) {
|
||||
*type = HAL_TYPE_UNINITIALIZED;
|
||||
}
|
||||
if (data) {
|
||||
*data = nullptr;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
76
core/wasm_shims/python_c_api_shim.cc
Normal file
76
core/wasm_shims/python_c_api_shim.cc
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
static PyTypeObject none_type = {"NoneType"};
|
||||
static PyObject none_object = {&none_type};
|
||||
|
||||
PyObject *PyExc_KeyError = reinterpret_cast<PyObject *>(1);
|
||||
PyObject *PyExc_StopIteration = reinterpret_cast<PyObject *>(2);
|
||||
PyObject *_Py_NoneStructPtr = &none_object;
|
||||
|
||||
int Py_IsInitialized(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyObject *PyErr_Occurred(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PyErr_Clear(void) {
|
||||
}
|
||||
|
||||
int PyErr_ExceptionMatches(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyCallable_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PyErr_Fetch(PyObject **exc, PyObject **val, PyObject **tb) {
|
||||
if (exc) {
|
||||
*exc = nullptr;
|
||||
}
|
||||
if (val) {
|
||||
*val = nullptr;
|
||||
}
|
||||
if (tb) {
|
||||
*tb = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PyErr_NormalizeException(PyObject **, PyObject **, PyObject **) {
|
||||
}
|
||||
|
||||
void PyErr_Print(void) {
|
||||
}
|
||||
|
||||
int PyUnicode_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyLong_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyFloat_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyGen_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyObject_Str(PyObject *) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
const char *PyUnicode_AsUTF8(PyObject *) {
|
||||
return "";
|
||||
}
|
||||
|
||||
void Py_DecRef(PyObject *) {
|
||||
}
|
||||
|
||||
}
|
||||
50
core/wasm_shims/pythonplugin/python_plugin.cc
Normal file
50
core/wasm_shims/pythonplugin/python_plugin.cc
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "pythonplugin/python_plugin.hh"
|
||||
|
||||
__attribute__((weak)) std::string handle_pyerror() {
|
||||
return "python disabled in wasm-safe probe";
|
||||
}
|
||||
|
||||
PythonPlugin *python_plugin = nullptr;
|
||||
|
||||
PythonPlugin *PythonPlugin::instantiate(struct _inittab *) {
|
||||
static PythonPlugin plugin;
|
||||
python_plugin = &plugin;
|
||||
python_plugin->status = PLUGIN_OK;
|
||||
return python_plugin;
|
||||
}
|
||||
|
||||
int PythonPlugin::configure(const char *, const char *) {
|
||||
status = PLUGIN_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
bool PythonPlugin::is_callable(const char *, const char *) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int PythonPlugin::call(const char *,
|
||||
const char *,
|
||||
boost::python::object,
|
||||
boost::python::object,
|
||||
boost::python::object &retval) {
|
||||
retval = boost::python::object();
|
||||
status = PLUGIN_NO_CALLABLE;
|
||||
return status;
|
||||
}
|
||||
|
||||
int PythonPlugin::run_string(const char *, boost::python::object &retval, bool) {
|
||||
retval = boost::python::object();
|
||||
status = PLUGIN_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
int PythonPlugin::call_method(boost::python::object, boost::python::object &retval) {
|
||||
retval = boost::python::object();
|
||||
status = PLUGIN_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
int PythonPlugin::initialize() {
|
||||
status = PLUGIN_OK;
|
||||
return status;
|
||||
}
|
||||
60
core/wasm_shims/pythonplugin/python_plugin.hh
Normal file
60
core/wasm_shims/pythonplugin/python_plugin.hh
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
extern std::string handle_pyerror();
|
||||
|
||||
enum pp_status {
|
||||
PLUGIN_NO_SECTION = -1,
|
||||
PLUGIN_NO_INIFILE = -2,
|
||||
PLUGIN_BAD_INIFILE = -3,
|
||||
PLUGIN_NO_TOPLEVEL = -4,
|
||||
PLUGIN_BAD_PATH = -5,
|
||||
PLUGIN_STAT_FAILED = -6,
|
||||
PLUGIN_INITTAB_FAILED = -7,
|
||||
PLUGIN_PYTHON_ALREADY_INITIALIZED = -8,
|
||||
PLUGIN_EXCEPTION_DURING_PATH_PREPEND = -9,
|
||||
PLUGIN_EXCEPTION_DURING_PATH_APPEND = -10,
|
||||
PLUGIN_INIT_EXCEPTION = -11,
|
||||
PLUGIN_PYTHON_NOT_INITIALIZED = -12,
|
||||
PLUGIN_PATH_TOO_LONG = -13,
|
||||
PLUGIN_OK = 0,
|
||||
PLUGIN_NO_CALLABLE = 1,
|
||||
PLUGIN_EXCEPTION = 2
|
||||
};
|
||||
|
||||
class PythonPlugin {
|
||||
public:
|
||||
static PythonPlugin *instantiate(struct _inittab *inittab = nullptr);
|
||||
int configure(const char *iniFilename = nullptr, const char *section = nullptr);
|
||||
bool is_callable(const char *module, const char *funcname);
|
||||
int call(const char *module,
|
||||
const char *callable,
|
||||
boost::python::object tupleargs,
|
||||
boost::python::object kwargs,
|
||||
boost::python::object &retval);
|
||||
int run_string(const char *cmd, boost::python::object &retval, bool as_file = false);
|
||||
int call_method(boost::python::object method, boost::python::object &retval);
|
||||
|
||||
int plugin_status() { return status; }
|
||||
bool usable() { return status >= PLUGIN_OK; }
|
||||
int initialize();
|
||||
const std::string &last_exception() { return exception_msg; }
|
||||
const std::string &last_errmsg() { return error_msg; }
|
||||
boost::python::object main_namespace;
|
||||
|
||||
private:
|
||||
PythonPlugin() = default;
|
||||
|
||||
int status = PLUGIN_OK;
|
||||
std::string exception_msg;
|
||||
std::string error_msg;
|
||||
int log_level = 0;
|
||||
};
|
||||
|
||||
extern PythonPlugin *python_plugin;
|
||||
|
||||
23
core/wasm_shims/pythonplugin/python_plugin_probe_main.cc
Normal file
23
core/wasm_shims/pythonplugin/python_plugin_probe_main.cc
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "pythonplugin/python_plugin.hh"
|
||||
|
||||
int main() {
|
||||
auto *plugin = PythonPlugin::instantiate(nullptr);
|
||||
if (!plugin) {
|
||||
return 1;
|
||||
}
|
||||
if (!plugin->usable()) {
|
||||
return 2;
|
||||
}
|
||||
boost::python::object retval;
|
||||
if (plugin->run_string("noop", retval, false) != PLUGIN_OK) {
|
||||
return 3;
|
||||
}
|
||||
if (plugin->is_callable(nullptr, "noop")) {
|
||||
return 4;
|
||||
}
|
||||
if (handle_pyerror().empty()) {
|
||||
return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
33
core/wasm_shims/rs274ngc_pre_probe_main.cc
Normal file
33
core/wasm_shims/rs274ngc_pre_probe_main.cc
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "canon_event_sink.h"
|
||||
#include "linuxcnc_canon_bridge.h"
|
||||
#include "linuxcnc_tooldata_fixture.h"
|
||||
#include "rs274ngc_interp.hh"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
int main() {
|
||||
cnc_sim_init_minimal_linuxcnc_tooldata();
|
||||
|
||||
CanonEventSink sink;
|
||||
cnc_sim_linuxcnc_set_canon_sink(&sink);
|
||||
|
||||
Interp interp;
|
||||
if (interp.init() != INTERP_OK) {
|
||||
return 1;
|
||||
}
|
||||
if (interp.sequence_number() != 0) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
const double start_x = sink.position().x;
|
||||
cnc_sim_linuxcnc_set_current_line(1);
|
||||
const int read_rc = interp.read("G91 G0 X1");
|
||||
if (read_rc != INTERP_OK) {
|
||||
return 3;
|
||||
}
|
||||
const int execute_rc = interp.execute();
|
||||
if (execute_rc != INTERP_OK && execute_rc != INTERP_EXECUTE_FINISH) {
|
||||
return 4;
|
||||
}
|
||||
return std::fabs(sink.position().x - (start_x + 1.0)) < 1e-9 ? 0 : 5;
|
||||
}
|
||||
11
core/wasm_shims/rtapi_compat.cc
Normal file
11
core/wasm_shims/rtapi_compat.cc
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
extern "C" int rtapi_snprintf(char *buf, unsigned long size, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
const int rc = std::vsnprintf(buf, static_cast<std::size_t>(size), fmt, ap);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
58
core/wasm_shims/tooldata/tooldata.hh
Normal file
58
core/wasm_shims/tooldata/tooldata.hh
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "nml_intf/canon.hh"
|
||||
#include "nml_intf/emc_nml.hh"
|
||||
|
||||
extern "C" {
|
||||
|
||||
typedef enum {
|
||||
IDX_OK = 0,
|
||||
IDX_NEW,
|
||||
IDX_FAIL,
|
||||
} toolidx_t;
|
||||
|
||||
typedef enum {
|
||||
DB_NOTUSED = 0,
|
||||
DB_ACTIVE,
|
||||
} tooldb_t;
|
||||
|
||||
typedef enum {
|
||||
SPINDLE_LOAD,
|
||||
SPINDLE_UNLOAD,
|
||||
TOOL_OFFSET,
|
||||
} tool_notify_t;
|
||||
|
||||
struct CANON_TOOL_TABLE tooldata_entry_init(void);
|
||||
toolidx_t tooldata_put(struct CANON_TOOL_TABLE tdata, int idx);
|
||||
toolidx_t tooldata_get(CANON_TOOL_TABLE *pdata, int idx);
|
||||
|
||||
void tooldata_init(bool random_tool_changer);
|
||||
void tooldata_reset(void);
|
||||
void tooldata_last_index_set(int idx);
|
||||
int tooldata_last_index_get(void);
|
||||
int tooldata_find_index_for_tool(int toolno);
|
||||
|
||||
void tooldata_format_toolline(int idx,
|
||||
bool ignore_zero_values,
|
||||
CANON_TOOL_TABLE tdata,
|
||||
char formatted_line[CANON_TOOL_ENTRY_LEN]);
|
||||
|
||||
void tooldata_add_init(int nonrandom_start_idx);
|
||||
int tooldata_read_entry(const char *input_line);
|
||||
|
||||
void tooldata_set_db(tooldb_t mode);
|
||||
int tooldata_load(const char *filename);
|
||||
int tooldata_save(const char *filename);
|
||||
int tool_mmap_creator(EMC_TOOL_STAT const *ptr, int random_toolchanger);
|
||||
int tool_mmap_user(void);
|
||||
void tool_mmap_close(void);
|
||||
bool tool_mmap_is_random_toolchanger(void);
|
||||
int tool_nml_register(CANON_TOOL_TABLE *tblptr);
|
||||
int tooldata_db_init(char progname_plus_args[], int random_toolchanger);
|
||||
int tooldata_db_notify(tool_notify_t ntype,
|
||||
int toolno,
|
||||
int pocketno,
|
||||
CANON_TOOL_TABLE tdata);
|
||||
int tooldata_db_getall(void);
|
||||
|
||||
} // extern "C"
|
||||
101
core/wasm_shims/tooldata/tooldata_common_probe_main.cc
Normal file
101
core/wasm_shims/tooldata/tooldata_common_probe_main.cc
Normal file
@@ -0,0 +1,101 @@
|
||||
#include "tooldata.hh"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
|
||||
std::string make_temp_template(const char *name) {
|
||||
const char *tmpdir = std::getenv("TMPDIR");
|
||||
std::string tmpl = std::string(tmpdir ? tmpdir : "/tmp") + "/" + name;
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
if (tool_mmap_user() != -1) {
|
||||
return 11;
|
||||
}
|
||||
if (tool_mmap_creator(nullptr, 1) != 0) {
|
||||
return 12;
|
||||
}
|
||||
if (tool_mmap_user() != 0) {
|
||||
return 13;
|
||||
}
|
||||
if (!tool_mmap_is_random_toolchanger()) {
|
||||
return 14;
|
||||
}
|
||||
|
||||
tooldata_init(true);
|
||||
tooldata_reset();
|
||||
tooldata_add_init(0);
|
||||
|
||||
if (tooldata_read_entry("T7 P12 Z3.5 D8 ;probe\n") != 12) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
CANON_TOOL_TABLE loaded = tooldata_entry_init();
|
||||
if (tooldata_get(&loaded, 12) != IDX_OK) {
|
||||
return 2;
|
||||
}
|
||||
if (loaded.toolno != 7 || loaded.pocketno != 12 ||
|
||||
loaded.offset.tran.z != 3.5 || loaded.diameter != 8.0 ||
|
||||
std::strcmp(loaded.comment, "probe") != 0) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
char line[CANON_TOOL_ENTRY_LEN] = {};
|
||||
tooldata_format_toolline(12, true, loaded, line);
|
||||
if (!std::strstr(line, "T7") || !std::strstr(line, "P12") ||
|
||||
!std::strstr(line, "D+8.000000") || !std::strstr(line, ";probe")) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
std::string path_template = make_temp_template("cnc_tooldata_common_probe_XXXXXX");
|
||||
std::vector<char> path(path_template.begin(), path_template.end());
|
||||
path.push_back('\0');
|
||||
const int fd = mkstemp(path.data());
|
||||
if (fd < 0) {
|
||||
return 5;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (tooldata_save(path.data()) != 0) {
|
||||
std::remove(path.data());
|
||||
return 6;
|
||||
}
|
||||
|
||||
tooldata_reset();
|
||||
if (tooldata_find_index_for_tool(7) != -1) {
|
||||
std::remove(path.data());
|
||||
return 7;
|
||||
}
|
||||
if (tooldata_load(path.data()) != 0) {
|
||||
std::remove(path.data());
|
||||
return 8;
|
||||
}
|
||||
std::remove(path.data());
|
||||
|
||||
if (tooldata_get(&loaded, 12) != IDX_OK || loaded.toolno != 7 ||
|
||||
loaded.pocketno != 12 || loaded.offset.tran.z != 3.5 ||
|
||||
loaded.diameter != 8.0) {
|
||||
return 9;
|
||||
}
|
||||
|
||||
tooldata_set_db(DB_ACTIVE);
|
||||
if (tooldata_load(path.data()) != -1) {
|
||||
return 10;
|
||||
}
|
||||
|
||||
tool_mmap_close();
|
||||
if (tool_mmap_user() != -1) {
|
||||
return 15;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
127
core/wasm_shims/tooldata/tooldata_mmap_backend.cc
Normal file
127
core/wasm_shims/tooldata/tooldata_mmap_backend.cc
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "tooldata.hh"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
|
||||
CANON_TOOL_TABLE tool_table[CANON_POCKETS_MAX];
|
||||
EMC_TOOL_STAT const *toolstat = nullptr;
|
||||
int last_index = 0;
|
||||
bool mmap_created = false;
|
||||
bool mmap_random_toolchanger = false;
|
||||
bool mmap_creator_called = false;
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
toolidx_t tooldata_put(CANON_TOOL_TABLE tdata, int idx) {
|
||||
if (!mmap_created) {
|
||||
return IDX_FAIL;
|
||||
}
|
||||
if (idx < 0 || idx >= CANON_POCKETS_MAX) {
|
||||
return IDX_FAIL;
|
||||
}
|
||||
|
||||
const toolidx_t result = idx > last_index ? IDX_NEW : IDX_OK;
|
||||
tool_table[idx] = tdata;
|
||||
if (idx > last_index) {
|
||||
last_index = idx;
|
||||
}
|
||||
if (idx == 0 && toolstat) {
|
||||
*(CANON_TOOL_TABLE *)(&toolstat->toolTableCurrent) = tdata;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
toolidx_t tooldata_get(CANON_TOOL_TABLE *pdata, int idx) {
|
||||
if (!mmap_created) {
|
||||
std::fprintf(stderr, "%5d tooldata_get() not mmapped BYE\n", getpid());
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!pdata || idx < 0 || idx >= CANON_POCKETS_MAX) {
|
||||
return IDX_FAIL;
|
||||
}
|
||||
*pdata = tool_table[idx];
|
||||
return IDX_OK;
|
||||
}
|
||||
|
||||
void tooldata_reset(void) {
|
||||
if (!mmap_created) {
|
||||
return;
|
||||
}
|
||||
|
||||
const CANON_TOOL_TABLE empty = tooldata_entry_init();
|
||||
for (int idx = 0; idx < CANON_POCKETS_MAX; ++idx) {
|
||||
tool_table[idx] = empty;
|
||||
}
|
||||
}
|
||||
|
||||
void tooldata_last_index_set(int idx) {
|
||||
if (!mmap_created) {
|
||||
return;
|
||||
}
|
||||
if (idx < 0 || idx >= CANON_POCKETS_MAX) {
|
||||
idx = 0;
|
||||
}
|
||||
last_index = idx;
|
||||
}
|
||||
|
||||
int tooldata_last_index_get(void) {
|
||||
if (!mmap_created) {
|
||||
return -1;
|
||||
}
|
||||
return last_index;
|
||||
}
|
||||
|
||||
int tooldata_find_index_for_tool(int toolno) {
|
||||
if (!mmap_created || toolno == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (!mmap_random_toolchanger && toolno == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int found = -1;
|
||||
for (int idx = 0; idx <= last_index && idx < CANON_POCKETS_MAX; ++idx) {
|
||||
if (tool_table[idx].toolno == toolno) {
|
||||
found = idx;
|
||||
if (idx != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
int tool_mmap_creator(EMC_TOOL_STAT const *ptr, int random_toolchanger) {
|
||||
if (mmap_creator_called) {
|
||||
std::fprintf(stderr, "Error: tool_mmap_creator already called BYE\n");
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
toolstat = ptr;
|
||||
mmap_creator_called = true;
|
||||
mmap_created = true;
|
||||
mmap_random_toolchanger = random_toolchanger;
|
||||
last_index = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tool_mmap_user(void) {
|
||||
return mmap_created ? 0 : -1;
|
||||
}
|
||||
|
||||
void tool_mmap_close(void) {
|
||||
mmap_created = false;
|
||||
mmap_random_toolchanger = false;
|
||||
toolstat = nullptr;
|
||||
last_index = 0;
|
||||
}
|
||||
|
||||
bool tool_mmap_is_random_toolchanger(void) {
|
||||
return mmap_random_toolchanger;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
340
core/wasm_shims/tooldata/tooldata_probe_main.cc
Normal file
340
core/wasm_shims/tooldata/tooldata_probe_main.cc
Normal file
@@ -0,0 +1,340 @@
|
||||
#include "tooldata/tooldata.hh"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
std::string make_temp_path(const char *name) {
|
||||
const char *tmpdir = std::getenv("TMPDIR");
|
||||
return std::string(tmpdir ? tmpdir : "/tmp") + "/" + name;
|
||||
}
|
||||
|
||||
class ScopedTempWorkdir {
|
||||
public:
|
||||
explicit ScopedTempWorkdir(const char *name_template) {
|
||||
cwd_fd_ = open(".", O_RDONLY);
|
||||
if (cwd_fd_ < 0) {
|
||||
return;
|
||||
}
|
||||
std::string path_template = make_temp_path(name_template);
|
||||
dir_buffer_.assign(path_template.begin(), path_template.end());
|
||||
dir_buffer_.push_back('\0');
|
||||
dir_ = mkdtemp(dir_buffer_.data());
|
||||
if (!dir_) {
|
||||
return;
|
||||
}
|
||||
if (chdir(dir_) != 0) {
|
||||
dir_ = nullptr;
|
||||
return;
|
||||
}
|
||||
ok_ = true;
|
||||
}
|
||||
|
||||
~ScopedTempWorkdir() {
|
||||
if (cwd_fd_ >= 0) {
|
||||
if (ok_) {
|
||||
fchdir(cwd_fd_);
|
||||
}
|
||||
close(cwd_fd_);
|
||||
}
|
||||
if (dir_) {
|
||||
rmdir(dir_);
|
||||
}
|
||||
}
|
||||
|
||||
bool ok() const {
|
||||
return ok_;
|
||||
}
|
||||
|
||||
private:
|
||||
int cwd_fd_ = -1;
|
||||
std::vector<char> dir_buffer_;
|
||||
char *dir_ = nullptr;
|
||||
bool ok_ = false;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
const pid_t creator_child = fork();
|
||||
if (creator_child < 0) {
|
||||
return 41;
|
||||
}
|
||||
if (creator_child == 0) {
|
||||
if (tool_mmap_creator(nullptr, 1) != 0) {
|
||||
_exit(42);
|
||||
}
|
||||
tool_mmap_creator(nullptr, 0);
|
||||
_exit(43);
|
||||
}
|
||||
int creator_status = 0;
|
||||
if (waitpid(creator_child, &creator_status, 0) != creator_child) {
|
||||
return 44;
|
||||
}
|
||||
if (!WIFEXITED(creator_status) || WEXITSTATUS(creator_status) == 0) {
|
||||
return 45;
|
||||
}
|
||||
|
||||
if (tool_mmap_user() != -1) {
|
||||
return 25;
|
||||
}
|
||||
CANON_TOOL_TABLE uncreated_tool = tooldata_entry_init();
|
||||
if (tooldata_put(uncreated_tool, 0) != IDX_FAIL) {
|
||||
return 27;
|
||||
}
|
||||
|
||||
const pid_t get_child = fork();
|
||||
if (get_child < 0) {
|
||||
return 46;
|
||||
}
|
||||
if (get_child == 0) {
|
||||
tooldata_get(&uncreated_tool, 0);
|
||||
_exit(47);
|
||||
}
|
||||
int get_status = 0;
|
||||
if (waitpid(get_child, &get_status, 0) != get_child) {
|
||||
return 48;
|
||||
}
|
||||
if (!WIFEXITED(get_status) || WEXITSTATUS(get_status) == 0) {
|
||||
return 38;
|
||||
}
|
||||
if (tooldata_last_index_get() != -1) {
|
||||
return 40;
|
||||
}
|
||||
if (tooldata_db_getall() != -1) {
|
||||
return 28;
|
||||
}
|
||||
std::string missing_db_program_with_arg_string =
|
||||
make_temp_path("cnc_tooldata_probe_missing_db_program arg");
|
||||
std::vector<char> missing_db_program_with_arg(
|
||||
missing_db_program_with_arg_string.begin(),
|
||||
missing_db_program_with_arg_string.end());
|
||||
missing_db_program_with_arg.push_back('\0');
|
||||
if (tooldata_db_init(missing_db_program_with_arg.data(), 1) != -1) {
|
||||
return 55;
|
||||
}
|
||||
const auto separator = missing_db_program_with_arg_string.find(' ');
|
||||
if (separator == std::string::npos || missing_db_program_with_arg[separator] != 0) {
|
||||
return 56;
|
||||
}
|
||||
std::string missing_db_program_string = make_temp_path("cnc_tooldata_probe_missing_db_program");
|
||||
std::vector<char> missing_db_program(
|
||||
missing_db_program_string.begin(),
|
||||
missing_db_program_string.end());
|
||||
missing_db_program.push_back('\0');
|
||||
if (tooldata_db_init(missing_db_program.data(), 1) != -1) {
|
||||
return 31;
|
||||
}
|
||||
char too_many_db_args[] = "/bin/true a b c d e f g h i";
|
||||
if (tooldata_db_init(too_many_db_args, 1) != -1) {
|
||||
return 32;
|
||||
}
|
||||
char non_db_program[] = "/bin/true";
|
||||
if (tooldata_db_init(non_db_program, 1) != -1) {
|
||||
return 33;
|
||||
}
|
||||
if (tool_nml_register(nullptr) != -1) {
|
||||
return 29;
|
||||
}
|
||||
alignas(EMC_TOOL_STAT) unsigned char toolstat_storage[sizeof(EMC_TOOL_STAT)] = {};
|
||||
auto *toolstat = reinterpret_cast<EMC_TOOL_STAT *>(toolstat_storage);
|
||||
if (tool_mmap_creator(toolstat, 1) != 0) {
|
||||
return 15;
|
||||
}
|
||||
if (tool_mmap_user() != 0) {
|
||||
return 26;
|
||||
}
|
||||
if (!tool_mmap_is_random_toolchanger()) {
|
||||
return 16;
|
||||
}
|
||||
tooldata_set_db(DB_ACTIVE);
|
||||
const std::string unavailable_db_path = make_temp_path("cnc_tooldata_probe_db_unavailable.tbl");
|
||||
if (tooldata_load(unavailable_db_path.c_str()) != -1) {
|
||||
return 30;
|
||||
}
|
||||
tooldata_set_db(DB_ACTIVE);
|
||||
tooldata_init(false);
|
||||
if (tooldata_save(nullptr) != 0) {
|
||||
return 34;
|
||||
}
|
||||
tooldata_set_db(DB_NOTUSED);
|
||||
tooldata_init(true);
|
||||
tooldata_reset();
|
||||
|
||||
CANON_TOOL_TABLE spindle = tooldata_entry_init();
|
||||
spindle.toolno = 0;
|
||||
spindle.pocketno = 0;
|
||||
if (tooldata_put(spindle, 0) != IDX_OK) {
|
||||
return 1;
|
||||
}
|
||||
if (toolstat->toolTableCurrent.toolno != 0 || toolstat->toolTableCurrent.pocketno != 0) {
|
||||
return 49;
|
||||
}
|
||||
|
||||
CANON_TOOL_TABLE tool = tooldata_entry_init();
|
||||
tool.toolno = 7;
|
||||
tool.pocketno = 12;
|
||||
tool.offset.tran.z = 3.5;
|
||||
tool.diameter = 8.0;
|
||||
std::strncpy(tool.comment, "probe", CANON_TOOL_COMMENT_SIZE - 1);
|
||||
if (tooldata_put(tool, 12) != IDX_NEW) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
CANON_TOOL_TABLE loaded = tooldata_entry_init();
|
||||
if (tooldata_get(&loaded, 12) != IDX_OK) {
|
||||
return 3;
|
||||
}
|
||||
if (loaded.toolno != 7 || loaded.pocketno != 12 || loaded.offset.tran.z != 3.5 || loaded.diameter != 8.0) {
|
||||
return 4;
|
||||
}
|
||||
char db_spindle_line[CANON_TOOL_ENTRY_LEN] = {};
|
||||
{
|
||||
ScopedTempWorkdir db_spindle_workdir("cnc_tooldata_probe_workdir.XXXXXX");
|
||||
if (!db_spindle_workdir.ok()) {
|
||||
return 35;
|
||||
}
|
||||
std::remove("./db_spindle.tbl");
|
||||
tooldata_set_db(DB_ACTIVE);
|
||||
if (tooldata_save(nullptr) != 0) {
|
||||
return 36;
|
||||
}
|
||||
FILE *db_spindle_fp = std::fopen("./db_spindle.tbl", "r");
|
||||
if (!db_spindle_fp) {
|
||||
return 37;
|
||||
}
|
||||
std::fread(db_spindle_line, 1, sizeof(db_spindle_line) - 1, db_spindle_fp);
|
||||
std::fclose(db_spindle_fp);
|
||||
std::remove("./db_spindle.tbl");
|
||||
tooldata_set_db(DB_NOTUSED);
|
||||
}
|
||||
if (!std::strstr(db_spindle_line, "T0") || std::strstr(db_spindle_line, "T7")) {
|
||||
return 38;
|
||||
}
|
||||
if (tooldata_find_index_for_tool(7) != 12) {
|
||||
return 5;
|
||||
}
|
||||
if (tooldata_find_index_for_tool(0) != 0) {
|
||||
return 6;
|
||||
}
|
||||
if (tooldata_find_index_for_tool(-1) != -1) {
|
||||
return 17;
|
||||
}
|
||||
|
||||
tooldata_init(false);
|
||||
if (tooldata_find_index_for_tool(0) != 0) {
|
||||
return 18;
|
||||
}
|
||||
tooldata_init(true);
|
||||
|
||||
tooldata_last_index_set(12);
|
||||
if (tooldata_last_index_get() != 12) {
|
||||
return 7;
|
||||
}
|
||||
if (tooldata_put(tool, -1) != IDX_FAIL) {
|
||||
return 50;
|
||||
}
|
||||
if (tooldata_put(tool, CANON_POCKETS_MAX) != IDX_FAIL) {
|
||||
return 51;
|
||||
}
|
||||
if (tooldata_last_index_get() != 12) {
|
||||
return 52;
|
||||
}
|
||||
if (tooldata_get(&loaded, -1) != IDX_FAIL) {
|
||||
return 53;
|
||||
}
|
||||
if (tooldata_get(&loaded, CANON_POCKETS_MAX) != IDX_FAIL) {
|
||||
return 54;
|
||||
}
|
||||
tooldata_last_index_set(CANON_POCKETS_MAX);
|
||||
if (tooldata_last_index_get() != 0) {
|
||||
return 24;
|
||||
}
|
||||
tooldata_last_index_set(12);
|
||||
|
||||
char line[CANON_TOOL_ENTRY_LEN] = {};
|
||||
tooldata_format_toolline(12, true, loaded, line);
|
||||
if (!std::strstr(line, "T7") || !std::strstr(line, "P12") || !std::strstr(line, "D+8.000000")) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
std::string path_template = make_temp_path("cnc_tooldata_probe_XXXXXX");
|
||||
std::vector<char> path(path_template.begin(), path_template.end());
|
||||
path.push_back('\0');
|
||||
const int fd = mkstemp(path.data());
|
||||
if (fd < 0) {
|
||||
return 9;
|
||||
}
|
||||
close(fd);
|
||||
tooldata_last_index_set(0);
|
||||
if (tooldata_save(path.data()) != 0) {
|
||||
std::remove(path.data());
|
||||
return 10;
|
||||
}
|
||||
|
||||
tooldata_reset();
|
||||
if (tooldata_find_index_for_tool(7) != -1) {
|
||||
std::remove(path.data());
|
||||
return 11;
|
||||
}
|
||||
if (tooldata_load(path.data()) != 0) {
|
||||
std::remove(path.data());
|
||||
return 12;
|
||||
}
|
||||
std::remove(path.data());
|
||||
|
||||
CANON_TOOL_TABLE reloaded = tooldata_entry_init();
|
||||
if (tooldata_get(&reloaded, 12) != IDX_OK) {
|
||||
return 13;
|
||||
}
|
||||
if (reloaded.toolno != 7 || reloaded.pocketno != 12 ||
|
||||
reloaded.offset.tran.z != 3.5 || reloaded.diameter != 8.0) {
|
||||
return 14;
|
||||
}
|
||||
|
||||
tooldata_init(false);
|
||||
std::string nonrandom_path_template = make_temp_path("cnc_tooldata_nonrandom_probe_XXXXXX");
|
||||
std::vector<char> nonrandom_path(nonrandom_path_template.begin(), nonrandom_path_template.end());
|
||||
nonrandom_path.push_back('\0');
|
||||
const int nonrandom_fd = mkstemp(nonrandom_path.data());
|
||||
if (nonrandom_fd < 0) {
|
||||
return 19;
|
||||
}
|
||||
FILE *nonrandom_fp = fdopen(nonrandom_fd, "w");
|
||||
if (!nonrandom_fp) {
|
||||
close(nonrandom_fd);
|
||||
std::remove(nonrandom_path.data());
|
||||
return 20;
|
||||
}
|
||||
std::fputs("T-1 P5 Z4.25\n", nonrandom_fp);
|
||||
std::fclose(nonrandom_fp);
|
||||
|
||||
if (tooldata_load(nonrandom_path.data()) != 0) {
|
||||
std::remove(nonrandom_path.data());
|
||||
return 21;
|
||||
}
|
||||
std::remove(nonrandom_path.data());
|
||||
|
||||
CANON_TOOL_TABLE nonrandom_spindle = tooldata_entry_init();
|
||||
if (tooldata_get(&nonrandom_spindle, 0) != IDX_OK) {
|
||||
return 22;
|
||||
}
|
||||
if (nonrandom_spindle.toolno != -1 || nonrandom_spindle.pocketno != 5 ||
|
||||
nonrandom_spindle.offset.tran.z != 4.25) {
|
||||
return 23;
|
||||
}
|
||||
|
||||
tool_mmap_close();
|
||||
if (tool_mmap_user() != -1) {
|
||||
return 39;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
47
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc
Normal file
47
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "tooldata.hh"
|
||||
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int MAX_DB_PROGRAM_ARGS = 10;
|
||||
bool db_live = false;
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
int tool_nml_register(CANON_TOOL_TABLE *tblptr) {
|
||||
return tblptr ? 0 : -1;
|
||||
}
|
||||
|
||||
int tooldata_db_init(char progname_plus_args[], int) {
|
||||
if (!progname_plus_args) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *saveptr = nullptr;
|
||||
char *program = strtok_r(progname_plus_args, " ", &saveptr);
|
||||
int argc = 0;
|
||||
for (char *token = program; token; token = strtok_r(nullptr, " ", &saveptr)) {
|
||||
++argc;
|
||||
if (argc >= MAX_DB_PROGRAM_ARGS) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!program || access(program, X_OK) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tooldata_db_notify(tool_notify_t, int, int, CANON_TOOL_TABLE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tooldata_db_getall(void) {
|
||||
return db_live ? 0 : -1;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
@@ -11,8 +11,8 @@ The browser calls only `cnc_sim_*` functions from `core/include/cnc_sim_api.h`.
|
||||
Test:
|
||||
|
||||
```bash
|
||||
g++ -std=c++17 -I core/include core/src/cnc_sim_api.cpp core/tests/cnc_sim_api_smoke.cpp -o /tmp/cnc_sim_api_smoke
|
||||
/tmp/cnc_sim_api_smoke
|
||||
g++ -std=c++17 -I core/include core/src/cnc_sim_api.cpp core/tests/cnc_sim_api_smoke.cpp -o ./cnc_sim_api_smoke
|
||||
./cnc_sim_api_smoke
|
||||
```
|
||||
|
||||
## Step 1: Temporary event parser
|
||||
@@ -102,8 +102,8 @@ Before porting `rs274ngc` sources to wasm, use the already-built native LinuxCNC
|
||||
|
||||
This builds `core/tools/linuxcnc_rs274_dump.cpp`, links LinuxCNC `librs274`, and writes:
|
||||
|
||||
- `/tmp/cnc_sim_linuxcnc_basic_motion.json`
|
||||
- `/tmp/cnc_sim_linuxcnc_basic_mill.json`
|
||||
- run-local output files under a per-run temporary `build_dir/outputs/`
|
||||
- example files: `cnc_sim_linuxcnc_basic_motion.json`, `cnc_sim_linuxcnc_basic_mill.json`
|
||||
|
||||
This is a native-only stepping stone. Once stable, the same event sink is used by the wasm build.
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ These are the first group to keep compiling while we peel away native-only depen
|
||||
- `interp_remap.cc`
|
||||
- `interp_setup.cc`
|
||||
- `interp_write.cc`
|
||||
- `inifile.cc`
|
||||
- `modal_state.cc`
|
||||
- `nurbs_additional_functions.cc`
|
||||
- `rs274ngc_pre.cc`
|
||||
@@ -64,7 +65,7 @@ These are not needed for the browser simulator ABI and should not be part of the
|
||||
|
||||
- Python/Boost.Python remap and named parameter hooks.
|
||||
- `dlopen`/`dlsym` interpreter loading in `interp_base.cc`.
|
||||
- mmap-backed `tooldata_mmap.cc`.
|
||||
- native mmap/filesystem storage in `tooldata_mmap.cc`.
|
||||
- persistent parameter file writes.
|
||||
- dynamic INI/HAL queries.
|
||||
|
||||
@@ -92,7 +93,9 @@ The next boundary is linking. Expected link risks:
|
||||
|
||||
- `PythonPlugin` and Boost.Python symbols from remap/named parameter paths.
|
||||
- Python module initialization symbols if the source backend reuses the existing builtin module setup.
|
||||
- `tooldata_*` implementations, currently mmap-backed in native LinuxCNC and unsuitable for wasm.
|
||||
- `tooldata_mmap.cc` native mmap/filesystem storage. `tooldata_common.cc` now
|
||||
remains in the wasm-safe core and links against browser-safe tooldata backend
|
||||
shims.
|
||||
- dynamic loader code in `interp_base.cc`.
|
||||
- parameter file persistence in `rs274ngc_pre.cc`.
|
||||
|
||||
@@ -112,13 +115,26 @@ and libraries for the dependencies that have not been replaced yet:
|
||||
- `libpyplugin` for Python remap and named-parameter hooks.
|
||||
- `liblinuxcncini` and `liblinuxcnchal` for INI/HAL named parameter paths.
|
||||
- `liblinuxcnc-uspace-posix` for `rtapi_*` user-space helpers.
|
||||
- `libtooldata` for the current mmap-backed native tool table.
|
||||
- `libtooldata` for the native source-link runner. The wasm-safe source probes
|
||||
instead compile LinuxCNC `tooldata_common.cc` with `tooldata_mmap_backend.cc`
|
||||
and `tooldata_runtime_stubs.cc`.
|
||||
|
||||
This is not wasm-ready yet, but it proves the simulator can own and compile the
|
||||
RS274 interpreter core sources directly. The next source-port boundary is to
|
||||
replace each support dependency with browser-safe shims instead of pulling in
|
||||
the LinuxCNC task, motion, HAL, and Python runtime layers.
|
||||
|
||||
The wasm-safe source manifest is `linuxcnc-rs274-wasm-source-files.txt`. The
|
||||
`rs274ngc_pre` wasm link and undefined-symbol probes read their LinuxCNC source
|
||||
list from that manifest so `inifile.cc`, `tooldata_common.cc`, and the
|
||||
interpreter sources stay on one source of truth.
|
||||
|
||||
When `CNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE=ON`, CMake also exposes
|
||||
`linuxcnc_rs274_wasm_safe_probe_objects` and the `EXCLUDE_FROM_ALL`
|
||||
`linuxcnc_rs274_wasm_safe_probe` executable. The executable mirrors the
|
||||
`rs274ngc_pre` shell link probe and is built only when explicitly requested, so
|
||||
the normal browser wasm artifact does not accidentally link the probe runtime.
|
||||
|
||||
The native runner used by this probe now recognizes simulator-owned control
|
||||
lines before handing code to LinuxCNC: `M428`, `M429`, `M430`, `G43.4`,
|
||||
`G43.5`, and `G49`. This keeps the direct runner aligned with the public
|
||||
|
||||
28
linuxcnc-rs274-wasm-source-files.txt
Normal file
28
linuxcnc-rs274-wasm-source-files.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
# LinuxCNC rs274 source subset for browser-safe source-link probing.
|
||||
# Format: group:path:note
|
||||
core:src/emc/rs274ngc/interp_arc.cc:arc geometry and canonical arc conversion
|
||||
core:src/emc/rs274ngc/interp_array.cc:block array initialization
|
||||
core:src/emc/rs274ngc/interp_base.cc:base interpreter interface; compile-safe with wasm dlfcn shim, runtime replacement still required
|
||||
core:src/emc/rs274ngc/interp_check.cc:error text and block checks
|
||||
core:src/emc/rs274ngc/interp_convert.cc:block-to-canon conversion
|
||||
core:src/emc/rs274ngc/interp_cycles.cc:canned cycles
|
||||
core:src/emc/rs274ngc/interp_execute.cc:execute parsed blocks
|
||||
core:src/emc/rs274ngc/interp_find.cc:geometry and tool lookup helpers; still depends on tooldata declarations
|
||||
core:src/emc/rs274ngc/interp_g7x.cc:lathe roughing cycles
|
||||
core:src/emc/rs274ngc/interp_inspection.cc:inspection helpers
|
||||
core:src/emc/rs274ngc/interp_internal.cc:internal setup and utility logic
|
||||
core:src/emc/rs274ngc/interp_inverse.cc:inverse time/feed helpers
|
||||
core:src/emc/rs274ngc/interp_queue.cc:canonical command queue
|
||||
core:src/emc/rs274ngc/interp_read.cc:line lexer/parser
|
||||
core:src/emc/rs274ngc/interp_setup.cc:setup initialization helpers; satisfied by wasm Boost.Python shim
|
||||
core:src/emc/rs274ngc/interp_write.cc:modal state writers
|
||||
core:src/emc/rs274ngc/modal_state.cc:state tag modal representation
|
||||
core:src/emc/rs274ngc/nurbs_additional_functions.cc:NURBS helpers
|
||||
core:src/emc/rs274ngc/interp_namedparams.cc:Python named-parameter hooks satisfied by wasm Boost.Python/Python C API shims
|
||||
core:src/emc/rs274ngc/interp_o_word.cc:O-word control flow and directory traversal; compile-safe with wasm shims
|
||||
core:src/emc/rs274ngc/interp_python.cc:Python remap support satisfied by wasm Python plugin shim
|
||||
core:src/emc/rs274ngc/interp_remap.cc:Python remap support satisfied by wasm Python plugin shim
|
||||
core:src/emc/rs274ngc/rs274ngc_pre.cc:Interp implementation covered by rs274ngc_pre link probe
|
||||
core:src/emc/tooldata/tooldata_common.cc:shared tool table parser/format logic linked with wasm-safe mmap backend
|
||||
core:src/emc/ini/inifile.cc:INI reader needed by rs274ngc_pre source-link probe
|
||||
blocked:src/emc/tooldata/tooldata_mmap.cc:native mmap implementation
|
||||
10
rs274ngc.var
10
rs274ngc.var
@@ -16,8 +16,8 @@
|
||||
5187 0.000000
|
||||
5188 0.000000
|
||||
5189 0.000000
|
||||
5210 0.000000
|
||||
5211 0.000000
|
||||
5210 1.000000
|
||||
5211 -1.000000
|
||||
5212 0.000000
|
||||
5213 0.000000
|
||||
5214 0.000000
|
||||
@@ -27,8 +27,8 @@
|
||||
5218 0.000000
|
||||
5219 0.000000
|
||||
5220 1.000000
|
||||
5221 0.000000
|
||||
5222 0.000000
|
||||
5221 0.015192
|
||||
5222 -1.041888
|
||||
5223 0.000000
|
||||
5224 0.000000
|
||||
5225 0.000000
|
||||
@@ -36,7 +36,7 @@
|
||||
5227 0.000000
|
||||
5228 0.000000
|
||||
5229 0.000000
|
||||
5230 0.000000
|
||||
5230 30.000000
|
||||
5241 0.000000
|
||||
5242 0.000000
|
||||
5243 0.000000
|
||||
|
||||
119
rs274ngc.var.bak
Normal file
119
rs274ngc.var.bak
Normal file
@@ -0,0 +1,119 @@
|
||||
5161 0.000000
|
||||
5162 0.000000
|
||||
5163 0.000000
|
||||
5164 0.000000
|
||||
5165 0.000000
|
||||
5166 0.000000
|
||||
5167 0.000000
|
||||
5168 0.000000
|
||||
5169 0.000000
|
||||
5181 0.000000
|
||||
5182 0.000000
|
||||
5183 0.000000
|
||||
5184 0.000000
|
||||
5185 0.000000
|
||||
5186 0.000000
|
||||
5187 0.000000
|
||||
5188 0.000000
|
||||
5189 0.000000
|
||||
5210 1.000000
|
||||
5211 -1.000000
|
||||
5212 0.000000
|
||||
5213 0.000000
|
||||
5214 0.000000
|
||||
5215 0.000000
|
||||
5216 0.000000
|
||||
5217 0.000000
|
||||
5218 0.000000
|
||||
5219 0.000000
|
||||
5220 1.000000
|
||||
5221 0.015192
|
||||
5222 -1.041888
|
||||
5223 0.000000
|
||||
5224 0.000000
|
||||
5225 0.000000
|
||||
5226 0.000000
|
||||
5227 0.000000
|
||||
5228 0.000000
|
||||
5229 0.000000
|
||||
5230 30.000000
|
||||
5241 0.000000
|
||||
5242 0.000000
|
||||
5243 0.000000
|
||||
5244 0.000000
|
||||
5245 0.000000
|
||||
5246 0.000000
|
||||
5247 0.000000
|
||||
5248 0.000000
|
||||
5249 0.000000
|
||||
5250 0.000000
|
||||
5261 0.000000
|
||||
5262 0.000000
|
||||
5263 0.000000
|
||||
5264 0.000000
|
||||
5265 0.000000
|
||||
5266 0.000000
|
||||
5267 0.000000
|
||||
5268 0.000000
|
||||
5269 0.000000
|
||||
5270 0.000000
|
||||
5281 0.000000
|
||||
5282 0.000000
|
||||
5283 0.000000
|
||||
5284 0.000000
|
||||
5285 0.000000
|
||||
5286 0.000000
|
||||
5287 0.000000
|
||||
5288 0.000000
|
||||
5289 0.000000
|
||||
5290 0.000000
|
||||
5301 0.000000
|
||||
5302 0.000000
|
||||
5303 0.000000
|
||||
5304 0.000000
|
||||
5305 0.000000
|
||||
5306 0.000000
|
||||
5307 0.000000
|
||||
5308 0.000000
|
||||
5309 0.000000
|
||||
5310 0.000000
|
||||
5321 0.000000
|
||||
5322 0.000000
|
||||
5323 0.000000
|
||||
5324 0.000000
|
||||
5325 0.000000
|
||||
5326 0.000000
|
||||
5327 0.000000
|
||||
5328 0.000000
|
||||
5329 0.000000
|
||||
5330 0.000000
|
||||
5341 0.000000
|
||||
5342 0.000000
|
||||
5343 0.000000
|
||||
5344 0.000000
|
||||
5345 0.000000
|
||||
5346 0.000000
|
||||
5347 0.000000
|
||||
5348 0.000000
|
||||
5349 0.000000
|
||||
5350 0.000000
|
||||
5361 0.000000
|
||||
5362 0.000000
|
||||
5363 0.000000
|
||||
5364 0.000000
|
||||
5365 0.000000
|
||||
5366 0.000000
|
||||
5367 0.000000
|
||||
5368 0.000000
|
||||
5369 0.000000
|
||||
5370 0.000000
|
||||
5381 0.000000
|
||||
5382 0.000000
|
||||
5383 0.000000
|
||||
5384 0.000000
|
||||
5385 0.000000
|
||||
5386 0.000000
|
||||
5387 0.000000
|
||||
5388 0.000000
|
||||
5389 0.000000
|
||||
5390 0.000000
|
||||
@@ -3,6 +3,61 @@ set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
missing_root=/tmp/does-not-exist-linuxcnc
|
||||
missing_root_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_missing_root.XXXXXX.log")
|
||||
grep -F 'exec 9>"${TMPDIR:-/tmp}/cnc_sim_rs274_source_link.lock"' test-linuxcnc-source-link.sh >/dev/null
|
||||
grep -F "flock 9" test-linuxcnc-source-link.sh >/dev/null
|
||||
grep -F 'exec 9>"${TMPDIR:-/tmp}/cnc_sim_linuxcnc_rs274_native.lock"' test-linuxcnc-rs274-native.sh >/dev/null
|
||||
grep -F "flock 9" test-linuxcnc-rs274-native.sh >/dev/null
|
||||
for script in \
|
||||
test-linuxcnc-bridge-native.sh \
|
||||
test-linuxcnc-rs274-native.sh \
|
||||
test-linuxcnc-api-native.sh; do
|
||||
if LINUXCNC_ROOT="$missing_root" "./$script" >"$missing_root_log" 2>&1; then
|
||||
echo "$script accepted missing LinuxCNC root: $missing_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing LinuxCNC root: $missing_root" "$missing_root_log" >/dev/null; then
|
||||
echo "$script did not report missing LinuxCNC root clearly" >&2
|
||||
sed -n '1,20p' "$missing_root_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$missing_root_log"
|
||||
|
||||
unknown_group_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_unknown_manifest_group.XXXXXX.txt")
|
||||
unknown_group_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_unknown_manifest_group.XXXXXX.log")
|
||||
printf 'bogus:src/emc/rs274ngc/interp_arc.cc:test unknown group\n' >"$unknown_group_manifest"
|
||||
for script in \
|
||||
test-linuxcnc-source-syntax.sh \
|
||||
test-linuxcnc-source-objects.sh \
|
||||
test-linuxcnc-source-link.sh; do
|
||||
if "./$script" "$unknown_group_manifest" >"$unknown_group_log" 2>&1; then
|
||||
echo "$script accepted unknown manifest group" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "unknown manifest group: bogus" "$unknown_group_log" >/dev/null; then
|
||||
echo "$script did not report unknown manifest group clearly" >&2
|
||||
sed -n '1,20p' "$unknown_group_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$unknown_group_manifest" "$unknown_group_log"
|
||||
|
||||
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_syntax_missing_source_manifest.XXXXXX.txt")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_native_syntax_missing_source.XXXXXX.log")
|
||||
printf 'core:src/emc/rs274ngc/does_not_exist.cc:test missing source\n' >"$missing_source_manifest"
|
||||
if ./test-linuxcnc-source-syntax.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "test-linuxcnc-source-syntax.sh accepted missing manifest file" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing manifest file: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then
|
||||
echo "test-linuxcnc-source-syntax.sh did not report missing manifest file clearly" >&2
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_source_manifest" "$missing_source_log"
|
||||
|
||||
./test-native.sh
|
||||
./test-linuxcnc-source-syntax.sh
|
||||
./test-linuxcnc-source-objects.sh
|
||||
|
||||
@@ -5,8 +5,14 @@ cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=${TMPDIR:-/tmp}/cnc_sim_native
|
||||
mkdir -p "$build_dir"
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_native.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
var_file="$build_dir/rs274ngc-api.var"
|
||||
cp "$linuxcnc_root/tests/halui/jogging/sim.var" "$var_file"
|
||||
|
||||
|
||||
@@ -5,8 +5,14 @@ cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=${TMPDIR:-/tmp}/cnc_sim_native
|
||||
mkdir -p "$build_dir"
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_native.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
"$cxx" -std=c++17 \
|
||||
-I core/include \
|
||||
|
||||
@@ -5,11 +5,23 @@ cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=${TMPDIR:-/tmp}/cnc_sim_native
|
||||
mkdir -p "$build_dir"
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_native.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
# The LinuxCNC rs274 backend path can bus-error when two dumps run concurrently.
|
||||
exec 9>"${TMPDIR:-/tmp}/cnc_sim_linuxcnc_rs274_native.lock"
|
||||
flock 9
|
||||
|
||||
var_file="$build_dir/rs274ngc.var"
|
||||
base_var_file="$build_dir/rs274ngc-base.var"
|
||||
ini_named_parameter_file="$(pwd)/tests/gcode/linuxcnc_ini_named_parameter.ini"
|
||||
output_dir="$build_dir/outputs"
|
||||
mkdir -p "$output_dir"
|
||||
cp "$linuxcnc_root/tests/halui/jogging/sim.var" "$base_var_file"
|
||||
cp "$base_var_file" "$var_file"
|
||||
|
||||
@@ -36,62 +48,65 @@ cp "$base_var_file" "$var_file"
|
||||
-lpython3.13 \
|
||||
-o "$build_dir/linuxcnc_rs274_dump"
|
||||
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_basic_motion.ngc >/tmp/cnc_sim_linuxcnc_basic_motion.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/basic_mill.ngc >/tmp/cnc_sim_linuxcnc_basic_mill.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_rtcp_controls.ngc >/tmp/cnc_sim_linuxcnc_rtcp_controls.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_spindle_direction.ngc >/tmp/cnc_sim_linuxcnc_spindle_direction.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_spindle_modes.ngc >/tmp/cnc_sim_linuxcnc_spindle_modes.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_spindle_orient.ngc >/tmp/cnc_sim_linuxcnc_spindle_orient.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_io_controls.ngc >/tmp/cnc_sim_linuxcnc_io_controls.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_override_controls.ngc >/tmp/cnc_sim_linuxcnc_override_controls.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_modal_state.ngc >/tmp/cnc_sim_linuxcnc_modal_state.json
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_modal_autorestore.ngc >/tmp/cnc_sim_linuxcnc_modal_autorestore.json
|
||||
if CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_modal_invalidate.ngc >/tmp/cnc_sim_linuxcnc_modal_invalidate.json 2>/tmp/cnc_sim_linuxcnc_modal_invalidate.err; then
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_basic_motion.ngc >"$output_dir/cnc_sim_linuxcnc_basic_motion.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/basic_mill.ngc >"$output_dir/cnc_sim_linuxcnc_basic_mill.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_rtcp_controls.ngc >"$output_dir/cnc_sim_linuxcnc_rtcp_controls.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_spindle_direction.ngc >"$output_dir/cnc_sim_linuxcnc_spindle_direction.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_spindle_modes.ngc >"$output_dir/cnc_sim_linuxcnc_spindle_modes.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_spindle_orient.ngc >"$output_dir/cnc_sim_linuxcnc_spindle_orient.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_io_controls.ngc >"$output_dir/cnc_sim_linuxcnc_io_controls.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_override_controls.ngc >"$output_dir/cnc_sim_linuxcnc_override_controls.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_modal_state.ngc >"$output_dir/cnc_sim_linuxcnc_modal_state.json"
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_modal_autorestore.ngc >"$output_dir/cnc_sim_linuxcnc_modal_autorestore.json"
|
||||
if CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_modal_invalidate.ngc >"$output_dir/cnc_sim_linuxcnc_modal_invalidate.json" 2>"$output_dir/cnc_sim_linuxcnc_modal_invalidate.err"; then
|
||||
echo "expected linuxcnc_modal_invalidate.ngc to fail" >&2
|
||||
exit 1
|
||||
fi
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_threading_sync.ngc >/tmp/cnc_sim_linuxcnc_threading_sync.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_threading_cycle.ngc >/tmp/cnc_sim_linuxcnc_threading_cycle.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_tool_number.ngc >/tmp/cnc_sim_linuxcnc_tool_number.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_program_stops.ngc >/tmp/cnc_sim_linuxcnc_program_stops.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coolant.ngc >/tmp/cnc_sim_linuxcnc_coolant.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_feed_modes.ngc >/tmp/cnc_sim_linuxcnc_feed_modes.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_motion_modes.ngc >/tmp/cnc_sim_linuxcnc_motion_modes.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_tool_length.ngc >/tmp/cnc_sim_linuxcnc_tool_length.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_dynamic_tool_length.ngc >/tmp/cnc_sim_linuxcnc_dynamic_tool_length.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycle.ngc >/tmp/cnc_sim_linuxcnc_canned_cycle.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycles_extended.ngc >/tmp/cnc_sim_linuxcnc_canned_cycles_extended.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycle_planes.ngc >/tmp/cnc_sim_linuxcnc_canned_cycle_planes.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_arc_planes.ngc >/tmp/cnc_sim_linuxcnc_arc_planes.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_arc_distance_modes.ngc >/tmp/cnc_sim_linuxcnc_arc_distance_modes.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_predefined_positions.ngc >/tmp/cnc_sim_linuxcnc_predefined_positions.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_machine_coordinates.ngc >/tmp/cnc_sim_linuxcnc_machine_coordinates.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_cutter_comp.ngc >/tmp/cnc_sim_linuxcnc_cutter_comp.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_comments.ngc >/tmp/cnc_sim_linuxcnc_comments.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_probe_no_error.ngc >/tmp/cnc_sim_linuxcnc_probe_no_error.json
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/smoke_oword_subprogram.ngc >/tmp/cnc_sim_linuxcnc_oword_subprogram.json
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_named_oword_subprogram.ngc >/tmp/cnc_sim_linuxcnc_named_oword_subprogram.json
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_oword_control_flow.ngc >/tmp/cnc_sim_linuxcnc_oword_control_flow.json
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_named_parameter_exists.ngc >/tmp/cnc_sim_linuxcnc_named_parameter_exists.json
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_indexed_parameters.ngc >/tmp/cnc_sim_linuxcnc_indexed_parameters.json
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_named_parameter_normalization.ngc >/tmp/cnc_sim_linuxcnc_named_parameter_normalization.json
|
||||
INI_FILE_NAME="$ini_named_parameter_file" CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_ini_named_parameter.ngc >/tmp/cnc_sim_linuxcnc_ini_named_parameter.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_threading_sync.ngc >"$output_dir/cnc_sim_linuxcnc_threading_sync.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_threading_cycle.ngc >"$output_dir/cnc_sim_linuxcnc_threading_cycle.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_tool_number.ngc >"$output_dir/cnc_sim_linuxcnc_tool_number.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_program_stops.ngc >"$output_dir/cnc_sim_linuxcnc_program_stops.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coolant.ngc >"$output_dir/cnc_sim_linuxcnc_coolant.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_feed_modes.ngc >"$output_dir/cnc_sim_linuxcnc_feed_modes.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_motion_modes.ngc >"$output_dir/cnc_sim_linuxcnc_motion_modes.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_tool_length.ngc >"$output_dir/cnc_sim_linuxcnc_tool_length.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_dynamic_tool_length.ngc >"$output_dir/cnc_sim_linuxcnc_dynamic_tool_length.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycle.ngc >"$output_dir/cnc_sim_linuxcnc_canned_cycle.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycles_extended.ngc >"$output_dir/cnc_sim_linuxcnc_canned_cycles_extended.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_canned_cycle_planes.ngc >"$output_dir/cnc_sim_linuxcnc_canned_cycle_planes.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_arc_planes.ngc >"$output_dir/cnc_sim_linuxcnc_arc_planes.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_arc_distance_modes.ngc >"$output_dir/cnc_sim_linuxcnc_arc_distance_modes.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_predefined_positions.ngc >"$output_dir/cnc_sim_linuxcnc_predefined_positions.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_machine_coordinates.ngc >"$output_dir/cnc_sim_linuxcnc_machine_coordinates.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_cutter_comp.ngc >"$output_dir/cnc_sim_linuxcnc_cutter_comp.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_comments.ngc >"$output_dir/cnc_sim_linuxcnc_comments.json"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_probe_no_error.ngc >"$output_dir/cnc_sim_linuxcnc_probe_no_error.json"
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/smoke_oword_subprogram.ngc >"$output_dir/cnc_sim_linuxcnc_oword_subprogram.json"
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_named_oword_subprogram.ngc >"$output_dir/cnc_sim_linuxcnc_named_oword_subprogram.json"
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_oword_control_flow.ngc >"$output_dir/cnc_sim_linuxcnc_oword_control_flow.json"
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_named_parameter_exists.ngc >"$output_dir/cnc_sim_linuxcnc_named_parameter_exists.json"
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_indexed_parameters.ngc >"$output_dir/cnc_sim_linuxcnc_indexed_parameters.json"
|
||||
CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_named_parameter_normalization.ngc >"$output_dir/cnc_sim_linuxcnc_named_parameter_normalization.json"
|
||||
INI_FILE_NAME="$ini_named_parameter_file" CNC_SIM_RS274_FILE_MODE=1 CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_ini_named_parameter.ngc >"$output_dir/cnc_sim_linuxcnc_ini_named_parameter.json"
|
||||
cp "$base_var_file" "$var_file"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_offsets.ngc >/tmp/cnc_sim_linuxcnc_coordinate_offsets.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_offsets.ngc >"$output_dir/cnc_sim_linuxcnc_coordinate_offsets.json"
|
||||
cp "$base_var_file" "$var_file"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_l20.ngc >/tmp/cnc_sim_linuxcnc_coordinate_l20.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_l20.ngc >"$output_dir/cnc_sim_linuxcnc_coordinate_l20.json"
|
||||
cp "$base_var_file" "$var_file"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_p0.ngc >/tmp/cnc_sim_linuxcnc_coordinate_p0.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_p0.ngc >"$output_dir/cnc_sim_linuxcnc_coordinate_p0.json"
|
||||
cp "$base_var_file" "$var_file"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_select_all.ngc >/tmp/cnc_sim_linuxcnc_coordinate_select_all.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_coordinate_select_all.ngc >"$output_dir/cnc_sim_linuxcnc_coordinate_select_all.json"
|
||||
cp "$base_var_file" "$var_file"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_g92_restore.ngc >/tmp/cnc_sim_linuxcnc_g92_restore.json
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_g92_restore.ngc >"$output_dir/cnc_sim_linuxcnc_g92_restore.json"
|
||||
cp "$base_var_file" "$var_file"
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_g52_offset.ngc >/tmp/cnc_sim_linuxcnc_g52_offset.json
|
||||
python3 - <<'PY'
|
||||
CNC_SIM_RS274_VAR="$var_file" "$build_dir/linuxcnc_rs274_dump" tests/gcode/linuxcnc_g52_offset.ngc >"$output_dir/cnc_sim_linuxcnc_g52_offset.json"
|
||||
CNC_SIM_RS274_NATIVE_OUTPUT_DIR="$output_dir" python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
OUTPUT_DIR = Path(os.environ["CNC_SIM_RS274_NATIVE_OUTPUT_DIR"])
|
||||
|
||||
def check(path, required):
|
||||
events = json.loads(Path(path).read_text())
|
||||
types = [event["type"] for event in events]
|
||||
@@ -103,11 +118,14 @@ def check(path, required):
|
||||
raise SystemExit(f"{path}: unexpected final XY position")
|
||||
return events
|
||||
|
||||
required_motion = {"set-units", "set-plane", "set-spindle", "rapid", "set-feed", "linear-feed", "arc-feed", "dwell", "program-end"}
|
||||
check("/tmp/cnc_sim_linuxcnc_basic_motion.json", required_motion)
|
||||
check("/tmp/cnc_sim_linuxcnc_basic_mill.json", required_motion | {"tool-change"})
|
||||
def load(name):
|
||||
return json.loads((OUTPUT_DIR / name).read_text())
|
||||
|
||||
controls = json.loads(Path("/tmp/cnc_sim_linuxcnc_rtcp_controls.json").read_text())
|
||||
required_motion = {"set-units", "set-plane", "set-spindle", "rapid", "set-feed", "linear-feed", "arc-feed", "dwell", "program-end"}
|
||||
check(OUTPUT_DIR / "cnc_sim_linuxcnc_basic_motion.json", required_motion)
|
||||
check(OUTPUT_DIR / "cnc_sim_linuxcnc_basic_mill.json", required_motion | {"tool-change"})
|
||||
|
||||
controls = load("cnc_sim_linuxcnc_rtcp_controls.json")
|
||||
kin = [event for event in controls if event["type"] == "kinematics-switch"]
|
||||
if [(event["reserved"], event["feed"]) for event in kin] != [(1, 1), (0, 0), (2, 1)]:
|
||||
raise SystemExit("unexpected kinematics switch sequence")
|
||||
@@ -115,7 +133,7 @@ rtcp = [event for event in controls if event["type"] == "rtcp-state"]
|
||||
if [(event["line"], event["tool"], event["feed"]) for event in rtcp] != [(3, 0, 0), (4, 7, 1)]:
|
||||
raise SystemExit("unexpected RTCP state sequence")
|
||||
|
||||
spindle = json.loads(Path("/tmp/cnc_sim_linuxcnc_spindle_direction.json").read_text())
|
||||
spindle = load("cnc_sim_linuxcnc_spindle_direction.json")
|
||||
spindle_states = [
|
||||
(event["line"], event["spindle"], event["reserved"])
|
||||
for event in spindle
|
||||
@@ -128,7 +146,7 @@ if (3, 1200, 2) not in spindle_states:
|
||||
if (4, 0, 0) not in spindle_states:
|
||||
raise SystemExit("missing M5 stopped spindle state")
|
||||
|
||||
spindle_modes = json.loads(Path("/tmp/cnc_sim_linuxcnc_spindle_modes.json").read_text())
|
||||
spindle_modes = load("cnc_sim_linuxcnc_spindle_modes.json")
|
||||
spindle_mode_states = [
|
||||
(event["line"], event["reserved"], event["feed"], event["tool"])
|
||||
for event in spindle_modes
|
||||
@@ -142,7 +160,7 @@ expected_spindle_mode_states = [
|
||||
if spindle_mode_states != expected_spindle_mode_states:
|
||||
raise SystemExit(f"unexpected G96/G97 spindle mode states: {spindle_mode_states!r}")
|
||||
|
||||
spindle_orient = json.loads(Path("/tmp/cnc_sim_linuxcnc_spindle_orient.json").read_text())
|
||||
spindle_orient = load("cnc_sim_linuxcnc_spindle_orient.json")
|
||||
if not any(
|
||||
event["type"] == "comment" and
|
||||
event["line"] == 2 and
|
||||
@@ -163,7 +181,7 @@ if not any(
|
||||
):
|
||||
raise SystemExit("missing M19 spindle orient wait state")
|
||||
|
||||
io_controls = json.loads(Path("/tmp/cnc_sim_linuxcnc_io_controls.json").read_text())
|
||||
io_controls = load("cnc_sim_linuxcnc_io_controls.json")
|
||||
io_states = [
|
||||
(event["line"], event["reserved"], event["tool"], event["feed"], event["arcTurns"], event["dwellSeconds"])
|
||||
for event in io_controls
|
||||
@@ -182,7 +200,7 @@ expected_io_states = [
|
||||
if io_states != expected_io_states:
|
||||
raise SystemExit(f"unexpected M62-M68 I/O states: {io_states!r}")
|
||||
|
||||
override_controls = json.loads(Path("/tmp/cnc_sim_linuxcnc_override_controls.json").read_text())
|
||||
override_controls = load("cnc_sim_linuxcnc_override_controls.json")
|
||||
override_states = [
|
||||
(event["line"], event["reserved"], event["tool"], event["feed"])
|
||||
for event in override_controls
|
||||
@@ -206,7 +224,7 @@ expected_override_states = [
|
||||
if override_states != expected_override_states:
|
||||
raise SystemExit(f"unexpected M48-M53 override states: {override_states!r}")
|
||||
|
||||
modal_state = json.loads(Path("/tmp/cnc_sim_linuxcnc_modal_state.json").read_text())
|
||||
modal_state = load("cnc_sim_linuxcnc_modal_state.json")
|
||||
if not any(
|
||||
event["type"] == "rapid" and
|
||||
event["line"] == 7 and
|
||||
@@ -226,7 +244,7 @@ if not any(
|
||||
):
|
||||
raise SystemExit("missing M72 restored XY plane arc")
|
||||
|
||||
modal_autorestore = json.loads(Path("/tmp/cnc_sim_linuxcnc_modal_autorestore.json").read_text())
|
||||
modal_autorestore = load("cnc_sim_linuxcnc_modal_autorestore.json")
|
||||
if not any(
|
||||
event["type"] == "rapid" and
|
||||
event["line"] == 9 and
|
||||
@@ -243,7 +261,7 @@ if not any(
|
||||
):
|
||||
raise SystemExit("missing M73 autorestored incremental caller move")
|
||||
|
||||
threading_sync = json.loads(Path("/tmp/cnc_sim_linuxcnc_threading_sync.json").read_text())
|
||||
threading_sync = load("cnc_sim_linuxcnc_threading_sync.json")
|
||||
sync_states = [
|
||||
(event["line"], event["reserved"], event["feed"], event["tool"])
|
||||
for event in threading_sync
|
||||
@@ -263,7 +281,7 @@ if not any(
|
||||
):
|
||||
raise SystemExit("missing G33.1 rigid tap motion line")
|
||||
|
||||
threading_cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_threading_cycle.json").read_text())
|
||||
threading_cycle = load("cnc_sim_linuxcnc_threading_cycle.json")
|
||||
if not any(
|
||||
event["type"] == "comment" and
|
||||
event["line"] == 4 and
|
||||
@@ -282,7 +300,7 @@ if not any(
|
||||
if not any(event["type"] == "program-end" and event["line"] == 5 for event in threading_cycle):
|
||||
raise SystemExit("missing G76 program end line number")
|
||||
|
||||
tool_number = json.loads(Path("/tmp/cnc_sim_linuxcnc_tool_number.json").read_text())
|
||||
tool_number = load("cnc_sim_linuxcnc_tool_number.json")
|
||||
if not any(
|
||||
event["type"] == "tool-change" and
|
||||
event["line"] == 2 and
|
||||
@@ -291,7 +309,7 @@ if not any(
|
||||
):
|
||||
raise SystemExit("missing M61 Q1 tool-number event line")
|
||||
|
||||
stops = json.loads(Path("/tmp/cnc_sim_linuxcnc_program_stops.json").read_text())
|
||||
stops = load("cnc_sim_linuxcnc_program_stops.json")
|
||||
stop_states = [
|
||||
(event["line"], event["reserved"])
|
||||
for event in stops
|
||||
@@ -301,7 +319,7 @@ for expected in [(2, 1), (3, 2), (4, 3), (4, 1), (5, 0)]:
|
||||
if expected not in stop_states:
|
||||
raise SystemExit(f"missing program stop state {expected!r}")
|
||||
|
||||
coolant = json.loads(Path("/tmp/cnc_sim_linuxcnc_coolant.json").read_text())
|
||||
coolant = load("cnc_sim_linuxcnc_coolant.json")
|
||||
coolant_states = [
|
||||
(event["line"], event["reserved"])
|
||||
for event in coolant
|
||||
@@ -311,7 +329,7 @@ for expected in [(2, 11), (3, 21), (4, 10), (4, 20)]:
|
||||
if expected not in coolant_states:
|
||||
raise SystemExit(f"missing coolant state {expected!r}")
|
||||
|
||||
feed_modes = json.loads(Path("/tmp/cnc_sim_linuxcnc_feed_modes.json").read_text())
|
||||
feed_modes = load("cnc_sim_linuxcnc_feed_modes.json")
|
||||
feed_mode_comments = [
|
||||
(event["line"], event["reserved"])
|
||||
for event in feed_modes
|
||||
@@ -329,7 +347,7 @@ for expected in [(3, 0), (4, 0)]:
|
||||
if expected not in feed_mode_events:
|
||||
raise SystemExit(f"missing feed mode event {expected!r}")
|
||||
|
||||
motion_modes = json.loads(Path("/tmp/cnc_sim_linuxcnc_motion_modes.json").read_text())
|
||||
motion_modes = load("cnc_sim_linuxcnc_motion_modes.json")
|
||||
motion_mode_states = [
|
||||
(event["line"], event["reserved"], event["feed"])
|
||||
for event in motion_modes
|
||||
@@ -339,7 +357,7 @@ for expected in [(2, 611, 0), (3, 612, 0), (4, 640, 0.05)]:
|
||||
if expected not in motion_mode_states:
|
||||
raise SystemExit(f"missing motion mode state {expected!r}")
|
||||
|
||||
tool_length = json.loads(Path("/tmp/cnc_sim_linuxcnc_tool_length.json").read_text())
|
||||
tool_length = load("cnc_sim_linuxcnc_tool_length.json")
|
||||
if not any(
|
||||
event["type"] == "comment" and
|
||||
event["line"] == 2 and
|
||||
@@ -357,7 +375,7 @@ if not any(
|
||||
):
|
||||
raise SystemExit("missing G49 tool length clear event")
|
||||
|
||||
dynamic_tool_length = json.loads(Path("/tmp/cnc_sim_linuxcnc_dynamic_tool_length.json").read_text())
|
||||
dynamic_tool_length = load("cnc_sim_linuxcnc_dynamic_tool_length.json")
|
||||
dynamic_offsets = [
|
||||
(event["line"], event["start"]["x"], event["start"]["z"])
|
||||
for event in dynamic_tool_length
|
||||
@@ -367,7 +385,7 @@ expected_dynamic_offsets = [(2, 1, 2), (3, 1.25, 2.5), (4, 1.25, 15), (5, 0, 0)]
|
||||
if dynamic_offsets != expected_dynamic_offsets:
|
||||
raise SystemExit(f"unexpected G43.1/G43.2 tool length offsets: {dynamic_offsets!r}")
|
||||
|
||||
cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_canned_cycle.json").read_text())
|
||||
cycle = load("cnc_sim_linuxcnc_canned_cycle.json")
|
||||
motions = [event for event in cycle if event["type"] in {"rapid", "linear-feed"}]
|
||||
expected_cycle = [
|
||||
("rapid", 0, 0, 5),
|
||||
@@ -380,7 +398,7 @@ actual_cycle = [(event["type"], event["end"]["x"], event["end"]["y"], event["end
|
||||
if actual_cycle != expected_cycle:
|
||||
raise SystemExit(f"unexpected G81/G80 expansion: {actual_cycle!r}")
|
||||
|
||||
cycle_planes = json.loads(Path("/tmp/cnc_sim_linuxcnc_canned_cycle_planes.json").read_text())
|
||||
cycle_planes = load("cnc_sim_linuxcnc_canned_cycle_planes.json")
|
||||
if not any(
|
||||
event["type"] == "linear-feed" and
|
||||
event["line"] == 4 and
|
||||
@@ -526,7 +544,7 @@ expected_plane_g87_sequence = [
|
||||
if plane_g87_sequence != expected_plane_g87_sequence:
|
||||
raise SystemExit(f"unexpected G19 G87 plane sequence: {plane_g87_sequence!r}")
|
||||
|
||||
extended_cycle = json.loads(Path("/tmp/cnc_sim_linuxcnc_canned_cycles_extended.json").read_text())
|
||||
extended_cycle = load("cnc_sim_linuxcnc_canned_cycles_extended.json")
|
||||
if not any(
|
||||
event["type"] == "linear-feed" and
|
||||
event["line"] == 3 and
|
||||
@@ -653,7 +671,7 @@ expected_g87_sequence = [
|
||||
if g87_sequence != expected_g87_sequence:
|
||||
raise SystemExit(f"unexpected G87 back-boring sequence: {g87_sequence!r}")
|
||||
|
||||
arc_planes = json.loads(Path("/tmp/cnc_sim_linuxcnc_arc_planes.json").read_text())
|
||||
arc_planes = load("cnc_sim_linuxcnc_arc_planes.json")
|
||||
if not any(
|
||||
event["type"] == "arc-feed" and
|
||||
event["line"] == 5 and
|
||||
@@ -683,7 +701,7 @@ if not any(
|
||||
):
|
||||
raise SystemExit("missing G19 YZ plane arc-feed mapping")
|
||||
|
||||
arc_distance = json.loads(Path("/tmp/cnc_sim_linuxcnc_arc_distance_modes.json").read_text())
|
||||
arc_distance = load("cnc_sim_linuxcnc_arc_distance_modes.json")
|
||||
arc_centers = [
|
||||
(event["line"], event["center"]["x"], event["center"]["y"])
|
||||
for event in arc_distance
|
||||
@@ -693,7 +711,7 @@ expected_arc_centers = [(5, 5, 0), (7, 15, 0), (9, 25, 0)]
|
||||
if arc_centers != expected_arc_centers:
|
||||
raise SystemExit(f"unexpected G90.1/G91.1 arc centers: {arc_centers!r}")
|
||||
|
||||
predefined = json.loads(Path("/tmp/cnc_sim_linuxcnc_predefined_positions.json").read_text())
|
||||
predefined = load("cnc_sim_linuxcnc_predefined_positions.json")
|
||||
predefined_rapids = [
|
||||
(
|
||||
event["line"],
|
||||
@@ -712,7 +730,7 @@ expected_predefined_rapids = [
|
||||
if predefined_rapids != expected_predefined_rapids:
|
||||
raise SystemExit(f"unexpected G28/G30 rapid sequence: {predefined_rapids!r}")
|
||||
|
||||
machine_coords = json.loads(Path("/tmp/cnc_sim_linuxcnc_machine_coordinates.json").read_text())
|
||||
machine_coords = load("cnc_sim_linuxcnc_machine_coordinates.json")
|
||||
machine_moves = [
|
||||
(
|
||||
event["type"], event["line"],
|
||||
@@ -730,7 +748,7 @@ expected_machine_moves = [
|
||||
if machine_moves != expected_machine_moves:
|
||||
raise SystemExit(f"unexpected G53 machine-coordinate moves: {machine_moves!r}")
|
||||
|
||||
cutter_comp = json.loads(Path("/tmp/cnc_sim_linuxcnc_cutter_comp.json").read_text())
|
||||
cutter_comp = load("cnc_sim_linuxcnc_cutter_comp.json")
|
||||
cutter_comp_motions = [
|
||||
event
|
||||
for event in cutter_comp
|
||||
@@ -758,11 +776,11 @@ actual_cutter_comp = [
|
||||
if actual_cutter_comp != expected_cutter_comp:
|
||||
raise SystemExit(f"unexpected cutter compensation path: {actual_cutter_comp!r}")
|
||||
|
||||
comments = json.loads(Path("/tmp/cnc_sim_linuxcnc_comments.json").read_text())
|
||||
comments = load("cnc_sim_linuxcnc_comments.json")
|
||||
if not any(event["type"] == "comment" and event["line"] == 2 for event in comments):
|
||||
raise SystemExit("missing LinuxCNC comment line event")
|
||||
|
||||
probe = json.loads(Path("/tmp/cnc_sim_linuxcnc_probe_no_error.json").read_text())
|
||||
probe = load("cnc_sim_linuxcnc_probe_no_error.json")
|
||||
probe_events = [
|
||||
(event["line"], event["reserved"], event["start"]["z"], event["end"]["z"])
|
||||
for event in probe
|
||||
@@ -787,7 +805,7 @@ if not any(
|
||||
):
|
||||
raise SystemExit("missing #5070 probe-tripped conditional motion")
|
||||
|
||||
oword = json.loads(Path("/tmp/cnc_sim_linuxcnc_oword_subprogram.json").read_text())
|
||||
oword = load("cnc_sim_linuxcnc_oword_subprogram.json")
|
||||
if not any(
|
||||
event["type"] == "linear-feed" and
|
||||
event["line"] == 8 and
|
||||
@@ -812,7 +830,7 @@ if any(
|
||||
):
|
||||
raise SystemExit("LinuxCNC O-word return should skip remaining subprogram body")
|
||||
|
||||
named_oword = json.loads(Path("/tmp/cnc_sim_linuxcnc_named_oword_subprogram.json").read_text())
|
||||
named_oword = load("cnc_sim_linuxcnc_named_oword_subprogram.json")
|
||||
if not any(
|
||||
event["type"] == "linear-feed" and
|
||||
event["line"] == 9 and
|
||||
@@ -845,7 +863,7 @@ if any(
|
||||
):
|
||||
raise SystemExit("LinuxCNC named O-word return should skip remaining subprogram body")
|
||||
|
||||
oword_flow = json.loads(Path("/tmp/cnc_sim_linuxcnc_oword_control_flow.json").read_text())
|
||||
oword_flow = load("cnc_sim_linuxcnc_oword_control_flow.json")
|
||||
if not any(event["type"] == "linear-feed" and event["line"] == 7 and event["end"]["x"] == 2 for event in oword_flow):
|
||||
raise SystemExit("missing LinuxCNC O-word elseif branch motion")
|
||||
if any(
|
||||
@@ -910,7 +928,7 @@ if not any(
|
||||
):
|
||||
raise SystemExit("missing LinuxCNC O-word do/continue skipped-body counter motion")
|
||||
|
||||
exists = json.loads(Path("/tmp/cnc_sim_linuxcnc_named_parameter_exists.json").read_text())
|
||||
exists = load("cnc_sim_linuxcnc_named_parameter_exists.json")
|
||||
exists_moves = [
|
||||
(event["line"], event["end"]["x"], event["end"]["y"])
|
||||
for event in exists
|
||||
@@ -920,7 +938,7 @@ expected_exists_moves = [(5, 1, 0), (8, 1, 1)]
|
||||
if exists_moves != expected_exists_moves:
|
||||
raise SystemExit(f"unexpected LinuxCNC EXISTS named parameter branch motions: {exists_moves!r}")
|
||||
|
||||
indexed = json.loads(Path("/tmp/cnc_sim_linuxcnc_indexed_parameters.json").read_text())
|
||||
indexed = load("cnc_sim_linuxcnc_indexed_parameters.json")
|
||||
indexed_moves = [
|
||||
(
|
||||
event["line"],
|
||||
@@ -947,7 +965,7 @@ expected_indexed_moves = [
|
||||
if indexed_moves != expected_indexed_moves:
|
||||
raise SystemExit(f"unexpected LinuxCNC indexed/indirect parameter motions: {indexed_moves!r}")
|
||||
|
||||
normalized = json.loads(Path("/tmp/cnc_sim_linuxcnc_named_parameter_normalization.json").read_text())
|
||||
normalized = load("cnc_sim_linuxcnc_named_parameter_normalization.json")
|
||||
normalized_moves = [
|
||||
(event["line"], event["end"]["x"], event["end"]["y"])
|
||||
for event in normalized
|
||||
@@ -957,7 +975,7 @@ expected_normalized_moves = [(4, 12, 0), (6, 12, 1)]
|
||||
if normalized_moves != expected_normalized_moves:
|
||||
raise SystemExit(f"unexpected LinuxCNC normalized named parameter motions: {normalized_moves!r}")
|
||||
|
||||
ini_named = json.loads(Path("/tmp/cnc_sim_linuxcnc_ini_named_parameter.json").read_text())
|
||||
ini_named = load("cnc_sim_linuxcnc_ini_named_parameter.json")
|
||||
ini_named_moves = [
|
||||
(event["line"], event["end"]["x"], event["end"]["y"])
|
||||
for event in ini_named
|
||||
@@ -967,7 +985,7 @@ expected_ini_named_moves = [(3, 3.25, 0), (5, 3.25, 1)]
|
||||
if ini_named_moves != expected_ini_named_moves:
|
||||
raise SystemExit(f"unexpected LinuxCNC INI named parameter motions: {ini_named_moves!r}")
|
||||
|
||||
coords = json.loads(Path("/tmp/cnc_sim_linuxcnc_coordinate_offsets.json").read_text())
|
||||
coords = load("cnc_sim_linuxcnc_coordinate_offsets.json")
|
||||
g5x = [event for event in coords if event["type"] == "set-g5x-offset"]
|
||||
g92 = [event for event in coords if event["type"] == "set-g92-offset"]
|
||||
rot = [event for event in coords if event["type"] == "set-xy-rotation"]
|
||||
@@ -993,7 +1011,7 @@ if not any(
|
||||
if not any(event["type"] == "program-end" and event["line"] == 5 for event in coords):
|
||||
raise SystemExit("missing coordinate program end line number")
|
||||
|
||||
l20 = json.loads(Path("/tmp/cnc_sim_linuxcnc_coordinate_l20.json").read_text())
|
||||
l20 = load("cnc_sim_linuxcnc_coordinate_l20.json")
|
||||
if not any(
|
||||
event["type"] == "set-g5x-offset" and
|
||||
event["line"] == 4 and
|
||||
@@ -1007,7 +1025,7 @@ if not any(
|
||||
if not any(event["type"] == "program-end" and event["line"] == 5 for event in l20):
|
||||
raise SystemExit("missing G10 L20 program end line number")
|
||||
|
||||
p0 = json.loads(Path("/tmp/cnc_sim_linuxcnc_coordinate_p0.json").read_text())
|
||||
p0 = load("cnc_sim_linuxcnc_coordinate_p0.json")
|
||||
if not any(
|
||||
event["type"] == "set-g5x-offset" and
|
||||
event["line"] == 3 and
|
||||
@@ -1021,7 +1039,7 @@ if not any(
|
||||
if not any(event["type"] == "program-end" and event["line"] == 4 for event in p0):
|
||||
raise SystemExit("missing G10 P0 program end line number")
|
||||
|
||||
select_all = json.loads(Path("/tmp/cnc_sim_linuxcnc_coordinate_select_all.json").read_text())
|
||||
select_all = load("cnc_sim_linuxcnc_coordinate_select_all.json")
|
||||
select_events = [
|
||||
(event["line"], event["tool"], event["start"]["x"])
|
||||
for event in select_all
|
||||
@@ -1041,7 +1059,7 @@ expected_select_events = [
|
||||
if select_events != expected_select_events:
|
||||
raise SystemExit(f"unexpected G54-G59.3 selection events: {select_events!r}")
|
||||
|
||||
g92_restore = json.loads(Path("/tmp/cnc_sim_linuxcnc_g92_restore.json").read_text())
|
||||
g92_restore = load("cnc_sim_linuxcnc_g92_restore.json")
|
||||
g92_states = [
|
||||
(event["line"], event["start"]["x"], event["start"]["y"], event["start"]["z"])
|
||||
for event in g92_restore
|
||||
@@ -1059,7 +1077,7 @@ if g92_states != expected_g92_states:
|
||||
if not any(event["type"] == "program-end" and event["line"] == 7 for event in g92_restore):
|
||||
raise SystemExit("missing G92 restore program end line number")
|
||||
|
||||
g52_offset = json.loads(Path("/tmp/cnc_sim_linuxcnc_g52_offset.json").read_text())
|
||||
g52_offset = load("cnc_sim_linuxcnc_g52_offset.json")
|
||||
g52_states = [
|
||||
(event["line"], event["start"]["x"], event["start"]["y"], event["start"]["z"])
|
||||
for event in g52_offset
|
||||
@@ -1079,45 +1097,45 @@ if not any(event["type"] == "program-end" and event["line"] == 7 for event in g5
|
||||
PY
|
||||
|
||||
echo "linuxcnc rs274 native smoke passed"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_basic_motion.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_basic_mill.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_rtcp_controls.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_spindle_direction.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_spindle_modes.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_spindle_orient.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_io_controls.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_override_controls.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_modal_state.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_modal_autorestore.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_threading_sync.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_threading_cycle.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_tool_number.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_program_stops.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_coolant.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_feed_modes.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_motion_modes.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_tool_length.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_dynamic_tool_length.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_canned_cycle.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_canned_cycles_extended.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_canned_cycle_planes.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_arc_planes.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_arc_distance_modes.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_predefined_positions.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_machine_coordinates.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_cutter_comp.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_comments.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_probe_no_error.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_oword_subprogram.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_named_oword_subprogram.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_oword_control_flow.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_named_parameter_exists.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_indexed_parameters.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_named_parameter_normalization.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_ini_named_parameter.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_offsets.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_l20.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_p0.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_coordinate_select_all.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_g92_restore.json"
|
||||
echo "dumped /tmp/cnc_sim_linuxcnc_g52_offset.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_basic_motion.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_basic_mill.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_rtcp_controls.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_spindle_direction.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_spindle_modes.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_spindle_orient.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_io_controls.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_override_controls.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_modal_state.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_modal_autorestore.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_threading_sync.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_threading_cycle.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_tool_number.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_program_stops.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_coolant.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_feed_modes.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_motion_modes.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_tool_length.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_dynamic_tool_length.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_canned_cycle.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_canned_cycles_extended.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_canned_cycle_planes.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_arc_planes.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_arc_distance_modes.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_predefined_positions.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_machine_coordinates.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_cutter_comp.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_comments.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_probe_no_error.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_oword_subprogram.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_named_oword_subprogram.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_oword_control_flow.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_named_parameter_exists.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_indexed_parameters.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_named_parameter_normalization.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_ini_named_parameter.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_coordinate_offsets.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_coordinate_l20.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_coordinate_p0.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_coordinate_select_all.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_g92_restore.json"
|
||||
echo "dumped $output_dir/cnc_sim_linuxcnc_g52_offset.json"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,11 +5,21 @@ cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=${TMPDIR:-/tmp}/cnc_sim_rs274_objects
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_rs274_objects.XXXXXX")
|
||||
python_includes=$(python3.13-config --includes 2>/dev/null || python3-config --includes)
|
||||
manifest=${1:-linuxcnc-rs274-source-files.txt}
|
||||
|
||||
rm -rf "$build_dir"
|
||||
mkdir -p "$build_dir"
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
@@ -27,6 +37,10 @@ sources=()
|
||||
while IFS=: read -r group path note; do
|
||||
case "$group" in
|
||||
core)
|
||||
if [[ ! -f "$linuxcnc_root/$path" ]]; then
|
||||
echo "missing manifest file: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
sources+=("$path")
|
||||
;;
|
||||
""|\#*|binding|tooldata)
|
||||
@@ -36,14 +50,15 @@ while IFS=: read -r group path note; do
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done < linuxcnc-rs274-source-files.txt
|
||||
done < "$manifest"
|
||||
|
||||
source_index=0
|
||||
for source in "${sources[@]}"; do
|
||||
obj="$build_dir/$(basename "$source" .cc).o"
|
||||
obj="$build_dir/linuxcnc_${source_index}.o"
|
||||
# shellcheck disable=SC2086
|
||||
"$cxx" "${common_flags[@]}" $python_includes -c "$linuxcnc_root/$source" -o "$obj"
|
||||
source_index=$((source_index + 1))
|
||||
done
|
||||
|
||||
echo "linuxcnc rs274 source object build passed (${#sources[@]} objects)"
|
||||
echo "built objects in $build_dir"
|
||||
|
||||
|
||||
@@ -6,16 +6,58 @@ cd "$(dirname "$0")"
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
python_includes=$(python3.13-config --includes 2>/dev/null || python3-config --includes)
|
||||
manifest=${1:-linuxcnc-rs274-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS=: read -r group path note; do
|
||||
case "$group" in
|
||||
""|\#*) continue ;;
|
||||
""|\#*)
|
||||
continue
|
||||
;;
|
||||
core|binding|tooldata)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest group: $group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if [[ ! -f "$linuxcnc_root/$path" ]]; then
|
||||
echo "missing manifest file: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
done < linuxcnc-rs274-source-files.txt
|
||||
done < "$manifest"
|
||||
|
||||
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_rs274_manifest_source.XXXXXX.txt")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_rs274_manifest_source.XXXXXX.log")
|
||||
printf 'core:src/emc/rs274ngc/does_not_exist.cc:test missing source\n' >"$missing_source_manifest"
|
||||
if ./test-linuxcnc-source-objects.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "linuxcnc source object probe accepted missing manifest file" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing manifest file: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then
|
||||
echo "linuxcnc source object probe did not report missing manifest file clearly" >&2
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ./test-linuxcnc-source-link.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "linuxcnc source link probe accepted missing manifest file" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing manifest file: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then
|
||||
echo "linuxcnc source link probe did not report missing manifest file clearly" >&2
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_source_manifest" "$missing_source_log"
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
@@ -45,4 +87,3 @@ for source in "${probe_sources[@]}"; do
|
||||
done
|
||||
|
||||
echo "linuxcnc rs274 source syntax probe passed"
|
||||
|
||||
|
||||
50
test-linuxcnc-wasm-blockers.sh
Executable file
50
test-linuxcnc-wasm-blockers.sh
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
|
||||
missing_root=/tmp/does-not-exist-linuxcnc
|
||||
missing_root_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_blocker_missing_root.XXXXXX.log")
|
||||
if LINUXCNC_ROOT="$missing_root" ./analyze-linuxcnc-wasm-blockers.sh "$manifest" >"$missing_root_log" 2>&1; then
|
||||
echo "wasm blocker analyzer accepted missing LinuxCNC root" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing LinuxCNC root: $missing_root" "$missing_root_log" >/dev/null; then
|
||||
echo "wasm blocker analyzer did not report missing LinuxCNC root clearly" >&2
|
||||
sed -n '1,20p' "$missing_root_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_root_log"
|
||||
|
||||
output=$(./analyze-linuxcnc-wasm-blockers.sh "$manifest")
|
||||
|
||||
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest_source.XXXXXX.txt")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest_source.XXXXXX.log")
|
||||
printf 'blocked:src/emc/tooldata/does_not_exist.cc:test missing blocked source\n' >"$missing_source_manifest"
|
||||
if ./analyze-linuxcnc-wasm-blockers.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "wasm blocker analyzer accepted missing manifest source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing manifest source: src/emc/tooldata/does_not_exist.cc" "$missing_source_log" >/dev/null; then
|
||||
echo "wasm blocker analyzer did not report missing manifest source clearly" >&2
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_source_manifest" "$missing_source_log"
|
||||
|
||||
grep -F "[python]" <<<"$output" >/dev/null
|
||||
grep -F "(none)" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
||||
grep -F "[dlopen]" <<<"$output" >/dev/null
|
||||
grep -F "(none)" <<<"$(sed -n '/^\[dlopen\]/,/^$/p' <<<"$output")" >/dev/null
|
||||
grep -F "[tooldata]" <<<"$output" >/dev/null
|
||||
grep -F "src/emc/tooldata/tooldata_mmap.cc" <<<"$output" >/dev/null
|
||||
grep -F "[tooldata-users]" <<<"$output" >/dev/null
|
||||
grep -F "(none)" <<<"$(sed -n '/^\[tooldata-users\]/,/^$/p' <<<"$output")" >/dev/null
|
||||
grep -F "[native-backend]" <<<"$output" >/dev/null
|
||||
grep -F "src/emc/tooldata/tooldata_mmap.cc" <<<"$(sed -n '/^\[native-backend\]/,/^$/p' <<<"$output")" >/dev/null
|
||||
grep -F "[native-fs]" <<<"$output" >/dev/null
|
||||
grep -F "src/emc/tooldata/tooldata_mmap.cc" <<<"$(sed -n '/^\[native-fs\]/,/^$/p' <<<"$output")" >/dev/null
|
||||
|
||||
echo "linuxcnc wasm blocker scan passed"
|
||||
260
test-linuxcnc-wasm-cmake-safe-probe.sh
Executable file
260
test-linuxcnc-wasm-cmake-safe-probe.sh
Executable file
@@ -0,0 +1,260 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_cmake_safe_probe.XXXXXX")
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
missing_root=/tmp/does-not-exist-linuxcnc
|
||||
missing_root_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_build_wasm_missing_root.XXXXXX.log")
|
||||
if LINUXCNC_ROOT="$missing_root" ./build-wasm.sh >"$missing_root_log" 2>&1; then
|
||||
echo "build-wasm accepted missing LinuxCNC root: $missing_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing LinuxCNC root: $missing_root" "$missing_root_log" >/dev/null; then
|
||||
echo "build-wasm did not report missing LinuxCNC root clearly" >&2
|
||||
sed -n '1,20p' "$missing_root_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -F 'exec 9>"${TMPDIR:-/tmp}/cnc_sim_build_wasm.lock"' build-wasm.sh >/dev/null
|
||||
grep -F "flock 9" build-wasm.sh >/dev/null
|
||||
rm -f "$missing_root_log"
|
||||
|
||||
missing_root_scripts=(
|
||||
test-linuxcnc-wasm-interp-base-link.sh
|
||||
test-linuxcnc-wasm-interp-find-link.sh
|
||||
test-linuxcnc-wasm-python-plugin-link.sh
|
||||
test-linuxcnc-wasm-rs274ngc-pre-object.sh
|
||||
test-linuxcnc-wasm-tooldata-common-link.sh
|
||||
test-linuxcnc-wasm-tooldata-link.sh
|
||||
test-linuxcnc-wasm-tooldata-mmap-symbols.sh
|
||||
test-linuxcnc-wasm-tooldata-runtime-symbols.sh
|
||||
)
|
||||
for script in "${missing_root_scripts[@]}"; do
|
||||
if LINUXCNC_ROOT="$missing_root" "./$script" >"$missing_root_log" 2>&1; then
|
||||
echo "$script accepted missing LinuxCNC root: $missing_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing LinuxCNC root: $missing_root" "$missing_root_log" >/dev/null; then
|
||||
echo "$script did not report missing LinuxCNC root clearly" >&2
|
||||
sed -n '1,20p' "$missing_root_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$missing_root_log"
|
||||
|
||||
missing_source_root=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_missing_linuxcnc_source_root.XXXXXX")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_linuxcnc_source.XXXXXX.log")
|
||||
mkdir -p "$missing_source_root/src" "$missing_source_root/include"
|
||||
|
||||
fixed_source_scripts=(
|
||||
"test-linuxcnc-wasm-interp-base-link.sh:src/emc/rs274ngc/interp_base.cc"
|
||||
"test-linuxcnc-wasm-interp-find-link.sh:src/emc/tooldata/tooldata_common.cc"
|
||||
"test-linuxcnc-wasm-rs274ngc-pre-object.sh:src/emc/rs274ngc/rs274ngc_pre.cc"
|
||||
"test-linuxcnc-wasm-tooldata-common-link.sh:src/emc/tooldata/tooldata_common.cc"
|
||||
"test-linuxcnc-wasm-tooldata-link.sh:src/emc/tooldata/tooldata_common.cc"
|
||||
)
|
||||
for script_and_path in "${fixed_source_scripts[@]}"; do
|
||||
script=${script_and_path%%:*}
|
||||
source_path=${script_and_path#*:}
|
||||
if LINUXCNC_ROOT="$missing_source_root" "./$script" >"$missing_source_log" 2>&1; then
|
||||
echo "$script accepted missing LinuxCNC source: $source_path" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing LinuxCNC source: $source_path" "$missing_source_log" >/dev/null; then
|
||||
echo "$script did not report missing LinuxCNC source clearly" >&2
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -rf "$missing_source_root"
|
||||
rm -f "$missing_source_log"
|
||||
|
||||
unknown_group_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_unknown_wasm_manifest_group.XXXXXX.txt")
|
||||
unknown_group_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_unknown_wasm_manifest_group.XXXXXX.log")
|
||||
printf 'bogus:src/emc/rs274ngc/interp_arc.cc:test unknown group\n' >"$unknown_group_manifest"
|
||||
for script in \
|
||||
analyze-linuxcnc-wasm-blockers.sh \
|
||||
test-linuxcnc-wasm-source-syntax.sh \
|
||||
test-linuxcnc-wasm-source-objects.sh \
|
||||
test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh \
|
||||
test-linuxcnc-wasm-rs274ngc-pre-link.sh; do
|
||||
if "./$script" "$unknown_group_manifest" >"$unknown_group_log" 2>&1; then
|
||||
echo "$script accepted unknown manifest group" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "unknown manifest group: bogus" "$unknown_group_log" >/dev/null; then
|
||||
echo "$script did not report unknown manifest group clearly" >&2
|
||||
sed -n '1,20p' "$unknown_group_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
rm -f "$unknown_group_manifest" "$unknown_group_log"
|
||||
|
||||
blocker_scan_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_blocker_scan.XXXXXX.log")
|
||||
./test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh >"$blocker_scan_log" 2>&1
|
||||
blocker_report_file=$(awk '/^wrote / { print $2 }' "$blocker_scan_log")
|
||||
if [[ -z "$blocker_report_file" || ! -f "$blocker_report_file" ]]; then
|
||||
echo "wasm rs274ngc_pre blocker scan did not preserve its report file" >&2
|
||||
sed -n '1,20p' "$blocker_scan_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$blocker_report_file" "$blocker_scan_log"
|
||||
|
||||
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_manifest_source.XXXXXX.txt")
|
||||
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_manifest_source.XXXXXX.log")
|
||||
printf 'core:src/emc/rs274ngc/does_not_exist.cc:test missing source\n' >"$missing_source_manifest"
|
||||
if ./test-linuxcnc-wasm-source-syntax.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "wasm source syntax probe accepted missing manifest source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing manifest source: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then
|
||||
echo "wasm source syntax probe did not report missing manifest source clearly" >&2
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ./test-linuxcnc-wasm-source-objects.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "wasm source object probe accepted missing manifest source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing manifest source: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then
|
||||
echo "wasm source object probe did not report missing manifest source clearly" >&2
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ./test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "wasm rs274ngc_pre blocker scan accepted missing manifest source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing manifest source: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then
|
||||
echo "wasm rs274ngc_pre blocker scan did not report missing manifest source clearly" >&2
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ./test-linuxcnc-wasm-rs274ngc-pre-link.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
||||
echo "wasm rs274ngc_pre link probe accepted missing manifest source" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -F "missing manifest source: src/emc/rs274ngc/does_not_exist.cc" "$missing_source_log" >/dev/null; then
|
||||
echo "wasm rs274ngc_pre link probe did not report missing manifest source clearly" >&2
|
||||
sed -n '1,20p' "$missing_source_log" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$missing_source_manifest" "$missing_source_log"
|
||||
|
||||
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||
default_manifest="$PWD/linuxcnc-rs274-wasm-source-files.txt"
|
||||
|
||||
manifest_core_count=0
|
||||
manifest_blocked_count=0
|
||||
while IFS=: read -r group path note; do
|
||||
case "$group" in
|
||||
core)
|
||||
manifest_core_count=$((manifest_core_count + 1))
|
||||
;;
|
||||
blocked)
|
||||
manifest_blocked_count=$((manifest_blocked_count + 1))
|
||||
;;
|
||||
""|\#*)
|
||||
continue
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest group: $group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if [[ ! -f "$linuxcnc_root/$path" ]]; then
|
||||
echo "missing manifest source: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
done < "$manifest"
|
||||
|
||||
required_shims=(
|
||||
wasm_shims/dlfcn.cc
|
||||
wasm_shims/emc_status_shim.cc
|
||||
wasm_shims/gettext_shim.cc
|
||||
wasm_shims/linuxcnc_runtime_shim.cc
|
||||
wasm_shims/python_c_api_shim.cc
|
||||
wasm_shims/rtapi_compat.cc
|
||||
wasm_shims/tooldata/tooldata_mmap_backend.cc
|
||||
wasm_shims/tooldata/tooldata_runtime_stubs.cc
|
||||
wasm_shims/pythonplugin/python_plugin.cc
|
||||
)
|
||||
required_project_sources=(
|
||||
src/canon_event_sink.cpp
|
||||
src/linuxcnc_canon_bridge.cpp
|
||||
src/linuxcnc_tooldata_fixture.cpp
|
||||
src/rtcp_kinematics.cpp
|
||||
)
|
||||
|
||||
if [[ "$manifest" == "$default_manifest" ]] && [[ "$manifest_core_count" -ne 25 || "$manifest_blocked_count" -ne 1 ]]; then
|
||||
echo "unexpected wasm manifest partition: core=$manifest_core_count blocked=$manifest_blocked_count" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$manifest_core_count" -eq 0 || "$manifest_blocked_count" -eq 0 ]]; then
|
||||
echo "unexpected wasm manifest partition: core=$manifest_core_count blocked=$manifest_blocked_count" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for shim in "${required_shims[@]}"; do
|
||||
if ! grep -F "$shim" core/CMakeLists.txt >/dev/null; then
|
||||
echo "missing CMake wasm-safe shim: $shim" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
for source in "${required_project_sources[@]}"; do
|
||||
if ! grep -F "$source" core/CMakeLists.txt >/dev/null; then
|
||||
echo "missing CMake wasm-safe project source: $source" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
grep -F "add_executable(linuxcnc_rs274_wasm_safe_probe EXCLUDE_FROM_ALL" core/CMakeLists.txt >/dev/null
|
||||
grep -F "wasm_shims/rs274ngc_pre_probe_main.cc" core/CMakeLists.txt >/dev/null
|
||||
grep -F "target_link_libraries(linuxcnc_rs274_wasm_safe_probe PRIVATE fmt)" core/CMakeLists.txt >/dev/null
|
||||
grep -F "add_custom_target(linuxcnc_rs274_wasm_blocked_sources" core/CMakeLists.txt >/dev/null
|
||||
grep -F "LinuxCNC source root does not exist" core/CMakeLists.txt >/dev/null
|
||||
grep -F 'if(NOT IS_DIRECTORY "${CNC_SIM_LINUXCNC_ROOT_ABS}")' core/CMakeLists.txt >/dev/null
|
||||
grep -F "LinuxCNC wasm source manifest is not a file" core/CMakeLists.txt >/dev/null
|
||||
grep -F 'if(IS_DIRECTORY "${CNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST}")' core/CMakeLists.txt >/dev/null
|
||||
grep -F "LinuxCNC wasm manifest source does not exist" core/CMakeLists.txt >/dev/null
|
||||
grep -F 'if(NOT EXISTS "${manifest_source}")' core/CMakeLists.txt >/dev/null
|
||||
grep -F "LinuxCNC wasm manifest source is not a file" core/CMakeLists.txt >/dev/null
|
||||
grep -F 'if(IS_DIRECTORY "${manifest_source}")' core/CMakeLists.txt >/dev/null
|
||||
awk '
|
||||
/set\(manifest_source/ { manifest_source = NR }
|
||||
/Unknown LinuxCNC wasm source manifest group/ { unknown_group = NR }
|
||||
END { exit !(unknown_group && manifest_source && unknown_group < manifest_source) }
|
||||
' core/CMakeLists.txt
|
||||
grep -F "LinuxCNC wasm source manifest has no blocked entries" core/CMakeLists.txt >/dev/null
|
||||
|
||||
if ! command -v cmake >/dev/null 2>&1; then
|
||||
echo "cmake not found; skipping linuxcnc wasm-safe CMake probe target"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cmake -S core -B "$build_dir" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCNC_SIM_LINUXCNC_ROOT="$linuxcnc_root" \
|
||||
-DCNC_SIM_LINUXCNC_WASM_SOURCE_MANIFEST="$manifest" \
|
||||
-DCNC_SIM_ENABLE_LINUXCNC_WASM_SAFE_PROBE=ON
|
||||
|
||||
cmake --build "$build_dir" --target linuxcnc_rs274_wasm_safe_probe_objects
|
||||
cmake --build "$build_dir" --target linuxcnc_rs274_wasm_safe_probe
|
||||
"$build_dir/linuxcnc_rs274_wasm_safe_probe"
|
||||
|
||||
echo "linuxcnc wasm-safe CMake probe target passed"
|
||||
40
test-linuxcnc-wasm-interp-base-link.sh
Executable file
40
test-linuxcnc-wasm-interp-base-link.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_interp_base_link.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$linuxcnc_root/src/emc/rs274ngc/interp_base.cc" ]]; then
|
||||
echo "missing LinuxCNC source: src/emc/rs274ngc/interp_base.cc" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
core/wasm_shims/dlfcn.cc \
|
||||
"$linuxcnc_root/src/emc/rs274ngc/interp_base.cc" \
|
||||
core/wasm_shims/interp_base_probe_main.cc \
|
||||
-o "$build_dir/interp_base_probe"
|
||||
|
||||
"$build_dir/interp_base_probe"
|
||||
|
||||
echo "linuxcnc wasm interp_base link probe passed"
|
||||
73
test-linuxcnc-wasm-interp-find-link.sh
Executable file
73
test-linuxcnc-wasm-interp-find-link.sh
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_interp_find_link.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
for required_source in \
|
||||
src/emc/tooldata/tooldata_common.cc \
|
||||
src/emc/rs274ngc/interp_find.cc; do
|
||||
if [[ ! -f "$linuxcnc_root/$required_source" ]]; then
|
||||
echo "missing LinuxCNC source: $required_source" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c "$linuxcnc_root/src/emc/tooldata/tooldata_common.cc" \
|
||||
-o "$build_dir/tooldata_common.o"
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c core/wasm_shims/tooldata/tooldata_mmap_backend.cc \
|
||||
-o "$build_dir/tooldata_mmap_backend.o"
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c core/wasm_shims/tooldata/tooldata_runtime_stubs.cc \
|
||||
-o "$build_dir/tooldata_runtime_stubs.o"
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c core/wasm_shims/rtapi_compat.cc \
|
||||
-o "$build_dir/rtapi_compat.o"
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c core/wasm_shims/interp_find_probe_stubs.cc \
|
||||
-o "$build_dir/interp_find_probe_stubs.o"
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c "$linuxcnc_root/src/emc/rs274ngc/interp_find.cc" \
|
||||
-o "$build_dir/interp_find.o"
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c core/wasm_shims/interp_find_probe_main.cc \
|
||||
-o "$build_dir/interp_find_probe_main.o"
|
||||
|
||||
"$cxx" \
|
||||
"$build_dir/tooldata_common.o" \
|
||||
"$build_dir/tooldata_mmap_backend.o" \
|
||||
"$build_dir/tooldata_runtime_stubs.o" \
|
||||
"$build_dir/rtapi_compat.o" \
|
||||
"$build_dir/interp_find_probe_stubs.o" \
|
||||
"$build_dir/interp_find.o" \
|
||||
"$build_dir/interp_find_probe_main.o" \
|
||||
-Wl,--gc-sections \
|
||||
-o "$build_dir/interp_find_probe"
|
||||
|
||||
"$build_dir/interp_find_probe"
|
||||
|
||||
echo "linuxcnc wasm interp_find link probe passed"
|
||||
35
test-linuxcnc-wasm-python-plugin-link.sh
Executable file
35
test-linuxcnc-wasm-python-plugin-link.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_python_plugin_link.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
core/wasm_shims/pythonplugin/python_plugin.cc \
|
||||
core/wasm_shims/pythonplugin/python_plugin_probe_main.cc \
|
||||
-o "$build_dir/python_plugin_probe"
|
||||
|
||||
"$build_dir/python_plugin_probe"
|
||||
|
||||
echo "linuxcnc wasm python_plugin link probe passed"
|
||||
167
test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh
Executable file
167
test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh
Executable file
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_rs274ngc_pre_link_blockers.XXXXXX")
|
||||
report_file=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_rs274ngc_pre_undefined.XXXXXX.txt")
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++20
|
||||
-DULAPI
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-include wctype.h
|
||||
-I "$(pwd)/core/include"
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
shim_sources=(
|
||||
core/wasm_shims/dlfcn.cc
|
||||
core/wasm_shims/emc_status_shim.cc
|
||||
core/wasm_shims/gettext_shim.cc
|
||||
core/wasm_shims/linuxcnc_runtime_shim.cc
|
||||
core/wasm_shims/python_c_api_shim.cc
|
||||
core/wasm_shims/rtapi_compat.cc
|
||||
core/wasm_shims/tooldata/tooldata_mmap_backend.cc
|
||||
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc
|
||||
core/wasm_shims/pythonplugin/python_plugin.cc
|
||||
)
|
||||
|
||||
project_sources=(
|
||||
core/src/canon_event_sink.cpp
|
||||
core/src/linuxcnc_canon_bridge.cpp
|
||||
core/src/linuxcnc_tooldata_fixture.cpp
|
||||
core/src/rtcp_kinematics.cpp
|
||||
)
|
||||
|
||||
linuxcnc_sources=()
|
||||
while IFS=: read -r group path note; do
|
||||
case "$group" in
|
||||
core)
|
||||
if [[ ! -f "$linuxcnc_root/$path" ]]; then
|
||||
echo "missing manifest source: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
linuxcnc_sources+=("$linuxcnc_root/$path")
|
||||
;;
|
||||
""|\#*|blocked)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest group: $group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done < "$manifest"
|
||||
|
||||
shim_index=0
|
||||
for source in "${shim_sources[@]}"; do
|
||||
obj="$build_dir/shim_${shim_index}.o"
|
||||
"$cxx" "${common_flags[@]}" -c "$source" -o "$obj"
|
||||
shim_index=$((shim_index + 1))
|
||||
done
|
||||
|
||||
project_index=0
|
||||
for source in "${project_sources[@]}"; do
|
||||
obj="$build_dir/project_${project_index}.o"
|
||||
"$cxx" "${common_flags[@]}" -c "$source" -o "$obj"
|
||||
project_index=$((project_index + 1))
|
||||
done
|
||||
|
||||
linuxcnc_index=0
|
||||
for source in "${linuxcnc_sources[@]}"; do
|
||||
obj="$build_dir/linuxcnc_${linuxcnc_index}.o"
|
||||
"$cxx" "${common_flags[@]}" -c "$source" -o "$obj"
|
||||
linuxcnc_index=$((linuxcnc_index + 1))
|
||||
done
|
||||
|
||||
undefined_file="$build_dir/undefined.raw"
|
||||
defined_file="$build_dir/defined.raw"
|
||||
|
||||
nm -u "$build_dir"/*.o \
|
||||
| awk '{print $2}' \
|
||||
| sed '/^$/d' \
|
||||
| LC_ALL=C sort -u \
|
||||
> "$undefined_file"
|
||||
|
||||
nm --defined-only "$build_dir"/*.o \
|
||||
| awk '{print $3}' \
|
||||
| sed '/^$/d' \
|
||||
| LC_ALL=C sort -u \
|
||||
> "$defined_file"
|
||||
|
||||
{
|
||||
comm -23 "$undefined_file" "$defined_file" \
|
||||
| grep -Ev '^(_GLOBAL_OFFSET_TABLE_|_Unwind_Resume)$' \
|
||||
| grep -Ev '^(__assert_fail|__cxa_|__divdc3|__dso_handle|__errno_location|__gxx_personality_v0|__isoc23_|__muldc3|__stack_chk_fail)' \
|
||||
| grep -Ev '^(abort|access|acos|asin|atan2|atof|atoi|basename|cabs|calloc|ceil|close|closedir|copysign|cos|cosl|exit|exp|fclose|fdatasync|fdopen|feof|fflush|fgetc|fgets|fileno|floor|fmod|fopen|fprintf|fputs|free|freelocale|fseek|fstat|ftell|fwrite|getcwd|getenv|getpid|gettimeofday|hypot|islower|isprint|isspace|isupper|isxdigit|link|localtime|log|lstat|malloc|memchr|memcmp|memcpy|memmove|memset|mkstemp|nearbyint|newlocale|open|opendir|perror|pow|printf|pthread_mutex_lock|pthread_mutex_unlock|putc|puts|read|readdir|realpath|realloc|remove|rename|setlocale|sin|sinl|snprintf|sprintf|sqrt|sscanf|stat|stderr|stdout|strcasecmp|strcat|strchr|strcmp|strcpy|strdup|strerror|strlen|strncasecmp|strncat|strncmp|strncpy|strrchr|strspn|strstr|strtod|strtok_r|strtol|strtoul|tan|tanl|tolower|toupper|towlower|unlink|uselocale|vfprintf|vsnprintf|wordexp|wordfree)$' \
|
||||
| grep -Ev '^(_ZN3fmt|_ZSt|_ZNSt|_ZNKSt|_ZNKRSt|_ZNS|_ZTI|_ZTS|_ZTV|_Zdl|_Znwm|_Znam|_Zda|_ZdaPv|_ZdaPvm|_ZdlPvm|_ZTv|_ZTh)'
|
||||
} > "$report_file" || true
|
||||
|
||||
if grep -F "_ZN6Interp13read_commentEPcPiP12block_structPd" "$report_file" >/dev/null; then
|
||||
echo "unexpected unresolved read_comment after interp_read.cc" >&2
|
||||
exit 1
|
||||
fi
|
||||
if grep -F "_ZN6Interp15find_tool_indexEP5setupiPi" "$report_file" >/dev/null; then
|
||||
echo "unexpected unresolved find_tool_index after interp_find.cc" >&2
|
||||
exit 1
|
||||
fi
|
||||
if grep -F "_ZN6Interp16find_named_paramEPKcPiPd" "$report_file" >/dev/null; then
|
||||
echo "unexpected unresolved find_named_param after interp_namedparams.cc" >&2
|
||||
exit 1
|
||||
fi
|
||||
if grep -Fx "emcStatus" "$report_file" >/dev/null; then
|
||||
echo "unexpected unresolved emcStatus after shim" >&2
|
||||
exit 1
|
||||
fi
|
||||
if grep -Fx "gettext" "$report_file" >/dev/null; then
|
||||
echo "unexpected unresolved gettext after shim" >&2
|
||||
exit 1
|
||||
fi
|
||||
if grep -Fx "_task" "$report_file" >/dev/null; then
|
||||
echo "unexpected unresolved _task after runtime shim" >&2
|
||||
exit 1
|
||||
fi
|
||||
if grep -Fx "builtin_modules" "$report_file" >/dev/null; then
|
||||
echo "unexpected unresolved builtin_modules after runtime shim" >&2
|
||||
exit 1
|
||||
fi
|
||||
for hal_symbol in \
|
||||
hal_get_param_value_by_name \
|
||||
hal_get_pin_value_by_name \
|
||||
hal_get_signal_value_by_name \
|
||||
hal_init \
|
||||
hal_ready; do
|
||||
if grep -Fx "$hal_symbol" "$report_file" >/dev/null; then
|
||||
echo "unexpected unresolved $hal_symbol after runtime shim" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
if [[ -s "$report_file" ]]; then
|
||||
echo "unexpected unresolved project symbols after rs274ngc_pre shim coverage:" >&2
|
||||
sed -n '1,120p' "$report_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "linuxcnc wasm rs274ngc_pre link blocker scan passed"
|
||||
echo "wrote $report_file"
|
||||
91
test-linuxcnc-wasm-rs274ngc-pre-link.sh
Executable file
91
test-linuxcnc-wasm-rs274ngc-pre-link.sh
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_rs274ngc_pre_link.XXXXXX")
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++20
|
||||
-DULAPI
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-I "$(pwd)/core/src"
|
||||
-include wctype.h
|
||||
-I "$(pwd)/core/include"
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
sources=(
|
||||
core/wasm_shims/dlfcn.cc
|
||||
core/wasm_shims/emc_status_shim.cc
|
||||
core/wasm_shims/gettext_shim.cc
|
||||
core/wasm_shims/linuxcnc_runtime_shim.cc
|
||||
core/wasm_shims/python_c_api_shim.cc
|
||||
core/wasm_shims/rtapi_compat.cc
|
||||
core/wasm_shims/tooldata/tooldata_mmap_backend.cc
|
||||
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc
|
||||
core/wasm_shims/pythonplugin/python_plugin.cc
|
||||
core/src/canon_event_sink.cpp
|
||||
core/src/linuxcnc_canon_bridge.cpp
|
||||
core/src/linuxcnc_tooldata_fixture.cpp
|
||||
core/src/rtcp_kinematics.cpp
|
||||
)
|
||||
|
||||
while IFS=: read -r group path note; do
|
||||
case "$group" in
|
||||
core)
|
||||
if [[ ! -f "$linuxcnc_root/$path" ]]; then
|
||||
echo "missing manifest source: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
sources+=("$linuxcnc_root/$path")
|
||||
;;
|
||||
""|\#*|blocked)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest group: $group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done < "$manifest"
|
||||
|
||||
sources+=(core/wasm_shims/rs274ngc_pre_probe_main.cc)
|
||||
|
||||
objects=()
|
||||
object_index=0
|
||||
for source in "${sources[@]}"; do
|
||||
obj="$build_dir/source_${object_index}.o"
|
||||
"$cxx" "${common_flags[@]}" -c "$source" -o "$obj"
|
||||
objects+=("$obj")
|
||||
object_index=$((object_index + 1))
|
||||
done
|
||||
|
||||
"$cxx" "${objects[@]}" \
|
||||
-Wl,--gc-sections \
|
||||
-lfmt \
|
||||
-o "$build_dir/rs274ngc_pre_probe"
|
||||
|
||||
"$build_dir/rs274ngc_pre_probe"
|
||||
|
||||
echo "linuxcnc wasm rs274ngc_pre link probe passed"
|
||||
36
test-linuxcnc-wasm-rs274ngc-pre-object.sh
Executable file
36
test-linuxcnc-wasm-rs274ngc-pre-object.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_rs274ngc_pre_object.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" ]]; then
|
||||
echo "missing LinuxCNC source: src/emc/rs274ngc/rs274ngc_pre.cc" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c "$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" \
|
||||
-o "$build_dir/rs274ngc_pre.o"
|
||||
|
||||
echo "linuxcnc wasm rs274ngc_pre object probe passed"
|
||||
81
test-linuxcnc-wasm-source-objects.sh
Executable file
81
test-linuxcnc-wasm-source-objects.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_safe_probe.XXXXXX")
|
||||
shim_sources=(
|
||||
core/wasm_shims/dlfcn.cc
|
||||
core/wasm_shims/emc_status_shim.cc
|
||||
core/wasm_shims/gettext_shim.cc
|
||||
core/wasm_shims/linuxcnc_runtime_shim.cc
|
||||
core/wasm_shims/python_c_api_shim.cc
|
||||
core/wasm_shims/rtapi_compat.cc
|
||||
core/wasm_shims/tooldata/tooldata_mmap_backend.cc
|
||||
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc
|
||||
core/wasm_shims/pythonplugin/python_plugin.cc
|
||||
)
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++20
|
||||
-DULAPI
|
||||
-include wctype.h
|
||||
-I "$(pwd)/core/include"
|
||||
-I "$(pwd)/core/src"
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
sources=()
|
||||
while IFS=: read -r group path note; do
|
||||
case "$group" in
|
||||
core)
|
||||
if [[ ! -f "$linuxcnc_root/$path" ]]; then
|
||||
echo "missing manifest source: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
sources+=("$path")
|
||||
;;
|
||||
""|\#*|blocked)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest group: $group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done < "$manifest"
|
||||
|
||||
shim_index=0
|
||||
for source in "${shim_sources[@]}"; do
|
||||
obj="$build_dir/shim_${shim_index}.o"
|
||||
"$cxx" "${common_flags[@]}" -c "$source" -o "$obj"
|
||||
shim_index=$((shim_index + 1))
|
||||
done
|
||||
|
||||
source_index=0
|
||||
for source in "${sources[@]}"; do
|
||||
obj="$build_dir/linuxcnc_${source_index}.o"
|
||||
"$cxx" "${common_flags[@]}" -c "$linuxcnc_root/$source" -o "$obj"
|
||||
source_index=$((source_index + 1))
|
||||
done
|
||||
|
||||
echo "linuxcnc wasm-safe source object probe passed (${#sources[@]} linuxcnc objects + ${#shim_sources[@]} shims)"
|
||||
59
test-linuxcnc-wasm-source-syntax.sh
Executable file
59
test-linuxcnc-wasm-source-syntax.sh
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||
cxx=${CXX:-g++}
|
||||
|
||||
if [[ ! -f "$manifest" ]]; then
|
||||
echo "missing manifest: $manifest" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
common_flags=(
|
||||
-std=c++20
|
||||
-DULAPI
|
||||
-fsyntax-only
|
||||
-include wctype.h
|
||||
-I "$(pwd)/core/include"
|
||||
-I "$(pwd)/core/src"
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
sources=()
|
||||
while IFS=: read -r group path note; do
|
||||
case "$group" in
|
||||
core)
|
||||
if [[ ! -f "$linuxcnc_root/$path" ]]; then
|
||||
echo "missing manifest source: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
sources+=("$path")
|
||||
;;
|
||||
""|\#*|blocked)
|
||||
;;
|
||||
*)
|
||||
echo "unknown manifest group: $group" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done < "$manifest"
|
||||
|
||||
for source in "${sources[@]}"; do
|
||||
"$cxx" "${common_flags[@]}" "$linuxcnc_root/$source"
|
||||
done
|
||||
|
||||
echo "linuxcnc wasm-safe source syntax probe passed (${#sources[@]} files)"
|
||||
41
test-linuxcnc-wasm-tooldata-common-link.sh
Executable file
41
test-linuxcnc-wasm-tooldata-common-link.sh
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_tooldata_common_link.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$linuxcnc_root/src/emc/tooldata/tooldata_common.cc" ]]; then
|
||||
echo "missing LinuxCNC source: src/emc/tooldata/tooldata_common.cc" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$linuxcnc_root/src/emc/tooldata"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
"$linuxcnc_root/src/emc/tooldata/tooldata_common.cc" \
|
||||
core/wasm_shims/tooldata/tooldata_mmap_backend.cc \
|
||||
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc \
|
||||
core/wasm_shims/tooldata/tooldata_common_probe_main.cc \
|
||||
-o "$build_dir/tooldata_common_probe"
|
||||
|
||||
"$build_dir/tooldata_common_probe"
|
||||
|
||||
echo "linuxcnc wasm tooldata_common link probe passed"
|
||||
41
test-linuxcnc-wasm-tooldata-link.sh
Executable file
41
test-linuxcnc-wasm-tooldata-link.sh
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_tooldata_link.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$linuxcnc_root/src/emc/tooldata/tooldata_common.cc" ]]; then
|
||||
echo "missing LinuxCNC source: src/emc/tooldata/tooldata_common.cc" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
"$linuxcnc_root/src/emc/tooldata/tooldata_common.cc" \
|
||||
core/wasm_shims/tooldata/tooldata_mmap_backend.cc \
|
||||
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc \
|
||||
core/wasm_shims/tooldata/tooldata_probe_main.cc \
|
||||
-o "$build_dir/tooldata_probe"
|
||||
|
||||
"$build_dir/tooldata_probe"
|
||||
|
||||
echo "linuxcnc wasm tooldata shim link probe passed"
|
||||
69
test-linuxcnc-wasm-tooldata-mmap-symbols.sh
Executable file
69
test-linuxcnc-wasm-tooldata-mmap-symbols.sh
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_tooldata_mmap_symbols.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c core/wasm_shims/tooldata/tooldata_mmap_backend.cc \
|
||||
-o "$build_dir/tooldata_mmap_backend.o"
|
||||
|
||||
nm --defined-only "$build_dir/tooldata_mmap_backend.o" \
|
||||
| awk '$2 ~ /^[A-Z]$/ {print $3}' \
|
||||
| LC_ALL=C sort -u \
|
||||
> "$build_dir/backend.exports"
|
||||
|
||||
expected_exports=(
|
||||
tool_mmap_close
|
||||
tool_mmap_creator
|
||||
tool_mmap_is_random_toolchanger
|
||||
tool_mmap_user
|
||||
tooldata_find_index_for_tool
|
||||
tooldata_get
|
||||
tooldata_last_index_get
|
||||
tooldata_last_index_set
|
||||
tooldata_put
|
||||
tooldata_reset
|
||||
)
|
||||
|
||||
printf '%s\n' "${expected_exports[@]}" | LC_ALL=C sort -u > "$build_dir/expected.exports"
|
||||
|
||||
if ! comm -23 "$build_dir/expected.exports" "$build_dir/backend.exports" > "$build_dir/missing.exports"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -s "$build_dir/missing.exports" ]]; then
|
||||
echo "missing wasm tooldata mmap backend exports:" >&2
|
||||
cat "$build_dir/missing.exports" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
comm -13 "$build_dir/expected.exports" "$build_dir/backend.exports" > "$build_dir/unexpected.exports"
|
||||
if [[ -s "$build_dir/unexpected.exports" ]]; then
|
||||
echo "unexpected wasm tooldata mmap backend exports:" >&2
|
||||
cat "$build_dir/unexpected.exports" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "linuxcnc wasm tooldata_mmap symbol probe passed"
|
||||
60
test-linuxcnc-wasm-tooldata-runtime-symbols.sh
Executable file
60
test-linuxcnc-wasm-tooldata-runtime-symbols.sh
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_linuxcnc_wasm_tooldata_runtime_symbols.XXXXXX")
|
||||
|
||||
if [[ ! -d "$linuxcnc_root" ]]; then
|
||||
echo "missing LinuxCNC root: $linuxcnc_root" >&2
|
||||
exit 1
|
||||
fi
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
common_flags=(
|
||||
-std=c++17
|
||||
-DULAPI
|
||||
-I "$(pwd)/core/wasm_shims"
|
||||
-I "$linuxcnc_root/src"
|
||||
-I "$linuxcnc_root/src/emc"
|
||||
-I "$linuxcnc_root/src/emc/nml_intf"
|
||||
-I "$linuxcnc_root/src/emc/rs274ngc"
|
||||
-I "$linuxcnc_root/src/emc/motion"
|
||||
-I "$linuxcnc_root/include"
|
||||
)
|
||||
|
||||
"$cxx" "${common_flags[@]}" \
|
||||
-c core/wasm_shims/tooldata/tooldata_runtime_stubs.cc \
|
||||
-o "$build_dir/tooldata_runtime_stubs.o"
|
||||
|
||||
nm --defined-only "$build_dir/tooldata_runtime_stubs.o" \
|
||||
| awk '$2 ~ /^[A-Z]$/ {print $3}' \
|
||||
| LC_ALL=C sort -u \
|
||||
> "$build_dir/runtime.exports"
|
||||
|
||||
expected_exports=(
|
||||
tool_nml_register
|
||||
tooldata_db_getall
|
||||
tooldata_db_init
|
||||
tooldata_db_notify
|
||||
)
|
||||
|
||||
printf '%s\n' "${expected_exports[@]}" | LC_ALL=C sort -u > "$build_dir/expected.exports"
|
||||
|
||||
comm -23 "$build_dir/expected.exports" "$build_dir/runtime.exports" > "$build_dir/missing.exports"
|
||||
if [[ -s "$build_dir/missing.exports" ]]; then
|
||||
echo "missing wasm tooldata runtime stub exports:" >&2
|
||||
cat "$build_dir/missing.exports" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
comm -13 "$build_dir/expected.exports" "$build_dir/runtime.exports" > "$build_dir/unexpected.exports"
|
||||
if [[ -s "$build_dir/unexpected.exports" ]]; then
|
||||
echo "unexpected wasm tooldata runtime stub exports:" >&2
|
||||
cat "$build_dir/unexpected.exports" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "linuxcnc wasm tooldata runtime symbol probe passed"
|
||||
@@ -4,8 +4,8 @@ set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
cxx=${CXX:-g++}
|
||||
build_dir=${TMPDIR:-/tmp}/cnc_sim_native
|
||||
mkdir -p "$build_dir"
|
||||
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/cnc_sim_native.XXXXXX")
|
||||
trap 'rm -rf "$build_dir"' EXIT
|
||||
|
||||
"$cxx" -std=c++17 -I core/include -I core/src \
|
||||
core/src/canon_event_sink.cpp \
|
||||
@@ -49,13 +49,18 @@ mkdir -p "$build_dir"
|
||||
"$build_dir/rtcp_kinematics_smoke"
|
||||
"$build_dir/simulator_gcode_controls_smoke"
|
||||
"$build_dir/cnc_sim_api_smoke"
|
||||
"$build_dir/cnc_sim_dump" tests/gcode/basic_mill.ngc >/tmp/cnc_sim_basic_mill.json
|
||||
"$build_dir/cnc_sim_dump" tests/gcode/incremental_and_r_arc.ngc >/tmp/cnc_sim_incremental_and_r_arc.json
|
||||
"$build_dir/cnc_sim_dump" tests/gcode/smoke_subprogram_m98.ngc >/tmp/cnc_sim_smoke_subprogram_m98.json
|
||||
"$build_dir/cnc_sim_dump" tests/gcode/smoke_oword_subprogram.ngc >/tmp/cnc_sim_smoke_oword_subprogram.json
|
||||
basic_mill_json="$build_dir/cnc_sim_basic_mill.json"
|
||||
incremental_arc_json="$build_dir/cnc_sim_incremental_and_r_arc.json"
|
||||
subprogram_m98_json="$build_dir/cnc_sim_smoke_subprogram_m98.json"
|
||||
oword_subprogram_json="$build_dir/cnc_sim_smoke_oword_subprogram.json"
|
||||
|
||||
"$build_dir/cnc_sim_dump" tests/gcode/basic_mill.ngc >"$basic_mill_json"
|
||||
"$build_dir/cnc_sim_dump" tests/gcode/incremental_and_r_arc.ngc >"$incremental_arc_json"
|
||||
"$build_dir/cnc_sim_dump" tests/gcode/smoke_subprogram_m98.ngc >"$subprogram_m98_json"
|
||||
"$build_dir/cnc_sim_dump" tests/gcode/smoke_oword_subprogram.ngc >"$oword_subprogram_json"
|
||||
|
||||
echo "native tests passed"
|
||||
echo "dumped /tmp/cnc_sim_basic_mill.json"
|
||||
echo "dumped /tmp/cnc_sim_incremental_and_r_arc.json"
|
||||
echo "dumped /tmp/cnc_sim_smoke_subprogram_m98.json"
|
||||
echo "dumped /tmp/cnc_sim_smoke_oword_subprogram.json"
|
||||
echo "dumped $basic_mill_json"
|
||||
echo "dumped $incremental_arc_json"
|
||||
echo "dumped $subprogram_m98_json"
|
||||
echo "dumped $oword_subprogram_json"
|
||||
|
||||
4
tests/gcode/linuxcnc_block_delete.ngc
Normal file
4
tests/gcode/linuxcnc_block_delete.ngc
Normal file
@@ -0,0 +1,4 @@
|
||||
G21 G90 G17 F100
|
||||
/N10 G1 X5
|
||||
G1 X2
|
||||
M30
|
||||
2
tests/gcode/linuxcnc_canned_cycle_a_error.ngc
Normal file
2
tests/gcode/linuxcnc_canned_cycle_a_error.ngc
Normal file
@@ -0,0 +1,2 @@
|
||||
G21 G90 G17
|
||||
G81 X1 A10 Z-1 R1
|
||||
2
tests/gcode/linuxcnc_canned_cycle_b_error.ngc
Normal file
2
tests/gcode/linuxcnc_canned_cycle_b_error.ngc
Normal file
@@ -0,0 +1,2 @@
|
||||
G21 G90 G17
|
||||
G81 X1 B10 Z-1 R1
|
||||
2
tests/gcode/linuxcnc_canned_cycle_c_error.ngc
Normal file
2
tests/gcode/linuxcnc_canned_cycle_c_error.ngc
Normal file
@@ -0,0 +1,2 @@
|
||||
G21 G90 G17
|
||||
G81 X1 C10 Z-1 R1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G18
|
||||
F100
|
||||
G81 X1 Z-1 R1
|
||||
3
tests/gcode/linuxcnc_canned_cycle_g18_r_less_y_error.ngc
Normal file
3
tests/gcode/linuxcnc_canned_cycle_g18_r_less_y_error.ngc
Normal file
@@ -0,0 +1,3 @@
|
||||
G21 G90 G18
|
||||
F100
|
||||
G81 X1 Y2 Z-1 R1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G19
|
||||
F100
|
||||
G81 Y1 Z-1 R1
|
||||
3
tests/gcode/linuxcnc_canned_cycle_g19_r_less_x_error.ngc
Normal file
3
tests/gcode/linuxcnc_canned_cycle_g19_r_less_x_error.ngc
Normal file
@@ -0,0 +1,3 @@
|
||||
G21 G90 G19
|
||||
F100
|
||||
G81 X2 Y1 Z-1 R1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G73 X1 Z-1 R1
|
||||
3
tests/gcode/linuxcnc_canned_cycle_g73_q0_error.ngc
Normal file
3
tests/gcode/linuxcnc_canned_cycle_g73_q0_error.ngc
Normal file
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G73 X1 Z-1 R1 Q0
|
||||
@@ -0,0 +1,4 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
S100 M3
|
||||
G74 X1 Z-1 R1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G74 X1 Z-1 R1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G82 X1 Z-1 R1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G83 X1 Z-1 R1
|
||||
3
tests/gcode/linuxcnc_canned_cycle_g83_q0_error.ngc
Normal file
3
tests/gcode/linuxcnc_canned_cycle_g83_q0_error.ngc
Normal file
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G83 X1 Z-1 R1 Q0
|
||||
@@ -0,0 +1,4 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
S100 M4
|
||||
G84 X1 Z-1 R1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G84 X1 Z-1 R1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G86 X1 Z-1 R1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G86 X1 Z-1 R1 P0.1
|
||||
@@ -0,0 +1,4 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
S100 M3
|
||||
G87 X1 Z-1 R1 J0.1 K0
|
||||
@@ -0,0 +1,4 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
S100 M3
|
||||
G87 X1 Z-1 R1 I0.1 K0
|
||||
@@ -0,0 +1,4 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
S100 M3
|
||||
G87 X1 Z-1 R1 I0.1 J0.1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G87 X1 Z-1 R1 I0.1 J0.1 K0
|
||||
@@ -0,0 +1,4 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
S100 M3
|
||||
G88 X1 Z-1 R1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G88 X1 Z-1 R1 P0.1
|
||||
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G89 X1 Z-1 R1
|
||||
3
tests/gcode/linuxcnc_canned_cycle_l0_error.ngc
Normal file
3
tests/gcode/linuxcnc_canned_cycle_l0_error.ngc
Normal file
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G81 X1 Z-1 R1 L0
|
||||
3
tests/gcode/linuxcnc_canned_cycle_missing_r_error.ngc
Normal file
3
tests/gcode/linuxcnc_canned_cycle_missing_r_error.ngc
Normal file
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G81 X1 Z-1
|
||||
3
tests/gcode/linuxcnc_canned_cycle_missing_z_error.ngc
Normal file
3
tests/gcode/linuxcnc_canned_cycle_missing_z_error.ngc
Normal file
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G81 X1 R1
|
||||
3
tests/gcode/linuxcnc_canned_cycle_r_less_z_error.ngc
Normal file
3
tests/gcode/linuxcnc_canned_cycle_r_less_z_error.ngc
Normal file
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G81 X1 Z2 R1
|
||||
3
tests/gcode/linuxcnc_canned_cycle_u_in_xy_error.ngc
Normal file
3
tests/gcode/linuxcnc_canned_cycle_u_in_xy_error.ngc
Normal file
@@ -0,0 +1,3 @@
|
||||
G21 G90 G17
|
||||
F100
|
||||
G81 X1 U2 Z-1 R1
|
||||
Reference in New Issue
Block a user