Hedronite Lesson · Polyglot-Dev / V · Tue 2026-10-06 · V row #6 (Duha 1 of 4)

Build V 0.5.2 from the tag on the lab Mac: v doctor and the repo map · Tag Clone · Build Local · Ask the Doctor · Walk the Tree

Clone the tag. Pin the seed. Build local. Ask the doctor. Walk the tree.

Lesson Class: Duha (V dual-seat · learn-first · contributor-aware · watch-not-adopt)
Focus: Tag Clone · Build Local · Ask the Doctor · Walk the Tree
Done-criteria: tag 0.5.2 built on the lab Mac; v doctor run; cmd/ vlib/ thirdparty/ mapped; one concrete difference from Asr #1
Grounding: vlang/v 0.5.2 (7647ce1) README + CONTRIBUTING + GNUmakefile + pref/default.v + vdoctor.v
Note: Lab Mac, macOS 27.0.1 Apple M4 · plain make exit 2 (vc tip) · vc 7eb8c54 + make local=1 exit 0 in 14.2 s · Nix Beat B skipped
Build Local
make local=1 skips the vc and tcc pulls, so a pinned seed stays pinned.
Ask the Doctor
v doctor shows seed hash, tag hash, and every C compiler in one table.
Walk the Tree
Compiler = cmd/v + vlib/v. v2_toberemoved and v3 are in-development rewrites.
Clone the tag. Pin the seed. Build local. Read the doctor before you file.

<!-- hal:authoritative:yaml -->

Clone the tag. Pin the seed. Build local. Ask the doctor. Walk the tree.

§I. Frame

Duha V session 1 of 4 (syllabus row #6), Tue 2026-10-06. Learn-first, contributor-aware, watch-not-adopt. Yesterday's Asr #1 built V on the box (Linux x86_64) and left one warning for today: pin the vc seed or make breaks. Today the same tag goes onto the lab Mac, an Apple M4 on macOS 27.0.1 with Apple clang 21.0.0. The goal is the contributor's view of a V checkout: what make fetches, what v doctor reports, and where the compiler lives in the tree. Every cite is vlang/v at tag 0.5.2 (commit 7647ce1).

§II. Four techniques

  1. Tag Clone. git clone --depth 1 --branch 0.5.2. README shows a plain --depth=1 clone of master; a lab wants the release.
  2. Build Local. The GNUmakefile wraps its vc and tcc pulls in ifndef local. make local=1 runs the same bootstrap against whatever seed sits in ./vc, so a pinned seed stays pinned.
  3. Ask the Doctor. v doctor prints one table: OS, CPU, V version, V home, git state of the checkout, and every C compiler it can find, bundled tcc included.
  4. Walk the Tree. CONTRIBUTING names the compiler's home (cmd/v/ and vlib/v/) and its three steps. Read the tree against that list before touching a file.

§III. The build, on the lab Mac

The tag clone took 4.0 s and landed on 7647ce1. Plain make then did what Asr #1 predicted. It cloned vlang/vc and pulled it to the tip, 475a2bd (2026-10-04), cloned the macOS arm64 tcc bundle, built v1 from the seed, and stopped when v1 rejected the 0.5.2 compiler source. The first error is the same one the box hit, in vlib/v/builder/c_error_report.v:456. The log prints 20 errors and then ... and 40 more errors. make exited 2 after 22.5 s.

The repair on the lab Mac is shorter than the box repair. git -C vc log --oneline | grep 'V 0.5.2' finds 7eb8c54a [v:master] 45ae01d... - V 0.5.2. Check that out, then run make local=1. The three bootstrap stages ran exactly as the GNUmakefile writes them:

cc -std=c99 -w -o v1 ./vc/v.c -lm -lpthread
./v1 -no-parallel -o v2 -gc none cmd/v
./v2 -nocache -o ./v -gc none cmd/v

Exit 0 in 14.2 s, and ./v version printed V 0.5.2 7647ce1. If the seed breaks, then a tag build fails before your own code is ever compiled; thus the seed is part of the pin, and local=1 is how you tell make so. Asr #1 ran the three commands by hand because a second plain make would pull vc back to the tip. make local=1 gives the same result and still runs the post-build detect_tcc.v check.

§IV. What v doctor says

v doctor is a real subcommand at 0.5.2 (listed in cmd/v/v.v, implemented in cmd/tools/vdoctor.v). On the lab Mac it exited 0 and reported:

FieldLab Mac value
V full versionV 0.5.2 45ae01d23168b6372f734eeb38a77360bbcf184a.7647ce1
OS / CPUmacOS 27.0.1 (26A434); 10 cpus, 64bit, Apple M4
V home / VMODULES / VTMPthe checkout; ~/.vmodules; /tmp/v_501
V git status0.5.2
cc / gcc / clangall Apple clang 21.0.0
tcc0.9.28rc 2026-07-24 HEAD@85ba3ae8 (AArch64 Darwin), branch thirdparty-macos-arm64 at 1d0ad0ec

Two lines repay attention. The full version carries two hashes. The long one matches the V commit named in the pinned seed's message, and 7647ce1 is the tag; a bug report with this line says exactly which seed built which source. And the tcc row shows the bundle is newer than the tag (built 2026-07-24, after the 2026-07-12 release). Only the seed was pinned. The tcc bundle floats, as it did on the box.

§V. The concrete difference from Asr #1

On the box, -showcc showed the bundled tcc compiling hello. On the lab Mac it shows 'cc', with -arch arm64 and -x objective-c. The reason is in vlib/v/pref/default.v, function try_to_use_tcc_by_default: on macOS the source says the bundled tcc "is sensitive to Apple SDK/header changes" and keeps it behind an explicit -cc tcc. Linux dev builds default to tcc; macOS dev builds default to clang.

Both paths work on the lab Mac. v run hello.v printed hello from the lab Mac, V 0.5.2 in 0.24 s with exit 0. The clang binary is 96,808 bytes; the same program with -cc tcc is 189,184 bytes. The generated C is 4320 lines here against 4963 on the box, because the builtin module emits per-platform code. One more split: v self on the lab Mac reported -cc tcc -gc none and rebuilt the compiler in 2.0 s. The compiler rebuilds itself with tcc even where user programs default to clang.

§VI. The repo map

CONTRIBUTING's Code Structure section is the map. The compiler is cmd/v/ (entry point cmd/v/v.v) plus vlib/v/. Inside vlib/v/, the pipeline is scanner and token, then parser (AST), then checker (types), then gen/c, gen/js, or gen/native. The rest of vlib/ is the standard library: builtin, os, time, net, json, veb, db, and more.

File counts on the lab Mac after the build (they include the cloned tcc):

PathFilesWhat lives there
cmd/345cmd/v (3 files), cmd/tools (99 entries: vdoctor.v, vfmt, test runners, git_pre_commit_hook.vsh), cmd/v2
vlib/10,692vlib/v has 7688 of them: the compiler modules and their tests
thirdparty/587C deps tracked in git (libgc, mbedtls, sokol, zstd and others) plus tcc/, which is not tracked: make clones it from vlang/tccbin
examples/602hello_world.v, the program README tells you to run first
doc/8docs.md, ownership.md

One trap for a newcomer. Three compiler trees sit side by side at 0.5.2. vlib/v is the one CONTRIBUTING documents. vlib/v2_toberemoved describes itself as "a new version of the compiler (still in development)", with a test runner in cmd/v2. vlib/v3 calls itself a "clean rewrite of the V compiler". Those are the authors' own labels for unfinished work. CONTRIBUTING documents only vlib/v, so a first patch belongs there or in a library module.

§VII. Lab

  1. Tag Clone into a scratch dir; confirm git rev-parse HEAD starts 7647ce1.
  2. Run plain make once. Record the exit code and git -C vc log -1 --format='%h %ci'.
  3. Pin vc to 7eb8c54, run make local=1, confirm ./v version.
  4. Run ./v doctor. Find the two hashes and the tcc branch.
  5. ./v -showcc -o /tmp/h hello.v, then ./v -cc tcc -showcc -o /tmp/h2 hello.v. Name the compiler each time.
  6. Count files under cmd, vlib, vlib/v, thirdparty. Find vlib/v/checker and vlib/v/gen/c.
  7. Run ./v self and read which C compiler it chose.

Evidence for this fire is in lab/ beside this file: lab.sh (the exact script), lab.log, make-plain.log, make-local.log, vdoctor.log, hello.v. Build tree on the lab Mac: ~/src/vlang-duha6/v (scratch, not a product checkout).

§VIII. Common mistakes

  1. Re-running plain make after pinning vc, which pulls the seed back to the tip.
  2. Treating "V 0.5.2" in v version as proof of a clean build without reading the hashes in v doctor.
  3. Assuming tcc compiled your program on a Mac. Check -showcc.
  4. Sending a first patch into vlib/v3 or vlib/v2_toberemoved.
  5. Deleting thirdparty/tcc as "vendored junk"; v self uses it.

§IX. Contributor-path takeaway

CONTRIBUTING gives one recovery rule for a broken compiler: "you can always simply run make" to fetch the C seed and rebuild. On master that holds, because the seed tracks master. On a release tag it fails, as the lab Mac showed today. The tag-safe recovery is: keep a backup v binary (CONTRIBUTING asks for this too), pin vc to the commit whose message names the release, and run make local=1. Put the v doctor table in any bug report so a maintainer can see seed, source, and C compiler in one read.

§X. V next to Rust, session 6

Would buy us: a compiler that rebuilds itself in about two seconds on the lab Mac, a doctor command that fits a bug report on one screen, and a tree small enough to read module by module. Would not buy us: a pinned toolchain by default (seed and tcc both float), one C compiler across platforms (tcc on Linux, clang on macOS), or one compiler tree (three coexist). rustup pins a toolchain by name and rust-toolchain.toml pins it per project; V's .vvmrc can delegate v run to a named version, but make at a tag does not pin its own seed. Verdict: learn the build, keep the pin notes, adopt nothing. Duha #7 reads CONTRIBUTING's ladder and runs v fmt and v test against this checkout tomorrow.

Related: ·

Clone the tag. Pin the seed. Build local. Read the doctor before you file.