From 8fb0bdd8586efc9ae1402e09ac227a1524404366 Mon Sep 17 00:00:00 2001 From: Christian Glombek Date: Fri, 31 Jul 2026 02:07:15 +0200 Subject: [PATCH] [posix] add `--version` to ot-ctl, ot-daemon and ot-cli (#13424) The POSIX binaries cannot report their own version. ot-daemon and ot-cli only log it to syslog at startup, and ot-ctl has no version output at all: `ot-ctl version` queries the daemon, so it needs one running and reports the daemon's version rather than the client's. This also makes the binaries awkward to package, as build systems commonly probe an installed executable with `--version` to check the version actually shipped. Add -V/--version to all three. ot-daemon and ot-cli, which share src/posix/main.c, print otGetVersionString(), the same string already logged at startup. ot-ctl is a standalone client that does not link the core library, so it prints PACKAGE_VERSION, which is its own build version and is available without a running daemon. -V rather than -v, as -v is already --verbose in main.c; using the same letter across all three keeps the binaries consistent. ot-ctl gains the PACKAGE_VERSION compile definition, matching how src/cli and src/ncp already receive it. For build environments other than CMake and GN, which define the macro themselves, openthread-posix-config.h falls back to "unknown" so the client stays compilable. $ ot-ctl --version thread-reference-20250612-1379-g221777306 $ ot-daemon --version OPENTHREAD/thread-reference-20250612-1379-g221777306; POSIX; Jul 29 2026 20:19:02 Assisted-By: Claude Fable 5 --- src/posix/client.cpp | 11 +++++++++-- src/posix/daemon.cmake | 3 +++ src/posix/main.c | 11 +++++++++-- src/posix/platform/openthread-posix-config.h | 11 +++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/posix/client.cpp b/src/posix/client.cpp index cbb4a24c9..496b61e6d 100644 --- a/src/posix/client.cpp +++ b/src/posix/client.cpp @@ -207,10 +207,12 @@ exit: constexpr char kOptInterfaceName = 'I'; constexpr char kOptHelp = 'h'; +constexpr char kOptVersion = 'V'; const struct option kOptions[] = { {"interface-name", required_argument, nullptr, kOptInterfaceName}, {"help", no_argument, nullptr, kOptHelp}, + {"version", no_argument, nullptr, kOptVersion}, {nullptr, 0, nullptr, 0}, }; @@ -221,7 +223,8 @@ void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode) " %s [Options] [--] ...\n" "Options:\n" " -h --help Display this usage information.\n" - " -I --interface-name name Thread network interface name.\n", + " -I --interface-name name Thread network interface name.\n" + " -V --version Display version information.\n", aProgramName); exit(aExitCode); } @@ -237,7 +240,7 @@ Config ParseArg(int &aArgCount, char **&aArgVector) optind = 1; - for (int index, option; (option = getopt_long(aArgCount, aArgVector, "+I:h", kOptions, &index)) != -1;) + for (int index, option; (option = getopt_long(aArgCount, aArgVector, "+I:hV", kOptions, &index)) != -1;) { switch (option) { @@ -247,6 +250,10 @@ Config ParseArg(int &aArgCount, char **&aArgVector) case kOptHelp: PrintUsage(aArgVector[0], stdout, OT_EXIT_SUCCESS); break; + case kOptVersion: + printf("%s\n", PACKAGE_VERSION); + exit(OT_EXIT_SUCCESS); + break; default: PrintUsage(aArgVector[0], stderr, OT_EXIT_FAILURE); break; diff --git a/src/posix/daemon.cmake b/src/posix/daemon.cmake index c63de45e4..25a9f745b 100644 --- a/src/posix/daemon.cmake +++ b/src/posix/daemon.cmake @@ -67,6 +67,9 @@ target_compile_definitions(ot-ctl PRIVATE $<$:HAVE_LIB$=1>) endif() +target_compile_definitions(ot-ctl PRIVATE + "PACKAGE_VERSION=\"${OT_PACKAGE_VERSION}\"") + target_compile_options(ot-ctl PRIVATE ${OT_CFLAGS} ) diff --git a/src/posix/main.c b/src/posix/main.c index 3fe53530b..d4f8bf51e 100644 --- a/src/posix/main.c +++ b/src/posix/main.c @@ -135,6 +135,7 @@ enum OT_POSIX_OPT_PERSISTENT_INTERFACE = 'p', OT_POSIX_OPT_TIME_SPEED = 's', OT_POSIX_OPT_VERBOSE = 'v', + OT_POSIX_OPT_VERSION = 'V', OT_POSIX_OPT_SHORT_MAX = 128, @@ -163,6 +164,7 @@ static const struct option kOptions[] = { {"tun-device", required_argument, NULL, OT_POSIX_OPT_TUN_DEVICE}, #endif {"verbose", no_argument, NULL, OT_POSIX_OPT_VERBOSE}, + {"version", no_argument, NULL, OT_POSIX_OPT_VERSION}, {0, 0, 0, 0}}; static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode) @@ -184,7 +186,8 @@ static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode) " --radio-version Print radio firmware version.\n" " -p --persistent-interface Persistent the created thread network interface\n" " -s --time-speed factor Time speed up factor.\n" - " -v --verbose Also log to stderr.\n", + " -v --verbose Also log to stderr.\n" + " -V --version Display version information.\n", aProgramName); #ifdef SIGRTMIN fprintf(aStream, @@ -217,7 +220,7 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig) while (true) { int index = 0; - int option = getopt_long(aArgCount, aArgVector, "B:d:hI:nps:v", kOptions, &index); + int option = getopt_long(aArgCount, aArgVector, "B:d:hI:nps:vV", kOptions, &index); if (option == -1) { @@ -260,6 +263,10 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig) case OT_POSIX_OPT_VERBOSE: aConfig->mIsVerbose = true; break; + case OT_POSIX_OPT_VERSION: + printf("%s\n", otGetVersionString()); + exit(OT_EXIT_SUCCESS); + break; case OT_POSIX_OPT_RADIO_VERSION: aConfig->mPrintRadioVersion = true; break; diff --git a/src/posix/platform/openthread-posix-config.h b/src/posix/platform/openthread-posix-config.h index 9dad79cc7..99c85c893 100644 --- a/src/posix/platform/openthread-posix-config.h +++ b/src/posix/platform/openthread-posix-config.h @@ -41,6 +41,17 @@ * This file includes the POSIX platform-specific configurations. */ +/** + * @def PACKAGE_VERSION + * + * The version string reported by `ot-ctl --version`. The OpenThread build + * systems define it; this fallback keeps the client compiling in custom + * build environments that do not. + */ +#ifndef PACKAGE_VERSION +#define PACKAGE_VERSION "unknown" +#endif + /** * @def OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE *