Create replacement API for Microsoft.DotNet.ProjectModel
This commit is contained in:
parent
4647a8a4bd
commit
40ff75d536
|
|
@ -38,6 +38,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{59E02BDF
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NuGetPackager", "tools\NuGetPackager\NuGetPackager.xproj", "{8B781D87-1FC3-4A34-9089-2BDF6B562B85}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NuGetPackager", "tools\NuGetPackager\NuGetPackager.xproj", "{8B781D87-1FC3-4A34-9089-2BDF6B562B85}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.Sources", "src\Microsoft.Extensions.ProjectModel.Sources\Microsoft.Extensions.ProjectModel.Sources.xproj", "{99D6CE89-7302-4C3A-83EB-D534C24644D2}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.ProjectModel.Tests", "test\Microsoft.Extensions.ProjectModel.Tests\Microsoft.Extensions.ProjectModel.Tests.xproj", "{1A66A831-4F06-46D9-B483-70A4E75A2F7F}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -88,6 +92,14 @@ Global
|
||||||
{8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.Build.0 = Release|Any CPU
|
{8B781D87-1FC3-4A34-9089-2BDF6B562B85}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{99D6CE89-7302-4C3A-83EB-D534C24644D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{99D6CE89-7302-4C3A-83EB-D534C24644D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{99D6CE89-7302-4C3A-83EB-D534C24644D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{99D6CE89-7302-4C3A-83EB-D534C24644D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1A66A831-4F06-46D9-B483-70A4E75A2F7F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -105,5 +117,7 @@ Global
|
||||||
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}
|
{8A2E6961-6B12-4A8E-8215-3E7301D52EAC} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}
|
||||||
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4}
|
{53F3B53D-303A-4DAA-9C38-4F55195FA5B9} = {66517987-2A5A-4330-B130-207039378FD4}
|
||||||
{8B781D87-1FC3-4A34-9089-2BDF6B562B85} = {59E02BDF-98DE-4D64-B576-2D0299D5E052}
|
{8B781D87-1FC3-4A34-9089-2BDF6B562B85} = {59E02BDF-98DE-4D64-B576-2D0299D5E052}
|
||||||
|
{99D6CE89-7302-4C3A-83EB-D534C24644D2} = {66517987-2A5A-4330-B130-207039378FD4}
|
||||||
|
{1A66A831-4F06-46D9-B483-70A4E75A2F7F} = {F5B382BC-258F-46E1-AC3D-10E5CCD55134}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<packageSources>
|
<packageSources>
|
||||||
|
<add key="msbuild" value="https://dotnet.myget.org/F/msbuild/api/v3/index.json" />
|
||||||
<add key="AspNetCore" value="https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json" />
|
<add key="AspNetCore" value="https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json" />
|
||||||
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
||||||
</packageSources>
|
</packageSources>
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"adx-nonshipping": {
|
||||||
|
"rules": [],
|
||||||
|
"packages": {
|
||||||
|
"Microsoft.Extensions.ProjectModel.Sources": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Default": {
|
"Default": {
|
||||||
"rules": [
|
"rules": [
|
||||||
"DefaultCompositeRule"
|
"DefaultCompositeRule"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"projects": [ "src"]
|
"projects": [ "src", "test"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,5 +21,11 @@ k-standard-goals
|
||||||
"-n src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec " +
|
"-n src/Microsoft.Extensions.SecretManager.Tools/Microsoft.Extensions.SecretManager.Tools.nuspec " +
|
||||||
"-n src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec " +
|
"-n src/Microsoft.Extensions.Caching.SqlConfig.Tools/Microsoft.Extensions.Caching.SqlConfig.Tools.nuspec " +
|
||||||
"-n src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec ");
|
"-n src/Microsoft.DotNet.Watcher.Tools/Microsoft.DotNet.Watcher.Tools.nuspec ");
|
||||||
|
|
||||||
|
DotnetPack("src/Microsoft.Extensions.ProjectModel.Sources/project.json", BUILD_DIR_LOCAL, E("Configuration"), E("KOREBUILD_DOTNET_PACK_OPTIONS") + " --no-build");
|
||||||
|
foreach (var nupkg in Files.Include(Path.Combine(BUILD_DIR_LOCAL, "*/" + E("Configuration") + "/*.nupkg")))
|
||||||
|
{
|
||||||
|
File.Copy(nupkg, Path.Combine(BUILD_DIR_LOCAL, Path.GetFileName(nupkg)), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
internal class DotNetProjectContext : IProjectContext
|
||||||
|
{
|
||||||
|
private readonly ProjectContext _projectContext;
|
||||||
|
private readonly OutputPaths _paths;
|
||||||
|
private readonly Lazy<JObject> _rawProject;
|
||||||
|
private readonly CommonCompilerOptions _compilerOptions;
|
||||||
|
|
||||||
|
public DotNetProjectContext(ProjectContext projectContext, string configuration, string outputPath)
|
||||||
|
{
|
||||||
|
if (projectContext == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(projectContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(configuration))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(configuration));
|
||||||
|
}
|
||||||
|
|
||||||
|
_rawProject = new Lazy<JObject>(() =>
|
||||||
|
{
|
||||||
|
using (var stream = new FileStream(projectContext.ProjectFile.ProjectFilePath, FileMode.Open, FileAccess.Read))
|
||||||
|
using (var streamReader = new StreamReader(stream))
|
||||||
|
using (var jsonReader = new JsonTextReader(streamReader))
|
||||||
|
{
|
||||||
|
return JObject.Load(jsonReader);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Configuration = configuration;
|
||||||
|
_projectContext = projectContext;
|
||||||
|
|
||||||
|
_paths = projectContext.GetOutputPaths(configuration, buidBasePath: null, outputPath: outputPath);
|
||||||
|
_compilerOptions = _projectContext.ProjectFile.GetCompilerOptions(TargetFramework, Configuration);
|
||||||
|
|
||||||
|
// Workaround https://github.com/dotnet/cli/issues/3164
|
||||||
|
IsClassLibrary = !(_compilerOptions.EmitEntryPoint
|
||||||
|
?? projectContext.ProjectFile.GetCompilerOptions(null, configuration).EmitEntryPoint.GetValueOrDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsClassLibrary { get; }
|
||||||
|
|
||||||
|
public NuGetFramework TargetFramework => _projectContext.TargetFramework;
|
||||||
|
public string Config => _paths.RuntimeFiles.Config;
|
||||||
|
public string DepsJson => _paths.RuntimeFiles.DepsJson;
|
||||||
|
public string RuntimeConfigJson => _paths.RuntimeFiles.RuntimeConfigJson;
|
||||||
|
public string PackagesDirectory => _projectContext.PackagesDirectory;
|
||||||
|
|
||||||
|
public string AssemblyFullPath =>
|
||||||
|
!IsClassLibrary && (_projectContext.IsPortable || TargetFramework.IsDesktop())
|
||||||
|
? _paths.RuntimeFiles.Executable
|
||||||
|
: _paths.RuntimeFiles.Assembly;
|
||||||
|
|
||||||
|
public string Configuration { get; }
|
||||||
|
public string ProjectFullPath => _projectContext.ProjectFile.ProjectFilePath;
|
||||||
|
public string ProjectName => _projectContext.ProjectFile.Name;
|
||||||
|
// TODO read from xproj if available
|
||||||
|
public string RootNamespace => _projectContext.ProjectFile.Name;
|
||||||
|
public string TargetDirectory => _paths.RuntimeOutputPath;
|
||||||
|
public string Platform => _compilerOptions.Platform;
|
||||||
|
|
||||||
|
public IEnumerable<string> CompilationItems
|
||||||
|
=> _compilerOptions.CompileInclude.ResolveFiles();
|
||||||
|
|
||||||
|
public IEnumerable<string> EmbededItems
|
||||||
|
=> _compilerOptions.EmbedInclude.ResolveFiles();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns string values of top-level keys in the project.json file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyName"></param>
|
||||||
|
/// <param name="propertyNameComparer"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string FindProperty(string propertyName) => FindProperty<string>(propertyName);
|
||||||
|
|
||||||
|
public TProperty FindProperty<TProperty>(string propertyName)
|
||||||
|
{
|
||||||
|
foreach (var item in _rawProject.Value)
|
||||||
|
{
|
||||||
|
if (item.Key.Equals(propertyName, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return item.Value.Value<TProperty>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return default(TProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.DotNet.ProjectModel.Files;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
internal static class IncludeContextExtensions
|
||||||
|
{
|
||||||
|
public static IEnumerable<string> ResolveFiles(this IncludeContext context)
|
||||||
|
{
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
return IncludeFilesResolver
|
||||||
|
.GetIncludeFiles(context, "/", diagnostics: null)
|
||||||
|
.Select(f => f.SourcePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
public interface IProjectContext
|
||||||
|
{
|
||||||
|
string ProjectName { get; }
|
||||||
|
string Configuration { get; }
|
||||||
|
string Platform { get; }
|
||||||
|
string ProjectFullPath { get; }
|
||||||
|
string RootNamespace { get; }
|
||||||
|
bool IsClassLibrary { get; }
|
||||||
|
NuGetFramework TargetFramework { get; }
|
||||||
|
string Config { get; }
|
||||||
|
string DepsJson { get; }
|
||||||
|
string RuntimeConfigJson { get; }
|
||||||
|
string PackagesDirectory { get; }
|
||||||
|
string TargetDirectory { get; }
|
||||||
|
string AssemblyFullPath { get; }
|
||||||
|
IEnumerable<string> CompilationItems { get; }
|
||||||
|
IEnumerable<string> EmbededItems { get; }
|
||||||
|
string FindProperty(string propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel.Internal
|
||||||
|
{
|
||||||
|
internal class DotNetCoreSdk
|
||||||
|
{
|
||||||
|
public string BasePath { get; set; }
|
||||||
|
public string Version { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel.Internal
|
||||||
|
{
|
||||||
|
internal class DotNetCoreSdkResolver
|
||||||
|
{
|
||||||
|
private readonly string _installationDir;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a resolver that uses the currently executing <see cref="Muxer"/> to find the .NET Core SDK installation
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DotNetCoreSdkResolver DefaultResolver = new DotNetCoreSdkResolver(Path.GetDirectoryName(new Muxer().MuxerPath));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates a resolver that locates the SDK
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="installationDir">The directory containing dotnet muxer, aka DOTNET_HOME</param>
|
||||||
|
public DotNetCoreSdkResolver(string installationDir)
|
||||||
|
{
|
||||||
|
_installationDir = installationDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find the latest SDK installation (uses SemVer 1.0 to determine what is "latest")
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Path to SDK root directory</returns>
|
||||||
|
public DotNetCoreSdk ResolveLatest()
|
||||||
|
{
|
||||||
|
var latest = FindInstalled()
|
||||||
|
.Select(d => new { path = d, version = SemanticVersion.Parse(Path.GetFileName(d)) })
|
||||||
|
.OrderByDescending(sdk => sdk.version)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (latest == null)
|
||||||
|
{
|
||||||
|
throw CreateSdkNotInstalledException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DotNetCoreSdk
|
||||||
|
{
|
||||||
|
BasePath = latest.path,
|
||||||
|
Version = latest.version.ToFullString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public DotNetCoreSdk ResolveProjectSdk(string projectDir)
|
||||||
|
{
|
||||||
|
var sdkVersion = ResolveGlobalJsonSdkVersion(projectDir);
|
||||||
|
if (string.IsNullOrEmpty(sdkVersion))
|
||||||
|
{
|
||||||
|
return ResolveLatest();
|
||||||
|
}
|
||||||
|
|
||||||
|
var sdk = FindInstalled()
|
||||||
|
.Where(p => Path.GetFileName(p).Equals(sdkVersion, StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Select(d => new { path = d, version = SemanticVersion.Parse(Path.GetFileName(d)) })
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (sdk == null)
|
||||||
|
{
|
||||||
|
throw CreateSdkNotInstalledException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DotNetCoreSdk
|
||||||
|
{
|
||||||
|
BasePath = sdk.path,
|
||||||
|
Version = sdk.version.ToFullString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Exception CreateSdkNotInstalledException()
|
||||||
|
{
|
||||||
|
return new DirectoryNotFoundException($"Could not find an installation of the .NET Core SDK in '{_installationDir}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> FindInstalled()
|
||||||
|
=> Directory.EnumerateDirectories(Path.Combine(_installationDir, "sdk"));
|
||||||
|
|
||||||
|
private string ResolveGlobalJsonSdkVersion(string start)
|
||||||
|
{
|
||||||
|
var dir = new DirectoryInfo(start);
|
||||||
|
FileInfo fileInfo = null;
|
||||||
|
while (dir != null)
|
||||||
|
{
|
||||||
|
var candidate = Path.Combine(dir.FullName, "global.json");
|
||||||
|
if (File.Exists(candidate))
|
||||||
|
{
|
||||||
|
fileInfo = new FileInfo(candidate);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dir = dir.Parent;
|
||||||
|
}
|
||||||
|
if (fileInfo == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var contents = File.ReadAllText(fileInfo.FullName);
|
||||||
|
var globalJson = JsonConvert.DeserializeObject<GlobalJsonStub>(contents);
|
||||||
|
return globalJson?.sdk?.version;
|
||||||
|
}
|
||||||
|
catch (JsonException)
|
||||||
|
{
|
||||||
|
// TODO log
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class GlobalJsonStub
|
||||||
|
{
|
||||||
|
public GlobalJsonSdkStub sdk { get; set; }
|
||||||
|
|
||||||
|
public class GlobalJsonSdkStub
|
||||||
|
{
|
||||||
|
public string version { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>99d6ce89-7302-4c3a-83eb-d534c24644d2</ProjectGuid>
|
||||||
|
<RootNamespace>Microsoft.Extensions.ProjectModel</RootNamespace>
|
||||||
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||||
|
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Extensions.ProjectModel.Internal;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the msbuild context used to parse a project model
|
||||||
|
/// </summary>
|
||||||
|
internal class MsBuildContext
|
||||||
|
{
|
||||||
|
public string MsBuildExecutableFullPath { get; private set; }
|
||||||
|
public string ExtensionsPath { get; private set; }
|
||||||
|
|
||||||
|
public static MsBuildContext FromCurrentDotNetSdk()
|
||||||
|
{
|
||||||
|
var sdk = DotNetCoreSdkResolver.DefaultResolver.ResolveLatest();
|
||||||
|
return FromDotNetSdk(sdk);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MsBuildContext FromDotNetSdk(DotNetCoreSdk sdk)
|
||||||
|
{
|
||||||
|
if (sdk == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(sdk));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MsBuildContext
|
||||||
|
{
|
||||||
|
// might change... See https://github.com/Microsoft/msbuild/issues/1136
|
||||||
|
MsBuildExecutableFullPath = Path.Combine(sdk.BasePath, "MSBuild.exe"),
|
||||||
|
ExtensionsPath = sdk.BasePath
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.Build.Execution
|
||||||
|
{
|
||||||
|
internal static class MsBuildExtensions
|
||||||
|
{
|
||||||
|
public static string FindProperty(this ProjectInstance projectInstance, string propertyName, StringComparison comparer)
|
||||||
|
=> projectInstance.Properties.FirstOrDefault(p => p.Name.Equals(propertyName, comparer))?.EvaluatedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Build.Execution;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
internal class MsBuildProjectContext : IProjectContext
|
||||||
|
{
|
||||||
|
private const string CompileItemName = "Compile";
|
||||||
|
private const string EmbedItemName = "EmbeddedResource";
|
||||||
|
private const string FullPathMetadataName = "FullPath";
|
||||||
|
|
||||||
|
private readonly ProjectInstance _project;
|
||||||
|
private readonly string _name;
|
||||||
|
|
||||||
|
public MsBuildProjectContext(string name, string configuration, ProjectInstance project)
|
||||||
|
{
|
||||||
|
_project = project;
|
||||||
|
|
||||||
|
Configuration = configuration;
|
||||||
|
_name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FindProperty(string propertyName)
|
||||||
|
{
|
||||||
|
return _project.GetProperty(propertyName)?.EvaluatedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ProjectName => FindProperty("ProjectName") ?? _name;
|
||||||
|
public string Configuration { get; }
|
||||||
|
|
||||||
|
public NuGetFramework TargetFramework => NuGetFramework.Parse(FindProperty("NuGetTargetMoniker"));
|
||||||
|
public bool IsClassLibrary => FindProperty("OutputType").Equals("Library", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
// TODO get from actual properties according to TFM
|
||||||
|
public string Config => AssemblyFullPath + ".config";
|
||||||
|
public string DepsJson => Path.Combine(TargetDirectory, Path.GetFileNameWithoutExtension(AssemblyFullPath) + ".deps.json");
|
||||||
|
public string RuntimeConfigJson => Path.Combine(TargetDirectory, Path.GetFileNameWithoutExtension(AssemblyFullPath) + ".runtimeconfig.json");
|
||||||
|
|
||||||
|
public string PackagesDirectory => FindProperty("NuGetPackageRoot");
|
||||||
|
public string AssemblyFullPath => FindProperty("TargetPath");
|
||||||
|
public string Platform => FindProperty("Platform");
|
||||||
|
public string ProjectFullPath => _project.FullPath;
|
||||||
|
public string RootNamespace => FindProperty("RootNamespace") ?? ProjectName;
|
||||||
|
public string TargetDirectory => FindProperty("TargetDir");
|
||||||
|
|
||||||
|
public IEnumerable<string> CompilationItems
|
||||||
|
=> _project.GetItems(CompileItemName).Select(i => i.GetMetadataValue(FullPathMetadataName));
|
||||||
|
|
||||||
|
public IEnumerable<string> EmbededItems
|
||||||
|
=> _project.GetItems(EmbedItemName).Select(i => i.GetMetadataValue(FullPathMetadataName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,198 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using Microsoft.Build.Construction;
|
||||||
|
using Microsoft.Build.Evaluation;
|
||||||
|
using Microsoft.Build.Execution;
|
||||||
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
using Microsoft.Extensions.FileProviders.Physical;
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
internal class MsBuildProjectContextBuilder
|
||||||
|
{
|
||||||
|
private string _configuration;
|
||||||
|
private IFileInfo _fileInfo;
|
||||||
|
private string[] _buildTargets;
|
||||||
|
private Dictionary<string, string> _globalProperties = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilder()
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilder WithBuildTargets(string[] targets)
|
||||||
|
{
|
||||||
|
if (targets == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(targets));
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildTargets = targets;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilder WithConfiguration(string configuration)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
WithProperty("Configuration", configuration);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilder WithDesignTimeBuild()
|
||||||
|
{
|
||||||
|
// don't to expensive things
|
||||||
|
WithProperty("DesignTimeBuild", "true");
|
||||||
|
WithProperty("_ResolveReferenceDependencies", "true");
|
||||||
|
WithProperty("BuildProjectReferences", "false");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilder WithMsBuild(MsBuildContext context)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Workaround https://github.com/Microsoft/msbuild/issues/999
|
||||||
|
Error: System.TypeInitializationException : The type initializer for 'BuildEnvironmentHelperSingleton' threw an exception.
|
||||||
|
Could not determine a valid location to MSBuild. Try running this process from the Developer Command Prompt for Visual Studio.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", context.MsBuildExecutableFullPath);
|
||||||
|
return WithProperty("MSBuildExtensionsPath", context.ExtensionsPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilder WithProperty(string property, string value)
|
||||||
|
{
|
||||||
|
_globalProperties[property] = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilder WithProjectFile(string filePath)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(filePath))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileInfo = new PhysicalFileInfo(new FileInfo(filePath));
|
||||||
|
return WithProjectFile(fileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilder WithProjectFile(IFileInfo fileInfo)
|
||||||
|
{
|
||||||
|
_fileInfo = fileInfo;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilder WithTargetFramework(NuGetFramework framework)
|
||||||
|
=> WithTargetFramework(framework.GetShortFolderName());
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilder WithTargetFramework(string framework)
|
||||||
|
=> WithProperty("TargetFramework", framework);
|
||||||
|
|
||||||
|
public virtual MsBuildProjectContext Build(bool ignoreBuildErrors = false)
|
||||||
|
{
|
||||||
|
var projectCollection = CreateProjectCollection();
|
||||||
|
var project = CreateProject(_fileInfo, _configuration, _globalProperties, projectCollection);
|
||||||
|
var projectInstance = CreateProjectInstance(project, _buildTargets, ignoreBuildErrors);
|
||||||
|
|
||||||
|
var name = Path.GetFileNameWithoutExtension(_fileInfo.Name);
|
||||||
|
return new MsBuildProjectContext(name, _configuration, projectInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Initialize()
|
||||||
|
{
|
||||||
|
WithBuildTargets(new[] { "ResolveReferences" });
|
||||||
|
WithMsBuild(MsBuildContext.FromCurrentDotNetSdk());
|
||||||
|
WithProperty("_ResolveReferenceDependencies", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual ProjectCollection CreateProjectCollection() => new ProjectCollection();
|
||||||
|
|
||||||
|
protected virtual Project CreateProject(IFileInfo fileInfo,
|
||||||
|
string configuration,
|
||||||
|
IDictionary<string, string> globalProps,
|
||||||
|
ProjectCollection projectCollection)
|
||||||
|
{
|
||||||
|
using (var stream = fileInfo.CreateReadStream())
|
||||||
|
{
|
||||||
|
var xmlReader = XmlReader.Create(stream);
|
||||||
|
|
||||||
|
var xml = ProjectRootElement.Create(xmlReader, projectCollection, preserveFormatting: true);
|
||||||
|
xml.FullPath = fileInfo.PhysicalPath;
|
||||||
|
|
||||||
|
return new Project(xml, globalProps, toolsVersion: null, projectCollection: projectCollection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual ProjectInstance CreateProjectInstance(Project project, string[] targets, bool ignoreErrors)
|
||||||
|
{
|
||||||
|
var projectInstance = project.CreateProjectInstance();
|
||||||
|
if (targets.Length == 0)
|
||||||
|
{
|
||||||
|
return projectInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
var logger = new InMemoryLogger();
|
||||||
|
projectInstance.Build(targets, new[] { logger });
|
||||||
|
|
||||||
|
if (!ignoreErrors && logger.Errors.Count > 0)
|
||||||
|
{
|
||||||
|
throw CreateBuildFailedException(project.FullPath, logger.Errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Exception CreateBuildFailedException(string filePath, IList<BuildErrorEventArgs> errors)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine($"Building '{filePath}' failed.");
|
||||||
|
|
||||||
|
for (var i = 0; i < errors.Count; i++)
|
||||||
|
{
|
||||||
|
sb.Append(i).Append(" :").AppendLine(errors[i].Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InMemoryLogger : ILogger
|
||||||
|
{
|
||||||
|
private readonly Stack<Action> _onShutdown = new Stack<Action>();
|
||||||
|
|
||||||
|
internal IList<BuildErrorEventArgs> Errors = new List<BuildErrorEventArgs>();
|
||||||
|
|
||||||
|
public string Parameters { get; set; }
|
||||||
|
public LoggerVerbosity Verbosity { get; set; }
|
||||||
|
|
||||||
|
public void Initialize(IEventSource eventSource)
|
||||||
|
{
|
||||||
|
eventSource.ErrorRaised += OnError;
|
||||||
|
_onShutdown.Push(() =>
|
||||||
|
{
|
||||||
|
eventSource.ErrorRaised -= OnError;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnError(object sender, BuildErrorEventArgs e)
|
||||||
|
{
|
||||||
|
Errors.Add(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
while (_onShutdown.Count > 0)
|
||||||
|
{
|
||||||
|
_onShutdown.Pop()?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"version": "1.0.0-*",
|
||||||
|
"shared": "**/*.cs",
|
||||||
|
"frameworks": {
|
||||||
|
"netstandard1.0": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,9 +11,11 @@
|
||||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>1a66a831-4f06-46d9-b483-70a4e75a2f7f</ProjectGuid>
|
||||||
|
<RootNamespace>Microsoft.Extensions.ProjectModel</RootNamespace>
|
||||||
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||||
|
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Extensions.ProjectModel.Internal;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
public class DotNetCoreSdkResolverTest : IDisposable
|
||||||
|
{
|
||||||
|
private readonly string _fakeInstallDir;
|
||||||
|
public DotNetCoreSdkResolverTest()
|
||||||
|
{
|
||||||
|
_fakeInstallDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
|
||||||
|
Directory.CreateDirectory(_fakeInstallDir);
|
||||||
|
Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ResolveLatest()
|
||||||
|
{
|
||||||
|
var project = Path.Combine(_fakeInstallDir, "project");
|
||||||
|
Directory.CreateDirectory(project);
|
||||||
|
Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.1"));
|
||||||
|
Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0"));
|
||||||
|
Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-beta1"));
|
||||||
|
var sdk = new DotNetCoreSdkResolver(_fakeInstallDir).ResolveLatest();
|
||||||
|
Assert.Equal("1.0.1", sdk.Version);
|
||||||
|
Assert.Equal(Path.Combine(_fakeInstallDir, "sdk", "1.0.1"), sdk.BasePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ResolveProjectSdk()
|
||||||
|
{
|
||||||
|
var project = Path.Combine(_fakeInstallDir, "project");
|
||||||
|
Directory.CreateDirectory(project);
|
||||||
|
Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0"));
|
||||||
|
Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-abc-123"));
|
||||||
|
Directory.CreateDirectory(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-xyz-123"));
|
||||||
|
File.WriteAllText(Path.Combine(_fakeInstallDir, "global.json"), @"{
|
||||||
|
""sdk"": {
|
||||||
|
""version"": ""1.0.0-abc-123""
|
||||||
|
}
|
||||||
|
}");
|
||||||
|
var sdk = new DotNetCoreSdkResolver(_fakeInstallDir).ResolveProjectSdk(project);
|
||||||
|
Assert.Equal("1.0.0-abc-123", sdk.Version);
|
||||||
|
Assert.Equal(Path.Combine(_fakeInstallDir, "sdk", "1.0.0-abc-123"), sdk.BasePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Directory.Delete(_fakeInstallDir, recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Extensions.ProjectModel.Internal;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
public class MsBuildFixture
|
||||||
|
{
|
||||||
|
private readonly SemanticVersion _minMsBuildVersion = SemanticVersion.Parse("1.0.0-preview3-00000");
|
||||||
|
|
||||||
|
internal MsBuildContext GetMsBuildContext()
|
||||||
|
{
|
||||||
|
// for CI
|
||||||
|
var sdk = DotNetCoreSdkResolver.DefaultResolver.ResolveLatest();
|
||||||
|
|
||||||
|
// for dev work in VS
|
||||||
|
if (SemanticVersion.Parse(sdk.Version) < _minMsBuildVersion)
|
||||||
|
{
|
||||||
|
var home = Environment.GetEnvironmentVariable("USERPROFILE")
|
||||||
|
?? Environment.GetEnvironmentVariable("HOME");
|
||||||
|
var dotnetHome = Path.Combine(home, ".dotnet");
|
||||||
|
var resovler = new DotNetCoreSdkResolver(dotnetHome);
|
||||||
|
sdk = resovler.ResolveLatest();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SemanticVersion.Parse(sdk.Version) < _minMsBuildVersion)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Version of .NET Core SDK found in '{sdk.BasePath}' is not new enough for these tests.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return MsBuildContext.FromDotNetSdk(sdk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
public class MsBuildProjectContextBuilderTest : IClassFixture<MsBuildFixture>
|
||||||
|
{
|
||||||
|
private const string SkipReason = "CI doesn't yet have a new enough version of .NET Core SDK";
|
||||||
|
|
||||||
|
private readonly MsBuildFixture _fixture;
|
||||||
|
|
||||||
|
public MsBuildProjectContextBuilderTest(MsBuildFixture fixture)
|
||||||
|
{
|
||||||
|
_fixture = fixture;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(Skip = SkipReason)]
|
||||||
|
public void ExecutesDesignTimeBuild()
|
||||||
|
{
|
||||||
|
using (var fileProvider = new TemporaryFileProvider())
|
||||||
|
{
|
||||||
|
// TODO When .NET Core SDK is available, detect and add to this test project
|
||||||
|
// fileProvider.Add("test.nuget.targets", "Import .NET Core SDK here");
|
||||||
|
fileProvider.Add("test.csproj", @"
|
||||||
|
<Project ToolsVersion=""14.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
|
||||||
|
<Import Project=""$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<RootNamespace>Microsoft.TestProject</RootNamespace>
|
||||||
|
<ProjectName>TestProject</ProjectName>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<TargetFrameworkIdentifier>.NETCoreApp</TargetFrameworkIdentifier>
|
||||||
|
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include=""**\*.cs"" Exclude=""Excluded.cs"" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Import Project=""$(MSBuildToolsPath)\Microsoft.CSharp.targets"" />
|
||||||
|
</Project>
|
||||||
|
");
|
||||||
|
fileProvider.Add("One.cs", "public class Abc {}");
|
||||||
|
fileProvider.Add("Two.cs", "public class Abc2 {}");
|
||||||
|
fileProvider.Add("Excluded.cs", "public class Abc {}");
|
||||||
|
|
||||||
|
var testContext = _fixture.GetMsBuildContext();
|
||||||
|
|
||||||
|
var expectedCompileItems = new[] { "One.cs", "Two.cs" }.Select(p => Path.Combine(fileProvider.Root, p)).ToArray();
|
||||||
|
var builder = new MsBuildProjectContextBuilder()
|
||||||
|
.WithMsBuild(testContext)
|
||||||
|
.WithDesignTimeBuild()
|
||||||
|
// In latest version of MSBuild, setting this property causes evaluation errors when SDK is not available
|
||||||
|
//.WithConfiguration("Debug")
|
||||||
|
.WithProjectFile(fileProvider.GetFileInfo("test.csproj"));
|
||||||
|
|
||||||
|
// TODO remove ignoreBuildErrors flag
|
||||||
|
// this always throws because Microsoft.NETCore.SDK is not available.
|
||||||
|
var context = builder.Build(ignoreBuildErrors: true);
|
||||||
|
|
||||||
|
Assert.False(fileProvider.GetFileInfo("bin").Exists);
|
||||||
|
Assert.False(fileProvider.GetFileInfo("obj").Exists);
|
||||||
|
Assert.Equal(expectedCompileItems, context.CompilationItems.OrderBy(i => i).ToArray());
|
||||||
|
Assert.Equal(Path.Combine(fileProvider.Root, "bin", "Debug", "test.dll"), context.AssemblyFullPath);
|
||||||
|
Assert.True(context.IsClassLibrary);
|
||||||
|
Assert.Equal("TestProject", context.ProjectName);
|
||||||
|
Assert.Equal(FrameworkConstants.CommonFrameworks.NetCoreApp10, context.TargetFramework);
|
||||||
|
Assert.Equal("Microsoft.TestProject", context.RootNamespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
internal class TemporaryFileProvider : PhysicalFileProvider
|
||||||
|
{
|
||||||
|
public TemporaryFileProvider()
|
||||||
|
:base(Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "tmpfiles", Guid.NewGuid().ToString())).FullName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(string filename, string contents)
|
||||||
|
{
|
||||||
|
File.WriteAllText(Path.Combine(this.Root, filename), contents, Encoding.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void Dispose()
|
||||||
|
{
|
||||||
|
base.Dispose();
|
||||||
|
Directory.Delete(Root, recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"buildOptions": {
|
||||||
|
"warningsAsErrors": true,
|
||||||
|
"keyFile": "../../tools/Key.snk"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"NuGet.Frameworks": "3.5.0-*",
|
||||||
|
"Microsoft.DotNet.Cli.Utils": "1.0.0-*",
|
||||||
|
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||||
|
"Microsoft.Build.Runtime": "15.1.298-preview5",
|
||||||
|
"Microsoft.Extensions.FileProviders.Physical": "1.1.0-*",
|
||||||
|
"Microsoft.Extensions.ProjectModel.Sources": {
|
||||||
|
"type": "build",
|
||||||
|
"version": "1.0.0-*"
|
||||||
|
},
|
||||||
|
"System.Runtime.InteropServices.RuntimeInformation": "4.0.0",
|
||||||
|
"dotnet-test-xunit": "2.2.0-*",
|
||||||
|
"xunit": "2.2.0-*"
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"netcoreapp1.0": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.NETCore.App": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "platform"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"testRunner": "xunit"
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue