commit 3ad7ea9ac8a11b814c0288fb0ec7f35cc4b20032
parent 9242af272b569d2335834ab5c18eb2130e870e46
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Tue, 9 Jun 2026 08:59:39 -0700
driver/runtime: resolve rt support dir from the real image path
The rt support-dir search derived <bindir>/../rt and <bindir>/support/rt by
splitting argv[0]. That fails when argv[0] is not a usable path -- a bare
program name when kit is on PATH, a relative invocation, or a tool symlink
whose directory holds no rt -- leaving only the cwd-relative ./rt. Fall back to
the actual image path (driver_self_exe_path: GetModuleFileNameW on Windows,
/proc/self/exe on Linux, ...) and retry the binary-relative roots against it.
argv[0] is still tried first, so POSIX behavior is unchanged; the fallback is
what makes <bindir>/support/rt resolve when kit.exe is invoked by bare name on
Windows (verified on the VM). tool_path (stat'd for rt-archive cache
invalidation) now holds an owned dup of whichever path located rt, freed in
driver_runtime_support_fini.
Diffstat:
2 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/driver/lib/runtime.c b/driver/lib/runtime.c
@@ -362,20 +362,43 @@ int driver_runtime_resolve(DriverEnv* env, const char* explicit_support_dir,
DriverRuntimeSupport zero = {0};
*out = zero;
+ char* self = NULL;
+ size_t self_size = 0;
+ const char* tool = argv0;
+
if (explicit_support_dir) {
rc = rt_try_support_root(env, explicit_support_dir, out);
} else if (rt_try_support_root(env, ".", out) == 0) {
rc = 0;
} else if (rt_try_argv0_checkout_root(env, argv0, out) == 0) {
rc = 0;
- } else {
- rc = rt_try_argv0_support(env, argv0, out);
+ } else if (rt_try_argv0_support(env, argv0, out) == 0) {
/* rt found as a <bindir>/support/rt sibling: this is a distribution
* install, not a build tree. Mark it so the on-demand rt archive lands
* in the user cache dir rather than polluting the install. */
- if (rc == 0) out->install_layout = 1;
+ rc = 0;
+ out->install_layout = 1;
+ } else if (driver_self_exe_path(env, &self, &self_size) == 0 && self) {
+ /* argv[0] wasn't a usable path for binary-relative discovery — a bare
+ * program name when kit is on PATH, a relative invocation, or a tool
+ * symlink whose directory holds no rt. Retry against the real image path
+ * (GetModuleFileNameW on Windows, /proc/self/exe on Linux, ...). */
+ tool = self;
+ if (rt_try_argv0_checkout_root(env, self, out) == 0) {
+ rc = 0;
+ } else if (rt_try_argv0_support(env, self, out) == 0) {
+ rc = 0;
+ out->install_layout = 1;
+ } else {
+ rc = 1;
+ }
+ } else {
+ rc = 1;
}
- if (rc == 0) out->tool_path = argv0;
+ /* Own the located image path: it outlives `self`'s free below and the
+ * caller's argv, and is stat'd later for rt-archive cache invalidation. */
+ if (rc == 0) out->tool_path = rt_dup(env, tool, &out->tool_path_size);
+ if (self) driver_free(env, self, self_size);
return rc;
}
@@ -383,6 +406,11 @@ void driver_runtime_support_fini(DriverEnv* env, DriverRuntimeSupport* s) {
rt_free_str(env, &s->include_dir, &s->include_dir_size);
rt_free_str(env, &s->rt_root, &s->rt_root_size);
rt_free_str(env, &s->support_root, &s->support_root_size);
+ if (s->tool_path && s->tool_path_size) {
+ driver_free(env, (void*)s->tool_path, s->tool_path_size);
+ s->tool_path = NULL;
+ s->tool_path_size = 0;
+ }
}
int driver_runtime_add_freestanding_headers(const DriverRuntimeSupport* s,
diff --git a/driver/lib/runtime.h b/driver/lib/runtime.h
@@ -13,7 +13,12 @@ typedef struct DriverRuntimeSupport {
size_t rt_root_size;
char* include_dir;
size_t include_dir_size;
+ /* Owned dup of the kit image path that located the rt tree — argv[0] when it
+ * was a usable path, else the real self-exe path (GetModuleFileNameW /
+ * /proc/self/exe). Stat'd for rt-archive cache invalidation; freed by
+ * driver_runtime_support_fini. */
const char* tool_path;
+ size_t tool_path_size;
/* Set when rt was resolved as a <bindir>/support/rt sibling, i.e. a
* distribution install rather than a source checkout. Steers the on-demand
* rt archive build toward the user cache dir instead of writing into the