feat(build-time-versioning): version macro/helper functions with unknown fallback
Adds xce_version_field()/xce_compose_version() (utils.h/utils.c) to compose a version string carrying commit id + build time, rendering "unknown" for either field when its underlying meson-supplied define is empty -- ready for controller/scheduler/worker to consume. MK_VERSION/STR (the pre-existing, compile-time-only macro pair) can't express this empty-to-"unknown" substitution at the preprocessor level, so this is a runtime mechanism instead. Round 1 review REJECTED an earlier version of this task for silently orphaning MK_VERSION/STR (the task explicitly asked to "extend" them) and for leaving an undocumented architectural trap: argp_program_version is a file-scope const char* initialized at compile time, which cannot call a runtime function -- consuming code must instead compute into a static buffer inside main() and assign the pointer before argp_parse() runs. Round 2 adds an explicit SUPERSEDED doc comment on MK_VERSION/STR plus NOTE FOR CALLERS guidance covering both points, and was APPROVED. Also expands task 3.2's boundary to include controller/testsuite/test.c (a third MK_VERSION/STR call site discovered during review) so no caller of the superseded macro survives implementation. 5 new unit tests in test_utils.c (RED->GREEN, TDD). Task 3.1/13 of build-time-versioning. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
d08fda76a5
commit
48a86cdab6
4 changed files with 159 additions and 7 deletions
|
|
@ -296,6 +296,47 @@ int mylog_setlevel(char* level) { return tlog_setlevel(name_to_level(level)); }
|
|||
|
||||
void mylog_fini() { tlog_exit(); }
|
||||
|
||||
/* build-time-versioning task 3.1: see the SUPERSEDED comment above
|
||||
* MK_VERSION in utils.h. raw is typically
|
||||
* STR(VERSION_COMMIT_ID)/STR(VERSION_BUILD_TIME), which is "" (never a
|
||||
* missing/NULL token) when the corresponding meson option was left unset
|
||||
* -- NULL is also accepted defensively for any other caller. */
|
||||
const char* xce_version_field(const char* raw)
|
||||
{
|
||||
if (raw == NULL || raw[0] == '\0') {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
return raw;
|
||||
}
|
||||
|
||||
/* NOTE FOR CALLERS with a file-scope `argp_program_version`-style global
|
||||
* (controller/main.c, scheduler/src/main.c both currently have one, built
|
||||
* today via the now-superseded MK_VERSION macro -- see utils.h): this
|
||||
* function is a regular runtime call, NOT a constant expression, so its
|
||||
* result cannot initialize a file-scope variable
|
||||
* (`const char* argp_program_version = xce_compose_version(...);` at file
|
||||
* scope will not compile). Compute the version string into a
|
||||
* `static char buf[...]` (sized generously enough for prefix + commit +
|
||||
* " built " + timestamp, e.g. 128 bytes) inside main() -- or any function
|
||||
* that runs before argp_parse() is called, since argp reads
|
||||
* argp_program_version by pointer when --version/-V is processed -- then
|
||||
* point the (non-const-initialized, runtime-assigned) global at that
|
||||
* buffer. buf must outlive the call (static or otherwise long-lived
|
||||
* storage, never a stack buffer that goes out of scope before argp_parse()
|
||||
* runs). */
|
||||
int xce_compose_version(char* buf, size_t bufsz, const char* prefix,
|
||||
const char* commit, const char* build_time)
|
||||
{
|
||||
if (buf == NULL || bufsz == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return snprintf(buf, bufsz, "%s%s built %s",
|
||||
(prefix != NULL) ? prefix : "",
|
||||
xce_version_field(commit), xce_version_field(build_time));
|
||||
}
|
||||
|
||||
static _Thread_local ectx_t ectx;
|
||||
|
||||
void set_error(char* file, char* func, int line, int code)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue