From c8bb7d74e634e7ec0530510b5bd409e2a9ed8c86 Mon Sep 17 00:00:00 2001 From: Luca Toniolo <10792599+grandixximo@users.noreply.github.com> Date: Mon, 12 Oct 2026 02:13:37 +1100 Subject: [PATCH] tests: tool-frame checks the helpers as a realtime component The test compiled kins_util.c into a userspace program with -DULAPI. Since kins_util.c exports its helpers for switchkins_core, EXPORT_SYMBOL is undefined there, which GCC 13 lets through as an implicit int and GCC 14 rejects, so the test failed to build on GCC 14. The checks now run in a component loaded after switchkins_core, which exports the helpers, the way tests/kins-jacobian checks the kinematics modules. A failed check fails the load. The checks themselves are unchanged. Reported by hdiethelm in #4670. Fixes #4670 --- tests/tool-frame/skip | 4 +- tests/tool-frame/test.sh | 21 +++---- .../{test_tool_frame.c => toolframecheck.c} | 56 ++++++++++++++++--- 3 files changed, 57 insertions(+), 24 deletions(-) rename tests/tool-frame/{test_tool_frame.c => toolframecheck.c} (96%) diff --git a/tests/tool-frame/skip b/tests/tool-frame/skip index ee99160224a..a12f31a77c2 100755 --- a/tests/tool-frame/skip +++ b/tests/tool-frame/skip @@ -1,4 +1,4 @@ #!/bin/sh -# This test compiles kins_util.c from the source tree, which is only -# available in run-in-place builds. Skip when testing installed packages. +# Builds a realtime component with halcompile, which needs the build +# tools present. Skip when testing installed packages. [ -z "$SYSTEM_BUILD" ] diff --git a/tests/tool-frame/test.sh b/tests/tool-frame/test.sh index 2dae535797b..1697d5f4a27 100755 --- a/tests/tool-frame/test.sh +++ b/tests/tool-frame/test.sh @@ -1,17 +1,12 @@ #!/bin/bash set -e -# RIP layout: $HEADERS is $TOPDIR/include -TOPDIR=$(dirname "$HEADERS") +halcompile --install toolframecheck.c >/dev/null -# kins_util.c holds the shared kinematics helpers. Only the tool frame ones -# are exercised here, so build with function sections and let the linker drop -# the rest rather than dragging in the HAL pin setup the others need. -gcc -O2 -Wall -ffunction-sections -fdata-sections -DULAPI \ - -I"$HEADERS" -I"$TOPDIR/src" -I"$TOPDIR/src/emc" \ - -o test_tool_frame test_tool_frame.c "$TOPDIR/src/emc/kinematics/kins_util.c" \ - -L"$LIBDIR" -Wl,-rpath,"$LIBDIR" -Wl,--gc-sections \ - -lposemath -llinuxcnchal -lm - -./test_tool_frame -rm -f test_tool_frame +# switchkins_core exports the kins_util.c helpers and provides no +# kinematics of its own, so the checker reaches them as motion's +# kinematics module would +hal=$(mktemp --suffix=.hal) +printf 'loadrt switchkins_core\nloadrt toolframecheck\n' > "$hal" +halrun -f "$hal" +rm -f "$hal" diff --git a/tests/tool-frame/test_tool_frame.c b/tests/tool-frame/toolframecheck.c similarity index 96% rename from tests/tool-frame/test_tool_frame.c rename to tests/tool-frame/toolframecheck.c index 00103cb4678..ceab3acee12 100644 --- a/tests/tool-frame/test_tool_frame.c +++ b/tests/tool-frame/toolframecheck.c @@ -1,25 +1,45 @@ /* Unit tests for the tool frame helpers in kins_util.c. + * + * Loaded after switchkins_core, which exports the helpers, so they are + * checked as built for realtime. A failed check fails the load, and a + * failed load fails the test. * * The property worth pinning down is that relating one tool axis convention * to the other is a rotation and not a change of sign: negating the third * column on its own leaves a reflection, which is not a frame any machine can * hold, and it silently loses tool x as well. + * + * Author: LinuxCNC + * License: GPL Version 2 + * System: Linux + * + * Copyright (c) 2026 All rights reserved. */ -#include -#include -#include -#include "emcpos.h" -#include "kinematics.h" +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("tool frame helper checker"); #define DEG (M_PI/180.0) #define NUTATION 45.0 +static int comp_id = -1; static int failures; static void check(int ok, const char *what) { - if (!ok) { printf("FAIL: %s\n", what); failures++; } + if (!ok) { + rtapi_print_msg(RTAPI_MSG_ERR, "toolframecheck: FAIL %s\n", what); + failures++; + } } static PmRotationMatrix mat(double xx, double yx, double zx, @@ -217,7 +237,7 @@ static int holds(const double *sols, int count, int njoints, return 0; } -int main(void) +static void run_checks(void) { PmRotationMatrix m, r; @@ -650,7 +670,25 @@ int main(void) "a missing target is refused"); } - if (failures) { printf("%d failure(s)\n", failures); return 1; } - printf("all tool frame checks passed\n"); +} + +int rtapi_app_main(void) +{ + comp_id = hal_init("toolframecheck"); + if (comp_id < 0) { return comp_id; } + + run_checks(); + + if (failures) { + rtapi_print_msg(RTAPI_MSG_ERR, "toolframecheck: %d check(s) failed\n", + failures); + hal_exit(comp_id); + return -ERANGE; + } + + rtapi_print("toolframecheck: all tool frame checks passed\n"); + hal_ready(comp_id); return 0; } + +void rtapi_app_exit(void) { hal_exit(comp_id); }