kit

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

commit 82ef995c9c7a61e8fed52f30e3eb019bd08bf95d
parent b0b93cc1caf3e43f8dfc363912764803e9c9dd25
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu, 18 Jun 2026 02:43:41 -0700

build: validate trace hit stats

Diffstat:
Mdriver/cmd/build_coord.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mtest/buildcoord/run.sh | 99++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 148 insertions(+), 7 deletions(-)

diff --git a/driver/cmd/build_coord.c b/driver/cmd/build_coord.c @@ -27,6 +27,7 @@ typedef struct BuildCli { KitSlice args[BUILD_MAX_ARGS]; size_t nargs; int verify; + int stats; } BuildCli; void driver_help_build(void) { @@ -35,19 +36,20 @@ void driver_help_build(void) { "\n" "USAGE\n" " kit build [--store DIR] [--root DIR] [--def FILE]\n" - " [--config K=V]... [--arg VALUE]... [--verify] TARGET\n" + " [--config K=V]... [--verify] [--stats] TARGET [-- ARG...]\n" " kit build config-get KEY # inside a build recipe\n" " kit build source PATH # inside a build recipe\n" " kit build glob PATTERN # inside a build recipe\n" - " kit build need [--config K=V]... TARGET # inside a build recipe\n" + " kit build need [--config K=V]... TARGET [-- ARG...]\n" + " # inside a build recipe\n" "\n" "OPTIONS\n" " --store DIR Build store root (default: $KIT cache/build)\n" " --root DIR Workspace root (default: .)\n" " --def FILE Build definition path (default: BUILD.kit)\n" " --config K=V Seed propagated configuration\n" - " --arg VALUE Add one target-local argv value\n" - " --verify Verify the returned output tree in the CAS\n"); + " --verify Verify the returned output tree in the CAS\n" + " --stats Print build-resolution counters to stderr\n"); } static const char* build_status_name(KitStatus st) { @@ -115,6 +117,19 @@ static int build_client_need_parse(BuildCli* cli, int argc, char** argv, driver_errf(BUILD_TOOL, "bad --config, expected K=V"); return 2; } + } else if (driver_streq(a, "--")) { + if (!cli->target) { + driver_errf(BUILD_TOOL, "missing client target before --"); + return 2; + } + while (++i < argc) { + if (cli->nargs >= BUILD_MAX_ARGS) { + driver_errf(BUILD_TOOL, "too many recipe arguments"); + return 2; + } + cli->args[cli->nargs++] = kit_slice_cstr(argv[i]); + } + break; } else if (driver_streq(a, "--arg") && i + 1 < argc) { if (cli->nargs >= BUILD_MAX_ARGS) { driver_errf(BUILD_TOOL, "too many --arg values"); @@ -265,12 +280,27 @@ static int build_parse_args(BuildCli* cli, int argc, char** argv) { driver_errf(BUILD_TOOL, "bad --config, expected K=V"); return 2; } + } else if (driver_streq(a, "--")) { + if (!cli->target) { + driver_errf(BUILD_TOOL, "missing target before --"); + return 2; + } + while (++i < argc) { + if (cli->nargs >= BUILD_MAX_ARGS) { + driver_errf(BUILD_TOOL, "too many recipe arguments"); + return 2; + } + cli->args[cli->nargs++] = kit_slice_cstr(argv[i]); + } + break; } else if (driver_streq(a, "--arg") && i + 1 < argc) { if (cli->nargs >= BUILD_MAX_ARGS) { driver_errf(BUILD_TOOL, "too many --arg values"); return 2; } cli->args[cli->nargs++] = kit_slice_cstr(argv[++i]); + } else if (driver_streq(a, "--stats")) { + cli->stats = 1; } else if (driver_streq(a, "--verify")) { cli->verify = 1; } else if (a[0] == '-') { @@ -290,6 +320,19 @@ static int build_parse_args(BuildCli* cli, int argc, char** argv) { return 0; } +static void build_print_stats(const KitBuildStats* s) { + if (!s) return; + driver_errf(BUILD_TOOL, + "stats deep_hits=%llu shallow_hits=%llu recipes_run=%llu " + "materialize_misses=%llu object_fetches=%llu trace_pulls=%llu", + (unsigned long long)s->deep_hits, + (unsigned long long)s->shallow_hits, + (unsigned long long)s->recipes_run, + (unsigned long long)s->materialize_misses, + (unsigned long long)s->object_fetches, + (unsigned long long)s->trace_pulls); +} + static int build_verify_tree(DriverEnv* env, const char* store, const uint8_t tree[KIT_BUILD_HASH_LEN]) { KitContext ctx = driver_env_to_context(env); @@ -398,6 +441,11 @@ int driver_build(int argc, char** argv) { rc = 1; goto out; } + if (cli.stats) { + KitBuildStats stats; + kit_build_stats(coord, &stats); + build_print_stats(&stats); + } if (cli.verify && build_verify_tree(&env, abs_store, result.output_tree) != 0) { diff --git a/test/buildcoord/run.sh b/test/buildcoord/run.sh @@ -32,12 +32,18 @@ recipe recipes/absent.sh recipe recipes/app.sh [target //argv:echo] recipe recipes/argv.sh +[target //cfg:probe] +recipe recipes/cfg.sh [target //lib:data] recipe recipes/lib.sh [target //needargv:probe] recipe recipes/needargv.sh [target //recipe:stamp] recipe recipes/recipe.sh +[target //stable:dep] +recipe recipes/stable_dep.sh +[target //stable:parent] +recipe recipes/stable_parent.sh EOF cat > "$ws/src/a.txt" <<'EOF' @@ -46,6 +52,9 @@ EOF cat > "$ws/src/b.txt" <<'EOF' beta EOF +cat > "$ws/src/noop.txt" <<'EOF' +first +EOF cat > "$ws/recipes/lib.sh" <<'EOF' #!/bin/sh @@ -86,11 +95,19 @@ mkdir -p "$KIT_BUILD_OUT" printf '%s\n' "$@" > "$KIT_BUILD_OUT/args.txt" EOF +cat > "$ws/recipes/cfg.sh" <<'EOF' +#!/bin/sh +set -eu +mkdir -p "$KIT_BUILD_OUT" +mode=$("$KIT" build config-get mode || true) +printf 'mode:%s\n' "$mode" > "$KIT_BUILD_OUT/mode.txt" +EOF + cat > "$ws/recipes/needargv.sh" <<'EOF' #!/bin/sh set -eu mkdir -p "$KIT_BUILD_OUT" -dep_dir=$("$KIT" build need --arg dep-one --arg dep-two //argv:echo) +dep_dir=$("$KIT" build need //argv:echo -- dep-one dep-two) cat "$dep_dir/args.txt" > "$KIT_BUILD_OUT/dep-args.txt" EOF @@ -100,6 +117,22 @@ set -eu mkdir -p "$KIT_BUILD_OUT" printf 'recipe:v1\n' > "$KIT_BUILD_OUT/stamp.txt" EOF + +cat > "$ws/recipes/stable_dep.sh" <<'EOF' +#!/bin/sh +set -eu +mkdir -p "$KIT_BUILD_OUT" +"$KIT" build source src/noop.txt >/dev/null +printf 'stable\n' > "$KIT_BUILD_OUT/stable.txt" +EOF + +cat > "$ws/recipes/stable_parent.sh" <<'EOF' +#!/bin/sh +set -eu +mkdir -p "$KIT_BUILD_OUT" +dep_dir=$("$KIT" build need //stable:dep) +cat "$dep_dir/stable.txt" > "$KIT_BUILD_OUT/stable.txt" +EOF chmod +x "$ws"/recipes/*.sh run_build() { @@ -209,11 +242,11 @@ else not_ok "buildcoord-absent-created-new-tree" "$work/absent-tree.diag" fi -build_assert_ok buildcoord-argv-top --arg one --arg two //argv:echo +build_assert_ok buildcoord-argv-top //argv:echo -- one two argv_path=$(tree_path_from "$work/buildcoord-argv-top.out") contains "buildcoord-argv-top-one" "$argv_path/args.txt" "one" contains "buildcoord-argv-top-two" "$argv_path/args.txt" "two" -build_assert_ok buildcoord-argv-changed --arg three //argv:echo +build_assert_ok buildcoord-argv-changed //argv:echo -- three argv_changed_path=$(tree_path_from "$work/buildcoord-argv-changed.out") contains "buildcoord-argv-changed-output" "$argv_changed_path/args.txt" "three" if [ "$argv_changed_path" != "$argv_path" ]; then @@ -248,5 +281,65 @@ else not_ok "buildcoord-recipe-edit-new-tree" "$work/recipe-tree.diag" fi +build_assert_ok buildcoord-stats-cold --stats //stable:parent +contains "buildcoord-stats-cold-recipes" "$work/buildcoord-stats-cold.err" \ + "recipes_run=2" +contains "buildcoord-stats-cold-no-deep" "$work/buildcoord-stats-cold.err" \ + "deep_hits=0" +contains "buildcoord-stats-cold-no-shallow" "$work/buildcoord-stats-cold.err" \ + "shallow_hits=0" + +build_assert_ok buildcoord-stats-deep --stats //stable:parent +contains "buildcoord-stats-deep-hit" "$work/buildcoord-stats-deep.err" \ + "deep_hits=1" +contains "buildcoord-stats-deep-no-run" "$work/buildcoord-stats-deep.err" \ + "recipes_run=0" + +cat > "$ws/src/noop.txt" <<'EOF' +second +EOF +build_assert_ok buildcoord-stats-shallow --stats //stable:parent +contains "buildcoord-stats-shallow-hit" "$work/buildcoord-stats-shallow.err" \ + "shallow_hits=1" +contains "buildcoord-stats-shallow-child-run" "$work/buildcoord-stats-shallow.err" \ + "recipes_run=1" +stable_shallow_path=$(tree_path_from "$work/buildcoord-stats-shallow.out") +contains "buildcoord-stats-shallow-output" "$stable_shallow_path/stable.txt" \ + "stable" + +build_assert_ok buildcoord-stats-cfg-cold --stats --config mode=debug //cfg:probe +contains "buildcoord-stats-cfg-cold-run" "$work/buildcoord-stats-cfg-cold.err" \ + "recipes_run=1" +build_assert_ok buildcoord-stats-cfg-deep --stats --config mode=debug //cfg:probe +contains "buildcoord-stats-cfg-deep-hit" "$work/buildcoord-stats-cfg-deep.err" \ + "deep_hits=1" +contains "buildcoord-stats-cfg-deep-no-run" "$work/buildcoord-stats-cfg-deep.err" \ + "recipes_run=0" +build_assert_ok buildcoord-stats-cfg-change --stats --config mode=release //cfg:probe +contains "buildcoord-stats-cfg-change-run" "$work/buildcoord-stats-cfg-change.err" \ + "recipes_run=1" +contains "buildcoord-stats-cfg-change-no-hit" "$work/buildcoord-stats-cfg-change.err" \ + "shallow_hits=0" +cfg_change_path=$(tree_path_from "$work/buildcoord-stats-cfg-change.out") +contains "buildcoord-stats-cfg-change-output" "$cfg_change_path/mode.txt" \ + "mode:release" + +build_assert_ok buildcoord-stats-argv-cold --stats //argv:echo -- stat-one +contains "buildcoord-stats-argv-cold-run" "$work/buildcoord-stats-argv-cold.err" \ + "recipes_run=1" +build_assert_ok buildcoord-stats-argv-deep --stats //argv:echo -- stat-one +contains "buildcoord-stats-argv-deep-hit" "$work/buildcoord-stats-argv-deep.err" \ + "deep_hits=1" +contains "buildcoord-stats-argv-deep-no-run" "$work/buildcoord-stats-argv-deep.err" \ + "recipes_run=0" +build_assert_ok buildcoord-stats-argv-change --stats //argv:echo -- stat-two +contains "buildcoord-stats-argv-change-run" "$work/buildcoord-stats-argv-change.err" \ + "recipes_run=1" +contains "buildcoord-stats-argv-change-no-hit" "$work/buildcoord-stats-argv-change.err" \ + "shallow_hits=0" +argv_stat_path=$(tree_path_from "$work/buildcoord-stats-argv-change.out") +contains "buildcoord-stats-argv-change-output" "$argv_stat_path/args.txt" \ + "stat-two" + kit_summary "buildcoord" kit_exit