Compare commits
7 Commits
4e246738ac
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c81f9d0111 | ||
|
|
c75eec1057 | ||
|
|
23e67bb6cd | ||
|
|
42e5b0784d | ||
|
|
64f336d6f2 | ||
|
|
fc56b11d8f | ||
|
|
fb9561ccc7 |
@@ -17,6 +17,7 @@ LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh "$manifest"
|
|||||||
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
||||||
|
|
||||||
python_blockers=()
|
python_blockers=()
|
||||||
|
python_compile_covered=()
|
||||||
core_python_sources=()
|
core_python_sources=()
|
||||||
dlopen_blockers=()
|
dlopen_blockers=()
|
||||||
core_dlopen_sources=()
|
core_dlopen_sources=()
|
||||||
@@ -61,6 +62,10 @@ wasm_safe_shim_in_build() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
python_compile_probe_covers() {
|
||||||
|
grep -F "$1" test-linuxcnc-wasm-python-c-api-symbols.sh >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
core_sources=()
|
core_sources=()
|
||||||
blocked_sources=()
|
blocked_sources=()
|
||||||
manifest_line_number=0
|
manifest_line_number=0
|
||||||
@@ -134,6 +139,9 @@ scan_source() {
|
|||||||
if grep -Eq 'Python\.h|boost/python|pythonplugin|PyObject|PyInit_' "$full_path"; then
|
if grep -Eq 'Python\.h|boost/python|pythonplugin|PyObject|PyInit_' "$full_path"; then
|
||||||
if [[ "$group" == "blocked" ]]; then
|
if [[ "$group" == "blocked" ]]; then
|
||||||
python_blockers+=("$path")
|
python_blockers+=("$path")
|
||||||
|
if python_compile_probe_covers "$path"; then
|
||||||
|
python_compile_covered+=("$path")
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
core_python_sources+=("$path")
|
core_python_sources+=("$path")
|
||||||
fi
|
fi
|
||||||
@@ -192,6 +200,7 @@ echo "blocked=$blocked_count"
|
|||||||
echo
|
echo
|
||||||
|
|
||||||
print_group "python" "${python_blockers[@]}"
|
print_group "python" "${python_blockers[@]}"
|
||||||
|
print_group "python-compile-covered" "${python_compile_covered[@]}"
|
||||||
print_group "dlopen" "${dlopen_blockers[@]}"
|
print_group "dlopen" "${dlopen_blockers[@]}"
|
||||||
print_group "tooldata" "${tooldata_blockers[@]}"
|
print_group "tooldata" "${tooldata_blockers[@]}"
|
||||||
print_group "tooldata-users" "${shimmed_tooldata_users[@]}"
|
print_group "tooldata-users" "${shimmed_tooldata_users[@]}"
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ run_parallel_wasm_probe "LinuxCNC wasm interp_base link probe" ./test-linuxcnc-w
|
|||||||
run_parallel_wasm_probe "LinuxCNC wasm interp_find link probe" ./test-linuxcnc-wasm-interp-find-link.sh
|
run_parallel_wasm_probe "LinuxCNC wasm interp_find link probe" ./test-linuxcnc-wasm-interp-find-link.sh
|
||||||
run_parallel_wasm_probe "LinuxCNC wasm python_plugin link probe" ./test-linuxcnc-wasm-python-plugin-link.sh
|
run_parallel_wasm_probe "LinuxCNC wasm python_plugin link probe" ./test-linuxcnc-wasm-python-plugin-link.sh
|
||||||
run_parallel_wasm_probe "LinuxCNC wasm Python C API symbol probe" ./test-linuxcnc-wasm-python-c-api-symbols.sh
|
run_parallel_wasm_probe "LinuxCNC wasm Python C API symbol probe" ./test-linuxcnc-wasm-python-c-api-symbols.sh
|
||||||
|
run_parallel_wasm_probe "LinuxCNC wasm Python binding link probe" ./test-linuxcnc-wasm-python-binding-link.sh
|
||||||
run_parallel_wasm_probe "LinuxCNC wasm rs274ngc_pre object probe" ./test-linuxcnc-wasm-rs274ngc-pre-object.sh
|
run_parallel_wasm_probe "LinuxCNC wasm rs274ngc_pre object probe" ./test-linuxcnc-wasm-rs274ngc-pre-object.sh
|
||||||
wait_parallel_wasm_probes
|
wait_parallel_wasm_probes
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ expected_counts = {
|
|||||||
"manifest-core": "core=26",
|
"manifest-core": "core=26",
|
||||||
"manifest-blocked": "blocked=9",
|
"manifest-blocked": "blocked=9",
|
||||||
"python": 8,
|
"python": 8,
|
||||||
|
"python-compile-covered": 8,
|
||||||
"tooldata": 1,
|
"tooldata": 1,
|
||||||
"native-backend": 1,
|
"native-backend": 1,
|
||||||
"native-fs": 1,
|
"native-fs": 1,
|
||||||
@@ -111,6 +112,8 @@ if sections.get("dlopen") != ["(none)"]:
|
|||||||
raise SystemExit("blocked dlopen section is no longer empty")
|
raise SystemExit("blocked dlopen section is no longer empty")
|
||||||
if sections.get("tooldata-users") != ["(none)"]:
|
if sections.get("tooldata-users") != ["(none)"]:
|
||||||
raise SystemExit("blocked tooldata-users section is no longer empty")
|
raise SystemExit("blocked tooldata-users section is no longer empty")
|
||||||
|
if sections.get("python") != sections.get("python-compile-covered"):
|
||||||
|
raise SystemExit("blocked Python sources are no longer fully compile-covered by the inert Python C API probe")
|
||||||
|
|
||||||
shim_paths = set(Path(line).as_posix() for line in subprocess.check_output(
|
shim_paths = set(Path(line).as_posix() for line in subprocess.check_output(
|
||||||
["./list-linuxcnc-wasm-safe-shims.sh"],
|
["./list-linuxcnc-wasm-safe-shims.sh"],
|
||||||
@@ -166,6 +169,7 @@ for phrase in [
|
|||||||
'parameter-file replacement through `filename + ".new"`',
|
'parameter-file replacement through `filename + ".new"`',
|
||||||
"O-word lookup and parameter-file replacement",
|
"O-word lookup and parameter-file replacement",
|
||||||
"Python/Boost.Python remap paths remain tracked blockers",
|
"Python/Boost.Python remap paths remain tracked blockers",
|
||||||
|
"Python/Boost.Python blockers are compile-covered by the inert Python C API probe",
|
||||||
"./check-linuxcnc-wasm-blockers-source-map.sh",
|
"./check-linuxcnc-wasm-blockers-source-map.sh",
|
||||||
"does not interpret G-code",
|
"does not interpret G-code",
|
||||||
]:
|
]:
|
||||||
|
|||||||
@@ -303,6 +303,45 @@ int main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::vector<CncSimEvent> percent_events;
|
||||||
|
CncSimHandle *percent_sim = cnc_sim_create();
|
||||||
|
cnc_sim_set_event_callback(percent_sim, collect_event, &percent_events);
|
||||||
|
ScopedEnv file_mode_env("CNC_SIM_RS274_FILE_MODE", "1");
|
||||||
|
const char percent_program[] =
|
||||||
|
"%\n"
|
||||||
|
"G21 G90\n"
|
||||||
|
"F100\n"
|
||||||
|
"G1 X1\n"
|
||||||
|
"%\n"
|
||||||
|
"G1 X99\n";
|
||||||
|
bool percent_ok = true;
|
||||||
|
percent_ok &= expect(cnc_sim_parse_program(percent_sim,
|
||||||
|
percent_program,
|
||||||
|
sizeof(percent_program) - 1) == 0,
|
||||||
|
cnc_sim_last_error(percent_sim));
|
||||||
|
std::vector<int> feed_lines;
|
||||||
|
std::vector<double> feed_x;
|
||||||
|
for (const auto &event : percent_events) {
|
||||||
|
if (event.type == CNC_SIM_EVENT_LINEAR_FEED) {
|
||||||
|
feed_lines.push_back(event.line);
|
||||||
|
feed_x.push_back(event.end.x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// LinuxCNC source basis: rs274ngc_pre.cc open() enables percent-file
|
||||||
|
// mode when the first nonblank line is '%'; interp_read.cc read_text()
|
||||||
|
// stops at the matching '%', so later program text is ignored.
|
||||||
|
percent_ok &= expect(feed_lines.size() == 1 &&
|
||||||
|
feed_lines[0] == 4 &&
|
||||||
|
feed_x.size() == 1 &&
|
||||||
|
near(feed_x[0], 1.0),
|
||||||
|
"expected LinuxCNC percent-file mode to ignore trailing text");
|
||||||
|
cnc_sim_destroy(percent_sim);
|
||||||
|
if (!percent_ok) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char config[] =
|
const char config[] =
|
||||||
"{\"backend\":\"linuxcnc-rs274\",\"rtcp\":{\"enabled\":true,\"toolLength\":100,\"toolLengths\":{\"7\":125}}}";
|
"{\"backend\":\"linuxcnc-rs274\",\"rtcp\":{\"enabled\":true,\"toolLength\":100,\"toolLengths\":{\"7\":125}}}";
|
||||||
const char program[] =
|
const char program[] =
|
||||||
|
|||||||
@@ -198,6 +198,44 @@ int main() {
|
|||||||
setenv("HOME", saved_home_value.c_str(), 1);
|
setenv("HOME", saved_home_value.c_str(), 1);
|
||||||
}
|
}
|
||||||
std::remove(path_append_ini);
|
std::remove(path_append_ini);
|
||||||
|
const char *section_path_append_ini = "/tmp/cnc_sim_python_plugin_probe_section_path_append.ini";
|
||||||
|
{
|
||||||
|
FILE *file = std::fopen(section_path_append_ini, "w");
|
||||||
|
if (!file) {
|
||||||
|
std::remove(ini);
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
std::fputs("[REMAP]\n"
|
||||||
|
"[PYTHON]\nTOPLEVEL = /tmp/cnc_sim_missing_python_section_toplevel.py\n"
|
||||||
|
"PATH_APPEND = ~/linuxcnc-python\n",
|
||||||
|
file);
|
||||||
|
std::fclose(file);
|
||||||
|
}
|
||||||
|
unsetenv("HOME");
|
||||||
|
// LinuxCNC source basis: python_plugin.cc configure() looks up TOPLEVEL in
|
||||||
|
// the caller-provided section, but PATH_APPEND entries are read from the
|
||||||
|
// fixed PYTHON section before initialize(); a PYTHON TOPLEVEL is ignored
|
||||||
|
// when the caller configures a different section.
|
||||||
|
if (plugin->configure(section_path_append_ini, "REMAP") != PLUGIN_EXCEPTION_DURING_PATH_APPEND) {
|
||||||
|
if (saved_home) {
|
||||||
|
setenv("HOME", saved_home_value.c_str(), 1);
|
||||||
|
}
|
||||||
|
std::remove(ini);
|
||||||
|
std::remove(section_path_append_ini);
|
||||||
|
return 51;
|
||||||
|
}
|
||||||
|
if (plugin->last_errmsg() != "bad path append") {
|
||||||
|
if (saved_home) {
|
||||||
|
setenv("HOME", saved_home_value.c_str(), 1);
|
||||||
|
}
|
||||||
|
std::remove(ini);
|
||||||
|
std::remove(section_path_append_ini);
|
||||||
|
return 52;
|
||||||
|
}
|
||||||
|
if (saved_home) {
|
||||||
|
setenv("HOME", saved_home_value.c_str(), 1);
|
||||||
|
}
|
||||||
|
std::remove(section_path_append_ini);
|
||||||
const char *plain_path_ini = "/tmp/cnc_sim_python_plugin_probe_plain_path.ini";
|
const char *plain_path_ini = "/tmp/cnc_sim_python_plugin_probe_plain_path.ini";
|
||||||
{
|
{
|
||||||
FILE *file = std::fopen(plain_path_ini, "w");
|
FILE *file = std::fopen(plain_path_ini, "w");
|
||||||
|
|||||||
@@ -123,6 +123,47 @@ int main() {
|
|||||||
nonrandom_spindle.offset.tran.z != 4.25) {
|
nonrandom_spindle.offset.tran.z != 4.25) {
|
||||||
return 20;
|
return 20;
|
||||||
}
|
}
|
||||||
|
CANON_TOOL_TABLE spindle_only = tooldata_entry_init();
|
||||||
|
spindle_only.toolno = 99;
|
||||||
|
spindle_only.pocketno = 0;
|
||||||
|
spindle_only.offset.tran.z = 9.0;
|
||||||
|
if (tooldata_put(spindle_only, 0) != IDX_OK) {
|
||||||
|
return 21;
|
||||||
|
}
|
||||||
|
CANON_TOOL_TABLE saved_nonspindle = tooldata_entry_init();
|
||||||
|
saved_nonspindle.toolno = 7;
|
||||||
|
saved_nonspindle.pocketno = 5;
|
||||||
|
saved_nonspindle.offset.tran.z = 4.25;
|
||||||
|
if (tooldata_put(saved_nonspindle, 1) == IDX_FAIL) {
|
||||||
|
return 26;
|
||||||
|
}
|
||||||
|
std::string nonrandom_save_template = make_temp_template("cnc_tooldata_common_nonrandom_save_XXXXXX");
|
||||||
|
std::vector<char> nonrandom_save_path(nonrandom_save_template.begin(), nonrandom_save_template.end());
|
||||||
|
nonrandom_save_path.push_back('\0');
|
||||||
|
const int nonrandom_save_fd = mkstemp(nonrandom_save_path.data());
|
||||||
|
if (nonrandom_save_fd < 0) {
|
||||||
|
return 22;
|
||||||
|
}
|
||||||
|
close(nonrandom_save_fd);
|
||||||
|
// LinuxCNC source basis: src/emc/tooldata/tooldata_common.cc saves
|
||||||
|
// nonrandom tool tables starting at pocket 1, so spindle pocket 0 is not
|
||||||
|
// emitted unless DB_ACTIVE selects the one-entry spindle save path.
|
||||||
|
if (tooldata_save(nonrandom_save_path.data()) != 0) {
|
||||||
|
std::remove(nonrandom_save_path.data());
|
||||||
|
return 23;
|
||||||
|
}
|
||||||
|
FILE *nonrandom_save_fp = std::fopen(nonrandom_save_path.data(), "r");
|
||||||
|
if (!nonrandom_save_fp) {
|
||||||
|
std::remove(nonrandom_save_path.data());
|
||||||
|
return 24;
|
||||||
|
}
|
||||||
|
char nonrandom_saved[CANON_TOOL_ENTRY_LEN * 2] = {};
|
||||||
|
std::fread(nonrandom_saved, 1, sizeof(nonrandom_saved) - 1, nonrandom_save_fp);
|
||||||
|
std::fclose(nonrandom_save_fp);
|
||||||
|
std::remove(nonrandom_save_path.data());
|
||||||
|
if (std::strstr(nonrandom_saved, "T99") || !std::strstr(nonrandom_saved, "T7")) {
|
||||||
|
return 25;
|
||||||
|
}
|
||||||
|
|
||||||
tooldata_init(true);
|
tooldata_init(true);
|
||||||
tooldata_set_db(DB_ACTIVE);
|
tooldata_set_db(DB_ACTIVE);
|
||||||
|
|||||||
@@ -203,6 +203,19 @@ int main() {
|
|||||||
if (separator == std::string::npos || missing_db_program_with_arg[separator] != 0) {
|
if (separator == std::string::npos || missing_db_program_with_arg[separator] != 0) {
|
||||||
return 56;
|
return 56;
|
||||||
}
|
}
|
||||||
|
char missing_db_program_with_args[] = "/tmp/cnc_tooldata_probe_missing_db_program alpha beta";
|
||||||
|
if (tooldata_db_init(missing_db_program_with_args, 0) != -1) {
|
||||||
|
return 83;
|
||||||
|
}
|
||||||
|
// LinuxCNC src/emc/tooldata/tooldata_db.cc tokenizes progname_plus_args
|
||||||
|
// in place with strtok_r() before checking whether argv[0] is executable.
|
||||||
|
if (missing_db_program_with_args[42] != 0 ||
|
||||||
|
missing_db_program_with_args[48] != 0 ||
|
||||||
|
std::strcmp(missing_db_program_with_args, "/tmp/cnc_tooldata_probe_missing_db_program") != 0 ||
|
||||||
|
std::strcmp(missing_db_program_with_args + 43, "alpha") != 0 ||
|
||||||
|
std::strcmp(missing_db_program_with_args + 49, "beta") != 0) {
|
||||||
|
return 84;
|
||||||
|
}
|
||||||
std::string missing_db_program_string = make_temp_path("cnc_tooldata_probe_missing_db_program");
|
std::string missing_db_program_string = make_temp_path("cnc_tooldata_probe_missing_db_program");
|
||||||
std::vector<char> missing_db_program(
|
std::vector<char> missing_db_program(
|
||||||
missing_db_program_string.begin(),
|
missing_db_program_string.begin(),
|
||||||
@@ -272,6 +285,23 @@ int main() {
|
|||||||
if (tooldata_put(tool, 12) != IDX_NEW) {
|
if (tooldata_put(tool, 12) != IDX_NEW) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
CANON_TOOL_TABLE lower_index_tool = tooldata_entry_init();
|
||||||
|
lower_index_tool.toolno = 3;
|
||||||
|
lower_index_tool.pocketno = 5;
|
||||||
|
// LinuxCNC src/emc/tooldata/tooldata_mmap.cc returns IDX_OK for writes at
|
||||||
|
// or below the current last_index and leaves last_index unchanged.
|
||||||
|
if (tooldata_put(lower_index_tool, 5) != IDX_OK) {
|
||||||
|
return 80;
|
||||||
|
}
|
||||||
|
if (tooldata_last_index_get() != 12) {
|
||||||
|
return 81;
|
||||||
|
}
|
||||||
|
CANON_TOOL_TABLE lower_index_loaded = tooldata_entry_init();
|
||||||
|
if (tooldata_get(&lower_index_loaded, 5) != IDX_OK ||
|
||||||
|
lower_index_loaded.toolno != 3 ||
|
||||||
|
lower_index_loaded.pocketno != 5) {
|
||||||
|
return 82;
|
||||||
|
}
|
||||||
|
|
||||||
CANON_TOOL_TABLE loaded = tooldata_entry_init();
|
CANON_TOOL_TABLE loaded = tooldata_entry_init();
|
||||||
if (tooldata_get(&loaded, 12) != IDX_OK) {
|
if (tooldata_get(&loaded, 12) != IDX_OK) {
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ a source-link/build guard only; it does not add CNC behavior and must not become
|
|||||||
|
|
||||||
- `src/emc/rs274ngc/gcodemodule.cc`, `canonmodule.cc`, `interpmodule.cc`, and
|
- `src/emc/rs274ngc/gcodemodule.cc`, `canonmodule.cc`, `interpmodule.cc`, and
|
||||||
`py*.cc` provide the Python and Boost.Python module binding blockers.
|
`py*.cc` provide the Python and Boost.Python module binding blockers.
|
||||||
|
- `test-linuxcnc-wasm-python-c-api-symbols.sh` compiles the blocked
|
||||||
|
Python/Boost.Python binding sources with inert Python/runtime shims so their
|
||||||
|
source surface is covered without enabling Python execution.
|
||||||
- `src/emc/rs274ngc/interp_python.cc`, `interp_remap.cc`,
|
- `src/emc/rs274ngc/interp_python.cc`, `interp_remap.cc`,
|
||||||
`interp_namedparams.cc`, `interp_o_word.cc`, `interp_setup.cc`, and
|
`interp_namedparams.cc`, `interp_o_word.cc`, `interp_setup.cc`, and
|
||||||
`rs274ngc_pre.cc` keep Python/Boost.Python remap paths as shimmed core
|
`rs274ngc_pre.cc` keep Python/Boost.Python remap paths as shimmed core
|
||||||
@@ -35,6 +38,7 @@ a source-link/build guard only; it does not add CNC behavior and must not become
|
|||||||
| Analyzer section | Count | Boundary |
|
| Analyzer section | Count | Boundary |
|
||||||
| --- | ---: | --- |
|
| --- | ---: | --- |
|
||||||
| `python` | 8 | Blocked Python/Boost.Python module sources. |
|
| `python` | 8 | Blocked Python/Boost.Python module sources. |
|
||||||
|
| `python-compile-covered` | 8 | Blocked Python/Boost.Python module sources compiled by the inert Python C API symbol probe while remaining blockers. |
|
||||||
| `dlopen` | 0 | blocked `dlopen` and blocked tooldata-users remain empty. |
|
| `dlopen` | 0 | blocked `dlopen` and blocked tooldata-users remain empty. |
|
||||||
| `tooldata` | 1 | Native tooldata mmap blocker. |
|
| `tooldata` | 1 | Native tooldata mmap blocker. |
|
||||||
| `tooldata-users` | 0 | Blocked tooldata user sources remain empty. |
|
| `tooldata-users` | 0 | Blocked tooldata user sources remain empty. |
|
||||||
@@ -80,6 +84,9 @@ Required tracked core examples:
|
|||||||
blocked-source replacements stay executable failures.
|
blocked-source replacements stay executable failures.
|
||||||
- The WASM blockers source-map guard validates LinuxCNC source/blocker
|
- The WASM blockers source-map guard validates LinuxCNC source/blocker
|
||||||
ownership and manifest drift only; it does not interpret G-code.
|
ownership and manifest drift only; it does not interpret G-code.
|
||||||
|
- Python/Boost.Python blockers are compile-covered by the inert Python C API probe,
|
||||||
|
but they remain tracked blockers until Python/remap execution is ported,
|
||||||
|
wrapped, or replaced by a source-backed browser-safe LinuxCNC adaptation.
|
||||||
|
|
||||||
## Checks
|
## Checks
|
||||||
|
|
||||||
|
|||||||
@@ -195,6 +195,14 @@ grep -F "src/emc/rs274ngc/gcodemodule.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<
|
|||||||
grep -F "src/emc/rs274ngc/interpmodule.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
grep -F "src/emc/rs274ngc/interpmodule.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
||||||
grep -F "src/emc/rs274ngc/pyarrays.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
grep -F "src/emc/rs274ngc/pyarrays.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
||||||
grep -F "src/emc/rs274ngc/pyparamclass.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
grep -F "src/emc/rs274ngc/pyparamclass.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
||||||
|
grep -F "[python-compile-covered]" <<<"$output" >/dev/null
|
||||||
|
grep -F "src/emc/rs274ngc/canonmodule.cc" <<<"$(sed -n '/^\[python-compile-covered\]/,/^$/p' <<<"$output")" >/dev/null
|
||||||
|
grep -F "src/emc/rs274ngc/gcodemodule.cc" <<<"$(sed -n '/^\[python-compile-covered\]/,/^$/p' <<<"$output")" >/dev/null
|
||||||
|
grep -F "src/emc/rs274ngc/interpmodule.cc" <<<"$(sed -n '/^\[python-compile-covered\]/,/^$/p' <<<"$output")" >/dev/null
|
||||||
|
grep -F "src/emc/rs274ngc/pyarrays.cc" <<<"$(sed -n '/^\[python-compile-covered\]/,/^$/p' <<<"$output")" >/dev/null
|
||||||
|
grep -F "src/emc/rs274ngc/pyparamclass.cc" <<<"$(sed -n '/^\[python-compile-covered\]/,/^$/p' <<<"$output")" >/dev/null
|
||||||
|
grep -F 'python_compile_probe_covers "$path"' analyze-linuxcnc-wasm-blockers.sh >/dev/null
|
||||||
|
grep -F 'test-linuxcnc-wasm-python-c-api-symbols.sh' analyze-linuxcnc-wasm-blockers.sh >/dev/null
|
||||||
grep -F "[dlopen]" <<<"$output" >/dev/null
|
grep -F "[dlopen]" <<<"$output" >/dev/null
|
||||||
grep -F "(none)" <<<"$(sed -n '/^\[dlopen\]/,/^$/p' <<<"$output")" >/dev/null
|
grep -F "(none)" <<<"$(sed -n '/^\[dlopen\]/,/^$/p' <<<"$output")" >/dev/null
|
||||||
grep -F "[tooldata]" <<<"$output" >/dev/null
|
grep -F "[tooldata]" <<<"$output" >/dev/null
|
||||||
|
|||||||
94
test-linuxcnc-wasm-python-binding-link.sh
Executable file
94
test-linuxcnc-wasm-python-binding-link.sh
Executable file
@@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# LinuxCNC source basis: src/emc/rs274ngc/canonmodule.cc, interpmodule.cc,
|
||||||
|
# and py*.cc are blocked Python/Boost.Python binding sources. This probe links
|
||||||
|
# the non-gcodemodule binding objects against inert Python/runtime shims, while
|
||||||
|
# keeping src/emc/rs274ngc/gcodemodule.cc isolated because it defines Canon
|
||||||
|
# callbacks that collide with the browser runtime bridge.
|
||||||
|
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
||||||
|
|
||||||
|
preflight_cache_dir=${CNC_SIM_PREFLIGHT_CACHE_DIR:-build/wasm-probe-preflight-cache}
|
||||||
|
python_build_dir=${CNC_SIM_WASM_PYTHON_C_API_BUILD_DIR:-build/wasm-python-c-api-symbols}
|
||||||
|
if [[ -z "$python_build_dir" ]]; then
|
||||||
|
echo "CNC_SIM_WASM_PYTHON_C_API_BUILD_DIR must not be empty" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "$python_build_dir" =~ [[:space:]] ]]; then
|
||||||
|
echo "CNC_SIM_WASM_PYTHON_C_API_BUILD_DIR must not contain whitespace: $python_build_dir" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mkdir -p "$python_build_dir"
|
||||||
|
python_build_dir=$(cd "$python_build_dir" && pwd)
|
||||||
|
if [[ "$python_build_dir" == "/" ]]; then
|
||||||
|
echo "CNC_SIM_WASM_PYTHON_C_API_BUILD_DIR must not be the filesystem root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exec 9>"$python_build_dir/python-binding-link.lock"
|
||||||
|
flock 9
|
||||||
|
|
||||||
|
CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" \
|
||||||
|
CNC_SIM_WASM_PYTHON_C_API_BUILD_DIR="$python_build_dir" \
|
||||||
|
./test-linuxcnc-wasm-python-c-api-symbols.sh
|
||||||
|
runtime_probe=$(CNC_SIM_PREFLIGHT_CACHE_DIR="$preflight_cache_dir" ./build-linuxcnc-wasm-link-probe.sh --mode runtime "$manifest")
|
||||||
|
runtime_dir=$(dirname "$runtime_probe")
|
||||||
|
runtime_signature="$runtime_dir/link.signature"
|
||||||
|
if [[ ! -f "$runtime_signature" ]]; then
|
||||||
|
echo "missing runtime link probe signature: $runtime_signature" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mapfile -t runtime_objects < <(awk 'flag{print} /^OBJECTS:$/{flag=1; next}' "$runtime_signature" | sed '/^$/d')
|
||||||
|
if [[ "${#runtime_objects[@]}" -eq 0 ]]; then
|
||||||
|
echo "runtime link probe signature did not list objects" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
non_gcode_binding_objects=(
|
||||||
|
"$python_build_dir/canonmodule.o"
|
||||||
|
"$python_build_dir/interpmodule.o"
|
||||||
|
"$python_build_dir/pyarrays.o"
|
||||||
|
"$python_build_dir/pyblock.o"
|
||||||
|
"$python_build_dir/pyemctypes.o"
|
||||||
|
"$python_build_dir/pyinterp1.o"
|
||||||
|
"$python_build_dir/pyparamclass.o"
|
||||||
|
)
|
||||||
|
for object in "${non_gcode_binding_objects[@]}" "$python_build_dir/gcodemodule.o"; do
|
||||||
|
if [[ ! -f "$object" ]]; then
|
||||||
|
echo "missing Python binding object: $object" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
main_source="$python_build_dir/python_binding_link_probe_main.cc"
|
||||||
|
main_object="$python_build_dir/python_binding_link_probe_main.o"
|
||||||
|
target="$python_build_dir/python_binding_link_probe"
|
||||||
|
cat > "$main_source" <<'EOF'
|
||||||
|
int main() { return 0; }
|
||||||
|
EOF
|
||||||
|
trap 'rm -f "$main_source" "$main_object"' EXIT
|
||||||
|
|
||||||
|
cxx=${CXX:-g++}
|
||||||
|
if [[ -z ${CXX:-} ]] && command -v ccache >/dev/null 2>&1; then
|
||||||
|
cxx="ccache $cxx"
|
||||||
|
fi
|
||||||
|
$cxx -std=c++17 -c "$main_source" -o "$main_object"
|
||||||
|
$cxx "${runtime_objects[@]}" "${non_gcode_binding_objects[@]}" "$main_object" \
|
||||||
|
-Wl,--no-gc-sections -lfmt -o "$target"
|
||||||
|
|
||||||
|
negative_log="$python_build_dir/python_binding_gcodemodule_collision.err"
|
||||||
|
if $cxx "${runtime_objects[@]}" "${non_gcode_binding_objects[@]}" "$python_build_dir/gcodemodule.o" "$main_object" \
|
||||||
|
-Wl,--no-gc-sections -lfmt -o "$python_build_dir/python_binding_link_probe_with_gcodemodule" \
|
||||||
|
2>"$negative_log"; then
|
||||||
|
echo "gcodemodule binding unexpectedly linked with runtime bridge Canon callbacks" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
grep -F "multiple definition of" "$negative_log" >/dev/null
|
||||||
|
grep -F "gcodemodule.o" "$negative_log" >/dev/null
|
||||||
|
grep -F "linuxcnc_canon_bridge.cpp" "$negative_log" >/dev/null
|
||||||
|
|
||||||
|
"$target"
|
||||||
|
|
||||||
|
echo "linuxcnc wasm Python binding link probe passed"
|
||||||
@@ -77,6 +77,8 @@ grep -F 'LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh "$mani
|
|||||||
grep -F 'LinuxCNC source basis: Puma560 DH parameter output is generated from' generate-linuxcnc-puma560-dh-parameters.sh >/dev/null
|
grep -F 'LinuxCNC source basis: Puma560 DH parameter output is generated from' generate-linuxcnc-puma560-dh-parameters.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: all-native guardrails lock source-backed manifests' test-all-native.sh >/dev/null
|
grep -F 'LinuxCNC source basis: all-native guardrails lock source-backed manifests' test-all-native.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: this probe derives required Python C API exports from' test-linuxcnc-wasm-python-c-api-symbols.sh >/dev/null
|
grep -F 'LinuxCNC source basis: this probe derives required Python C API exports from' test-linuxcnc-wasm-python-c-api-symbols.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC source basis: src/emc/rs274ngc/canonmodule.cc, interpmodule.cc,' test-linuxcnc-wasm-python-binding-link.sh >/dev/null
|
||||||
|
grep -F 'LinuxCNC wasm Python binding link probe' build-wasm.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: this probe compares wasm-safe tooldata runtime stubs' test-linuxcnc-wasm-tooldata-runtime-symbols.sh >/dev/null
|
grep -F 'LinuxCNC source basis: this probe compares wasm-safe tooldata runtime stubs' test-linuxcnc-wasm-tooldata-runtime-symbols.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: the standalone probe links src/emc/rs274ngc/interp_base.cc' test-linuxcnc-wasm-interp-base-link.sh >/dev/null
|
grep -F 'LinuxCNC source basis: the standalone probe links src/emc/rs274ngc/interp_base.cc' test-linuxcnc-wasm-interp-base-link.sh >/dev/null
|
||||||
grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and' test-linuxcnc-wasm-python-plugin-link.sh >/dev/null
|
grep -F 'LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc and' test-linuxcnc-wasm-python-plugin-link.sh >/dev/null
|
||||||
|
|||||||
Reference in New Issue
Block a user