Skip to content

Commit 592d765

Browse files
committed
Document ion-build as the primary workflow in README, skills, and spec.
Replace manual gcc-first usage with ion.toml manifests and per-example build commands; document ion-build --manifest in ION_SPEC section 10.1.
1 parent dec0f6b commit 592d765

5 files changed

Lines changed: 69 additions & 86 deletions

File tree

.cursor/skills/ion-integration-tests/SKILL.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ paths:
1515

1616
End-to-end tests: Ion → C → gcc → run executable → assert exit code (or assert compile failure).
1717

18-
The harness runs tests under `tests/` only. Files in `examples/` are documented demos - compile and run them manually (see [README.md](../../../README.md)); they are not in the integration manifest.
18+
The harness runs tests under `tests/` only. Files in `examples/` are documented demos; build and run them with `ion-build` and per-example manifests (see [README.md](../../../README.md#example-programs)). Regenerate committed `examples/*.c` snapshots with `ion-compiler` after codegen changes.
1919

2020
**Example output policy:** Top-level single-file examples commit one merged `.c` next to the `.ion`. `text_summary/` commits one `.c` plus `sample.txt`. Multi-file `data_lib/` keeps `.ion` only (see `examples/data_lib/README.md`).
2121

@@ -29,7 +29,7 @@ for f in examples/*.ion; do ./target/release/ion-compiler "$f"; done
2929

3030
Multi-file `examples/data_lib/` has no committed `.c`; see `examples/data_lib/README.md`.
3131

32-
Link and run like integration tests (`gcc` + `runtime/ion_runtime.c` + `-lpthread`; on Windows MinGW add `-lws2_32`).
32+
To build examples, use `ion-build` (see README). Manual `gcc` + `runtime/ion_runtime.c` is for the test harness and advanced debugging only.
3333

3434
## Run tests
3535

@@ -56,7 +56,7 @@ COMPILER=../target/debug/ion-compiler ION_BUILD=../target/debug/ion-build CC=cla
5656
RUNTIME_OBJ=/tmp/ion_runtime.o ./test_runner.sh
5757
```
5858

59-
**Harness link step:** On startup, `test_runner.sh` precompiles `runtime/ion_runtime.c` once to `RUNTIME_OBJ` (default `.ion_test_runtime.o`) and links that object for each `run` test and `test_multifile`. Same `gcc` flags as before; manual example compiles below still use `ion_runtime.c` directly.
59+
**Harness link step:** On startup, `test_runner.sh` precompiles `runtime/ion_runtime.c` once to `RUNTIME_OBJ` (default `.ion_test_runtime.o`) and links that object for each `run` test and `test_multifile`. This path uses `ion-compiler` and `gcc` directly, not `ion-build`. Example programs under `examples/` use `ion-build` per README.
6060

6161
**Windows:** Use Git Bash, not WSL. Rebuild release after compiler changes. Stop `ion-lsp` if build fails with "Access is denied".
6262

.cursor/skills/writing-ion-code/SKILL.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ fn main() -> int {
5656
}
5757
```
5858

59-
Import paths are string literals relative to the compiling file. Use `pub fn` in library modules; call with `alias::name(...)`.
59+
Import paths like `import "stdlib/io.ion" as io;` resolve via stdlib search paths (`ion.toml`, `ION_STDLIB`, project `stdlib/`). Same-directory and `../` relative paths still work. Use `pub fn` in library modules; call with `alias::name(...)`.
6060

6161
## Core syntax (verified)
6262

@@ -123,7 +123,7 @@ Fn literals lower to static C functions and must not reference outer bindings (o
123123

124124
## Documentation comments
125125

126-
Ion uses plain `//` line comments only — no `///` or `//!`. Contiguous `//` lines **immediately above** a declaration (no blank line before the declaration) are attached as documentation for IDE hover; the same rule applies when `pub` precedes the item. A blank line breaks association. File-level overview comments go at the top of the file before imports. Section-divider comment blocks in examples should be separated from declarations by a blank line. See ION_SPEC §12.6.
126+
Ion uses plain `//` line comments only. No `///` or `//!`. Contiguous `//` lines **immediately above** a declaration (no blank line before the declaration) are attached as documentation for IDE hover; the same rule applies when `pub` precedes the item. A blank line breaks association. File-level overview comments go at the top of the file before imports. Section-divider comment blocks in examples should be separated from declarations by a blank line. See ION_SPEC section 12.6.
127127

128128
**Unsafe and FFI**
129129

@@ -144,16 +144,19 @@ Built-ins: `Vec<T>`, `String`, `Box<T>`, `Option<T>`, `Result<T, E>` (define enu
144144

145145
## Build and verify
146146

147-
With `ion.toml` at the project root (or example directory):
147+
With `ion.toml` in the project or example directory (or `examples/*.toml` with `--manifest`):
148148

149149
```powershell
150150
cargo build --release --bin ion-build
151-
.\target\release\ion-build.exe build
152-
.\target\<output>.exe
151+
cd examples # or example subdirectory with ion.toml
152+
..\target\release\ion-build.exe build --manifest spawn_channel.toml
153+
.\target\spawn_channel.exe
153154
echo $LASTEXITCODE
154155
```
155156

156-
For a single file without a manifest, use `ion-compiler` plus manual `gcc` (see `ion-lang` skill). On Windows add `-lws2_32` for channel/spawn programs. Stop `ion-lsp` if rebuild fails with "Access is denied".
157+
Multi-file: `cd examples\data_lib` then `..\..\target\release\ion-build.exe build`. See [examples/data_lib/README.md](../../../examples/data_lib/README.md).
158+
159+
For codegen inspection or `tests/` integration harness work, use `ion-compiler` plus manual `gcc` (see `ion-lang` skill). On Windows add `-lws2_32` for channel/spawn when linking manually. Stop `ion-lsp` if rebuild fails with "Access is denied".
157160

158161
For programs under `tests/`, follow the `ion-integration-tests` skill (`test_expectations.tsv` row required).
159162

.cursor/skills/writing-ion-code/references/verified-patterns.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,14 @@ fn main() -> int {
117117

118118
Non-`pub` items are file-private. Qualified names use `alias::item`.
119119

120-
Multi-file compile (manual):
120+
Multi-file build (`ion-build` with `mode = "multi"` in `ion.toml`):
121+
122+
```powershell
123+
cd examples\data_lib
124+
..\..\target\release\ion-build.exe build
125+
```
126+
127+
Manual codegen only (emits `.c`/`.h` in cwd):
121128

122129
```bash
123130
./target/release/ion-compiler --mode multi --output app path/to/main.ion

ION_SPEC.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,8 @@ cargo build --release --bin ion-build
11941194
.\target\release\ion-build.exe build
11951195
```
11961196

1197+
Manifest discovery walks upward from the current directory for a file named `ion.toml`. To use another filename (for example `examples/http_server.toml`), pass `--manifest <path>`; the manifest's parent directory is the project root and `main` paths are relative to that directory.
1198+
11971199
`ion-compiler` remains available for codegen inspection, LSP internals, and integration tests that grep `.c` output. It does not require `ion.toml`.
11981200

11991201
**`ion.toml` fields (tooling, not language semantics):**

README.md

Lines changed: 47 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ Source: [examples/hello_world_safe.ion](examples/hello_world_safe.ion). For a mi
114114

115115
### Advanced: Manual Transpile and Link
116116

117-
For codegen inspection or debugging, use `ion-compiler` directly:
117+
For codegen inspection, integration test workflows, or debugging generated C, use `ion-compiler` directly (see [ION_SPEC.md section 10.1](ION_SPEC.md#101-project-build-ion-build)):
118118

119119
```bash
120120
./target/release/ion-compiler examples/hello_world.ion
@@ -123,107 +123,77 @@ gcc examples/hello_world.c runtime/ion_runtime.c -o hello_world \
123123
./hello_world
124124
```
125125

126-
### Single-File Mode (Default)
126+
The integration harness (`tests/test_runner.sh`) calls `ion-compiler` and `gcc` this way. Application development should use `ion-build` instead.
127127

128-
**Step 1: Compile Ion to C**
128+
### Project manifests (`ion.toml`)
129129

130-
```bash
131-
./target/release/ion-compiler input.ion
132-
```
133-
134-
This generates `input.c` in the same directory as the source file.
135-
136-
**Step 2: Compile C to Executable**
137-
138-
The generated C code requires the Ion runtime library:
139-
140-
```bash
141-
gcc input.c runtime/ion_runtime.c -o input -I. -I.. -Iruntime -I../runtime -lpthread
142-
```
130+
`ion-build` discovers `ion.toml` by walking up from the current directory. Required fields: `name`, `main`, `output`. Common optional fields: `mode` (`single` or `multi`), `out_dir` (default `target`), `cflags`, `ldflags`, `stdlib_paths`.
143131

144-
**Required flags:**
145-
- `input.c` - generated C file
146-
- `runtime/ion_runtime.c` - Ion runtime (when running from project root)
147-
- `-I. -I.. -Iruntime -I../runtime` - include paths for runtime headers
148-
- `-lpthread` - pthread library (required for channels and spawn)
149-
- `-o input` - output executable name
132+
Root [ion.toml](ion.toml) builds [examples/hello_world_safe.ion](examples/hello_world_safe.ion). Per-example manifests live under [examples/](examples/) (for example `spawn_channel.toml`, `http_server.toml`, `examples/data_lib/ion.toml`). Use `--manifest path` when the file is not named `ion.toml`:
150133

151-
**Step 3: Run**
152-
153-
```bash
154-
./input
134+
```powershell
135+
cd examples
136+
..\target\release\ion-build.exe build --manifest http_server.toml
137+
.\target\http_server.exe
155138
```
156139

157-
### FFI with POSIX Functions
158-
159-
If your Ion program uses FFI names that conflict with Ion keywords (`recv`, `send`), add `-D` flags when linking:
140+
FFI programs that rename C symbols (for example `recv_sys`) set compile-time `-D` flags in `cflags`, not `ldflags`. See [examples/http_server.toml](examples/http_server.toml).
160141

161-
```bash
162-
gcc http_server.c runtime/ion_runtime.c -o http_server \
163-
-I. -I.. -Iruntime -I../runtime -lpthread \
164-
-Drecv_sys=recv -Dsend_sys=send -Dclose=closesocket -lws2_32
165-
```
142+
### Multi-file projects
166143

167-
On Linux or macOS, omit `-lws2_32` and `-Dclose=closesocket`. `ion_net_init()` is a no-op outside Windows.
144+
Multi-file mode (`mode = "multi"` in `ion.toml`) transpiles each module to `.c`/`.h`, compiles objects, and links one executable. Artifacts default to `out_dir` (usually `target/`), not the source tree.
168145

169-
### Multi-File Mode
170-
171-
```bash
172-
./target/release/ion-compiler --mode multi --output myprogram main.ion
146+
```powershell
147+
cd examples\data_lib
148+
..\..\target\release\ion-build.exe build
149+
.\target\data_lib.exe
173150
```
174151

175-
This parses imported modules, generates `.c` and `.h` per module, compiles object files, and links with the runtime. The `--output` flag sets the executable name (defaults to the main module name). Multi-file mode handles compilation and linking; you do not need to run `gcc` manually.
152+
For manual multi-file codegen in the source directory (no `ion-build`), use `ion-compiler --mode multi --output NAME main.ion`. See [examples/data_lib/README.md](examples/data_lib/README.md).
176153

177154
## Example Programs
178155

179-
Top-level `examples/*.ion` files each have a checked-in merged `examples/*.c` codegen snapshot. Regenerate after compiler codegen changes:
156+
Top-level `examples/*.ion` files each have a checked-in merged `examples/*.c` codegen snapshot. Regenerate after compiler codegen changes (from repo root, relative paths keep portable banners):
180157

181158
```bash
182159
for f in examples/*.ion; do ./target/release/ion-compiler "$f"; done
183160
./target/release/ion-compiler examples/text_summary/text_summary.ion
184161
```
185162

186-
Top-level single-file examples (including `channel_worker.ion`) commit a merged `.c` snapshot next to the `.ion`. The `text_summary/` subdirectory also commits one `.c` (it needs `sample.txt`). Multi-file `examples/data_lib/` keeps only `.ion` sources; see [examples/data_lib/README.md](examples/data_lib/README.md) for build output (`.c`/`.h` generated in place, not committed).
187-
188-
Compile and run any single-file example:
189-
190-
```bash
191-
./target/release/ion-compiler examples/spawn_channel.ion
192-
gcc examples/spawn_channel.c runtime/ion_runtime.c -o spawn_channel \
193-
-I. -Iruntime -lpthread -lws2_32 # omit -lws2_32 on Linux/macOS
194-
./spawn_channel
195-
```
163+
Committed `.c` snapshots are for review and `ion-compiler` regression; building and running examples uses `ion-build` and the manifests below.
196164

197-
For `http_server.ion`, add `-Drecv_sys=recv -Dsend_sys=send` when linking.
165+
**Build and run** (from `examples/` unless noted):
198166

199-
| File | What it demonstrates |
200-
|------|---------------------|
201-
| [examples/hello_world.ion](examples/hello_world.ion) | Minimal FFI `write()` to stdout |
202-
| [examples/hello_world_safe.ion](examples/hello_world_safe.ion) | stdlib `io` module |
203-
| [examples/spawn_channel.ion](examples/spawn_channel.ion) | `spawn` with cross-thread channels |
204-
| [examples/http_server.ion](examples/http_server.ion) | Sockets, FFI, concurrent clients via `spawn` |
205-
| [examples/showcase.ion](examples/showcase.ion) | Mixed language features: tuples, `+=`, `push_byte`, spawn/channels, capture-free fn literals |
206-
| [examples/access_log.ion](examples/access_log.ion) | Log parsing, `loop`/`break`, match guards, spawn, channels, fmt/io |
207-
| [examples/minimal.ion](examples/minimal.ion) | Smallest valid program |
208-
| [examples/channel_worker.ion](examples/channel_worker.ion) | Channel worker: `spawn` sums jobs from a channel |
209-
| [examples/text_summary/text_summary.ion](examples/text_summary/text_summary.ion) | `fs` file read, string iteration, line/word/byte counts |
210-
| [examples/data_lib/main.ion](examples/data_lib/main.ion) | Multi-module library (`catalog.ion`); see [data_lib/README.md](examples/data_lib/README.md) |
167+
```powershell
168+
# Single-file example with a manifest in examples/
169+
..\target\release\ion-build.exe build --manifest spawn_channel.toml
170+
.\target\spawn_channel.exe
211171
212-
Build `data_lib` (multi-file):
172+
# http_server (FFI cflags in http_server.toml)
173+
..\target\release\ion-build.exe build --manifest http_server.toml
213174
214-
```powershell
215-
cd examples\data_lib
175+
# text_summary (has its own ion.toml; needs sample.txt in that directory)
176+
cd text_summary
216177
..\..\target\release\ion-build.exe build
217-
.\target\data_lib.exe
178+
.\target\text_summary.exe
218179
```
219180

220-
Or with `ion-compiler` directly (emits `.c`/`.h` in the current directory):
181+
On Linux or macOS, use `./target/release/ion-build` and drop `.exe`. Windows channel/spawn builds add `-lws2_32` automatically.
221182

222-
```bash
223-
cd examples/data_lib
224-
../../target/release/ion-compiler --mode multi --output data_lib main.ion
225-
./data_lib
226-
```
183+
| File | Manifest | What it demonstrates |
184+
|------|----------|---------------------|
185+
| [examples/hello_world.ion](examples/hello_world.ion) | (use `ion-compiler` only; no stdlib) | Minimal FFI `write()` to stdout |
186+
| [examples/hello_world_safe.ion](examples/hello_world_safe.ion) | [hello_world_safe.toml](examples/hello_world_safe.toml) or root [ion.toml](ion.toml) | stdlib `io` module |
187+
| [examples/spawn_channel.ion](examples/spawn_channel.ion) | [spawn_channel.toml](examples/spawn_channel.toml) | `spawn` with cross-thread channels |
188+
| [examples/http_server.ion](examples/http_server.ion) | [http_server.toml](examples/http_server.toml) | Sockets, FFI, concurrent clients via `spawn` |
189+
| [examples/showcase.ion](examples/showcase.ion) | [showcase.toml](examples/showcase.toml) | Mixed language features |
190+
| [examples/access_log.ion](examples/access_log.ion) | [access_log.toml](examples/access_log.toml) | Log parsing, spawn, channels, fmt/io |
191+
| [examples/minimal.ion](examples/minimal.ion) | (transpile-only with `ion-compiler`) | Smallest valid program |
192+
| [examples/channel_worker.ion](examples/channel_worker.ion) | [channel_worker.toml](examples/channel_worker.toml) | Channel worker |
193+
| [examples/text_summary/text_summary.ion](examples/text_summary/text_summary.ion) | [text_summary/ion.toml](examples/text_summary/ion.toml) | `fs` read, string iteration, counts |
194+
| [examples/data_lib/main.ion](examples/data_lib/main.ion) | [data_lib/ion.toml](examples/data_lib/ion.toml) | Multi-module library; see [data_lib/README.md](examples/data_lib/README.md) |
195+
196+
`examples/data_lib/` keeps only `.ion` sources; `ion-build` writes `.c`, `.h`, and the executable under `examples/data_lib/target/` (not committed).
227197

228198
## Project Structure
229199

@@ -233,8 +203,9 @@ cd examples/data_lib
233203
│ ├── lexer/ # Tokenizer
234204
│ ├── parser/ # AST construction
235205
│ ├── ast/ # AST node definitions
236-
│ ├── compiler/ # Compilation driver (module resolution, cycle detection)
237-
│ ├── tc/ # Type Checker (safety checks, visibility, qualified names)
206+
│ ├── compiler/ # Module resolution, import paths
207+
│ ├── build/ # ion.toml, ion-build driver, C toolchain
208+
│ ├── tc/ # Type checker (safety, visibility, qualified names)
238209
│ ├── ir/ # Intermediate representation
239210
│ └── cgen/ # C code generator
240211
├── runtime/ # C runtime headers

0 commit comments

Comments
 (0)