question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

MSBuild 15 Sdk Design

See original GitHub issue

MSBuild will allow third-party-defined and dynamically-delivered extensions of the build process via the new “Sdk” concept. This will extend the experience delivered with RC.2 to include an acquisition process.

Changes to project files

An Sdk can be consumed in two ways: with implicit top and bottom imports at through the Sdk attribute on the Project element:

<Project Sdk="Microsoft.NET.Sdk">
...
</Project>

and through a modified <Import> element with the Sdk attribute:

<Project>
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk/1.0.0" />
...
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk/1.0.0" />
</Project>

The former mechanism is syntactic sugar for the latter, with an Sdk.props import at the top of the project and an Sdk.targets import at its bottom.

User experience

When a user opens an Sdk-using project in an IDE, the IDE will try to evaluate the project. MSBuild will coordinate with the IDE to fetch and integrate all required Sdks. The IDE will probably wish to display a progress bar for any required downloads.

On the command line, a dotnet restore or msbuild.exe /t:Restore invocation will fetch required Sdks before proceeding with the restore process, ensuring that only one user gesture is required to bring the project to a buildable state.

Sdk acquisition

How does MSBuild know how to acquire an Sdk when it needs to? Through a provider model. A caller of the MSBuild APIs can provide an instance of a new interface ISdkResolver which will be used to map the XML from above to files on the local filesystem.

Note: Although the acquisition could differ between builds the resolved SDK would be identical.

struct SdkReference
{
    public string Name;
    public Version? Version;
}

interface ISdkResolver
{
    public Dictionary<SdkReference, Path> Resolve(IEnumerable<SdkReference>);
}

We expect most ISdkResolver implementations to additionally have affordances for reporting progress back to a UI and to log using the MSBuild log interface.

🚧 Exposing logging may require an interface change here.

🚧 Do we need to pass path-to-project, so that something NuGet-like can walk up to find its feed configuration?

MSBuild evaluation changes

MSBuild will collect Sdks needed for a given project early in its evaluation (before pass 1 expands imports). It will then unify Sdks specified within the project with those specified in the (optional) lineup file. This produces a list of Sdks that is then passed to ISdkResolver.Resolve(), producing a lookup table for Sdk imports.

Evaluator.GetCurrentDirectoryForConditionEvaluation should return the Sdk directory if there is an Sdk attribute on an import, so that you can have something like Condition="Exists('Sdk\Sdk.props')" on an Sdk import.

Evaluation pass 1 (properties and imports) then continues as usual. When considering an Import element with an Sdk attribute, the specified Project attribute is treated as a relative path from the base Sdk path looked up in the table generated in the new pre-pass-1 step.

Lineups

After growing past being “small” projects, most repos/solutions will want a simple way to manage the set of Sdks they use–for instance, to unify versions of Sdks available for projects within the repo. This will be accomplished by a lineup file, format TBD, that MSBuild will consider when putting together the list of available Sdks.

🚧 What does this look like on disk?

We expect a few common patterns of use:

  • Small-scale “demo projects”
    • Consist of ~1 project.
    • Do not have a lineup file.
    • Specify Sdk version for any “non-core” Sdk referenced.
  • Larger-scale projects
    • Have many projects in a solution.
    • Specify a lineup
    • Do not specify versions in the project files themselves, only in the lineup.

Project Load

We’ll need to add to ProjectLoadSettings so a user can opt out of SDK resolution. They would need to specify both IgnoreMissingImports and a new DoNotResolveSdks if they wanted to open a project without getting errors. But this would allow minimal property evaluation without resolving anything.

Concrete work items

  • Get feedback from VS folks
    • Especially around UI needs for status updating.
  • Expose ISdkResolver definition for prototyping.
  • Implement Sdk-aware imports (#1400)
  • Implement Sdk-gathering (pass 0.5)
  • Augment build-starting methods to accept an ISdkResolver
    • In BuildParameters? BuildRequestData?
  • Minimal FilesystemSdkResolver for prototyping and testing
    • Maybe looks in NuGet cache folder? That’d get us a long way toward seeing what the once-everything-is-downloaded scenario looks like.
  • Implement NuGetSdkResolver: https://github.com/NuGet/Home/issues/5220
    • Straw man implementation idea: write sdk names + package versions to a minimal project file, restore it out of proc, return paths 🚧 magically.
  • Use resolvers in various scenarios
    • Change MSBuild.exe to use a resolver
    • Change dotnet CLI to invoke MSBuild with a resolver
    • Change VS to invoke MSBuild with a resolver
    • Change VS Code to invoke MSBuild with a resolver
    • Change VS Mac to invoke MSBuild with a resolver
    • 🚧 Some of those could be helped by changing the default, if blocking evaluation without progress reporting is ok. Probably is for OmniSharp (out of proc) and CLI (synchronous command line build). UIs probably want advanced progress reporting + cancellability.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:19
  • Comments:31 (20 by maintainers)

github_iconTop GitHub Comments

3reactions
jeffklcommented, Dec 19, 2016

@AndyGerlicher What do you think about making this more generic and extensible? Right now it’s specifically for resolving SDKs but do you think we’ll ever want to resolve other project assets? My thought was to have the logic be more centered around resolving assets, one of which would be an SDK. Something like:

public interface AssetResolver
{
    IEnumerable<IResolvedAsset> Resolve(IEnumerable<IAsset> assets);
}

public enum AssetType
{
    None,
    SDK,
}

public interface IAsset
{
    AssetType AssetType { get; }
    string Name { get; }
    Version Version { get; }
}

public interface IResolvedAsset : IAsset
{
    /// <summary>
    /// The path to the resolved asset.
    /// </summary>
    string Path { get; }
}

Thoughts?

2reactions
magolcommented, Jan 10, 2017

Will this changes allso apply to c++ project?

Read more comments on GitHub >

github_iconTop Results From Across the Web

MSBuild reference for .NET SDK projects
Reference for the MSBuild properties and items that are understood by the .NET SDK.
Read more >
Building normal .Net project with MSBuild 15 which ships ...
I am building this project using MSBuild 15 which ships with VS 2017, which is at the location - C:\Program Files (x86)\Microsoft Visual ......
Read more >
MSBuild.SDK.SystemWeb
This MSBuild SDK is designed to allow for the easy creation and use of SDK (shortform) projects targeting ASP.NET 4.x using System.Web.
Read more >
MSBuild
Microsoft Build Engine, or MSBuild, is a set of free and open-source build tools for managed code under the Common Language Infrastructure as...
Read more >
Authoring MSBuild Project SDKs | David's Blog
First, what exact is an MSBuild project SDK? They're a new mechanism introduced in MSBuild 15 (Visual Studio 2017) which simplifies how ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found