feat(build-time-versioning): controller/scheduler --version and startup log

Migrates argp_program_version in controller/main.c, scheduler/main.c,
and xce_test's test.c from the compile-time MK_VERSION/STR construction
to xce_compose_version(), computed into a static buffer and assigned
before argp_parse() runs (argp_program_version is a file-scope pointer,
not a constant expression it can be initialized from at compile time).

Each daemon's startup log now carries the identical version string
(never recomputed) on its first INFO line -- scheduler's BOTH
mutually-exclusive branches (--peers and no-peers), not just the one
literally named in the task text, since "when the daemon starts" is
unconditional.

Live-verified: --version and startup-log output are byte-identical for
both daemons across all branches. No remaining MK_VERSION callers
repo-wide.

Task 3.2/13 of build-time-versioning.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-08-20 11:02:56 +00:00
parent 854f776733
commit 88649a0462
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
4 changed files with 65 additions and 15 deletions

View file

@ -22,8 +22,13 @@ extern int scheduler_req_handler(xce_request_t*, void*);
static char doc[] = "xce_scheduler";
static char args_doc[] = "";
const char* argp_program_version
= MK_VERSION("xce v0.0.0.1-", STR(VERSION_COMMIT_ID));
/* build-time-versioning task 3.2: no longer a compile-time initializer --
* argp reads this by pointer when --version/-V is processed, and
* xce_compose_version() (utils.h) is a runtime function, not a constant
* expression, so it cannot initialize a file-scope global. main() assigns
* this to a static buffer, computed via xce_compose_version(), before
* argp_parse() runs. See utils.h's NOTE FOR TASK 3.2 above MK_VERSION. */
const char* argp_program_version = NULL;
const char* argp_program_bug_address = BUG_EMAIL;
/* Long-option identifiers (beyond ASCII range to avoid collisions with the
@ -224,9 +229,21 @@ int main(int argc, char* argv[])
xce_client_config_t config;
xce_cluster_config_t cluster_cfg = { 0 };
const xce_cluster_config_t* cluster_cfg_ptr = NULL;
/* build-time-versioning task 3.2: composed once, read by both
* argp_program_version (--version/-V) and the startup INFO log below --
* never recomputed, so the two can never disagree (Req 2.2). static so
* it outlives this point in main() (contract documented on
* xce_compose_version() in utils.c). */
static char version_buf[128];
memset(&arguments, 0x0, sizeof(arguments));
/* Must run before argp_parse(): argp reads argp_program_version by
* pointer when --version/-V is processed. */
xce_compose_version(version_buf, sizeof(version_buf), "xce v0.0.0.1-",
STR(VERSION_COMMIT_ID), STR(VERSION_BUILD_TIME));
argp_program_version = version_buf;
argp_parse(&argp, argc, argv, 0, 0, &arguments);
if (arguments.logfile != NULL) {
@ -374,11 +391,12 @@ int main(int argc, char* argv[])
"only <=%d validated for HA",
cluster_cfg.candidates_count, N_MAX_MASTERS);
}
INFO("HA cluster config: %d candidate(s), identity=%s",
cluster_cfg.candidates_count, cluster_cfg.identity);
INFO("HA cluster config: %d candidate(s), identity=%s, version %s",
cluster_cfg.candidates_count, cluster_cfg.identity, version_buf);
cluster_cfg_ptr = &cluster_cfg;
} else {
INFO("No --peers flag; using single-controller path");
INFO("No --peers flag; using single-controller path, version %s",
version_buf);
}
init_config(&config);