Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,29 @@ cd src/tests

---

## Analysis Tools

Code analyzers, API compatibility validation, and ILLink trimming are **disabled by default** to speed up local builds and CI. Before checking in, you SHOULD run analysis to catch issues early. Pass these MSBuild properties to enable them:

| Property | What it enables |
|----------|----------------|
| `/p:RunAnalyzersInBuild=true` | Roslyn code analyzers (style, correctness, performance) and API compatibility validation |
| `/p:RunILLinkInBuild=true` | ILLink trimming analysis for shared-framework libraries |

**Run analysis before check-in:**
```bash
./build.sh libs -rc release /p:RunAnalyzersInBuild=true /p:RunILLinkInBuild=true
```

Or for a single project:
```bash
dotnet build /p:RunAnalyzersInBuild=true
```

These checks run automatically in the global-build CI pipeline, so fixing issues locally avoids CI failures.

---

## Troubleshooting

| Error | Solution |
Expand Down
5 changes: 3 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -354,8 +354,9 @@
</ItemGroup>

<PropertyGroup Condition="'$(IsSourceProject)' == 'true'">
<!-- Must be defined in a props file as imports in Microsoft.DotNet.ApiCompat.Task.targets depend on it. -->
<ApiCompatValidateAssemblies>true</ApiCompatValidateAssemblies>
<!-- Must be defined in a props file as imports in Microsoft.DotNet.ApiCompat.Task.targets depend on it.
ApiCompat is disabled by default to speed up local builds unless RunAnalyzersInBuild is set. -->
<ApiCompatValidateAssemblies Condition="'$(RunAnalyzersInBuild)' == 'true'">true</ApiCompatValidateAssemblies>
</PropertyGroup>

<PropertyGroup Condition="'$(IsGeneratorProject)' == 'true'">
Expand Down
46 changes: 45 additions & 1 deletion docs/project/analyzers.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,50 @@
## Enabling analyzers and other analysis tools

By default, code analyzers, API compatibility validation, and ILLink trimming analysis are **disabled** during local builds and CI to improve build performance. To enable them, pass the corresponding MSBuild properties on the command line or set them in your environment.

### Analyzers

To run all Roslyn code analyzers (style, correctness, performance, etc.) during the build:

```bash
./build.sh libs -c Release /p:RunAnalyzersInBuild=true
```

This sets `RunAnalyzers=true`, which enables the analyzer packages declared in [`eng/Analyzers.targets`](../../eng/Analyzers.targets) (including `Microsoft.CodeAnalysis.NetAnalyzers`, `StyleCop.Analyzers`, and others) and applies the rule severities from the [`eng/CodeAnalysis.src.globalconfig`](../../eng/CodeAnalysis.src.globalconfig) and [`eng/CodeAnalysis.test.globalconfig`](../../eng/CodeAnalysis.test.globalconfig) files.

You can also enable analyzers for a single project build:

```bash
dotnet build /p:RunAnalyzersInBuild=true
```

### API compatibility validation

API compatibility checks (`ApiCompatValidateAssemblies`) are also gated on `RunAnalyzersInBuild`. When enabled, the build validates that your changes don't introduce unintentional API breaks. See [APICompat](../workflow/building/libraries/README.md#apicompat) for more details.

### ILLink trimming

To run ILLink trimming analysis during the build:

```bash
./build.sh libs -c Release /p:RunILLinkInBuild=true
```

### Enabling everything

To enable all analysis tools at once:

```bash
./build.sh libs -c Release /p:RunAnalyzersInBuild=true /p:RunILLinkInBuild=true
```

These features are automatically run in the global-build CI pipeline for all PRs to ensure code quality without impacting regular build times.

> **Note:** Reference assembly projects and source-build always have analyzers disabled regardless of these settings.

## Adding new analyzers to the build

This repo relies on [.NET Compiler Platform analyzers](https://learn.microsoft.com/visualstudio/code-quality/roslyn-analyzers-overview) to help validate the correctness, performance, and maintainability of the code. Several existing analyzer packages are wired into the build, but it is easy to augment the utilized packages in order to experiment with additional analyzers.
This repo relies on [.NET Compiler Platform analyzers](https://learn.microsoft.com/visualstudio/code-quality/roslyn-analyzers-overview) to help validate the correctness, performance, and maintainability of the code. Several existing analyzer packages are wired into the build, but it is easy to augment the utilized packages in order to experiment with additional analyzers.

To add an analyzer package to the build:
1. Select a package you want to employ, for example https://www.nuget.org/packages/SonarAnalyzer.CSharp/. This analyzer package's name is `SonarAnalyzer.CSharp` and the latest version as of this edit is `8.50.0.58025`.
Expand Down
21 changes: 21 additions & 0 deletions docs/workflow/building/libraries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,27 @@ One can build in Debug or Release mode from the root by doing `./build.sh libs -

One can build 32- or 64-bit binaries or for any architecture by specifying in the root `./build.sh libs -arch [value]` or in a project `/p:TargetArchitecture=[value]` after the `dotnet build` command.

### Building with Analyzers and Linker

By default, code analyzers and ILLink trimming are disabled during local builds and CI to improve build performance. To enable these features during a build, pass the following properties:

- **Analyzers**: To run code analyzers during the build, use `/p:RunAnalyzersInBuild=true`:
```bash
./build.sh libs -c Release /p:RunAnalyzersInBuild=true
```

- **ILLink Trimming**: To run ILLink trimming during the build, use `/p:RunILLinkInBuild=true`:
```bash
./build.sh libs -c Release /p:RunILLinkInBuild=true
```

- **Both**: To enable both analyzers and trimming:
```bash
./build.sh libs -c Release /p:RunAnalyzersInBuild=true /p:RunILLinkInBuild=true
```

These features are automatically run in the global-build CI pipeline for all PRs to ensure code quality without impacting regular build times. Individual projects can still override these settings by explicitly setting `RunAnalyzers` or `ILLinkTrimAssembly` properties in their project files.

## Working in Visual Studio

If you are working on Windows, and use Visual Studio, you can open individual libraries projects into it. From within Visual Studio you can then build, debug, and run tests.
Expand Down
5 changes: 5 additions & 0 deletions eng/Analyzers.targets
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
<Project>
<PropertyGroup>
<!-- By default, analyzers are disabled to speed up local builds and CI.
Set RunAnalyzersInBuild=true to enable analyzers during the build. -->
<RunAnalyzers Condition="'$(RunAnalyzers)' == '' and '$(RunAnalyzersInBuild)' != 'true'">false</RunAnalyzers>
</PropertyGroup>
<PropertyGroup Condition="'$(UsingMicrosoftNoTargetsSdk)' == 'true' or
'$(UsingMicrosoftDotNetSharedFrameworkSdk)' == 'true' or
'$(MSBuildProjectExtension)' == '.pkgproj' or
Expand Down
32 changes: 27 additions & 5 deletions eng/pipelines/global-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,21 +82,43 @@ extends:
eq(variables['isRollingBuild'], true))

#
# Build Libraries (all TFMs) and create packages on a non Windows operating system.
# Build Libraries with all configurations including analyzers and linker
#
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/common/global-build-job.yml
buildConfig: debug
buildConfig: release
platforms:
- linux_x64_dev_innerloop
- windows_x64
- osx_arm64
jobParameters:
nameSuffix: Libraries_WithPackages
buildArgs: -subset libs -pack
nameSuffix: Libraries_AnalyzersLinker
buildArgs: -subset libs -restore -build -pack -c $(_BuildConfig) /p:RunAnalyzersInBuild=true /p:RunILLinkInBuild=true
timeoutInMinutes: 120
condition:
or(
eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_non_mono_and_wasm.containsChange'], true),
eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(variables['isRollingBuild'], true))

#
# Build CoreCLR CoreLib and tools with analyzers and linker
#
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/common/global-build-job.yml
buildConfig: release
platforms:
- linux_x64_dev_innerloop
jobParameters:
nameSuffix: CoreClr_Tools_AnalyzersLinker
buildArgs: -subset clr.corelib+tools -c $(_BuildConfig) /p:RunAnalyzersInBuild=true /p:RunILLinkInBuild=true
timeoutInMinutes: 120
condition:
or(
eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_illink.containsChange'], true),
eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_cdac.containsChange'], true),
eq(variables['isRollingBuild'], true))

#
Expand Down
1 change: 1 addition & 0 deletions src/libraries/oob-trim.proj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

<Target Name="TrimOOBAssemblies"
AfterTargets="Build"
Condition="'$(RunILLinkInBuild)' == 'true'"
DependsOnTargets="GetTrimOOBAssembliesInputs;PrepareForAssembliesTrim"
Inputs="$(ILLinkTasksAssembly);@(OOBAssemblyToTrim);@(OOBAssemblyReference);@(OOBLibrarySuppressionsXml)"
Outputs="$(OOBAssembliesTrimMarkerFile)">
Expand Down
1 change: 1 addition & 0 deletions src/libraries/sfx-finish.proj
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@

<Target Name="TrimSharedFrameworkAssemblies"
AfterTargets="Build"
Condition="'$(RunILLinkInBuild)' == 'true'"
DependsOnTargets="ResolveProjectReferences;GetTrimSharedFrameworkAssembliesInputs;PrepareForAssembliesTrim"
Inputs="@(SharedFrameworkAssembly);@(SharedFrameworkSuppressionsXml);$(ILLinkTasksAssembly)"
Outputs="$(SharedFrameworkAssembliesTrimMarkerFile)">
Expand Down
Loading