d5728334d6
Add a CMake module that writes rust-project.json on every configure so rust-analyzer can resolve the no-Cargo crate layout, sysroot crates, and proc-macro attributes without Cargo. Co-Authored-By: qwen (lmstudio/qwen3.8-27b@q3_k_xl): LSP setup
173 lines
5.9 KiB
Markdown
173 lines
5.9 KiB
Markdown
# AGENTS.md
|
|
|
|
## Project Overview
|
|
|
|
This project is a small Rust common library and runtime built without Cargo.
|
|
CMake invokes `rustc` directly. The library provides a low-footprint subset
|
|
of standard-library-like functionality:
|
|
|
|
- `Result`, `Duration`, and formatting from `core`
|
|
- `Vec`, `String`, `vec![]`, and `format!` from `alloc`
|
|
- project-local `print!` and `println!` macros
|
|
- direct platform stdout, heap calls, and busy-wait sleep
|
|
|
|
The project contains:
|
|
|
|
- `src/lib.rs`: the `#![no_std]` common library API
|
|
- `src/io.rs`: the `core::fmt::Write` stdout backend
|
|
- `src/runtime.rs`: allocator, async polling, monotonic sleep, and platform
|
|
entry helpers
|
|
- `macros/src/lib.rs`: host-side `#[rslibc_macros::main]` attribute macro
|
|
- `runtime/main.rs`: minimal example entry point
|
|
- `cmake/RustLSP.cmake`: generates `rust-project.json` for rust-analyzer
|
|
- `CMakeLists.txt`: direct `rustc` library, macro, and executable commands
|
|
|
|
## No-Std Design
|
|
|
|
- Keep `#![no_std]` in both the library and runtime.
|
|
- Do not add Rust `std` to the target library or runtime, and do not add
|
|
Cargo unless explicitly requested.
|
|
- The host-side procedural macro may use `proc_macro` and host libraries;
|
|
it is not linked into the target executable.
|
|
- `core` is allowed and is the foundation for `Result`, formatting, slices,
|
|
and other basic language-library functionality.
|
|
- `alloc` is allowed through `extern crate alloc`; it supplies `Vec` and
|
|
related heap-backed types.
|
|
- The final runtime must provide its own global allocator and panic handler;
|
|
`rslibc::entry!` supplies them to an executable.
|
|
- Keep OS integration in small FFI modules. Do not pull in a general-purpose
|
|
runtime or C I/O layer for basic output.
|
|
- `rslibc_macros::main` can wrap `async fn main()` with the small `block_on`
|
|
executor. It is only a polling loop and does not provide Tokio-style I/O
|
|
or a reactor; delays use the busy-wait `rslibc::runtime::sleep`.
|
|
- Keep unsafe code inside small safe wrappers. Application code should be
|
|
able to use calls such as:
|
|
|
|
```rust
|
|
let values = rslibc::vec![1, 2, 3];
|
|
rslibc::println!("values = {:?}", values);
|
|
```
|
|
|
|
## Platform Runtime
|
|
|
|
- Unix stdout calls libc `write` with file descriptor `1`.
|
|
- Windows stdout calls `GetStdHandle` and `WriteFile` through `kernel32`.
|
|
- Windows allocation calls `HeapAlloc` and `HeapFree` through the system
|
|
heap.
|
|
- Sleep uses a monotonic clock: `clock_gettime` on Unix and
|
|
`QueryPerformanceCounter` on Windows.
|
|
- The Windows runtime dynamically links only the platform support needed by
|
|
`alloc` and the compiler runtime. Do not statically link the full C
|
|
runtime.
|
|
- Keep `panic=abort` enabled.
|
|
|
|
## Build System
|
|
|
|
CMake is configured with `LANGUAGES NONE` and invokes `rustc` through three
|
|
custom commands. CMake 4.4's experimental native Rust support
|
|
(`CMAKE_EXPERIMENTAL_RUST`) was evaluated and rejected: it compiles each
|
|
source file as its own crate, so multi-module crates break; it links Rust
|
|
libraries into executables as native `.lib` inputs instead of `--extern`;
|
|
and it has no `proc-macro` crate type. Keep the direct `rustc` commands.
|
|
|
|
The three custom commands are:
|
|
|
|
1. Compile `macros/src/lib.rs` as a host procedural macro.
|
|
2. Compile `src/lib.rs` and its modules to `librslibc.rlib`.
|
|
3. Compile the minimal `runtime/main.rs` and link it against that rlib.
|
|
|
|
Configure and build a release executable with Ninja:
|
|
|
|
```sh
|
|
cmake -S . -B build -GNinja -DCMAKE_BUILD_TYPE=Release
|
|
cmake --build build
|
|
```
|
|
|
|
Build only the host macro with:
|
|
|
|
```sh
|
|
cmake --build build --target rslibc_macros
|
|
```
|
|
|
|
Build only the common library with:
|
|
|
|
```sh
|
|
cmake --build build --target rslibc_library
|
|
```
|
|
|
|
Run it on Unix:
|
|
|
|
```sh
|
|
./build/rslibc_example
|
|
```
|
|
|
|
Run it on Windows:
|
|
|
|
```powershell
|
|
.\build\rslibc_example.exe
|
|
```
|
|
|
|
`CMAKE_BUILD_TYPE` is translated explicitly to rustc flags:
|
|
|
|
- `Release`: `-C opt-level=3 -C debuginfo=0`
|
|
- `RelWithDebInfo`: `-C opt-level=3 -C debuginfo=2`
|
|
- Other or unset configurations: `-C opt-level=0 -C debuginfo=2`
|
|
|
|
## LSP
|
|
|
|
rust-analyzer works without Cargo through a generated manifest:
|
|
|
|
- `cmake/RustLSP.cmake` runs on every configure and writes
|
|
`rust-project.json` (git-ignored) describing the three crates and the
|
|
toolchain sysroot, so `core`, `alloc`, and proc-macro attributes resolve.
|
|
- Requires the rustup components:
|
|
`rustup component add rust-analyzer rust-src`.
|
|
- Open the repository root in the editor so rust-analyzer picks up
|
|
`rust-project.json`. Re-run CMake configure after changing the crate
|
|
layout or switching toolchains.
|
|
|
|
## Verification
|
|
|
|
After changing the source or build configuration, run a clean release build
|
|
and execute the example:
|
|
|
|
```sh
|
|
rm -rf build
|
|
cmake -S . -B build -GNinja -DCMAKE_BUILD_TYPE=Release
|
|
cmake --build build
|
|
./build/rslibc_example
|
|
```
|
|
|
|
On Windows, use `Remove-Item -Recurse -Force build` and run
|
|
`build\\rslibc_example.exe` instead. Confirm that stdout contains
|
|
`100% done`.
|
|
|
|
When size matters, inspect the Windows executable after a release build.
|
|
Avoid adding formatting, allocation, or OS dependencies unless they are
|
|
needed by the library API.
|
|
|
|
## Commit Messages
|
|
|
|
- Follow the 50/72 rule: subject lines are at most 50 characters and body
|
|
lines are wrapped at 72 characters.
|
|
- Use conventional prefixes such as `feat:`, `fix:`, `docs:`, `chore:`,
|
|
and `ci:`.
|
|
- Separate the subject from the body with a blank line.
|
|
- Keep commit messages concise.
|
|
- Include a `Co-Authored-By:` trailer for every agent or model that
|
|
contributed to the commit, one trailer per co-author:
|
|
|
|
```text
|
|
Co-Authored-By: qwen (lmstudio/qwen3.6-27b-mtp): wrote tests + build
|
|
Co-Authored-By: luna (openrouter/openai/gpt-5.6-luna): reviewed edge cases
|
|
```
|
|
|
|
## Editing Guidelines
|
|
|
|
- Keep changes minimal and directly related to the request.
|
|
- Use four-space indentation in Rust and CMake.
|
|
- Keep normal text in Markdown within 80 columns where practical.
|
|
- Do not add speculative abstractions or dependencies.
|
|
- Update this file when the build workflow, library API, supported
|
|
platforms, or source layout changes.
|