{"id":51002103,"url":"https://github.com/yeet-src/toolchain","last_synced_at":"2026-06-20T15:33:11.083Z","repository":{"id":365702486,"uuid":"1273342708","full_name":"yeet-src/toolchain","owner":"yeet-src","description":"Static, version-pinned build toolchain for yeet scripts","archived":false,"fork":false,"pushed_at":"2026-06-18T14:25:57.000Z","size":82,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-18T14:26:55.083Z","etag":null,"topics":["clang","ebpf","llvm","static-binaries","toolchain","yeet"],"latest_commit_sha":null,"homepage":"https://yeet.cx","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yeet-src.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-18T12:35:00.000Z","updated_at":"2026-06-18T14:26:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yeet-src/toolchain","commit_stats":null,"previous_names":["yeet-src/toolchain"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/yeet-src/toolchain","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeet-src%2Ftoolchain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeet-src%2Ftoolchain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeet-src%2Ftoolchain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeet-src%2Ftoolchain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yeet-src","download_url":"https://codeload.github.com/yeet-src/toolchain/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeet-src%2Ftoolchain/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34576042,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-20T02:00:06.407Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clang","ebpf","llvm","static-binaries","toolchain","yeet"],"created_at":"2026-06-20T15:33:10.272Z","updated_at":"2026-06-20T15:33:11.078Z","avatar_url":"https://github.com/yeet-src.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# toolchain\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/st-ignucius.jpg\" alt=\"St. IGNUcius blesses your static build\" width=\"320\"\u003e\u003cbr\u003e\n  \u003cem\u003eSt. IGNUcius blesses your statically-linked build.\u003c/em\u003e\n\u003c/p\u003e\n\nStatic, version-pinned build tools for yeet scripts, so a project's `make`\nruns with **no system C/BPF toolchain** installed. This repo *produces and\npublishes* the toolchain; consumers (e.g. `script-template`) fetch it on demand\ninto a shared per-machine cache.\n\n## What it ships\n\nEach tool is a fully-static binary (no shared-library deps), built or fetched\nper arch (`x86_64`, `aarch64`) and published on an immutable, semver-tagged\nrelease **`vMAJOR.MINOR.PATCH`** (`v0.6.0`, `v0.6.1`, …). The tag carries the\nversion, so the assets are plain-named (`clang-x86_64`, `make-aarch64`, …); a\nconsumer pins one version.\n\nCI picks the bump from the commits since the last release, via a `[bump:LEVEL]`\nmarker in the commit **subject** (the body is free prose — put the marker on the\nsubject line, like `[skip ci]`; for squash merges that's the PR title):\n\n| Marker | Bump | Notes |\n| --- | --- | --- |\n| *(none)* or `[bump:minor]` | **minor** `X.Y+1.0` | the default — a normal push |\n| `[bump:patch]` | **patch** `X.Y.Z+1` | only if **every** commit in the release range is `[bump:patch]` |\n| `[bump:major]` | **major** `X+1.0.0` | one such commit makes the whole release major |\n\nThe release takes the highest level any commit asks for. A PR check\n(`commit-convention.yml`) rejects malformed markers (e.g. `[bump:pacth]`)\nbefore merge, so a typo can't silently mis-version a release.\n\n| tool      | for                                                | source |\n|-----------|----------------------------------------------------|--------|\n| `clang`   | compile `*.bpf.c` (`-target bpf`)                  | built from LLVM source, musl-static |\n| `make`    | drive the build                                    | built from GNU make source, musl-static |\n| `git`     | `git init` a generated project                     | built from git source, musl-static, lean (no https) |\n| `bpftool` | `vmlinux.h` (BTF dump) + link BPF objects          | official static release, re-hosted |\n| `veristat`| check `*.bpf.o` load + BPF verifier statistics     | official static release, re-hosted |\n| `esbuild` | bundle the JS entry                                | official static (Go) binary, re-hosted |\n| `gh`      | release/PR automation (CI + consumer tooling)      | official static (Go) binary, re-hosted |\n| `bpf/*.h` | libbpf program headers (`\u003cbpf/bpf_helpers.h\u003e`, …)  | libbpf bundled with bpftool |\n\nThe table above is the **build** toolchain — what `make` resolves. The same\nrelease also carries two assets for the optional kernel-matrix *test* runner —\n**not** build tools (they need host KVM + root, so `make` never touches them;\nthe test harness fetches them on demand):\n\n- **qemu** (`qemu-\u003carch\u003e.tar.gz`) — built from source like clang, then trimmed\n  to the binary plus the few firmware blobs its machine loads (see\n  [`build/Dockerfile.qemu`](build/Dockerfile.qemu)).\n- **lvh** (`lvh-\u003carch\u003e`) — [cilium's little-vm-helper](https://github.com/cilium/little-vm-helper),\n  which boots the kernel images qemu runs. A single static Go binary distributed\n  only as an OCI image, so it's re-hosted like bpftool (see\n  [`build/fetch-lvh.sh`](build/fetch-lvh.sh)). Bundling it lets the runner skip a\n  docker bootstrap.\n\n```\nbuild/      reproducible recipe — Dockerfile.{clang,make,git,qemu}, build-*.sh,\n            fetch-*.sh, versions.env (pins + checksums)\ninclude/    arch-independent libbpf SDK headers (source for the headers tarball)\nembed/      the glue a template carries: toolchain.mk + fetch-toolchain.sh\n.github/    vendor.yml — builds on native runners and publishes the release\n```\n\nBuilt binaries (`x86_64/`, `aarch64/`) are **not committed** — they're the\nrelease assets. Only the recipe, headers, and embed glue are tracked.\n\n## Consuming it\n\nA template carries the [`embed/`](embed/) glue plus a `toolchain.lock`\n(a copy of [`build/versions.env`](build/versions.env): pins + checksums +\n`TOOLCHAIN_BASE_URL`). The project's `build/toolchain.mk` resolves each tool\nfrom the cache, and `build/fetch-toolchain.sh` downloads any missing one (once)\nfrom this repo's release, checksum-verified. Pull updates with\n`git subtree pull` (or copy `embed/` + `build/versions.env`).\n\n## Releasing\n\nChange a tool pin in [`build/versions.env`](build/versions.env) and push — the\n[`vendor-toolchain`](.github/workflows/vendor.yml) workflow rebuilds clang/make/\ngit (and the test-runner qemu) on native x86_64 and arm64 runners, re-hosts\nbpftool/veristat/lvh/esbuild/gh/headers,\n**computes the next semver tag** (highest existing, bumped by the level the\ncommit messages ask for — minor by default), publishes all assets to\nthat immutable release, and records the version + checksums into `versions.env`.\nThe version bumps only when this repo changes, so consumers re-fetch only on a\nreal toolchain change.\n\n### Back-patching an older line\n\nEvery time `master` cuts a new line (`vX.Y.0`), CI **auto-opens** the\n`release/vX.Y` maintenance branch at that commit (patches and flavor builds\ndon't open a line). So to ship a fix on an older release while `master` has\nmoved on, just PR it into the existing branch:\n\n```\n# release/v0.6 already exists (opened when v0.6.0 was cut)\n# open a PR against release/v0.6, then merge (rebase)\n```\n\nA push to `release/*` runs the same workflow, but the version is scoped **by\nname** to that line's tags — so a fix on `release/v0.6` publishes `v0.6.1`,\nindependent of whatever `master` is on. On `release/*` an unmarked commit\ndefaults to a **patch** bump (not minor), so a hotfix can't accidentally collide\nwith a mainline tag; use `[bump:minor]`/`[bump:major]` to override. (If a line\npredates auto-creation, fork it manually: `git branch release/vX.Y vX.Y.0 \u0026\u0026\ngit push origin release/vX.Y`.)\n\n### Flavored variants\n\nA **flavor** is an opt-in variant of an existing release, tagged\n`vX.Y.Z-\u003cflavor\u003e` (e.g. `v0.6.0-asan`). Run the workflow manually from the\nActions tab with the **`flavor`** input set: it pins to the latest clean\nrelease reachable, appends the suffix, and publishes a separate (prerelease)\nrelease **without bumping the version line**. Flavored tags are unordered — the\nversion computation matches only clean `vX.Y[.Z]` tags, so a flavor never\nbecomes a baseline or shifts mainline. Consumers stay on clean versions by\ndefault and opt in by pinning `TOOLCHAIN_VERSION=X.Y.Z-\u003cflavor\u003e`.\n\n(The suffix is a label only — producing genuinely different binaries for a\nflavor, e.g. via extra build-args, is wired up per flavor when defined.)\n\nTo avoid burning an hour rebuilding clang on every push, the workflow only\nrebuilds a from-source tool when its inputs changed: a `detect` step\nfingerprints each tool's Dockerfile plus the version vars it consumes against\nthe previous release, and reuses that release's binary for anything unchanged\n(so editing only `Dockerfile.git` rebuilds just git). To force a full\nfrom-source rebuild, run the workflow manually from the Actions tab with the\n**`rebuild_all`** box ticked.\n\nBuild a single tool locally:\n\n```sh\nbuild/build-clang.sh arm64        # or amd64; also build-make.sh / build-git.sh / build-qemu.sh\nbuild/fetch-bpftool.sh            # prebuilt; also fetch-veristat.sh / fetch-lvh.sh / fetch-esbuild.sh / fetch-gh.sh / fetch-libbpf-headers.sh\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyeet-src%2Ftoolchain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyeet-src%2Ftoolchain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyeet-src%2Ftoolchain/lists"}