kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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