Table of Contents

Source generators

A source generator is a plug-in that runs inside the C# compiler. While a project compiles, the compiler gives the generator a read-only model of the program: the syntax of every source file, and the symbols of every type, including those of referenced assemblies. The generator can add C# files to the compilation and report diagnostics, but it cannot change or remove code that is already there. What it adds is compiled with the rest of the project, as if the project's author had written it.

A generator suits work that is mechanical but has to follow the program, such as listing every class marked with an attribute. Doing that at run time is reflection: the program searches its own metadata while it runs. Doing it at build time produces ordinary code that names each class directly, which costs nothing at startup and works where reflection is not available. Generators are incremental: the compiler caches the output of each step and reruns a step only when its input changed, so a generator that depends only on a build property is not rerun when a source file is edited.

Build settings do not reach a generator on their own. A project lists each MSBuild property a generator may read as a CompilerVisibleProperty, and the build writes those properties into an editorconfig file that it hands to the compiler, where the generator reads them as build_property.<Name>.

The trap is code nobody can see. Generated files are not in the project folder, so a reader can look for a class that the compiler sees but the file list does not show, and a mistake in a generator surfaces as a compile error in a file nobody wrote. A generator also sees only what the compilation sees: a class the project cannot access, such as a private nested class or an internal class of another assembly, is out of reach of the code it generates.

In Cosmos, a kernel is compiled ahead of time and kernel code does not use reflection, so the kernel cannot search its assemblies for drivers when it boots. DriverManifestGenerator, in Cosmos.Kernel.SourceGenerators, does that search at build time: it finds every [Driver] class in the kernel project and in the referenced assemblies that reference Cosmos.Kernel.HAL, and writes DriverManifest.g.cs, which constructs each one. CosmosEntryPointGenerator writes the entry point that calls the manifest. Cosmos.Sdk turns EmitCompilerGeneratedFiles on, so both files are also written under obj/ for reading, and a marked class the generator cannot construct is reported with warning COSMOSGEN001 rather than dropped in silence. See The attribute and the manifest and the Driver manifest.