Generating API files in the build
editThe Meziantou.Framework.PublicApiGenerator.MSBuild package writes the API files of a project after each build, and can check them instead of writing them.
Set up the project
Reference the package and set PublicApiGeneratorOutputPath, the only required property:
<ItemGroup>
<PackageReference Include="Meziantou.Framework.PublicApiGenerator.MSBuild" Version="x.y.z" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup>
<PublicApiGeneratorOutputPath>PublicApi/PublicApi.g.cs</PublicApiGeneratorOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Remove="PublicApi/**" />
</ItemGroup>- The path is relative to the project directory. With the default
SingleFilelayout, it is the path of the file; with the other layouts, it is a directory. - Exclude the API files from the compilation with
Compile Remove, or write them outside of the project directory: otherwise the next build compiles the stubs with your code and fails with duplicate declarations. - A build that generates or checks the API files fails when
PublicApiGeneratorOutputPathis not set.
The files are written after the Build target, from the assembly the build produced. Design-time builds, such as the ones of your IDE, do not generate them.
Options
Set these properties in the project file, in a Directory.Build.props file to configure several projects at once, or on the command line with -p:<Name>=<Value>:
| Property | Default | Description |
|---|---|---|
PublicApiGeneratorOutputPath | (required) | The file (SingleFile layout) or the directory (other layouts) to write, relative to the project directory. |
PublicApiGeneratorFileLayout | SingleFile | SingleFile, OneFilePerNamespace or OneFilePerType. See File layouts. |
PublicApiGeneratorIncludeAutoGeneratedComment | true | Starts each file with a // <auto-generated/> comment. Set it to false to omit it. |
PublicApiGeneratorGenerateOnBuild | true | Writes the API files after each build. |
PublicApiGeneratorVerifyNoChangeOnBuild | false | Checks the API files instead of writing them. See Check the API files in CI. |
When both PublicApiGeneratorGenerateOnBuild and PublicApiGeneratorVerifyNoChangeOnBuild are false, the package does nothing. To split the API into one file per namespace:
<PropertyGroup>
<PublicApiGeneratorOutputPath>PublicApi</PublicApiGeneratorOutputPath>
<PublicApiGeneratorFileLayout>OneFilePerNamespace</PublicApiGeneratorFileLayout>
</PropertyGroup>Multi-targeted projects
For a project that sets TargetFrameworks, the files are written once, after all the target frameworks are built: the assemblies of all the target frameworks are merged into one set of files, with #if blocks for the declarations that differ. Nothing else to configure. See Multi-targeted libraries.
Check the API files in CI
Set PublicApiGeneratorVerifyNoChangeOnBuild to true to compare the API files with the build output instead of writing them:
dotnet build -p:PublicApiGeneratorVerifyNoChangeOnBuild=trueThis mode takes precedence over PublicApiGeneratorGenerateOnBuild: no file is written. The build fails with one error per difference:
File '…' is out of date.: the public API changed and the file was not regenerated.Expected file '…' does not exist.: a file is missing, for instance for a new namespace withOneFilePerNamespace.Unexpected file '…' exists in the output directory.: with a directory layout, a file that the generator would not write, such as the file of a removed type.
Line endings are ignored by the comparison, so a checkout that converts them does not fail the check. To fix an error, build without the property, and commit the changes of the API files.
Run the check in the same configuration as the one you generate the files with: when it is not the same, the API can be different, for instance when some code is only compiled in Debug.
Removed types leave files behind
With the OneFilePerNamespace and OneFilePerType layouts, the build writes the files of the current API but never deletes a file. When you remove or rename a type or a namespace, its old file stays in the directory, and the check reports it as an unexpected file. Delete the directory and build again to get exactly the files of the current API. The SingleFile layout does not have this issue.