diff --git a/NuGet.Config b/NuGet.Config
index e7b530794..4d79bc8e0 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -5,7 +5,7 @@
-
+
diff --git a/build/Compile.targets b/build/Compile.targets
index b2ebb2ebc..d2a3747aa 100644
--- a/build/Compile.targets
+++ b/build/Compile.targets
@@ -12,5 +12,14 @@
+
+
+
+
+
+
diff --git a/build/DependencyVersions.props b/build/DependencyVersions.props
index d7025d1ce..f331b31f9 100644
--- a/build/DependencyVersions.props
+++ b/build/DependencyVersions.props
@@ -2,7 +2,7 @@
2.0.0-preview1-002101-00
- 15.2.0-preview-000093-02
+ 15.3.0-preview-000111-01
2.0.0-rc4-61325-08
2.0.0-alpha-20170428-1
4.3.0-beta1-2418
@@ -11,9 +11,9 @@
$(CLI_SharedFrameworkVersion)
$(CLI_SharedFrameworkVersion)
$(CLI_SharedFrameworkVersion)
- 1.0.0-beta2-20170425-201
- 1.0.0-beta2-20170425-203
- 1.0.0-beta2-20170425-203
+ 1.0.0-beta2-20170427-205
+ 1.0.0-beta2-20170427-205
+ 1.0.0-beta2-20170427-205
2.0.0-preview1-002101
2.0.0-preview1-002101
0.1.0-alpha-142
diff --git a/build/MSBuildExtensions.targets b/build/MSBuildExtensions.targets
index 9b99b96b9..b8d2d97e9 100644
--- a/build/MSBuildExtensions.targets
+++ b/build/MSBuildExtensions.targets
@@ -9,7 +9,6 @@
- 15.0/Imports/Microsoft.Common.props/ImportBefore
Microsoft.NETCoreSdk.BundledVersions.props
@@ -59,12 +58,9 @@ Copyright (c) .NET Foundation. All rights reserved.
-
-
+
-
diff --git a/build/OutputDirectories.props b/build/OutputDirectories.props
index 3376d5475..904e381f7 100644
--- a/build/OutputDirectories.props
+++ b/build/OutputDirectories.props
@@ -15,5 +15,6 @@
$(RepoRoot)/artifacts/testpackages/
$(OutputDirectory)/dotnet$(ExeExtension)
$(IntermediateDirectory)/GeneratedMSBuildExtensions
+ $(IntermediateDirectory)/MSBuildSdkResolver
diff --git a/build/package/Installer.MSI.targets b/build/package/Installer.MSI.targets
index 86e81c22b..c132efdb0 100644
--- a/build/package/Installer.MSI.targets
+++ b/build/package/Installer.MSI.targets
@@ -146,13 +146,13 @@
diff --git a/build_projects/update-dependencies/Config.cs b/build_projects/update-dependencies/Config.cs
index e9c08ac10..9938cce68 100644
--- a/build_projects/update-dependencies/Config.cs
+++ b/build_projects/update-dependencies/Config.cs
@@ -2,6 +2,9 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
+using System.IO;
+using System.Linq;
+using System.Xml.Linq;
namespace Microsoft.DotNet.Scripts
{
@@ -35,11 +38,10 @@ namespace Microsoft.DotNet.Scripts
private Lazy _password = new Lazy(() => GetEnvironmentVariable("GITHUB_PASSWORD"));
private Lazy _dotNetVersionUrl = new Lazy(() => GetEnvironmentVariable("DOTNET_VERSION_URL", "https://raw.githubusercontent.com/dotnet/versions/master/build-info"));
- private Lazy _roslynVersionFragment = new Lazy(() => GetEnvironmentVariable("ROSLYN_VERSION_FRAGMENT", "dotnet/roslyn/netcore1.0"));
- private Lazy _coreSetupVersionFragment = new Lazy(() => GetEnvironmentVariable("CORESETUP_VERSION_FRAGMENT", "dotnet/core-setup/master"));
+ private Lazy _coreSetupVersionFragment = new Lazy(() => GetEnvironmentVariable("CORESETUP_VERSION_FRAGMENT", GetDefaultCoreSetupVersionFragment()));
private Lazy _gitHubUpstreamOwner = new Lazy(() => GetEnvironmentVariable("GITHUB_UPSTREAM_OWNER", "dotnet"));
private Lazy _gitHubProject = new Lazy(() => GetEnvironmentVariable("GITHUB_PROJECT", "cli"));
- private Lazy _gitHubUpstreamBranch = new Lazy(() => GetEnvironmentVariable("GITHUB_UPSTREAM_BRANCH", "master"));
+ private Lazy _gitHubUpstreamBranch = new Lazy(() => GetEnvironmentVariable("GITHUB_UPSTREAM_BRANCH", GetDefaultUpstreamBranch()));
private Lazy _gitHubPullRequestNotifications = new Lazy(() =>
GetEnvironmentVariable("GITHUB_PULL_REQUEST_NOTIFICATIONS", "")
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
@@ -51,7 +53,6 @@ namespace Microsoft.DotNet.Scripts
public string Email => _email.Value;
public string Password => _password.Value;
public string DotNetVersionUrl => _dotNetVersionUrl.Value;
- public string RoslynVersionFragment => _roslynVersionFragment.Value;
public string CoreSetupVersionFragment => _coreSetupVersionFragment.Value;
public string GitHubUpstreamOwner => _gitHubUpstreamOwner.Value;
public string GitHubProject => _gitHubProject.Value;
@@ -73,5 +74,38 @@ namespace Microsoft.DotNet.Scripts
return value;
}
+
+ private static string GetDefaultUpstreamBranch()
+ {
+ return GetRepoMSBuildPropValue("BranchInfo.props", "BranchName") ?? "master";
+ }
+
+ private static string GetDefaultCoreSetupVersionFragment()
+ {
+ string coreSetupChannel = GetRepoMSBuildPropValue("BundledRuntimes.props", "CoreSetupChannel") ?? "master";
+
+ return $"dotnet/core-setup/{coreSetupChannel}";
+ }
+
+ private static string GetRepoMSBuildPropValue(string propsFileName, string propertyName)
+ {
+ var propsFilePath = Path.Combine(Dirs.RepoRoot, "build", propsFileName);
+ var root = XDocument.Load(propsFilePath).Root;
+ var ns = root.Name.Namespace;
+
+ var value = root
+ .Elements(ns + "PropertyGroup")
+ .Elements(ns + propertyName)
+ .FirstOrDefault()
+ ?.Value;
+
+ if (string.IsNullOrEmpty(value))
+ {
+ Console.WriteLine($"Could not find a property named '{propertyName}' in {propsFilePath}");
+ return null;
+ }
+
+ return value;
+ }
}
}
diff --git a/build_projects/update-dependencies/Program.cs b/build_projects/update-dependencies/Program.cs
index 6da45dc9a..296ad2d0a 100644
--- a/build_projects/update-dependencies/Program.cs
+++ b/build_projects/update-dependencies/Program.cs
@@ -25,7 +25,6 @@ namespace Microsoft.DotNet.Scripts
List buildInfos = new List();
- buildInfos.Add(GetBuildInfo("Roslyn", s_config.RoslynVersionFragment, fetchLatestReleaseFile: false));
buildInfos.Add(GetBuildInfo("CoreSetup", s_config.CoreSetupVersionFragment, fetchLatestReleaseFile: false));
IEnumerable updaters = GetUpdaters();
diff --git a/run-build.ps1 b/run-build.ps1
index e97c49c1e..4781c68fa 100644
--- a/run-build.ps1
+++ b/run-build.ps1
@@ -104,8 +104,8 @@ if ($LastExitCode -ne 0)
# install the post-PJnistic stage0
$dotnetInstallPath = Join-Path $toolsLocalPath "dotnet-install.ps1"
-Write-Host "$dotnetInstallPath -Channel ""release/2.0.0"" -InstallDir $env:DOTNET_INSTALL_DIR -Architecture ""$Architecture"""
-Invoke-Expression "$dotnetInstallPath -Channel ""release/2.0.0"" -InstallDir $env:DOTNET_INSTALL_DIR -Architecture ""$Architecture"""
+Write-Host "$dotnetInstallPath -Channel ""release/2.0.0"" -Version ""2.0.0-preview1-005867"" -InstallDir $env:DOTNET_INSTALL_DIR -Architecture ""$Architecture"""
+Invoke-Expression "$dotnetInstallPath -Channel ""release/2.0.0"" -Version ""2.0.0-preview1-005867"" -InstallDir $env:DOTNET_INSTALL_DIR -Architecture ""$Architecture"""
if ($LastExitCode -ne 0)
{
Write-Output "The .NET CLI installation failed with exit code $LastExitCode"
diff --git a/run-build.sh b/run-build.sh
index 77034b6a6..aa9c877da 100755
--- a/run-build.sh
+++ b/run-build.sh
@@ -177,8 +177,8 @@ if [ $EXIT_CODE != 0 ]; then
fi
# now execute the script
-echo "installing CLI: $dotnetInstallPath --channel \"release/2.0.0\" --install-dir $DOTNET_INSTALL_DIR --architecture \"$ARCHITECTURE\" $LINUX_PORTABLE_INSTALL_ARGS"
-$dotnetInstallPath --channel "release/2.0.0" --install-dir $DOTNET_INSTALL_DIR --architecture "$ARCHITECTURE" $LINUX_PORTABLE_INSTALL_ARGS
+echo "installing CLI: $dotnetInstallPath --channel \"release/2.0.0\" --version \"2.0.0-preview1-005867\" --install-dir $DOTNET_INSTALL_DIR --architecture \"$ARCHITECTURE\" $LINUX_PORTABLE_INSTALL_ARGS"
+$dotnetInstallPath --channel "release/2.0.0" --version "2.0.0-preview1-005867" --install-dir $DOTNET_INSTALL_DIR --architecture "$ARCHITECTURE" $LINUX_PORTABLE_INSTALL_ARGS
EXIT_CODE=$?
if [ $EXIT_CODE != 0 ]; then
echo "run-build: Error: Boot-strapping post-PJ stage0 with exit code $EXIT_CODE." >&2
diff --git a/src/Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.csproj b/src/Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.csproj
index 5d14b7b57..bc95703fb 100644
--- a/src/Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.csproj
+++ b/src/Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.csproj
@@ -20,7 +20,8 @@
-
+
+
@@ -31,4 +32,4 @@
-
\ No newline at end of file
+
diff --git a/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.Common.cs b/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.Common.cs
new file mode 100644
index 000000000..580d1220b
--- /dev/null
+++ b/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.Common.cs
@@ -0,0 +1,36 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Diagnostics;
+using System.Text;
+
+namespace Microsoft.DotNet.MSBuildSdkResolver
+{
+ internal static partial class Interop
+ {
+ internal static string hostfxr_resolve_sdk(string exe_dir, string working_dir)
+ {
+ var buffer = new StringBuilder(capacity: 64);
+
+ for (;;)
+ {
+ int size = hostfxr_resolve_sdk(exe_dir, working_dir, buffer, buffer.Capacity);
+ if (size <= 0)
+ {
+ Debug.Assert(size == 0);
+ return null;
+ }
+
+ if (size <= buffer.Capacity)
+ {
+ break;
+ }
+
+ buffer.Capacity = size;
+ }
+
+ return buffer.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.NETFramework.cs b/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.NETFramework.cs
new file mode 100644
index 000000000..d1d567e8b
--- /dev/null
+++ b/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.NETFramework.cs
@@ -0,0 +1,45 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#if NET46
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Microsoft.DotNet.MSBuildSdkResolver
+{
+ internal static partial class Interop
+ {
+ static Interop()
+ {
+ PreloadLibrary("hostfxr.dll");
+ }
+
+ // MSBuild SDK resolvers are required to be AnyCPU, but we have a native dependency and .NETFramework does not
+ // have a built-in facility for dynamically loading user native dlls for the appropriate platform. We therefore
+ // preload the version with the correct architecture (from a corresponding sub-folder relative to us) on static
+ // construction so that subsequent P/Invokes can find it.
+ private static void PreloadLibrary(string dllFileName)
+ {
+ string basePath = Path.GetDirectoryName(typeof(Interop).Assembly.Location);
+ string architecture = IntPtr.Size == 8 ? "x64" : "x86";
+ string dllPath = Path.Combine(basePath, architecture, dllFileName);
+
+ // return value is intentially ignored as we let the subsequent P/Invokes fail naturally.
+ LoadLibraryExW(dllPath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
+ }
+
+ // lpFileName passed to LoadLibraryEx must be a full path.
+ private const int LOAD_WITH_ALTERED_SEARCH_PATH = 0x8;
+
+ [DllImport("kernel32", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
+ private static extern IntPtr LoadLibraryExW(string lpFileName, IntPtr hFile, int dwFlags);
+
+ [DllImport("hostfxr", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
+ private static extern int hostfxr_resolve_sdk(string exe_dir, string working_dir, [Out] StringBuilder buffer, int buffer_size);
+ }
+}
+
+#endif // NET46
\ No newline at end of file
diff --git a/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.NETStandard.cs b/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.NETStandard.cs
new file mode 100644
index 000000000..bff6fd84b
--- /dev/null
+++ b/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.NETStandard.cs
@@ -0,0 +1,37 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+// NOTE: Currently, only the NET46 build ships (with Visual Studio/desktop msbuild),
+// but the netstandard1.3 adaptation here acts a proof-of-concept for cross-platform
+// portability of the underlying hostfxr API and gives us build and test coverage
+// on non-Windows machines.
+#if NETSTANDARD1_3
+
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Microsoft.DotNet.MSBuildSdkResolver
+{
+ internal static partial class Interop
+ {
+ internal static readonly bool s_runningOnWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+
+ private static int hostfxr_resolve_sdk(string exe_dir, string working_dir, [Out] StringBuilder buffer, int buffer_size)
+ {
+ // hostfxr string encoding is platform -specific so dispatch to the
+ // appropriately annotated P/Invoke for the current platform.
+ return s_runningOnWindows
+ ? windows_hostfxr_resolve_sdk(exe_dir, working_dir, buffer, buffer_size)
+ : unix_hostfxr_resolve_sdk(exe_dir, working_dir, buffer, buffer_size);
+ }
+
+ [DllImport("hostfxr", EntryPoint = nameof(hostfxr_resolve_sdk), CharSet = CharSet.Unicode, ExactSpelling=true, CallingConvention = CallingConvention.Cdecl)]
+ private static extern int windows_hostfxr_resolve_sdk(string exe_dir, string working_dir, [Out] StringBuilder buffer, int buffer_size);
+
+ // CharSet.Ansi is UTF8 on Unix
+ [DllImport("hostfxr", EntryPoint = nameof(hostfxr_resolve_sdk), CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
+ private static extern int unix_hostfxr_resolve_sdk(string exe_dir, string working_dir, [Out] StringBuilder buffer, int buffer_size);
+ }
+}
+
+#endif // NETSTANDARD1_3
\ No newline at end of file
diff --git a/src/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs b/src/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs
new file mode 100644
index 000000000..6048d3d59
--- /dev/null
+++ b/src/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs
@@ -0,0 +1,126 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using Microsoft.Build.Framework;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Microsoft.DotNet.MSBuildSdkResolver
+{
+ public sealed class DotNetMSBuildSdkResolver : SdkResolver
+ {
+ public override string Name => "Microsoft.DotNet.MSBuildSdkResolver";
+
+ // Default resolver has priority 10000 and we want to go before it and leave room on either side of us.
+ public override int Priority => 5000;
+
+ public override SdkResult Resolve(SdkReference sdkReference, SdkResolverContext context, SdkResultFactory factory)
+ {
+ // These are overrides that are used to force the resolved SDK tasks and targets to come from a given
+ // base directory and report a given version to msbuild (which may be null if unknown. One key use case
+ // for this is to test SDK tasks and targets without deploying them inside the .NET Core SDK.
+ string msbuildSdksDir = Environment.GetEnvironmentVariable("DOTNET_MSBUILD_SDK_RESOLVER_SDKS_DIR");
+ string netcoreSdkVersion = Environment.GetEnvironmentVariable("DOTNET_MSBUILD_SDK_RESOLVER_SDKS_VER");
+
+ if (msbuildSdksDir == null)
+ {
+ string netcoreSdkDir = ResolveNetcoreSdkDirectory(context);
+ if (netcoreSdkDir == null)
+ {
+ return factory.IndicateFailure(
+ new[]
+ {
+ "Unable to locate the .NET Core SDK. Check that it is installed and that the version"
+ + " specified in global.json (if any) matches the installed version."
+ });
+ }
+
+ msbuildSdksDir = Path.Combine(netcoreSdkDir, "Sdks");
+ netcoreSdkVersion = new DirectoryInfo(netcoreSdkDir).Name;;
+ }
+
+ string msbuildSdkDir = Path.Combine(msbuildSdksDir, sdkReference.Name, "Sdk");
+ if (!Directory.Exists(msbuildSdkDir))
+ {
+ return factory.IndicateFailure(
+ new[]
+ {
+ $"{msbuildSdkDir} not found. Check that a recent enough .NET Core SDK is installed"
+ + " and/or increase the version specified in global.json. "
+ });
+ }
+
+ return factory.IndicateSuccess(msbuildSdkDir, netcoreSdkVersion);
+ }
+
+ private string ResolveNetcoreSdkDirectory(SdkResolverContext context)
+ {
+ foreach (string exeDir in GetDotnetExeDirectoryCandidates())
+ {
+ string workingDir = context.SolutionFilePath ?? context.ProjectFilePath;
+ string netcoreSdkDir = Interop.hostfxr_resolve_sdk(exeDir, workingDir);
+
+ if (netcoreSdkDir != null)
+ {
+ return netcoreSdkDir;
+ }
+ }
+
+ return null;
+ }
+
+ // Search for [ProgramFiles]\dotnet in this order.
+ private static readonly string[] s_programFiles = new[]
+ {
+ // "c:\Program Files" on x64 machine regardless process architecture.
+ // Undefined on x86 machines.
+ "ProgramW6432",
+
+ // "c:\Program Files (x86)" on x64 machine regardless of process architecture
+ // Undefined on x86 machines.
+ "ProgramFiles(x86)",
+
+ // "c:\Program Files" or "C:\Program Files (x86)" on x64 machine depending on process architecture.
+ // "c:\Program Files" on x86 machines (therefore not redundant with the two locations above in that case).
+ //
+ // NOTE: hostfxr will search this on its own if multilevel lookup is not disable, but we do it explicitly
+ // to prevent an environment with disabled multilevel lookup from crippling desktop msbuild and VS.
+ "ProgramFiles",
+ };
+
+ private List GetDotnetExeDirectoryCandidates()
+ {
+ string environmentOverride = Environment.GetEnvironmentVariable("DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR");
+ if (environmentOverride != null)
+ {
+ return new List(capacity: 1) { environmentOverride };
+ }
+
+ // Initial capacity is 2 because while there are 3 candidates, we expect at most 2 unique ones (x64 + x86)
+ // Also, N=3 here means that we needn't be concerned with the O(N^2) complexity of the foreach + contains.
+ var candidates = new List(capacity: 2);
+ foreach (string variable in s_programFiles)
+ {
+ string directory = Environment.GetEnvironmentVariable(variable);
+ if (directory == null)
+ {
+ continue;
+ }
+
+ directory = Path.Combine(directory, "dotnet");
+ if (!candidates.Contains(directory))
+ {
+ candidates.Add(directory);
+ }
+ }
+
+ if (candidates.Count == 0)
+ {
+ candidates.Add(null);
+ }
+
+ return candidates;
+ }
+ }
+}
diff --git a/src/Microsoft.DotNet.MSBuildSdkResolver/Microsoft.DotNet.MSBuildSdkResolver.csproj b/src/Microsoft.DotNet.MSBuildSdkResolver/Microsoft.DotNet.MSBuildSdkResolver.csproj
new file mode 100644
index 000000000..335eed3ce
--- /dev/null
+++ b/src/Microsoft.DotNet.MSBuildSdkResolver/Microsoft.DotNet.MSBuildSdkResolver.csproj
@@ -0,0 +1,39 @@
+
+
+
+
+ $(SdkVersion)
+ netstandard1.3;net46
+ netstandard1.3
+ AnyCPU
+ win-x86;win-x64
+ true
+ ../../tools/Key.snk
+ true
+ true
+ false
+ $(SdkResolverOutputDirectory)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ x86/hostfxr.dll
+ PreserveNewest
+
+
+ x64/hostfxr.dll
+ PreserveNewest
+
+
+
+
diff --git a/src/Microsoft.DotNet.MSBuildSdkResolver/Microsoft.DotNet.MSBuildSdkResolver.sln b/src/Microsoft.DotNet.MSBuildSdkResolver/Microsoft.DotNet.MSBuildSdkResolver.sln
new file mode 100644
index 000000000..4d5062122
--- /dev/null
+++ b/src/Microsoft.DotNet.MSBuildSdkResolver/Microsoft.DotNet.MSBuildSdkResolver.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26425.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.MSBuildSdkResolver", "Microsoft.DotNet.MSBuildSdkResolver.csproj", "{DCB2A518-7BC6-43F5-BE2C-13B11A1F3961}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.MSBuildSdkResolver.Tests", "..\..\test\Microsoft.DotNet.MSBuildSdkResolver.Tests\Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj", "{CC488F39-E106-4BF4-9599-19A265AFD9AC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DCB2A518-7BC6-43F5-BE2C-13B11A1F3961}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DCB2A518-7BC6-43F5-BE2C-13B11A1F3961}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DCB2A518-7BC6-43F5-BE2C-13B11A1F3961}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DCB2A518-7BC6-43F5-BE2C-13B11A1F3961}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CC488F39-E106-4BF4-9599-19A265AFD9AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CC488F39-E106-4BF4-9599-19A265AFD9AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CC488F39-E106-4BF4-9599-19A265AFD9AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CC488F39-E106-4BF4-9599-19A265AFD9AC}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/redist/redist.csproj b/src/redist/redist.csproj
index 540a64ac4..0bea23856 100644
--- a/src/redist/redist.csproj
+++ b/src/redist/redist.csproj
@@ -159,6 +159,7 @@
diff --git a/test/Microsoft.DotNet.Cli.Tests.sln b/test/Microsoft.DotNet.Cli.Tests.sln
index 30e4e2f60..ffc08cbd5 100644
--- a/test/Microsoft.DotNet.Cli.Tests.sln
+++ b/test/Microsoft.DotNet.Cli.Tests.sln
@@ -76,6 +76,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-store.Tests", "dotne
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-back-compat.Tests", "dotnet-back-compat.Tests\dotnet-back-compat.Tests.csproj", "{27351B2F-325B-4843-9F4C-BC53FD06A7B5}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.MSBuildSdkResolver.Tests", "Microsoft.DotNet.MSBuildSdkResolver.Tests\Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj", "{42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -506,6 +508,18 @@ Global
{27351B2F-325B-4843-9F4C-BC53FD06A7B5}.Release|x64.Build.0 = Release|Any CPU
{27351B2F-325B-4843-9F4C-BC53FD06A7B5}.Release|x86.ActiveCfg = Release|Any CPU
{27351B2F-325B-4843-9F4C-BC53FD06A7B5}.Release|x86.Build.0 = Release|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Debug|x64.Build.0 = Debug|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Debug|x86.Build.0 = Debug|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Release|x64.ActiveCfg = Release|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Release|x64.Build.0 = Release|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Release|x86.ActiveCfg = Release|Any CPU
+ {42A0CAB4-FFAD-47D4-9880-C0F4EDCF93DE}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/GivenAnMSBuildSdkResolver.cs b/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/GivenAnMSBuildSdkResolver.cs
new file mode 100644
index 000000000..bfbf14e4a
--- /dev/null
+++ b/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/GivenAnMSBuildSdkResolver.cs
@@ -0,0 +1,70 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections.Generic;
+using Microsoft.Build.Framework;
+using Xunit;
+using System.Linq;
+using Xunit.Abstractions;
+using System;
+using Microsoft.DotNet.MSBuildSdkResolver;
+
+namespace Microsoft.DotNet.Cli.Utils.Tests
+{
+ public class GivenAnMSBuildSdkResolver
+ {
+ private ITestOutputHelper _logger;
+
+ public GivenAnMSBuildSdkResolver(ITestOutputHelper logger)
+ {
+ _logger = logger;
+ }
+
+ [Fact]
+ public void ItHasCorrectNameAndPriority()
+ {
+ var resolver = new DotNetMSBuildSdkResolver();
+
+ Assert.Equal(5000, resolver.Priority);
+ Assert.Equal("Microsoft.DotNet.MSBuildSdkResolver", resolver.Name);
+ }
+
+ [Fact]
+ public void ItCallsNativeCodeWithoutCrashing() // WIP: placeholder to get plumbing through
+ {
+ var resolver = new DotNetMSBuildSdkResolver();
+ var result = (MockResult)resolver.Resolve(
+ new SdkReference("Microsoft.NET.Sdk", null, null),
+ new MockContext(),
+ new MockFactory());
+
+ _logger.WriteLine($"success: {result.Success}");
+ _logger.WriteLine($"errors: {string.Join(Environment.NewLine, result.Errors ?? Array.Empty())}");
+ _logger.WriteLine($"warnings: {string.Join(Environment.NewLine, result.Warnings ?? Array.Empty())}");
+ _logger.WriteLine($"path: {result.Path}");
+ _logger.WriteLine($"version: {result.Version}");
+ }
+
+ private sealed class MockContext : SdkResolverContext
+ {
+ }
+
+ private sealed class MockFactory : SdkResultFactory
+ {
+ public override SdkResult IndicateFailure(IEnumerable errors, IEnumerable warnings = null)
+ => new MockResult { Success = false, Errors = errors, Warnings = warnings };
+
+ public override SdkResult IndicateSuccess(string path, string version, IEnumerable warnings = null)
+ => new MockResult { Success = true, Path = path, Version = version, Warnings = warnings };
+ }
+
+ private sealed class MockResult : SdkResult
+ {
+ public new bool Success { get => base.Success; set => base.Success = value; }
+ public string Version { get; set; }
+ public string Path { get; set; }
+ public IEnumerable Errors { get; set; }
+ public IEnumerable Warnings { get; set; }
+ }
+ }
+}
diff --git a/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj b/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj
new file mode 100644
index 000000000..bfc8f571a
--- /dev/null
+++ b/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/Microsoft.DotNet.MSBuildSdkResolver.Tests.csproj
@@ -0,0 +1,30 @@
+
+
+
+
+ net46;$(CliTargetFramework)
+ $(CliTargetFramework)
+ $(CLI_SharedFrameworkVersion)
+ Exe
+ ../../tools/Key.snk
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/xunit.runner.json b/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/xunit.runner.json
new file mode 100644
index 000000000..34b2fe2cd
--- /dev/null
+++ b/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/xunit.runner.json
@@ -0,0 +1,3 @@
+{
+ "shadowCopy": false
+}
\ No newline at end of file