git:20261019.dfc73da to git:20261021.87e69cd

1 added, 0 removed. Audit A to A.

---
name: uloop-compile-check
description: "Compile C# with the Unity-bundled Roslyn compiler without launching or contacting the Unity Editor; reports errors and warnings only."
+ internal: true
---
# uloop compile-check
Compile the project's C# offline, without starting Unity or sending anything to a running Editor.
It replays the response files Unity wrote during its last build with
the C# compiler bundled in the Editor install; the output lands in `Library/uloop/compile-check/`
and is never loaded by Unity.
## When to use
- You want to know whether the code compiles, without starting the Editor or waiting for an import
and a domain reload, and the result need not be live in the Editor yet.
## When not to use
- You want the change reflected in the Editor (play mode, tests, a tool call): run `uloop compile`.
- You just added or removed an `.asmdef`, added a reference to one, or changed scripting defines:
run `uloop compile` once first; the response files describe the previous build only, so the run
is refused with `COMPILE_CHECK_UNITY_BUILD_REQUIRED`.
- The project has no `Library` yet (a fresh clone, or an Editor that has never opened it): there is
no build to replay, so the run is refused with the same code. Let Unity build once, with
`uloop launch` or headless (`<Unity executable> -batchmode -nographics -quit -projectPath <dir>`).
After that one build, compile-check works without the Editor until an `.asmdef` or build-setting
change makes it ask for another (see Limitations).
## Usage
```bash
uloop compile-check
uloop compile-check --all --project-path /path/to/project
```
By default it compiles the assemblies whose sources changed since the last Unity build, plus every
assembly that references one of them. Independent assemblies compile at the same time (`--jobs`
caps how many; `--jobs 1` is sequential). An assembly whose inputs are exactly as the previous run
read them is not compiled again: its recorded diagnostics are reported, errors included. `--all`
compiles every assembly from scratch, the way out if a reused result ever looks wrong.
Once compile-check has compiled a large assembly in full without errors, an edit that keeps every
declaration is checked on its changed files only, in a few seconds, and the assembly is listed in
`FastCheckedAssemblies`. Compiled in full instead (`FastPathFallbacks` says why when the check was
tried): the first run after a Unity build; a run that adds, removes or renames a `.cs` file, or
changes more than 30 files; an edit that changes a declaration (a `using` directive counts); the
first run after a full compile that had errors; and an assembly compiled only because one it
references changed, which records no baseline. A change to the public surface also compiles the
dependents that can see it: those that write a changed name, or all of them when no name carries the
change; `SurfaceChecks` says which and why. Details and times: `references/full-compiles.md`.
Full compiles run the project's analyzers with the response file's flags, `-warnaserror` included.
The changed-files check skips the assembly-wide rules in `FastChecks[].UncheckedCodes`, so run once
with `--full` before finishing: it compiles in full what differs from its last full compile and
reuses the rest; right after a run that compiled in full it takes about a second. When warnings are
errors, such a rule (CS0414, for example) can fail that run only. A run that stops on declaration
errors (an unknown type, say) reports neither body errors nor analyzer diagnostics: fix them and run
again.
## Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| `--all` | flag | Compile every assembly instead of only the changed ones and their dependents |
| `--full` | flag | Compile changed assemblies in full instead of checking only their changed files |
| `--editor-version <version>` | string | Use this Unity Editor version's compiler instead of ProjectVersion.txt |
| `--jobs <N>` | number | Compile up to N assemblies at once (default: half the CPUs, at least 1; `1` compiles sequentially) |
| `--max-depth <N>` | number | Search depth when locating the project (default: 3, -1 for unlimited) |
| `--project-path <path>` | string | Target another Unity project instead of the current directory |
## Output
A JSON payload; an empty list means the case did not occur in this run:
- `Success`: whether the compile produced no errors
- `ErrorCount`, `WarningCount`: totals across every compiled and reused assembly
- `Errors`, `Warnings`: each with `Message`, `Code`, `File`, `Line`, `Column`, `Assembly`
- `CompiledAssemblies`: compiled by this run, in dependency order
- `ReusedAssemblies`: reported from the previous run's result, without compiling
- `BlockedAssemblies`: not compiled because an assembly they reference has errors, as in Unity's
build; fix those and run again
- `FastCheckedAssemblies`: checked on their changed files only
- `FastChecks`: per fast-checked assembly, `ChangedFiles`, `UncheckedCodes` (rules only `--full` runs),
`GeneratorsNotRerun`, and `Reused` (the same edit's previous check, reported again)
- `FastPathFallbacks`: `Assembly` and `Reason` for each assembly compiled in full instead
- `FastPathBaselineNotes`: `Assembly` and `Reason` for each successful full compile that left no
baseline for the next check
- `SurfaceChecks`: per assembly others reference that this run compiled, replayed or fast-checked
without errors: `Kept`, or the `ChangedNames` a dependent must write to be affected (`Unnamed`
says why no name tells the change), and the compiled `Dependents` it reached, each with the
`Name` that selected it
- `SkippedAssemblies`: how many were left out because nothing they can see changed
- `ResponseFileSet`, `ProjectRoot`: the Bee build the run replayed and the resolved project root
- `Message`: one-line summary
- `NextActions`: the next step (fix and rerun, `--full` for the skipped rules, or `uloop compile` to
make the result live); empty when nothing changed
The process exits 1 when `ErrorCount` is greater than zero, and when the command itself fails, such
as with `COMPILE_CHECK_UNITY_BUILD_REQUIRED`; then no payload is printed and the error, with its
`ErrorCode`, goes to stderr. One compile-check runs per project at a time; a second waits up to
five minutes, then fails with `COMPILE_CHECK_PROJECT_BUSY`. Run it once more rather than retrying in
a loop.
## Limitations
- It replays the last Unity build's response files. A new or deleted `.asmdef`, a changed `.asmdef`
reference, an `.asmdef` that stopped building for the Editor, or a newly required precompiled
reference stops the run and asks for `uloop compile`.
- Build settings are compared against a record the first run after a Unity build writes: a
removed scripting define, a changed `csc.rsp`, `defineConstraints`, `versionDefines`,
`packages-lock.json` or `manifest.json` stops the run, and a scripting define the last build lacks
stops it when `ProjectSettings.asset` was saved after that build. A change made before that first
run (other than an added define) is not seen, so run `uloop compile` after one. Under a Unity 6
build profile that overrides Player Settings or carries its own defines, only the global
ProjectSettings defines are compared.
- A reference removed from an `.asmdef` stops the run too; the four references Unity adds on its own
are allowed, and a reference that matches no `.asmdef` in the project is not judged.
- A new `.cs` file outside every `.asmdef` goes to `Assembly-CSharp` or a sibling by Unity's path
rules (`Editor` folders, `Assets/Plugins`); if the last build did not produce that assembly, the run
stops and asks for `uloop compile`. A new script in a package folder without an `.asmdef` is not seen.
- A generator that reads a referenced assembly is not rerun for a change in that assembly; run
`uloop compile` after one.