driver.h (17565B)
1 #ifndef KIT_DRIVER_H 2 #define KIT_DRIVER_H 3 4 #include <kit/compile.h> 5 #include <kit/core.h> 6 #include <kit/dbg.h> 7 #include <kit/driver.h> 8 #include <kit/jit.h> 9 10 #include "env.h" 11 12 /* The kit CLI driver. Multi-call binary: dispatches to a named tool 13 * front-ends by argv[0]'s basename, falling back to argv[1] (e.g. 14 * `kit cc ...`). The driver only depends on libkit's public API 15 * (<kit/...>); it has no access to libkit's internal headers. 16 * 17 * Preprocessor-only mode is `cc -E` — there is no separate `cpp` tool. */ 18 19 /* Multi-call entry: dispatches by argv[0] basename (or argv[1] fallback). */ 20 int driver_main(int argc, char** argv); 21 22 /* Direct entry per tool. Each lives in driver/<tool>.c. */ 23 int driver_cc(int argc, char** argv); 24 int driver_check(int argc, char** argv); 25 int driver_build_exe(int argc, char** argv); 26 int driver_build_lib(int argc, char** argv); 27 int driver_build_obj(int argc, char** argv); 28 int driver_build(int argc, char** argv); 29 int driver_make(int argc, char** argv); 30 int driver_build_exe_ex(int argc, char** argv, const KitDriverExtension*); 31 int driver_build_lib_ex(int argc, char** argv, const KitDriverExtension*); 32 int driver_build_obj_ex(int argc, char** argv, const KitDriverExtension*); 33 int driver_install(int argc, char** argv); 34 int driver_cpp(int argc, char** argv); 35 int driver_as(int argc, char** argv); 36 int driver_ld(int argc, char** argv); 37 int driver_ar(int argc, char** argv); 38 int driver_cpio(int argc, char** argv); 39 int driver_ranlib(int argc, char** argv); 40 int driver_strip(int argc, char** argv); 41 int driver_objcopy(int argc, char** argv); 42 int driver_image(int argc, char** argv); 43 int driver_objdump(int argc, char** argv); 44 int driver_dbg(int argc, char** argv); 45 int driver_run(int argc, char** argv); 46 int driver_dbg_ex(int argc, char** argv, const KitDriverExtension*); 47 int driver_run_ex(int argc, char** argv, const KitDriverExtension*); 48 int driver_emu(int argc, char** argv); 49 int driver_nm(int argc, char** argv); 50 int driver_size(int argc, char** argv); 51 int driver_addr2line(int argc, char** argv); 52 int driver_symbolize(int argc, char** argv); 53 int driver_strings(int argc, char** argv); 54 int driver_cas(int argc, char** argv); 55 int driver_pkg(int argc, char** argv); 56 int driver_xxd(int argc, char** argv); 57 int driver_cmp(int argc, char** argv); 58 int driver_hash(int argc, char** argv); 59 int driver_sha256sum(int argc, char** argv); 60 int driver_b2sum(int argc, char** argv); 61 int driver_crc32(int argc, char** argv); 62 int driver_compress(int argc, char** argv); 63 int driver_gzip(int argc, char** argv); 64 int driver_gunzip(int argc, char** argv); 65 int driver_lz4(int argc, char** argv); 66 int driver_lz4c(int argc, char** argv); 67 int driver_disas(int argc, char** argv); 68 int driver_mc(int argc, char** argv); 69 int driver_gram(int argc, char** argv); 70 int driver_targets(int argc, char** argv); 71 72 /* Per-tool help printers. Write a multi-section help text to stdout and 73 * return. The tool entry-points call these when invoked with no args, -h, 74 * or --help (objdump excepts -h, since GNU objdump uses it for section 75 * headers — only --help triggers help there). */ 76 void driver_help_cc(void); 77 void driver_help_check(void); 78 void driver_help_build_exe(void); 79 void driver_help_build_lib(void); 80 void driver_help_build_obj(void); 81 void driver_help_build(void); 82 void driver_help_make(void); 83 void driver_help_install(void); 84 void driver_help_cpp(void); 85 void driver_help_as(void); 86 void driver_help_ld(void); 87 void driver_help_ar(void); 88 void driver_help_cpio(void); 89 void driver_help_ranlib(void); 90 void driver_help_strip(void); 91 void driver_help_objcopy(void); 92 void driver_help_image(void); 93 void driver_help_objdump(void); 94 void driver_help_dbg(void); 95 void driver_help_run(void); 96 void driver_help_emu(void); 97 void driver_help_nm(void); 98 void driver_help_size(void); 99 void driver_help_addr2line(void); 100 void driver_help_symbolize(void); 101 void driver_help_strings(void); 102 void driver_help_cas(void); 103 void driver_help_pkg(void); 104 void driver_help_xxd(void); 105 void driver_help_cmp(void); 106 void driver_help_hash(void); 107 void driver_help_sha256sum(void); 108 void driver_help_b2sum(void); 109 void driver_help_crc32(void); 110 void driver_help_compress(void); 111 void driver_help_gzip(void); 112 void driver_help_gunzip(void); 113 void driver_help_lz4(void); 114 void driver_help_lz4c(void); 115 void driver_help_disas(void); 116 void driver_help_mc(void); 117 void driver_help_gram(void); 118 void driver_help_targets(void); 119 120 /* Multi-call top-level help (`kit`, `kit -h`, `kit --help`, 121 * `kit help`). Lists public tools in task-oriented groups with a one-line 122 * summary and explains the multi-call dispatch. Writes to stdout. */ 123 void driver_help_top(void); 124 125 /* ---------------------------------------------------------------------- 126 * Version / build provenance (driver/version.c) 127 * 128 * The single source of truth for the version string is the committed top-level 129 * VERSION file (CalVer YYYY.MINOR.PATCH); the build id (short git hash, with a 130 * "-dirty" suffix or "unknown" when unavailable) and host triple are injected 131 * at build time. These are driver-internal accessors, not libkit public API. 132 * See doc/plan/SELFDIST.md. 133 * ---------------------------------------------------------------------- */ 134 const char* kit_version_string(void); /* e.g. "2026.6.0" */ 135 const char* kit_build_id(void); /* e.g. "a3f91c2" / "unknown" */ 136 const char* kit_host_triple(void); /* e.g. "aarch64-macos" */ 137 138 /* Print the shared version banner to stdout. A NULL tool prints 139 * "kit <ver> (<build>, <triple>)" 140 * and a non-NULL tool prints 141 * "kit <tool> <ver> (<build>, <triple>)" 142 * so `kit --version` and `cc --version` / `ld --version` answer uniformly. */ 143 void driver_print_version(const char* tool); 144 145 /* Returns 1 when the tool's first argument (argv[1]) is "--version". Only the 146 * first argument counts, so a sub-flag that legitimately spells --version 147 * (e.g. `pkg create --version <ver>`) is never hijacked; `cc --version` and 148 * `kit cc --version` both present --version as the dispatched tool's argv[1]. */ 149 int driver_argv_wants_version(int argc, char** argv); 150 151 /* ---------------------------------------------------------------------- 152 * Self-distribution: `kit update` + the embedded release trust anchor 153 * (driver/cmd/update.c, driver/release_key.c). See doc/plan/SELFDIST.md. 154 * ---------------------------------------------------------------------- */ 155 int driver_update(int argc, char** argv); 156 void driver_help_update(void); 157 158 /* `kit update` verifies a downloaded release against this built-in set of 159 * minisign public keys; any one key verifying suffices, which supports 160 * overlap-window key rotation. The real release key's secret is held offline; 161 * the in-tree default is a clearly-labelled NON-RELEASE test key so the 162 * hermetic end-to-end test and the `make dist` fallback signer verify against a 163 * built-in anchor. A `kit update --key` override lets mirrors/forks supply 164 * their own. */ 165 typedef struct KitReleaseKey { 166 const char* label; /* human label */ 167 const char* pubkey; /* minisign public-key file text (comment + base64) */ 168 } KitReleaseKey; 169 170 /* Borrow the embedded release public-key set; *count receives its length. */ 171 const KitReleaseKey* driver_release_keys(unsigned* count); 172 173 /* Borrow the compiled stable channel-index URL. An empty string means this 174 * development build intentionally has no default channel. */ 175 const char* driver_release_index_url(void); 176 177 /* Tool grouping, used by `install` to pick a default set without 178 * duplicating the tool list. The centralized table in main.c tags every 179 * row; the groups with a non-zero bit make up the default install set 180 * (the binutils/compiler toolchain plus the byte utilities whose names 181 * match standard commands). */ 182 typedef enum DriverToolGroup { 183 DRIVER_GROUP_OTHER = 0, 184 DRIVER_GROUP_TOOLCHAIN = 1u << 0, /* binutils + compiler driver */ 185 DRIVER_GROUP_BYTEUTIL = 1u << 1, /* standard-named byte utilities */ 186 } DriverToolGroup; 187 188 /* Read-only views over the centralized tool table (main.c), so the 189 * `install` tool always reflects exactly the tools compiled into this 190 * binary. Indices are stable within a process and run 0..count-1. */ 191 unsigned driver_tool_count(void); 192 const char* driver_tool_name(unsigned index); /* NULL if out of range */ 193 unsigned driver_tool_groups(unsigned index); /* 0 if out of range */ 194 int driver_tool_public(unsigned index); /* listed in help/install --all */ 195 /* Index of the tool named `name`, or -1 if there is no such tool. */ 196 int driver_tool_find(const char* name); 197 198 /* Returns 1 if `arg` is "--help" or "-help". The short "-h" is treated 199 * as a help request by every tool except objdump (where it means 200 * "section headers"); callers that want to honour it should test it 201 * explicitly via driver_argv_wants_help(..., 1). */ 202 int driver_is_help_flag(const char* arg); 203 204 /* Scan argv[1..argc-1] for a help request, returning 1 on a hit. Triggers 205 * on "--help" / "-help" always, and on "-h" when accept_short_h is set. 206 * Tool entries also treat argc < 2 (no positional or option args) as a 207 * help request — the convention is "no args means show help". */ 208 int driver_argv_wants_help(int argc, char** argv, int accept_short_h); 209 210 /* Parse a target triple string (`<arch>[-<vendor>]-<os>[-<env>]`) into a 211 * KitTargetSpec. Recognized arches: x86_64/amd64, i386/i486/i586/i686, aarch64/ 212 * arm64, arm/armv7, riscv64, riscv32, wasm32, wasm64. `wasm64` is recognized as 213 * a reserved spelling, but compiler target construction rejects it in v1. 214 * Recognized OSes (scanned across the remaining components, so vendor tokens 215 * like `pc`/`apple`/`unknown` are skipped): linux, android, darwin/macos, 216 * ios/iphoneos, iphonesimulator/ios-simulator, windows/win32, wasi, 217 * none/freestanding. Sets arch/os/obj/ptr_size/ptr_align/big_endian; pic and 218 * code_model are left at their defaults. Returns 0 on success, nonzero on 219 * unrecognized arch or NULL inputs. */ 220 int driver_target_from_triple(const char* triple, KitTargetSpec* out); 221 222 /* Render a canonical driver target triple into `buf`. Returns 0 on success, 223 * nonzero when `buf` is too small. */ 224 int driver_target_to_triple(KitTargetSpec target, char* buf, size_t cap); 225 226 /* Map an architecture-name literal (the arch component of a triple: 227 * x86_64/amd64, i386/i486/i586/i686, aarch64/arm64, arm/armv7, riscv64, 228 * riscv32, wasm32, wasm64) to its KitArchKind and natural pointer size. 229 * `wasm64` is reserved but unsupported for v1 code generation. The single 230 * authority for arch-name spellings; driver_target_from_triple uses the same 231 * table. Returns 0 on success, nonzero on an unrecognized name or a NULL 232 * argument. Out-pointers may be NULL. */ 233 int driver_arch_from_name(const char* name, KitArchKind* arch_out, 234 uint8_t* ptr_size_out); 235 236 /* Diagnose an invalid target against the public target-profile registry. A 237 * close authoritative triple/selector is suggested; otherwise the diagnostic 238 * points to `kit targets`. This never changes the caller's status or input. */ 239 void driver_err_unknown_target(const char* tool, const char* value); 240 241 /* Whether `path` is a compilable source file: a path some registered frontend 242 * claims (via the canonical extension registry, case-insensitively), excluding 243 * C headers. The C frontend registers ".h" so language-for-path can identify 244 * headers, but a header is not a translation unit to compile. The single 245 * source of truth for source classification shared by cc/build/run/dbg, so 246 * adding a frontend extension reaches every tool at once. */ 247 int driver_path_is_source(const char* path); 248 249 /* ---------------------------------------------------------------------- 250 * Shared scalar parsing helpers 251 * 252 * Small, OS-neutral parsers the byte/binutils tools used to each open-code. 253 * Implemented in driver/env/common.c. 254 * ---------------------------------------------------------------------- */ 255 256 /* Parse SOURCE_DATE_EPOCH into a u64 seconds count. Returns 0 when the variable 257 * is unset, empty, or not all decimal digits ("no epoch"). */ 258 uint64_t driver_epoch_from_env(void); 259 260 /* Parse a non-negative integer that is either decimal or `0x`/`0X`-prefixed 261 * hex. Rejects empty input, a bare `0x` with no digits, and any non-digit. 262 * Returns 0 on success (value in *out), nonzero on a malformed string. */ 263 int driver_parse_u64(const char* s, uint64_t* out); 264 265 typedef struct DriverSuggestion { 266 const char* value; 267 uint16_t distance; 268 } DriverSuggestion; 269 270 /* Return up to out_cap close authoritative values, ordered by edit distance 271 * with registry order as the stable tie-break. Work and storage are bounded: 272 * inputs/candidates longer than 64 bytes are ignored and no allocation occurs. 273 * Exact values are not returned; callers remain responsible for validation and 274 * must never treat a suggestion as an autocorrection. */ 275 size_t driver_suggest_values(const char* input, const char* const* candidates, 276 size_t candidate_count, DriverSuggestion* out, 277 size_t out_cap); 278 279 /* Map one hex digit (0-9, a-f, A-F) to its 0..15 value, or -1 if `c` is not a 280 * hex digit. */ 281 int driver_hex_nibble(char c); 282 283 /* Join two path components into a freshly heap-allocated, NUL-terminated string 284 * `<a>/<b>`. A '/' separator is inserted iff `a` is non-empty and does not 285 * already end in '/' or '\\' (so Windows-style separators are not doubled). An 286 * empty `a` yields just `<b>` (relative to the current directory); a NULL/empty 287 * `b` yields a copy of `a`. When `out_size` is non-NULL it receives the 288 * allocation size (length + 1) for a later driver_free. Returns NULL only on 289 * allocation failure. */ 290 char* driver_path_join(DriverEnv* env, const char* a, const char* b, 291 size_t* out_size); 292 293 typedef struct DriverTargetFeatures { 294 DriverEnv* env; 295 KitTargetFeature* features; 296 uint32_t nfeatures; 297 uint32_t cap_features; 298 KitSlice isa; 299 KitSlice cpu; 300 KitSlice tune; 301 KitSlice abi; 302 } DriverTargetFeatures; 303 304 /* Shared target-feature parser. Canonical spelling is `-mattr=+foo,-bar`; 305 * GCC/clang-style `-mfoo` and `-mno-foo` are accepted as aliases and lowered 306 * into the same KitTargetFeature list before libkit sees the target. */ 307 int driver_target_features_init(DriverTargetFeatures*, DriverEnv*, 308 int argc_bound); 309 void driver_target_features_fini(DriverTargetFeatures*, DriverEnv*); 310 int driver_target_features_try_consume(DriverTargetFeatures*, DriverEnv*, 311 const char* tool, int argc, char** argv, 312 int* i); 313 /* Consume Darwin linker target spellings shared by ld/build-exe: 314 * -arch, -platform_version, and the *_version_min compatibility flags. 315 * Returns 1 when a flag was consumed, 0 when argv[*i] is unrelated, and -1 316 * after emitting a diagnostic. */ 317 int driver_darwin_platform_try_consume(const char* tool, int argc, char** argv, 318 int* i, KitTargetSpec* target, 319 int pic_explicit); 320 int driver_target_options(const DriverTargetFeatures*, const char* tool, 321 KitTargetSpec, KitTargetOptions* out); 322 KitStatus driver_target_new(const KitContext*, KitTargetSpec, 323 const DriverTargetFeatures*, const char* tool, 324 KitTarget** out); 325 326 /* Default PIC/PIE model for a target. Hosted targets default to PIE, 327 * matching modern gcc/clang and platform norms (ELF -> ET_DYN, Mach-O -> 328 * MH_PIE, PE/COFF -> .reloc + DYNAMIC_BASE). Freestanding targets (no 329 * dynamic loader) and WASM stay non-PIE. */ 330 KitPic driver_default_pic(KitObjFmt obj, KitOSKind os); 331 332 /* Resolve whether the link step should emit a position-independent 333 * executable. An explicit -pie always wins; -shared and -r (relocatable) 334 * always suppress it; otherwise it follows the target's PIC model. */ 335 int driver_link_pie(KitTargetSpec target, int explicit_pie, int shared, 336 int relocatable); 337 338 /* Per-target driver defaults, centralizing the per-OS forks the cc/build 339 * drivers used to inline. */ 340 341 /* Default executable name when the user gives no -o: "a.exe" on Windows 342 * (PE/COFF), "a.out" elsewhere. */ 343 const char* driver_default_exe_name(KitTargetSpec target); 344 345 /* Default relocatable-object extension for the target: ".obj" (len 4) on 346 * Windows, ".o" (len 2) elsewhere. NULL out-pointers are ignored. */ 347 void driver_default_obj_ext(KitTargetSpec target, const char** ext_out, 348 size_t* ext_len_out); 349 350 /* Whether `<sysroot>/lib` should be folded into the library search path for 351 * this target (Windows mingw import-library tree). */ 352 int driver_target_needs_sysroot_libdir(KitTargetSpec target); 353 354 /* Whether the hosted libc profile is engaged by default for this target 355 * (Windows-COFF, given a sysroot and no -nostdlib). */ 356 int driver_target_default_hosted_profile(KitTargetSpec target); 357 358 /* Whether a shared-library link should still use hosted CRT/libc scaffolding 359 * and the kit runtime. Most targets leave shared output standalone; Android 360 * NDK DSOs require crtbegin_so.o/crtend_so.o and Bionic DSOs. */ 361 int driver_target_shared_uses_hosted(KitTargetSpec target); 362 363 /* Set `target->code_model` from a -mcmodel= value. Accepts the x86 spellings 364 * (small/medium/large), the RISC-V aliases (medlow->small, medany->medium), 365 * and kernel as a conservative alias for large. Returns 0 on success, 1 on an 366 * unknown value (diagnostic via `tool`). */ 367 int driver_record_mcmodel(KitTargetSpec* target, const char* tool, 368 const char* val); 369 370 #endif