Skip to content
Purview Dev logo

Configuration Reference

Stable Build SDK Reviewed 2026-10-28 purview-dev/build-sdk Star on GitHub 1 central-package-management code-style csharp developer-experience developer-tooling devex dotnet msbuild msbuild-sdk nuget project-templates roslyn roslyn-analyzers roslyn-generators tunit xunit

Set any of these properties before the <Import> in your Directory.Build.props (most are consumed during Sdk.props evaluation). Explicit values set before the import are always preserved.

PropertyDefaultDescription
UsePackageJsonVersiontruetrue enables version detection, false disables it, and Strict requires version detection to succeed (build fails if no version source can be resolved).
RootPackageJson(auto-discovered)Explicit path to a package.json. Relative paths are resolved from the project directory.
EnableVersionDetectionCachetrueEnables local caching of auto-discovered package.json version results.
VersionDetectionLogEnabledfalseEmits a high-importance message showing the detected package version.

See Version Detection for the full resolution rules.

PropertyDefaultDescription
NamespacePrefix(required)Root namespace prefix, e.g. Acme. Results in Acme.MyProject.
DisableNamespacePrefixCheckfalseSet to true to suppress the build error for missing NamespacePrefix.
DisablePurviewStylePolicyValidationfalseSet to true to stop ValidatePurviewStylePolicy failing the build (PRSGD0006-PRSGD0009) when the repository .editorconfig overrides dotnet_style_require_accessibility_modifiers, hides IDE0040/IDE1006, disables the Style category in bulk, weakens the _camelCase private instance field rule, or adds the accessibility rules to NoWarn. Entries the SDK injects itself (the test-context rule set, CA1515 for Aspire hosts and CLI apps) are ignored. See Style policy.
PurviewTestContextNoWarnCA1002;CA1012;CA1034;CA1047;CA1050;CA1051;CA1062;CA1064;CA1515;CA1707Production API-surface rules exempted in test and shared-testing projects (they keep the strict style contract). Override before the SDK import to narrow or extend the list.
DisablePurviewTestContextRuleSetfalseSet to true to make test and shared-testing projects enforce the production API-surface rules as well.
PurviewSharedTestingOutputTypeLibraryOutput type forced on IsSharedTestingProject projects; Library also clears IsTestProject/IsTestingPlatformApplication. Set to Exe before the SDK import to keep the test packages’ executable/test-host shape.
TargetFrameworknet10.0Override the default TFM per-project or globally. Defaults to netstandard2.0 for projects declaring IsRoslynComponent=true. To multi-target from a central, overridable definition rather than a hard-coded list, see Target framework sets.
DisableUnconditionalProjectDeclarationCheckfalseSet to true to suppress PurviewConditionedProjectDeclaration. The SDK reads TargetFramework, TargetFrameworks, IsRoslynComponent, IsRoslynComponentOnly, IsPackable and PurviewTargetFrameworkSet from the project XML before the project body is evaluated, so it cannot evaluate a Condition on them and will not see the declaration — the SDK default applies instead. Declare those properties unconditionally, or set them in a file imported before this SDK.
IsRoslynComponentfalseWhen explicitly true, applies source-generator defaults: a single netstandard2.0 target, LangVersion=latest, Nullable=enable, TreatWarningsAsErrors=true, Deterministic=true, extended analyzer rules, SourceLink with EmbedUntrackedSources=true, compiler-generated output under the intermediate directory, no dependency file, symbol packaging (IncludeSymbols=false by default), telemetry exclusion, and package build output. Packable Roslyn components automatically pack the built analyzer assembly and its PDB into analyzers/dotnet/cs/ (PurviewPackAnalyzerPdb=true; set false only when symbols are delivered another way — NuGet’s .snupkg cannot host analyzers/dotnet/cs symbols). Pack-time validation (ValidateRoslynComponentCompilerSettings) fails the pack if the compiler defaults are missing unless DisableRoslynCompilerDefaultsValidation=true. Roslyn development dependencies (Microsoft.CodeAnalysis.*, Microsoft.CodeAnalysis.Analyzers) default to PrivateAssets="all".
PackProjectReferencedSourceGeneratorstrueAutomatically packs analyzer ProjectReference outputs and their runtime dependencies under analyzers/dotnet/cs/. Set to false to opt out; set Pack="false" on an individual reference to exclude only that generator.
SourceLinkPackageNameMicrosoft.SourceLink.GitHubSourceLink provider. Set to Microsoft.SourceLink.AzureDevOps.Git for ADO repos.
DisableSourceLinkfalseSet to true to stop the SDK from adding the configured SourceLink package automatically.
EnableAssemblyNameGenerationtrueWhen true (default), AssemblyName and PackageId derive from the fully evaluated RootNamespace. When explicitly false, standard .NET behaviour applies ($(MSBuildProjectName)). Explicit <AssemblyName>/<PackageId> in a .csproj always take precedence.
DisableProjectFileNamingConventionCheckfalseSet to true to disable the validation that requires MyProject\MyProject.csproj naming alignment.
DisableGenerateAssemblyInfoClassfalseSet to true to disable the generated AssemblyInfo helper source.
DisableGenerateAssemblyIdentifierClassfalse (true for test and shared-testing projects)Set to true to disable the generated assembly identifier marker class. See Assembly identifier class.
AssemblyIdentifierClassName<project name minus NamespacePrefix, dots removed>AssemblyOverrides the name of the generated assembly identifier marker class.
AutoIncludeUsingstrueControls SDK-added global usings for NamespacePrefix and RootNamespace.
NamespaceRemoveSuffix(built-in list)Item type listing the suffixes stripped from RootNamespace. Remove an entry after the Sdk.props import to keep that suffix in the namespace, e.g. <NamespaceRemoveSuffix Remove="Abstractions" />. Roslyn component names are not in the list — SourceGenerator, SourceGenerators, SourceGeneration, Generators, Analyzers, CodeFixers and CodeFixes are part of a component’s identity, and a generator, its analyzers and its code fixes are separate assemblies that each need their own namespace. Add one with <NamespaceRemoveSuffix Include="Analyzers" /> if a repository really wants it collapsed. See Namespace stripping.

A multi-targeting repository otherwise hard-codes its TFM list in every project, so a lifecycle change — a release leaving support, a new one arriving — is an edit in every repository that has to be found and kept consistent. Name a set instead and the decision moves into the SDK, so bumping Purview.BuildSdk moves every consumer at once:

<PropertyGroup>
<PurviewTargetFrameworkSet>Supported</PurviewTargetFrameworkSet>
</PropertyGroup>
SetResolves toUse for
Currentnet10.0The default. A single target, stated explicitly.
Latestnet11.0Newest release only.
Supportednet10.0;net11.0A package that should work on anything still in support.
Broadnet8.0;net9.0;net10.0Every shipped release — widest reach without committing to the newest major while it is pre-GA.
Allnet8.0;net9.0;net10.0;net11.0Broad plus the newest major.

net8.0 and net9.0 are deliberately outside Supported: both are at or near end of support, so a new package should not imply a commitment to them. Choose Broad to keep them.

Broad and All differ by one real product decision — whether the package commits to the newest release — so they are separate names rather than one set that silently widens every consumer of it.

A set is always in play: Current applies when nothing is selected, which resolves to the same single TFM the SDK used to hard-code. The out-of-box result is therefore unchanged — but the value is named and overridable in one place, so moving a repository (or every repository) between runtimes is a property change rather than an edit in each project.

Overrides are layered, narrowest first:

  1. an explicit TargetFramework/TargetFrameworks in the project always wins. Like the set selection itself, this is read from the project XML, so it must be declared unconditionally to be seen;
  2. a PurviewTargetFrameworkSet in the project wins over one the repository selected;
  3. a repository can redefine any set with PurviewTargetFrameworks<Set> — PurviewTargetFrameworksSupported, PurviewTargetFrameworksBroad, and so on — set before the SDK import. This is also how a set is pinned while a consumer is not ready to follow the SDK’s definition;
  4. otherwise the table above applies.

A project declaring TargetFrameworks keeps TargetFramework empty, as a multi-targeting project must: MSBuild honours the singular property ahead of the list, so a default left in place there would quietly collapse the project to a single target and break every multi-targeting consumer of it.

PropertyDefaultDescription
PurviewTargetFrameworkSetCurrentCurrent, Latest, Supported, Broad or All. An unrecognised name fails the build with PurviewInvalidTargetFrameworkSet rather than silently falling back to the single-TFM default. A single-entry set resolves to TargetFramework, so it does not pay for an outer multi-targeting build.
PurviewTargetFrameworksCurrentnet10.0Redefines the Current set.
PurviewTargetFrameworksLatestnet11.0Redefines the Latest set.
PurviewTargetFrameworksSupportednet10.0;net11.0Redefines the Supported set.
PurviewTargetFrameworksBroadnet8.0;net9.0;net10.0Redefines the Broad set.
PurviewTargetFrameworksAllnet8.0;net9.0;net10.0;net11.0Redefines the All set.

Roslyn components are not covered: a component targets netstandard2.0 so every compiler host can load it. Selecting a set on one is ignored and reported as PurviewTargetFrameworkSetIgnored.

Set the property in Directory.Build.props for a repository-wide choice, or in a .csproj for a single project. Because the SDK is imported before the project body is evaluated, a .csproj selection is read from the project XML directly — so declare it unconditionally. A Condition on it cannot be evaluated that early and is reported as PurviewConditionedProjectDeclaration.

The SDK also supports repo/site metadata properties for generated package metadata and docs links. These values are consumed before the import and are useful when a repository wants a single shared project URL or docs base URL instead of repeating it per project:

PropertyDefaultDescription
PurviewHomepage(repo-specific)Base site URL for the repository or product docs. In this repo it is set to https://purview.dev/.
PurviewProjectUrl(repo-specific)Public project page URL; usually derived from PurviewHomepage plus a project path.
PurviewDocsUrl(repo-specific)Public docs URL; often derived from PurviewHomepage plus a docs path.

These values are not mandatory, but they provide a consistent place to keep package metadata and docs links aligned with the repo’s site structure.

For projects where IsPackable=true, the SDK provides these defaults only when the consuming project has not supplied a value:

PropertyDefaultDescription
GenerateDocumentationFiletrueEmits XML documentation.
IncludeSymbolstrueProduces a symbol package (false for Roslyn components — their PDB ships inside the .nupkg under analyzers/dotnet/cs/ via PurviewPackAnalyzerPdb=true).
SymbolPackageFormatsnupkgSymbol package format. Always the modern .snupkg; the legacy .symbols.nupkg is never produced by default.
PublishRepositoryUrltruePublishes the repository URL.
EmbedUntrackedSourcestrueEmbeds untracked sources for SourceLink.
DebugTypeportableEnsures portable PDBs for symbol-package delivery.
IncludeSourcetrueIncludes source files in the package.

Portable PDBs are delivered through the .snupkg; the normal .nupkg does not receive PDB files unless the project explicitly opts in (for example by adding .pdb to AllowedOutputExtensionsInPackageBuildOutputFolder).

The SDK never forces organization/package-specific metadata — Authors, Company, PackageLicenseExpression, PackageLicenseFile, Description, PackageTags, PackageProjectUrl, and repository URLs are left to the repository or individual package. IsPackable is not set blindly: it defaults to false and only becomes true when a project explicitly opts in.

Non-packable projects default WarnOnPackingNonPackableProject=false, so solution-wide pack operations skip them silently.

PropertyDefaultDescription
DisableAutoCopySdkFilesfalseMaster switch that disables repo-level SDK file bootstrapping.
BootstrapEditorConfigToRepoRoottrueCopies the SDK .editorconfig to the repository root when missing.
RepositoryEditorConfigFilePath(auto-detected)Override the destination path for the bootstrapped .editorconfig.
BootstrapGlobalJsonToRepoRoottrueCreates a global.json at the repository root when missing.
RepositoryGlobalJsonFilePath(auto-detected)Override the destination path for the bootstrapped global.json.
PurviewBuildSdkVersionForGlobalJson(restored package version, else the version it was packed as)Version written to the msbuild-sdks.Purview.BuildSdk entry in a bootstrapped global.json.
PurviewRepoBootstrapModeIfMissingIfMissing never touches an existing file, Always overwrites it, WarnOnDrift reports that an existing file differs from the SDK-provided one, and Never skips bootstrapping entirely.
PurviewRepoBootstrapCopyRetries3Copy attempts before a bootstrap write failure is reported.
PurviewRepoBootstrapCopyRetryDelayMilliseconds500Base delay between bootstrap write attempts.
PurviewRepoBootstrapCopyFailureAsErrortrueWhen false, a bootstrap write that still fails after every retry is reported as a warning and the build continues.
PurviewSuppressCopyRetryWarningstrueDemotes MSB3026 copy retry notices to messages. Set to false to see every retry attempt.

Bootstrap writes are staged into a temporary file and renamed into place, so editors and tools never observe a partially written .editorconfig or global.json. Because every project in a solution runs the same bootstrapping targets, a lost race between parallel projects is a no-op: an existing file is treated as success rather than a copy failure.

PropertyDefaultDescription
PurviewAutoSdkPacktrueWhen true, automatically packs the Sdk/ folder contents into the NuGet package with the correct root-level paths. Disable this for MSBuild SDK projects.

The SDK writes nothing into an agent directory. It used to mirror a package’s .agents/** into the consuming repository; that is gone, because the skills CLI covers it. See Agent Skills.

PropertyDefaultDescription
ExcludePurviewTelemetryfalseSet to true to exclude Purview.Telemetry.SourceGenerator from all projects.
ExcludeMSTelemetryExtensionfalseSet to true to exclude Microsoft.Extensions.Telemetry.Abstractions. Only relevant when ExcludePurviewTelemetry is also false — when ExcludePurviewTelemetry=true the whole telemetry group is skipped anyway.

Blazor WebAssembly, browser-safe libraries and BFF hosts

Section titled “Blazor WebAssembly, browser-safe libraries and BFF hosts”
PropertyDefaultDescription
IsBffProjecttrue for a web SDK project named *BffClassifies a BFF host. false opts out, true opts in.
IsBlazorHostProject(computed)true for a web SDK project referencing a WebAssembly client. false opts out.
PurviewAutoBlazorClientReferencetrueA host <Name> references its <Name>.Client automatically.
DisablePurviewBlazorWebAssemblyDefaultsfalseKeeps the generic defaults on a WebAssembly client. Set before the SDK import.
PurviewBrowserSafe(unset)true on a class library applies IsAotCompatible, SupportedPlatform browser and the browser-safe WarningsAsErrors.
PurviewBrowserSafeWarningsAsErrorstruefalse keeps trim/AOT diagnostics as warnings.
PurviewBrowserSafeWarningCodesCA1416, IL2001-IL2128, IL3000-IL3005, IL3050-IL3059The ids added to WarningsAsErrors.
DisablePurviewBrowserSafeReferenceCheckfalseTurns off PRBLZ0001.
PurviewBrowserSafeReferenceCheckAsErrorfalseReports PRBLZ0001 as an error.
PurviewBffExposesApitrue if the BFF references Microsoft.AspNetCore.OpenApiWhether a BFF keeps the OpenAPI interceptor namespace.
PropertyDefaultDescription
TestingFrameworkTUnitTesting framework. Supported values: TUnit, Xunit, None.
SubstituteFrameworkTUnitMocksMocking provider. Supported values: TUnitMocks, NSubstitute, None.
TestDataFrameworkBogusTest data provider. Supported values: Bogus, None.
DisableAutoInternalsVisibleTofalseSet to true to disable automatic InternalsVisibleTo generation for test types and shared testing projects.

See Engineering Principles for the policy-level testing guidance and Testing Wiring for the implementation details.

The SDK exports its properties via CompilerVisibleProperty, so analyzers and source generators can read them through build_property.<PropertyName>:

PropertyDescription
UsePackageJsonVersionWhether version detection from package.json is active.
RootPackageJsonResolved path to the package.json used for version detection.
RepoRootRepo root directory found via .git auto-discovery.
VersionPackage/assembly version, sourced from package.json when detection is enabled.
PackageVersionNuGet package version, sourced from package.json when detection is enabled.
NamespacePrefixRequired namespace prefix used to derive RootNamespace.
DisableNamespacePrefixCheckDisables the build error for missing NamespacePrefix.
TestingFrameworkSelected testing framework (TUnit, Xunit, or None).
SubstituteFrameworkSelected mocking provider (TUnitMocks, NSubstitute, or None).
TestDataFrameworkSelected test data provider (Bogus or None).
SourceLinkPackageNameSourceLink package ID added by the SDK.
DisableSourceLinkDisables automatic SourceLink integration.
ExcludePurviewTelemetryOpt-out for Purview.Telemetry.SourceGenerator.
ExcludeMSTelemetryExtensionOpt-out for Microsoft.Extensions.Telemetry.Abstractions.
PurviewAutoSdkPackWhen true, automatically packs the Sdk/ folder contents into the NuGet package.
DisableGenerateAssemblyInfoClassDisables generated AssemblyInfo helper source.
DisableGenerateAssemblyIdentifierClassDisables the generated assembly identifier marker class.
AssemblyIdentifierClassNameName of the generated assembly identifier marker class.
EnableAssemblyNameGenerationWhen true (default), AssemblyName derives from RootNamespace.
DisableAutoInternalsVisibleToDisables automatic InternalsVisibleTo generation.
AutoIncludeUsingsControls SDK-added global usings.
IsCSharpProjectTrue when the project is a .csproj.
IsTestProjectTrue when project name ends with a supported test suffix.
IsSharedTestingProjectTrue for known shared testing helper project names; the project is forced to OutputType=Library (see PurviewSharedTestingOutputType).
TestingTypeDetected test category suffix from project name.
TargetProjectNameInferred target project name for test projects.
IsContainerProjectTrue when Dockerfile markers indicate container defaults.
IsSdkProjectTrue when an SDK value is detected from project/import declaration.
SdkProjectNameDetected SDK name (e.g. Microsoft.NET.Sdk.Web).
IsWebProjectMarker used in SDK web-project behaviour.
IsWebSdkProjectTrue when SdkProjectName is Microsoft.NET.Sdk.Web.
IsWorkerSdkProjectTrue when SdkProjectName is Microsoft.NET.Sdk.Worker.
IsAspireHostProjectTrue when SDK starts with Aspire.Sdk.Host.
IsCLIProjectTrue when the project is a CLI project.
IsSharedProjectTrue when the project is a shared project.
EditorConfigFilePathPath to the SDK-provided .editorconfig injected into @(EditorConfigFiles).
RepositoryEditorConfigFilePathDestination path for bootstrapping a physical repo-level .editorconfig.
BootstrapEditorConfigToRepoRootWhen true (default), copies the SDK .editorconfig to RepositoryEditorConfigFilePath if missing.
RepositoryGlobalJsonFilePathDestination path for bootstrapping a physical repo-level global.json.
BootstrapGlobalJsonToRepoRootWhen true (default), creates global.json at RepositoryGlobalJsonFilePath if missing.
PurviewBuildSdkVersionForGlobalJsonVersion used for msbuild-sdks.Purview.BuildSdk when bootstrapping global.json.
DisableAutoCopySdkFilesWhen true, disables SDK auto-copy/bootstrap for repo files (.editorconfig, global.json).
CurrentYearCurrent year used in generated assembly metadata.
AutoGeneratedAssemblyInfoFileFile name of the generated AssemblyInfo source file (written under the intermediate Properties/ folder).
AutoGeneratedAssemblyIdentifierFileFile name of the generated assembly identifier source file (written under the intermediate Properties/ folder).

Roslyn components additionally expose LangVersion, Nullable, TreatWarningsAsErrors, EnforceExtendedAnalyzerRules, Deterministic, ContinuousIntegrationBuild, and EmbedUntrackedSources as compiler-visible properties so downstream tooling can confirm the shipped analyzer packages were built with the standard settings.

Example: switch a repo to Xunit + NSubstitute and disable Bogus

Section titled “Example: switch a repo to Xunit + NSubstitute and disable Bogus”
<Project>
<PropertyGroup>
<NamespacePrefix>Acme</NamespacePrefix>
<TestingFramework>Xunit</TestingFramework>
<SubstituteFramework>NSubstitute</SubstituteFramework>
<TestDataFramework>None</TestDataFramework>
</PropertyGroup>
<Import Sdk="Purview.BuildSdk" Project="Sdk.props" />
</Project>