MSBuild 15.3 includes an new API, Microsoft.Build.Framework.SdkResolver. (see dotnet/msbuild#2002). In theory, we could implement a NuGetPackageSdkResolver that resolves the "Sdk" property to files in the NuGet cache.
Goal
Distribute versioned MSBuild tasks, targets, and other tooling as a NuGet package.
Usage
<Project>
<Sdk Name="Microsoft.NET.Sdk" />
<Sdk Name="Microsoft.NET.Test.Sdk" MinimumVersion="15.0.0" />
<Sdk Name="my.team.shared.buildsettings" Version="1.0.0-*" />
</Project>
In this example, Microsoft.Net.Sdk is not a nuget package, so the resolver would no-op.
On the other hand, Microsoft.NET.Test.Sdk and my.team.shared.buildsettings are nuget packages that contains MSbuild targets and tasks. The resolver could download these packages to make them available to MSBuild.
Layout of an "SDK" package
(pkg root)/
- build/
- Sdk/
+ Sdk.props
+ Sdk.targets
What the resolver does
(pseudocode)
class NuGetSdkResolver : Microsoft.Build.Framework.SdkResolver
{
public override SdkResult Resolve(SdkReference sdk, SdkResolverContext context, SdkResultFactory factory)
{
var resolvedVersion = ChoosePackageVersionOrDefault(sdk.Version ?? sdk.MinimumVersion);
RestorePackageIfNotFound(sdk.Name, resolvedVersion);
var sdkPath = Path.Combine("%NUGET_PACKAGES%", sdk.Name, resolvedVersion, "build/Sdk");
return factory.IndicateSuccess(sdkPath, resolvedVersion);
}
}
Why not just use a PackageReference?
Many simple scenarios are already solved by adding build assets to a package, however, MSBuild tooling from an NuGet package still has some limitations:
- Build requires two msbuild invocations.
msbuild /t:Restore && msbuild /t:Build. Just running msbuild /t:Restore;Build causes issues because nuget.g.targets and UsingTasks are not resolved soon enough.
- You have to express
TargetFramework to make PackageReference work. This property only makes sense for csproj, but doesn't have meaning for MSBuild scripts that do other build automation.
- You cannot have a PackageReference that conditionally adds more PackageReferences or DotNetCliToolReference.
- Users have to know to set
PrivateAssets=All to avoid having tooling packages end up in the generated nuspec.
- You have to import Microsoft.Common.targets (and everything it brings with it) in order to use PackageReference.
One possibility
If this were implemented, I could easily create a package that looks like this:
Microsoft.AspNetCore.LTS.Lineup.nupkg/
- build
- Sdk/
Sdk.targets
Tasks.dll
<!-- Sdk.targets -->
<Project>
<UsingTask AssemblyFile="Tasks.dll" TaskName="CustomAspNet.Build.Task" />
<ItemGroup>
<!-- Update package references to the preferred lineup version if they are included in the project.-->
<PackageReference Update="Kestrel" Version="1.0.4" IsImplicitlyDefined="true" />
<PackageReference Update="Mvc" Version="1.0.5" IsImplicitlyDefined="true" />
<!-- add a CLI tool -->
<DotNetCliToolReference Include="dotnet-watch" Version="1.0.1" />
</ItemGroup>
</Project>
This could solve the "Lineups" feature. #2572
cc @emgarten @AndyGerlicher @AArnott @nguerrera
MSBuild 15.3 includes an new API, Microsoft.Build.Framework.SdkResolver. (see dotnet/msbuild#2002). In theory, we could implement a
NuGetPackageSdkResolverthat resolves the "Sdk" property to files in the NuGet cache.Goal
Distribute versioned MSBuild tasks, targets, and other tooling as a NuGet package.
Usage
In this example,
Microsoft.Net.Sdkis not a nuget package, so the resolver would no-op.On the other hand,
Microsoft.NET.Test.Sdkandmy.team.shared.buildsettingsare nuget packages that contains MSbuild targets and tasks. The resolver could download these packages to make them available to MSBuild.Layout of an "SDK" package
What the resolver does
(pseudocode)
Why not just use a PackageReference?
Many simple scenarios are already solved by adding build assets to a package, however, MSBuild tooling from an NuGet package still has some limitations:
msbuild /t:Restore && msbuild /t:Build. Just runningmsbuild /t:Restore;Buildcauses issues becausenuget.g.targetsandUsingTasksare not resolved soon enough.TargetFrameworkto make PackageReference work. This property only makes sense for csproj, but doesn't have meaning for MSBuild scripts that do other build automation.PrivateAssets=Allto avoid having tooling packages end up in the generated nuspec.One possibility
If this were implemented, I could easily create a package that looks like this:
This could solve the "Lineups" feature. #2572
cc @emgarten @AndyGerlicher @AArnott @nguerrera