commit b02403a3bef7110de12cc1abf50be58fdb36f6cd
parent 1a1d67691c24338bdec361ea3ffe2a3f11982c11
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Thu, 16 Jul 2026 10:10:50 -0700
hosted: canonicalize support and native SDK discovery
Diffstat:
11 files changed, 281 insertions(+), 81 deletions(-)
diff --git a/driver/cmd/build.c b/driver/cmd/build.c
@@ -116,6 +116,7 @@ typedef struct BuildOptions {
int function_sections; /* -ffunction-sections */
int data_sections; /* -fdata-sections */
int auto_var_init; /* -ftrivial-auto-var-init= (KitAutoVarInit) */
+ int stack_protector; /* KitStackProtectorMode */
int lto; /* -flto/-fno-lto */
uint64_t disabled_backend_features;
uint8_t default_visibility; /* KitSymVis */
@@ -172,6 +173,26 @@ static int build_lang_from_name(BuildOptions* o, const char* name,
return 0;
}
+static void build_err_unknown_language(BuildOptions* o, const char* flag,
+ const char* value) {
+ const char* const known[] = {"c", "asm", "assembler", "s",
+ "toy", "wasm", "wat"};
+ const char* candidates[sizeof known / sizeof known[0]];
+ DriverSuggestion suggestions[3];
+ size_t i, count = 0, n;
+ for (i = 0; i < sizeof known / sizeof known[0]; ++i) {
+ KitLanguage lang;
+ if (build_lang_from_name(o, known[i], &lang) == 0)
+ candidates[count++] = known[i];
+ }
+ n = driver_suggest_values(value, candidates, count, suggestions, 3);
+ if (n)
+ driver_errf(o->tool, "unsupported %s language: %s; did you mean '%s'?",
+ flag, value, suggestions[0].value);
+ else
+ driver_errf(o->tool, "unsupported %s language: %s", flag, value);
+}
+
/* ===================================================================== */
/* allocation / lifetime */
/* ===================================================================== */
@@ -323,8 +344,7 @@ static int build_try_scopable(BuildOptions* o, BuildGroup* g, int argc,
return -1;
}
if (build_lang_from_name(o, argv[*i], &lang) != 0) {
- driver_errf(o->tool, "unsupported -x language: %.*s",
- KIT_SLICE_ARG(kit_slice_cstr(argv[*i])));
+ build_err_unknown_language(o, "-x", argv[*i]);
return -1;
}
g->forced_lang = lang;
@@ -334,8 +354,7 @@ static int build_try_scopable(BuildOptions* o, BuildGroup* g, int argc,
KitLanguage lang;
BuildFeFlag* f;
if (build_lang_from_name(o, a + 2, &lang) != 0) {
- driver_errf(o->tool, "unsupported -X language: %.*s",
- KIT_SLICE_ARG(kit_slice_cstr(a + 2)));
+ build_err_unknown_language(o, "-X", a + 2);
return -1;
}
if (++(*i) >= argc) {
@@ -614,11 +633,23 @@ static int build_parse(int argc, char** argv, BuildOptions* o) {
continue;
}
if (driver_streq(a, "-fno-stack-protector")) {
+ o->stack_protector = KIT_STACK_PROTECTOR_NONE;
+ continue;
+ }
+ if (driver_streq(a, "-fstack-protector")) {
+ o->stack_protector = KIT_STACK_PROTECTOR_BASIC;
+ continue;
+ }
+ if (driver_streq(a, "-fstack-protector-strong")) {
+ o->stack_protector = KIT_STACK_PROTECTOR_STRONG;
+ continue;
+ }
+ if (driver_streq(a, "-fstack-protector-all")) {
+ o->stack_protector = KIT_STACK_PROTECTOR_ALL;
continue;
}
if (driver_strneq(a, "-fstack-protector", 17)) {
- driver_errf(o->tool,
- "%.*s is not supported yet; use -fno-stack-protector",
+ driver_errf(o->tool, "unsupported stack protector mode: %.*s",
KIT_SLICE_ARG(kit_slice_cstr(a)));
return 1;
}
@@ -1003,8 +1034,7 @@ static int build_parse(int argc, char** argv, BuildOptions* o) {
return 1;
}
if (driver_target_from_triple(argv[i], &t) != 0) {
- driver_errf(o->tool, "unrecognized target triple: %.*s",
- KIT_SLICE_ARG(kit_slice_cstr(argv[i])));
+ driver_err_unknown_target(o->tool, argv[i]);
return 1;
}
pic = o->target.pic;
@@ -1019,8 +1049,7 @@ static int build_parse(int argc, char** argv, BuildOptions* o) {
KitTargetSpec t;
uint8_t pic;
if (driver_target_from_triple(a + 9, &t) != 0) {
- driver_errf(o->tool, "unrecognized target triple: %.*s",
- KIT_SLICE_ARG(kit_slice_cstr(a + 9)));
+ driver_err_unknown_target(o->tool, a + 9);
return 1;
}
pic = o->target.pic;
@@ -1089,38 +1118,39 @@ static int build_is_link_output(const BuildOptions* o) {
return o->kind == BUILD_OUT_EXE || (o->kind == BUILD_OUT_LIB && o->dynamic);
}
-/* A sysroot on its own engages the hosted libc profile (matching clang/gcc).
- * -ffreestanding / -nostdinc / -nostdlib opt back out; -dynamic (shared) keeps
- * its standalone meaning. */
+/* A sysroot on its own engages the hosted compiler profile (matching
+ * clang/gcc). -ffreestanding / -nostdinc opt out of hosted headers; the
+ * -nostdlib family only suppresses link additions. */
static void build_enable_hosted_for_sysroot(BuildOptions* o) {
if (o->wants_hosted_libc) return;
if (o->shared && !driver_target_shared_uses_hosted(o->target)) return;
if (!o->sysroot || !o->sysroot[0]) return;
if (o->freestanding || o->nostdinc) return;
- if (o->no_stdlib || o->no_defaultlibs) return;
o->wants_hosted_libc = 1;
}
static void build_apply_default_hosted_profile(BuildOptions* o) {
+ KitTargetSpec host;
+ int native_macos;
if (!driver_target_default_hosted_profile(o->target)) return;
- if (o->no_stdlib || o->no_defaultlibs || o->wants_hosted_libc) return;
- if (!o->sysroot || !o->sysroot[0]) return;
+ if (o->wants_hosted_libc) return;
+ if (o->freestanding || o->nostdinc) return;
+ host = driver_host_target();
+ native_macos = host.os == KIT_OS_MACOS && o->target.os == KIT_OS_MACOS;
+ if ((!o->sysroot || !o->sysroot[0]) && !native_macos) return;
o->wants_hosted_libc = 1;
}
static int build_apply_hosted_profile(BuildOptions* o) {
+ int link_action;
int shared_hosted = o->shared && driver_target_shared_uses_hosted(o->target);
if (!o->wants_hosted_libc || (o->shared && !shared_hosted)) return 0;
- if (o->no_stdlib || o->no_defaultlibs) {
- driver_errf(o->tool,
- "-lc hosted expansion is disabled by -nostdlib/-nodefaultlibs");
- return 1;
- }
- /* build-* always links (or archives) its outputs, so the crt inputs always
- * apply: pass link_action = 1. */
+ link_action = build_is_link_output(o) && !o->no_stdlib && !o->no_defaultlibs;
+ /* Hosted defines/includes apply to every build-* compile. Only an executable
+ * or dynamic-library output consumes CRT/libc link inputs. */
return driver_link_inputs_apply_hosted(
&o->inputs, &o->hosted, &o->groups[0].cf, &o->link, o->target, o->sysroot,
- o->static_link, o->shared, o->no_startfiles, 1);
+ o->static_link, o->shared, o->no_startfiles, link_action);
}
/* ===================================================================== */
@@ -1309,6 +1339,7 @@ static void build_fill_code(const BuildOptions* o, KitCodeOptions* code) {
code->data_sections = o->data_sections ? true : false;
code->disabled_backend_features = o->disabled_backend_features;
code->trivial_auto_var_init = (uint8_t)o->auto_var_init;
+ code->stack_protector = (uint8_t)o->stack_protector;
code->lto = o->lto ? true : false;
code->epoch = o->epoch;
}
@@ -2429,18 +2460,35 @@ static int build_main(int argc, char** argv, int kind, const char* tool,
if (driver_runtime_resolve(&env, o.support_dir, o.driver_path, &runtime) ==
0) {
runtime_resolved = 1;
- if (driver_runtime_add_freestanding_headers(&runtime, &o.groups[0].cf) !=
- 0) {
- driver_errf(tool, "failed to add freestanding headers");
- rc = 1;
- goto done;
- }
} else {
driver_errf(tool, "support dir not found");
rc = 1;
goto done;
}
+ /* Hosted defines/includes are a compile property and therefore apply to
+ * build-obj/build-lib as well as executable links. Link-only search paths,
+ * CRT objects, and libraries stay inside the link-output branch below. */
+ build_enable_hosted_for_sysroot(&o);
+ build_apply_default_hosted_profile(&o);
+ if (build_apply_hosted_profile(&o) != 0) {
+ rc = 1;
+ goto done;
+ }
+ /* Hosted system headers precede Kit's freestanding fallback headers. This
+ * keeps <stdlib.h> on the native SDK while retaining compiler builtins that
+ * the SDK does not provide. */
+ if (!o.nostdinc &&
+ (o.hosted.profile_name
+ ? driver_runtime_append_freestanding_headers(&runtime,
+ &o.groups[0].cf)
+ : driver_runtime_add_freestanding_headers(&runtime,
+ &o.groups[0].cf)) != 0) {
+ driver_errf(tool, "failed to add freestanding headers");
+ rc = 1;
+ goto done;
+ }
+
if (build_is_link_output(&o)) {
if (driver_link_inputs_append_windows_lib_dirs(&o.inputs, &o.sysroot,
o.target) != 0) {
@@ -2452,12 +2500,6 @@ static int build_main(int argc, char** argv, int kind, const char* tool,
rc = 1;
goto done;
}
- build_enable_hosted_for_sysroot(&o);
- build_apply_default_hosted_profile(&o);
- if (build_apply_hosted_profile(&o) != 0) {
- rc = 1;
- goto done;
- }
if (driver_link_inputs_resolve_pending(&o.inputs, o.target,
o.static_link) != 0) {
rc = 1;
@@ -2601,22 +2643,17 @@ void driver_help_build_exe(void) {
" -h, --help Show this help\n"
" --version Show Kit version\n"
"\n"
- "CURRENT RELEASE REQUIREMENTS\n"
- " Use --support-dir \"$DIST/support\" from a relocated tree. Hosted\n"
- " cross builds require --sysroot. Native macOS builds currently\n"
- " require -isysroot \"$(kit cc -print-sysroot)\". Pass linker\n"
- " scripts and entries directly as -T SCRIPT -e SYMBOL; the common\n"
- " -Wl,-T,... spelling is not accepted in this release.\n"
+ "DISCOVERY AND REQUIREMENTS\n"
+ " Relocated distributions discover sibling support automatically;\n"
+ " --support-dir remains an authoritative override. Native macOS uses\n"
+ " the discovered SDK by default. Hosted cross builds require --sysroot.\n"
"\n"
"EXAMPLES\n"
" DIST=\"$PWD/kit\"; K=\"$DIST/bin/kit\"\n"
- " SDK=\"$(\"$K\" cc -print-sysroot)\"\n"
- " \"$K\" build-exe --support-dir \"$DIST/support\" \\\n"
- " -isysroot \"$SDK\" main.c util.c -o app\n"
+ " \"$K\" build-exe main.c util.c -o app\n"
"\n"
" # Flag-scoped C groups plus an assembly source.\n"
- " \"$K\" build-exe --support-dir \"$DIST/support\" \\\n"
- " -isysroot \"$SDK\" --group -DLEFT=20 -- left.c \\\n"
+ " \"$K\" build-exe --group -DLEFT=20 -- left.c \\\n"
" --group -DRIGHT=22 -- right.c main.c helper.s -o grouped\n"
"\n"
" # Freestanding: provide startup code and a linker script.\n"
@@ -2666,10 +2703,11 @@ void driver_help_build_lib(void) {
" -h, --help Show this help\n"
" --version Show Kit version\n"
"\n"
- "CURRENT RELEASE REQUIREMENTS\n"
- " Use --support-dir \"$DIST/support\" from a relocated tree and an\n"
- " explicit SDK/sysroot for hosted headers. Static .a output is the\n"
- " portable library shape; -dynamic/-shared is ELF-only.\n"
+ "DISCOVERY AND REQUIREMENTS\n"
+ " Relocated distributions discover sibling support automatically.\n"
+ " Native macOS discovers its SDK; hosted cross targets require an\n"
+ " explicit sysroot. Static .a output is the portable library shape;\n"
+ " -dynamic/-shared is ELF-only.\n"
"\n"
"EXAMPLES\n"
" DIST=\"$PWD/kit\"; K=\"$DIST/bin/kit\"\n"
@@ -2734,9 +2772,10 @@ void driver_help_build_obj(void) {
" One-source object/assembly output defaults to <base>.o/.s. -o is\n"
" required for multi-source object combination and --emit=c; use\n"
" -o for stable IR filenames. -fsyntax-only writes nothing. A\n"
- " relocated distribution currently needs --support-dir. Hosted\n"
- " headers require an explicit SDK/sysroot. Use --emit=c only at -O0\n"
- " in this release; optimized portable-C emission can terminate Kit.\n"
+ " relocated distribution discovers sibling support automatically.\n"
+ " Native macOS discovers its SDK; hosted cross targets require an\n"
+ " explicit sysroot. Portable-C output uses the\n"
+ " -O0 semantic pipeline; -O1/-O2 are accepted and normalized to -O0.\n"
"\n"
"EXAMPLES\n"
" DIST=\"$PWD/kit\"; K=\"$DIST/bin/kit\"\n"
diff --git a/driver/cmd/cpp.c b/driver/cmd/cpp.c
@@ -5,6 +5,8 @@
#include "cflags.h"
#include "driver.h"
+#include "hosted.h"
+#include "runtime.h"
/* `kit cpp` — standalone C preprocessor. Reads one C source (path or
* `-` for stdin), writes the preprocessed token stream to `-o PATH` or
@@ -29,6 +31,10 @@ typedef struct CppOptions {
const char* output_path;
const char* source_path; /* NULL when stdin source */
int from_stdin;
+ int freestanding;
+ int nostdinc;
+ const char* sysroot;
+ const char* support_dir;
KitTargetSpec target;
} CppOptions;
@@ -120,13 +126,49 @@ static int cpp_parse(int argc, char** argv, CppOptions* o, DriverEnv* env,
return 1;
}
if (driver_target_from_triple(argv[i], &o->target) != 0) {
- driver_errf(CPP_TOOL, "unrecognized target: %.*s",
- KIT_SLICE_ARG(kit_slice_cstr(argv[i])));
+ driver_err_unknown_target(CPP_TOOL, argv[i]);
return 1;
}
continue;
}
+ if (driver_streq(a, "--sysroot") || driver_streq(a, "-isysroot")) {
+ if (++i >= argc) {
+ driver_errf(CPP_TOOL, "%s requires an argument", a);
+ return 1;
+ }
+ o->sysroot = argv[i];
+ continue;
+ }
+ if (driver_strneq(a, "--sysroot=", 10)) {
+ o->sysroot = a + 10;
+ continue;
+ }
+ if (driver_streq(a, "--support-dir")) {
+ if (++i >= argc) {
+ driver_errf(CPP_TOOL, "--support-dir requires an argument");
+ return 1;
+ }
+ o->support_dir = argv[i];
+ continue;
+ }
+ if (driver_strneq(a, "--support-dir=", 14)) {
+ o->support_dir = a + 14;
+ continue;
+ }
+ if (driver_streq(a, "-ffreestanding")) {
+ o->freestanding = 1;
+ continue;
+ }
+ if (driver_streq(a, "-fhosted")) {
+ o->freestanding = 0;
+ continue;
+ }
+ if (driver_streq(a, "-nostdinc")) {
+ o->nostdinc = 1;
+ continue;
+ }
+
{
int tr =
driver_target_features_try_consume(tf, env, CPP_TOOL, argc, argv, &i);
@@ -169,6 +211,8 @@ int driver_cpp(int argc, char** argv) {
CppOptions o = {0};
DriverCflags cf = {0};
DriverTargetFeatures tf = {0};
+ DriverHostedPlan hosted = {0};
+ DriverRuntimeSupport runtime = {0};
KitContext ctx;
KitPreprocessOptions pp;
KitTarget* target = NULL;
@@ -181,6 +225,8 @@ int driver_cpp(int argc, char** argv) {
size_t stdin_size = 0;
int rc = 1;
int loaded = 0;
+ int runtime_resolved = 0;
+ int hosted_engaged = 0;
if (argc < 2 || driver_argv_wants_help(argc, argv, 1)) {
driver_help_cpp();
@@ -189,7 +235,9 @@ int driver_cpp(int argc, char** argv) {
driver_env_init(&env);
- if (driver_cflags_init(&cf, &env, argc) != 0 ||
+ if (driver_cflags_init(&cf, &env,
+ argc + DRIVER_HOSTED_MAX_DEFINES +
+ DRIVER_HOSTED_MAX_INCLUDES) != 0 ||
driver_target_features_init(&tf, &env, argc) != 0) {
driver_errf(CPP_TOOL, "out of memory");
driver_target_features_fini(&tf, &env);
@@ -204,10 +252,40 @@ int driver_cpp(int argc, char** argv) {
driver_env_fini(&env);
return 2;
}
- driver_cflags_fill_pp(&cf, &pp);
-
ctx = driver_env_to_context(&env);
+ if (!o.freestanding && !o.nostdinc &&
+ (o.sysroot || driver_target_default_hosted_profile(o.target))) {
+ DriverHostedRequest req = {0};
+ uint32_t i;
+ req.env = &env;
+ req.tool = CPP_TOOL;
+ req.target = o.target;
+ req.sysroot = o.sysroot;
+ req.link_inputs = 0;
+ if (driver_hosted_resolve(&req, &hosted) != 0) goto out;
+ hosted_engaged = hosted.profile_name != NULL;
+ for (i = 0; i < hosted.nsystem_includes; ++i)
+ cf.system_include_dirs[cf.nsystem_include_dirs++] =
+ hosted.system_includes[i];
+ for (i = 0; i < hosted.ndefines; ++i)
+ cf.defines[cf.ndefines++] = hosted.defines[i];
+ }
+
+ if (driver_runtime_resolve(&env, o.support_dir, argv[0], &runtime) != 0) {
+ driver_errf(CPP_TOOL, "support dir not found");
+ goto out;
+ }
+ runtime_resolved = 1;
+ if (!o.nostdinc &&
+ (hosted_engaged
+ ? driver_runtime_append_freestanding_headers(&runtime, &cf)
+ : driver_runtime_add_freestanding_headers(&runtime, &cf)) != 0) {
+ driver_errf(CPP_TOOL, "failed to add freestanding headers");
+ goto out;
+ }
+ driver_cflags_fill_pp(&cf, &pp);
+
if (o.from_stdin) {
if (!driver_read_stdin(&env, &stdin_buf, &stdin_size)) {
driver_errf(CPP_TOOL, "failed to read stdin");
@@ -260,6 +338,8 @@ out:
if (writer) kit_writer_close(writer);
if (loaded) ctx.file_io->release(ctx.file_io->user, &src);
if (stdin_buf) driver_free(&env, stdin_buf, stdin_size);
+ if (runtime_resolved) driver_runtime_support_fini(&env, &runtime);
+ driver_hosted_plan_fini(&env, &hosted);
driver_target_features_fini(&tf, &env);
driver_cflags_fini(&cf, &env);
driver_env_fini(&env);
diff --git a/driver/lib/hosted.c b/driver/lib/hosted.c
@@ -68,13 +68,22 @@ int driver_hosted_dirs_resolve(const DriverHostedRequest* req,
if (env_sysroot && env_sysroot[0]) sysroot = env_sysroot;
}
if (sysroot) {
+ if (!driver_path_exists(sysroot)) {
+ driver_errf(req->tool, "sysroot not found: %.*s",
+ KIT_SLICE_ARG(kit_slice_cstr(sysroot)));
+ return 1;
+ }
if (hosted_dirs_from_sysroot(out, req->target, sysroot) != 0) {
driver_hosted_dirs_fini(out);
return 1;
}
} else {
KitTargetSpec host = driver_host_target();
- if (req->target.os == host.os && req->target.arch == host.arch)
+ if (host.os == KIT_OS_MACOS && req->target.os == KIT_OS_MACOS)
+ /* One installed macOS SDK serves both supported Darwin architectures;
+ * allow native cross-arch x86_64<->aarch64 without xcrun. */
+ (void)driver_default_hosted_dirs(req->env, req->target, out);
+ else if (req->target.os == host.os && req->target.arch == host.arch)
(void)driver_default_hosted_dirs(req->env, req->target, out);
else if (host.os == KIT_OS_MACOS &&
(req->target.os == KIT_OS_IOS ||
@@ -94,7 +103,6 @@ int driver_hosted_resolve(const DriverHostedRequest* req,
if (!req || !out || !req->env || !req->tool) return 1;
*out = zero;
if (driver_hosted_dirs_resolve(req, &dirs) != 0) {
- driver_errf(req->tool, "out of memory");
return 1;
}
ops = hosted_ops_for(req->target);
diff --git a/include/kit/os.h b/include/kit/os.h
@@ -61,6 +61,12 @@ typedef struct KitOsHostedPlan {
size_t owned_system_include_sizes[KIT_OS_HOSTED_MAX_INCLUDES];
uint32_t nsystem_includes;
KitDefine defines[KIT_OS_HOSTED_MAX_DEFINES];
+ /* Dynamic predefine bodies are copied into plan-owned storage. Literal
+ * predefines leave these slots NULL. This keeps KitDefine slices valid until
+ * kit_os_hosted_plan_fini even when a resolver formats a value on its stack
+ * (for example Android's API level). */
+ char* owned_define_bodies[KIT_OS_HOSTED_MAX_DEFINES];
+ size_t owned_define_body_sizes[KIT_OS_HOSTED_MAX_DEFINES];
uint32_t ndefines;
char* lib_search_dirs[KIT_OS_HOSTED_MAX_LIB_SEARCH_DIRS];
size_t lib_search_dir_sizes[KIT_OS_HOSTED_MAX_LIB_SEARCH_DIRS];
diff --git a/recipes/buildkit/common.sh b/recipes/buildkit/common.sh
@@ -622,6 +622,7 @@ driver/env/uctx_rv64_freebsd.c" ;;
bk_enabled KIT_TOOL_DISAS_ENABLED && tool_srcs="$tool_srcs driver/cmd/disas.c"
bk_enabled KIT_TOOL_MC_ENABLED && tool_srcs="$tool_srcs driver/cmd/mc.c"
bk_enabled KIT_TOOL_GRAM_ENABLED && tool_srcs="$tool_srcs driver/cmd/gram.c"
+ bk_enabled KIT_TOOL_TARGETS_ENABLED && tool_srcs="$tool_srcs driver/cmd/targets.c"
bk_enabled KIT_TOOL_UPDATE_ENABLED && tool_srcs="$tool_srcs driver/cmd/update.c"
shared=""
diff --git a/scripts/hosted.sh b/scripts/hosted.sh
@@ -39,16 +39,36 @@ set -u
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
KIT="${KIT:-$ROOT/build/kit}"
-SUPPORT_SET="
-linux-glibc-aa64 linux-glibc-x64 linux-glibc-rv64
-linux-musl-aa64 linux-musl-x64 linux-musl-rv64
-freebsd-aa64 freebsd-x64 freebsd-rv64
-windows-aa64 windows-x64
-android-aa64
-macos-aa64 macos-x64
-freestanding-aa64 freestanding-x64 freestanding-rv64 freestanding-rv32 freestanding-arm32
+SUPPORT_SET_FALLBACK="
+linux-glibc-aa64 linux-musl-aa64 freebsd-aa64 android-aa64 freestanding-aa64
+linux-glibc-x64 linux-musl-x64 freebsd-x64 freestanding-x64
+linux-glibc-rv64 linux-musl-rv64 freebsd-rv64 freestanding-rv64
+freestanding-rv32 freestanding-arm32
+windows-aa64 windows-x64 macos-aa64 macos-x64
"
+# A built candidate is the authority for selectors/triples. Keep the literal
+# fallback only for bootstrap/provisioning before `make bin`; once `kit
+# targets` is available, list/expand/doctor consume its versioned TSV registry.
+# iOS/Wasm profiles are intentionally filtered here because this script has no
+# provision/run personality for them yet; they remain visible in `kit targets`.
+TARGET_REGISTRY_TSV=""
+if [ -x "$KIT" ]; then
+ TARGET_REGISTRY_TSV="$("$KIT" targets --format=tsv 2>/dev/null || true)"
+fi
+SUPPORT_SET="$SUPPORT_SET_FALLBACK"
+if [ -n "$TARGET_REGISTRY_TSV" ]; then
+ registry_support_set="$(printf '%s\n' "$TARGET_REGISTRY_TSV" | awk -F '\t' '
+ $1 ~ /^linux-(glibc|musl)-(aa64|x64|rv64)$/ ||
+ $1 ~ /^freebsd-(aa64|x64|rv64)$/ ||
+ $1 ~ /^windows-(aa64|x64)$/ ||
+ $1 == "android-aa64" ||
+ $1 ~ /^macos-(aa64|x64)$/ ||
+ $1 ~ /^freestanding-(aa64|x64|rv64|rv32|arm32)$/ { print $1 }
+ ')"
+ [ -n "$registry_support_set" ] && SUPPORT_SET="$registry_support_set"
+fi
+
die() { printf 'hosted: %s\n' "$*" >&2; exit 1; }
# ---- target parsing --------------------------------------------------------
@@ -105,7 +125,17 @@ parse_target() {
}
triple_of() {
+ local canonical registry_triple
parse_target "$1"
+ canonical="$(canon_token "$1")"
+ if [ -n "$TARGET_REGISTRY_TSV" ]; then
+ registry_triple="$(printf '%s\n' "$TARGET_REGISTRY_TSV" | awk -F '\t' \
+ -v selector="$canonical" '$1 == selector { print $2; exit }')"
+ if [ -n "$registry_triple" ]; then
+ printf '%s\n' "$registry_triple"
+ return
+ fi
+ fi
case "$T_OS" in
linux)
local suf=gnu; [ "$T_LIBC" = musl ] && suf=musl
@@ -241,11 +271,10 @@ cc_target() {
local triple sysroot; triple="$(triple_of "$target")"; sysroot="$(path_of "$target")"
local args=()
if [ "$T_OS" = macos ]; then
- # Compile against the Xcode/CLT SDK. A native-arch build omits -target so
- # the host default applies; a cross to the other macOS arch (e.g. x86_64 on
- # Apple silicon, run via Rosetta) needs the explicit target.
- local sdk; sdk="$(xcrun --show-sdk-path 2>/dev/null)"
- [ -n "$sdk" ] && args+=(-isysroot "$sdk")
+ # Kit discovers and applies the native Xcode/CLT SDK itself. A native-arch
+ # build omits -target so the host default applies; a cross to the other
+ # macOS arch (e.g. x86_64 on Apple silicon, run via Rosetta) needs only the
+ # explicit target. No SDK-discovery helper is part of this path.
local ha; ha="$(uname -m 2>/dev/null)"
case "$T_ARCH:$ha" in
x64:arm64|x64:aarch64|aarch64:x86_64|aarch64:amd64) args+=(-target "$triple") ;;
diff --git a/src/os/android/hosted.c b/src/os/android/hosted.c
@@ -7,7 +7,8 @@ static unsigned android_api_level(KitTargetSpec target) {
return api < 21u ? 21u : api;
}
-static int hosted_add_android_defines(KitOsHostedPlan* plan,
+static int hosted_add_android_defines(const KitOsHostedRequest* req,
+ KitOsHostedPlan* plan,
KitTargetSpec target) {
char api_buf[4];
int n = snprintf(api_buf, sizeof api_buf, "%u", android_api_level(target));
@@ -19,7 +20,8 @@ static int hosted_add_android_defines(KitOsHostedPlan* plan,
kit_os_hosted_add_define(plan, "__linux", "1") != 0 ||
kit_os_hosted_add_define(plan, "linux", "1") != 0 ||
kit_os_hosted_add_define(plan, "__ELF__", "1") != 0 ||
- kit_os_hosted_add_define(plan, "__ANDROID_API__", api_buf) != 0)
+ kit_os_hosted_add_define_owned(plan, req->host, req->host_user,
+ "__ANDROID_API__", api_buf) != 0)
return 1;
return 0;
}
@@ -46,7 +48,7 @@ static int hosted_resolve_android(const KitOsHostedRequest* req,
plan->profile_name =
req->shared_link ? "android-bionic-shared" : "android-bionic-dynamic";
if (!req->shared_link) plan->interp_path = "/system/bin/linker64";
- if (hosted_add_android_defines(plan, req->target) != 0 ||
+ if (hosted_add_android_defines(req, plan, req->target) != 0 ||
kit_os_hosted_add_incdirs(plan, req->host, req->host_user, dirs) != 0) {
kit_os_hosted_errf(req->host, req->host_user, req->tool, "out of memory");
return 1;
diff --git a/src/os/hosted.c b/src/os/hosted.c
@@ -176,6 +176,30 @@ int kit_os_hosted_add_define(KitOsHostedPlan* plan, const char* name,
return 0;
}
+int kit_os_hosted_add_define_owned(KitOsHostedPlan* plan,
+ const KitOsHostedHost* host,
+ void* host_user, const char* name,
+ const char* body) {
+ size_t index, len, size;
+ char* copy;
+ if (!plan || !host || !host->alloc || !host->free || !name || !body)
+ return 1;
+ if (plan->ndefines >= KIT_OS_HOSTED_MAX_DEFINES) return 1;
+ len = strlen(body);
+ size = len + 1u;
+ copy = (char*)host->alloc(host_user, size);
+ if (!copy) return 1;
+ memcpy(copy, body, size);
+ index = plan->ndefines;
+ if (kit_os_hosted_add_define(plan, name, copy) != 0) {
+ host->free(host_user, copy, size);
+ return 1;
+ }
+ plan->owned_define_bodies[index] = copy;
+ plan->owned_define_body_sizes[index] = size;
+ return 0;
+}
+
int kit_os_hosted_add_clang_compat_defines(KitOsHostedPlan* plan) {
if (kit_os_hosted_add_define(plan, "__clang__", "1") != 0 ||
kit_os_hosted_add_define(plan, "__clang_major__", "17") != 0 ||
@@ -221,6 +245,11 @@ void kit_os_hosted_plan_fini(const KitOsHostedHost* host, void* host_user,
host->free(host_user, plan->owned_system_includes[i],
plan->owned_system_include_sizes[i]);
}
+ for (i = 0; i < plan->ndefines; ++i) {
+ if (plan->owned_define_bodies[i])
+ host->free(host_user, plan->owned_define_bodies[i],
+ plan->owned_define_body_sizes[i]);
+ }
for (i = 0; i < plan->nlib_search_dirs; ++i) {
if (plan->lib_search_dirs[i])
host->free(host_user, plan->lib_search_dirs[i],
diff --git a/src/os/hosted_internal.h b/src/os/hosted_internal.h
@@ -25,6 +25,10 @@ int kit_os_hosted_add_incdirs(KitOsHostedPlan* plan,
const KitOsHostedDirs* dirs);
int kit_os_hosted_add_define(KitOsHostedPlan* plan, const char* name,
const char* body);
+int kit_os_hosted_add_define_owned(KitOsHostedPlan* plan,
+ const KitOsHostedHost* host,
+ void* host_user, const char* name,
+ const char* body);
int kit_os_hosted_add_clang_compat_defines(KitOsHostedPlan* plan);
#endif
diff --git a/src/os/macos/hosted.c b/src/os/macos/hosted.c
@@ -111,7 +111,10 @@ static int hosted_sysroot_layout_darwin(KitOsHostedDirs* dirs,
const KitOsHostedOps kit_os_macos_hosted_ops = {
.obj = KIT_OBJ_MACHO,
- .default_profile = 0,
+ /* Native Darwin compilation is hosted by default. Driver-side host/OS
+ * gating prevents this policy from borrowing a Darwin SDK when kit runs
+ * on another operating system. */
+ .default_profile = 1,
.needs_sysroot_libdir = 0,
.uses_framework_dirs = 1,
.resolve = hosted_resolve_darwin,
diff --git a/test/buildcmds/run.sh b/test/buildcmds/run.sh
@@ -80,10 +80,9 @@ run_fail bo-autovar-pattern-rejected "$KIT" build-obj \
contains bo-autovar-pattern-rejected-diag \
"$work/bo-autovar-pattern-rejected.err" "not yet supported"
-run_fail bo-stack-protector-rejected "$KIT" build-obj \
+run_ok bo-stack-protector-strong "$KIT" build-obj \
-fstack-protector-strong -c -Iinc hello.c -o stack_protector.o
-contains bo-stack-protector-rejected-diag \
- "$work/bo-stack-protector-rejected.err" "not supported yet"
+assert_file_exists bo-stack-protector-strong-file stack_protector.o
run_fail bo-general-regs-only-fp "$KIT" build-obj \
-mgeneral-regs-only -c fp.c -o fp.o