|
1 | 1 | # CLAUDE.md |
2 | 2 |
|
3 | 3 | This file provides guidance to Claude Code (claude.ai/code) when working with |
4 | | -code in this repository. |
| 4 | +the Dune codebase. |
5 | 5 |
|
6 | | -# Dune Development Guide |
| 6 | +## Quick Reference |
7 | 7 |
|
8 | | -## Key Architecture |
| 8 | +**Most Common Commands:** |
| 9 | +```bash |
| 10 | +dune build @check # Quick build (recommended for development) |
| 11 | +dune runtest dir/ # Run tests in specific directory |
| 12 | +dune fmt # Auto-format code (always run before committing) |
| 13 | +dune promote # Accept test output changes (ask user first) |
| 14 | +make dev # Full build (bootstraps automatically if needed) |
| 15 | +``` |
| 16 | + |
| 17 | +**Special Operations (Ask User First):** |
| 18 | +```bash |
| 19 | +make bootstrap # Rebuild entire toolchain from scratch |
| 20 | +``` |
| 21 | + |
| 22 | +Note: `dune` refers to `./dune.exe` (the bootstrapped version). |
| 23 | + |
| 24 | +## Project Overview |
| 25 | + |
| 26 | +Dune is a self-hosting OCaml build system that uses itself to build itself. |
| 27 | + |
| 28 | +**Key Concepts:** |
| 29 | +- **Bootstrap**: Building dune from scratch using `make bootstrap` (ask user |
| 30 | + first) |
| 31 | +- **Cram Tests**: `.t` files containing shell commands and expected outputs |
| 32 | +- **Test Promotion**: Accepting new test outputs when behavior changes |
| 33 | +- **Self-hosting**: Dune builds itself using a previously built version |
| 34 | + |
| 35 | +## Architecture |
9 | 36 |
|
10 | 37 | **Directory Structure:** |
11 | | -- `bench` - contain benchmarks |
12 | | -- `bin` - dune's command line |
13 | | -- `boot` - building dune itself |
14 | | -- `doc` - documentation |
15 | | -- `otherlibs` - public libraries that live in this repository. not necessarily dune related |
| 38 | +- `bench` - performance benchmarks |
| 39 | +- `bin` - dune's command line interface |
| 40 | +- `boot` - bootstrap mechanism for building dune itself |
| 41 | +- `doc` - user documentation |
| 42 | +- `otherlibs` - public libraries (dune-configurator, dune-build-info, etc.) |
16 | 43 | - `src` - the majority of the source code |
17 | 44 | - `src/dune_rules` - build rule generation (main logic) |
18 | 45 | - `src/dune_engine` - incremental build engine |
19 | 46 | - `src/dune_lang` - configuration file parser |
20 | | -- `test` - dune's test suite |
21 | | -- `vendor` - 3rd party code pulled into dune. |
| 47 | + - `src/dune_pkg` - package management |
| 48 | + - `src/fiber` - async/concurrency library |
| 49 | + - `src/stdune` - dune's standard library |
| 50 | + - `src/dune_tui` - terminal UI components |
| 51 | +- `test` - dune's test suite (`.t` files are cram tests) |
| 52 | +- `vendor` - 3rd party code pulled into dune |
22 | 53 |
|
23 | | -## Build Commands |
| 54 | +## Development Workflow |
| 55 | + |
| 56 | +### Build Commands |
24 | 57 | ```bash |
25 | | -make check # Quick build (recommended for development) |
26 | | -make dev # Full build |
27 | | -make fmt # Auto-format code (always run before committing) |
| 58 | +dune build @check # Quick build (recommended for development) |
| 59 | +dune build @install # Full build |
| 60 | +dune fmt # Auto-format code (always run before committing) |
28 | 61 | ``` |
29 | 62 |
|
30 | | -## Test Commands |
| 63 | +### Bootstrap Process |
| 64 | + |
| 65 | +**What it is:** Bootstrap solves Dune's circular dependency (Dune builds Dune) |
| 66 | +using `boot/bootstrap.ml` - a mini-build system that creates `_boot/dune.exe` |
| 67 | +without reading any dune files. |
| 68 | + |
| 69 | +**When needed:** |
| 70 | +- Fresh repository checkout (no `_boot/dune.exe` exists) |
| 71 | +- Changes to core build system dependencies in `boot/libs.ml` |
| 72 | +- After certain clean operations that remove `_boot/` |
| 73 | + |
| 74 | +**Why ask user first:** Bootstrap rebuilds the entire toolchain from scratch |
| 75 | +using a carefully orchestrated process. Most development uses the existing |
| 76 | +`_boot/dune.exe`. |
| 77 | + |
| 78 | +**When NOT to bootstrap:** For normal development work, use `dune build @check` |
| 79 | +or `make dev`. Bootstrap is only needed for the specific circumstances above. |
| 80 | + |
| 81 | +**Commands:** |
| 82 | +- `make bootstrap` - Full bootstrap rebuild (ask user first) |
| 83 | +- `make test-bootstrap` - Test bootstrap mechanism |
| 84 | +- `make dev` - Automatically bootstraps only if necessary |
| 85 | + |
| 86 | +### Test Commands |
31 | 87 | ```bash |
32 | | -dune runtest dir/test.t # To run a .t test (each .t is a full dune project) |
33 | | -dune promote dir/test.t # To accept test output changes |
34 | | -make test # To run all tests (567+ tests, very slow) |
| 88 | +dune runtest dir/ # Run tests in specific directory |
| 89 | +dune runtest dir/test.t # Run specific .t test (cram test) |
| 90 | +dune runtest # Run all tests (567+ tests, very slow) |
| 91 | +``` |
| 92 | + |
| 93 | +**Output Handling:** Dune is generally silent when building and only outputs |
| 94 | +errors. Avoid truncating output from `dune build` and `dune runtest`. If |
| 95 | +`dune runtest` gives too much output, run something of smaller scope instead. |
| 96 | + |
| 97 | +**Test Promotion:** When tests fail due to output changes, ask user before |
| 98 | +running `dune promote` to accept changes. |
| 99 | + |
| 100 | +**Experimentation:** Create cram tests (`.t` files) to experiment with how |
| 101 | +things work. Don't run commands manually - run them through `dune runtest` to |
| 102 | +capture and verify behavior. |
| 103 | + |
| 104 | +**Printf Debugging:** When confused about behavior, use `Dune_console` |
| 105 | +(commonly aliased as `Console`) for debugging: |
| 106 | +```ocaml |
| 107 | +Console.printf "something: %s" (Something.to_dyn something |> Dyn.to_string); |
35 | 108 | ``` |
| 109 | +This output will appear in cram test diffs, making it easy to observe values. |
36 | 110 |
|
37 | | -## Development Guidelines |
38 | | -- Always verify changes build with `make check` |
39 | | -- Run `make fmt` to ensure code formatting (requires ocamlformat 0.27.0) |
| 111 | +### Development Guidelines |
| 112 | +- Always verify changes build with `dune build @check` |
| 113 | +- Run `dune fmt` to ensure code formatting (requires ocamlformat 0.27.0) |
40 | 114 | - Keep lines under 80 characters |
41 | | -- Don't add excessive comments unless prompted |
| 115 | +- Only add comments for complex algorithms or when explicitly requested |
42 | 116 | - Don't disable warnings or tests unless prompted |
43 | 117 | - Use pattern-matching and functional programming idioms |
44 | 118 | - Avoid `assert false` and other unreachable code |
45 | 119 |
|
46 | | -## Important Notes |
| 120 | +## Code Conventions |
47 | 121 |
|
| 122 | +### OCaml Patterns |
| 123 | +- Every `.ml` file needs corresponding `.mli` (except type-only files) |
| 124 | +- Use `Code_error.raise` instead of `assert false` for better error messages |
| 125 | +- Qualify record construction: `{ Module.field = value }` |
| 126 | +- Prefer destructuring over projection: `let { Module.field; _ } = record` not |
| 127 | + `record.Module.field` |
| 128 | +- Pattern match exhaustively in `to_dyn` functions: `let to_dyn {a; b; c} = ...` |
| 129 | + |
| 130 | +## Critical Constraints |
| 131 | + |
| 132 | +**NEVER do these things:** |
48 | 133 | - NEVER create files unless absolutely necessary |
49 | | -- ALWAYS prefer editing existing files |
50 | 134 | - NEVER proactively create documentation files (*.md) or README files |
51 | 135 | - NEVER stage or commit changes unless explicitly requested |
52 | 136 | - NEVER run `dune clean` |
53 | 137 | - NEVER use the `--force` argument |
54 | 138 | - NEVER try to build dune manually to run a test |
| 139 | + |
| 140 | +**ALWAYS do these things:** |
| 141 | +- ALWAYS prefer editing existing files over creating new ones |
| 142 | +- ALWAYS ask user before running `dune promote` or `make bootstrap` |
0 commit comments