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