Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use MSBuild SDK Resolvers #974

Merged
merged 7 commits into from
Oct 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion NuGet.Config
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
<clear />
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
<add key="cli-deps" value="https://dotnet.myget.org/F/cli-deps/api/v3/index.json" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, we actually want to terminate the cli-deps feed, since it was actually built to contain all the packages the CLI depends on, but we have moved away from that approach since then.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this was an old feed from long ago.

<add key="dotnet-cli" value="https://dotnet.myget.org/F/cli-deps/api/v3/index.json" />
</packageSources>
</configuration>
59 changes: 53 additions & 6 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,27 @@ Task("InstallMonoAssets")
Run("chmod", $"+x '{CombinePaths(env.Folders.Mono, "run")}'");
});

void CopyDotNetHostResolver(BuildEnvironment env, string os, string arch, string hostFileName, string targetFolderBase, bool copyToArchSpecificFolder)
{
var source = CombinePaths(
env.Folders.Tools,
$"runtime.{os}-{arch}.Microsoft.NETCore.DotNetHostResolver",
"runtimes",
$"{os}-{arch}",
"native",
hostFileName);

var targetFolder = targetFolderBase;

if (copyToArchSpecificFolder)
{
targetFolder = CombinePaths(targetFolderBase, arch);
DirectoryHelper.ForceCreate(targetFolder);
}

FileHelper.Copy(source, CombinePaths(targetFolder, hostFileName));
}

/// <summary>
/// Create '.msbuild' folder and copy content to it.
/// </summary>
Expand All @@ -227,17 +248,43 @@ Task("CreateMSBuildFolder")
{
DirectoryHelper.ForceCreate(env.Folders.MSBuild);

if (!Platform.Current.IsWindows)
string sdkResolverTFM;

if (Platform.Current.IsWindows)
{
Information("Copying Mono MSBuild runtime...");
DirectoryHelper.Copy(env.Folders.MonoMSBuildRuntime, env.Folders.MSBuild);
Information("Copying MSBuild runtime...");
var msbuildRuntimeFolder = CombinePaths(env.Folders.Tools, "Microsoft.Build.Runtime", "contentFiles", "any", "net46");
DirectoryHelper.Copy(msbuildRuntimeFolder, env.Folders.MSBuild);
sdkResolverTFM = "net46";
}
else
{
Information("Copying MSBuild runtime...");
Information("Copying Mono MSBuild runtime...");
DirectoryHelper.Copy(env.Folders.MonoMSBuildRuntime, env.Folders.MSBuild);
sdkResolverTFM = "netstandard1.5";
}

var msbuildRuntimeFolder = CombinePaths(env.Folders.Tools, "Microsoft.Build.Runtime", "contentFiles", "any", "net46");
DirectoryHelper.Copy(msbuildRuntimeFolder, env.Folders.MSBuild);
// Copy MSBuild SDK Resolver and DotNetHostResolver
Information("Coping MSBuild SDK resolver...");
var sdkResolverFolder = CombinePaths(env.Folders.Tools, "Microsoft.DotNet.MSBuildSdkResolver", "lib", sdkResolverTFM);
var msbuildSdkResolverFolder = CombinePaths(env.Folders.MSBuild, "SdkResolvers", "Microsoft.DotNet.MSBuildSdkResolver");
DirectoryHelper.ForceCreate(msbuildSdkResolverFolder);
FileHelper.Copy(
source: CombinePaths(sdkResolverFolder, "Microsoft.DotNet.MSBuildSdkResolver.dll"),
destination: CombinePaths(msbuildSdkResolverFolder, "Microsoft.DotNet.MSBuildSdkResolver.dll"));

if (Platform.Current.IsWindows)
{
CopyDotNetHostResolver(env, "win", "x86", "hostfxr.dll", msbuildSdkResolverFolder, copyToArchSpecificFolder: true);
CopyDotNetHostResolver(env, "win", "x64", "hostfxr.dll", msbuildSdkResolverFolder, copyToArchSpecificFolder: true);
}
else if (Platform.Current.IsMacOS)
{
CopyDotNetHostResolver(env, "osx", "x64", "libhostfxr.dylib", msbuildSdkResolverFolder, copyToArchSpecificFolder: false);
}
else if (Platform.Current.IsLinux)
{
CopyDotNetHostResolver(env, "linux", "x64", "libhostfxr.so", msbuildSdkResolverFolder, copyToArchSpecificFolder: false);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the lack of linux-x86 no longer an issue for you?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized that it's kind of a non-issue since .NET Core isn't supported on linux-x86 anyway. Since I can't install a .NET Core SDK on linux-x86, I can't see a need to resolve to it on linux-x86. 😄

}

// Copy content of Microsoft.Net.Compilers
Expand Down
12 changes: 6 additions & 6 deletions build.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
"LegacyDotNetVersion": "1.0.0-preview2-1-003177",
"RequiredMonoVersion": "5.2.0.196",
"DownloadURL": "https://omnisharpdownload.blob.core.windows.net/ext",
"MonoRuntimeMacOS": "mono.osx-5.2.0.213.zip",
"MonoRuntimeLinux32": "mono.linux-x86-5.2.0.213.zip",
"MonoRuntimeLinux64": "mono.linux-x86_64-5.2.0.213.zip",
"MonoFramework": "framework-5.2.0.213.zip",
"MonoMSBuildRuntime": "Microsoft.Build.Runtime.Mono-alpha5.zip",
"MonoMSBuildLib": "Microsoft.Build.Lib.Mono-alpha5.zip",
"MonoRuntimeMacOS": "mono.osx-5.2.0.215.zip",
"MonoRuntimeLinux32": "mono.linux-x86-5.2.0.215.zip",
"MonoRuntimeLinux64": "mono.linux-x86_64-5.2.0.215.zip",
"MonoFramework": "framework-5.2.0.215.zip",
"MonoMSBuildRuntime": "Microsoft.Build.Runtime.Mono-alpha6.zip",
"MonoMSBuildLib": "Microsoft.Build.Lib.Mono-alpha6.zip",
"HostProjects": [
"OmniSharp.Stdio",
"OmniSharp.Http"
Expand Down
3 changes: 2 additions & 1 deletion src/OmniSharp.MSBuild/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("OmniSharp.MSBuild.Tests")]
[assembly: InternalsVisibleTo("OmniSharp.MSBuild.Tests")]
[assembly: InternalsVisibleTo("TestUtility")]
44 changes: 40 additions & 4 deletions src/OmniSharp.MSBuild/MSBuildEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,40 @@ public static void Initialize(ILogger logger)
return;
}

LogSummary(logger);
}

internal static void InitializeForTest(ILogger logger)
{
// For tests, we only initialize in standalone mode.

if (s_isInitialized)
{
throw new InvalidOperationException("MSBuild environment is already initialized.");
}

if (TryWithLocalMSBuild(allowMonoPaths: false))
{
s_kind = MSBuildEnvironmentKind.StandAlone;
s_isInitialized = true;
}
else
{
s_kind = MSBuildEnvironmentKind.Unknown;
logger.LogError("MSBuild environment could not be initialized.");
s_isInitialized = false;
}

if (!s_isInitialized)
{
return;
}

LogSummary(logger);
}

private static void LogSummary(ILogger logger)
{
var summary = new StringBuilder();
switch (s_kind)
{
Expand Down Expand Up @@ -295,7 +329,7 @@ private static bool TrySetRoslynTargetsPathAndCscTool()
return false;
}

private static bool TryWithLocalMSBuild()
private static bool TryWithLocalMSBuild(bool allowMonoPaths = true)
{
var msbuildDirectory = FindMSBuildDirectory();
if (msbuildDirectory == null)
Expand All @@ -312,12 +346,14 @@ private static bool TryWithLocalMSBuild()

SetMSBuildExePath(msbuildExePath);

if (!TrySetMSBuildExtensionsPathToXBuild())
s_msbuildExtensionsPath = msbuildDirectory;

if (allowMonoPaths)
{
s_msbuildExtensionsPath = msbuildDirectory;
TrySetMSBuildExtensionsPathToXBuild();
TrySetTargetFrameworkRootPathToXBuildFrameworks();
}

TrySetTargetFrameworkRootPathToXBuildFrameworks();
TrySetRoslynTargetsPathAndCscTool();

return true;
Expand Down
20 changes: 2 additions & 18 deletions src/OmniSharp.MSBuild/MSBuildProjectSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,22 +306,6 @@ private static string FindSolutionFilePath(string rootPath, ILogger logger)
return result.FilePath;
}

private string GetSdksPath(string projectFilePath)
{
var info = _dotNetCli.GetInfo(Path.GetDirectoryName(projectFilePath));

if (info.IsEmpty || string.IsNullOrWhiteSpace(info.BasePath))
{
return null;
}

var result = Path.Combine(info.BasePath, "Sdks");

return Directory.Exists(result)
? result
: null;
}

private ProjectFileInfo LoadProject(string projectFilePath)
{
_logger.LogInformation($"Loading project: {projectFilePath}");
Expand All @@ -331,7 +315,7 @@ private ProjectFileInfo LoadProject(string projectFilePath)

try
{
project = ProjectFileInfo.Create(projectFilePath, _environment.TargetDirectory, GetSdksPath(projectFilePath), _loggerFactory.CreateLogger<ProjectFileInfo>(), _options, diagnostics);
project = ProjectFileInfo.Create(projectFilePath, _environment.TargetDirectory, _loggerFactory.CreateLogger<ProjectFileInfo>(), _options, diagnostics);

if (project == null)
{
Expand All @@ -357,7 +341,7 @@ private void OnProjectChanged(string projectFilePath, bool allowAutoRestore)
if (_projects.TryGetValue(projectFilePath, out var oldProjectFileInfo))
{
var diagnostics = new List<MSBuildDiagnosticsMessage>();
var newProjectFileInfo = oldProjectFileInfo.Reload(_environment.TargetDirectory, GetSdksPath(projectFilePath), _loggerFactory.CreateLogger<ProjectFileInfo>(), _options, diagnostics);
var newProjectFileInfo = oldProjectFileInfo.Reload(_environment.TargetDirectory, _loggerFactory.CreateLogger<ProjectFileInfo>(), _options, diagnostics);

if (newProjectFileInfo != null)
{
Expand Down
94 changes: 37 additions & 57 deletions src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ private ProjectFileInfo(
}

public static ProjectFileInfo Create(
string filePath, string solutionDirectory, string sdksPath, ILogger logger,
string filePath, string solutionDirectory, ILogger logger,
MSBuildOptions options = null, ICollection<MSBuildDiagnosticsMessage> diagnostics = null)
{
if (!File.Exists(filePath))
{
return null;
}

var projectInstance = LoadProject(filePath, solutionDirectory, sdksPath, logger, options, diagnostics, out var targetFrameworks);
var projectInstance = LoadProject(filePath, solutionDirectory, logger, options, diagnostics, out var targetFrameworks);
if (projectInstance == null)
{
return null;
Expand All @@ -90,65 +90,51 @@ public static ProjectFileInfo Create(
}

private static ProjectInstance LoadProject(
string filePath, string solutionDirectory, string sdksPath, ILogger logger,
string filePath, string solutionDirectory, ILogger logger,
MSBuildOptions options, ICollection<MSBuildDiagnosticsMessage> diagnostics, out ImmutableArray<string> targetFrameworks)
{
options = options ?? new MSBuildOptions();

var globalProperties = GetGlobalProperties(options, solutionDirectory, sdksPath, logger);
var globalProperties = GetGlobalProperties(options, solutionDirectory, logger);

const string MSBuildSDKsPath = "MSBuildSDKsPath";
var oldSdksPathValue = Environment.GetEnvironmentVariable(MSBuildSDKsPath);
try
{
if (globalProperties.TryGetValue(MSBuildSDKsPath, out var sdksPathValue))
{
Environment.SetEnvironmentVariable(MSBuildSDKsPath, sdksPathValue);
}

var collection = new ProjectCollection(globalProperties);

var toolsVersion = options.ToolsVersion;
if (string.IsNullOrEmpty(toolsVersion) || Version.TryParse(toolsVersion, out _))
{
toolsVersion = collection.DefaultToolsVersion;
}

toolsVersion = GetLegalToolsetVersion(toolsVersion, collection.Toolsets);
var collection = new ProjectCollection(globalProperties);

// Evaluate the MSBuild project
var project = collection.LoadProject(filePath, toolsVersion);
var toolsVersion = options.ToolsVersion;
if (string.IsNullOrEmpty(toolsVersion) || Version.TryParse(toolsVersion, out _))
{
toolsVersion = collection.DefaultToolsVersion;
}

var targetFramework = project.GetPropertyValue(PropertyNames.TargetFramework);
targetFrameworks = PropertyConverter.SplitList(project.GetPropertyValue(PropertyNames.TargetFrameworks), ';');
toolsVersion = GetLegalToolsetVersion(toolsVersion, collection.Toolsets);

// If the project supports multiple target frameworks and specific framework isn't
// selected, we must pick one before execution. Otherwise, the ResolveReferences
// target might not be available to us.
if (string.IsNullOrWhiteSpace(targetFramework) && targetFrameworks.Length > 0)
{
// For now, we'll just pick the first target framework. Eventually, we'll need to
// do better and potentially allow OmniSharp hosts to select a target framework.
targetFramework = targetFrameworks[0];
project.SetProperty(PropertyNames.TargetFramework, targetFramework);
}
else if (!string.IsNullOrWhiteSpace(targetFramework) && targetFrameworks.Length == 0)
{
targetFrameworks = ImmutableArray.Create(targetFramework);
}
// Evaluate the MSBuild project
var project = collection.LoadProject(filePath, toolsVersion);

var projectInstance = project.CreateProjectInstance();
var buildResult = projectInstance.Build(TargetNames.Compile,
new[] { new MSBuildLogForwarder(logger, diagnostics) });
var targetFramework = project.GetPropertyValue(PropertyNames.TargetFramework);
targetFrameworks = PropertyConverter.SplitList(project.GetPropertyValue(PropertyNames.TargetFrameworks), ';');

return buildResult
? projectInstance
: null;
// If the project supports multiple target frameworks and specific framework isn't
// selected, we must pick one before execution. Otherwise, the ResolveReferences
// target might not be available to us.
if (string.IsNullOrWhiteSpace(targetFramework) && targetFrameworks.Length > 0)
{
// For now, we'll just pick the first target framework. Eventually, we'll need to
// do better and potentially allow OmniSharp hosts to select a target framework.
targetFramework = targetFrameworks[0];
project.SetProperty(PropertyNames.TargetFramework, targetFramework);
}
finally
else if (!string.IsNullOrWhiteSpace(targetFramework) && targetFrameworks.Length == 0)
{
Environment.SetEnvironmentVariable(MSBuildSDKsPath, oldSdksPathValue);
targetFrameworks = ImmutableArray.Create(targetFramework);
}

var projectInstance = project.CreateProjectInstance();
var buildResult = projectInstance.Build(TargetNames.Compile,
new[] { new MSBuildLogForwarder(logger, diagnostics) });

return buildResult
? projectInstance
: null;
}

private static string GetLegalToolsetVersion(string toolsVersion, ICollection<Toolset> toolsets)
Expand Down Expand Up @@ -232,10 +218,10 @@ private static ProjectData CreateProjectData(ProjectInstance projectInstance, Im
}

public ProjectFileInfo Reload(
string solutionDirectory, string sdksPath, ILogger logger,
string solutionDirectory, ILogger logger,
MSBuildOptions options = null, ICollection<MSBuildDiagnosticsMessage> diagnostics = null)
{
var projectInstance = LoadProject(FilePath, solutionDirectory, sdksPath, logger, options, diagnostics, out var targetFrameworks);
var projectInstance = LoadProject(FilePath, solutionDirectory, logger, options, diagnostics, out var targetFrameworks);
if (projectInstance == null)
{
return null;
Expand All @@ -257,7 +243,7 @@ public bool IsUnityProject()
});
}

private static Dictionary<string, string> GetGlobalProperties(MSBuildOptions options, string solutionDirectory, string sdksPath, ILogger logger)
private static Dictionary<string, string> GetGlobalProperties(MSBuildOptions options, string solutionDirectory, ILogger logger)
{
var globalProperties = new Dictionary<string, string>
{
Expand All @@ -278,12 +264,6 @@ private static Dictionary<string, string> GetGlobalProperties(MSBuildOptions opt
userOptionValue: options.MSBuildExtensionsPath,
environmentValue: MSBuildEnvironment.MSBuildExtensionsPath);

globalProperties.AddPropertyIfNeeded(
logger,
PropertyNames.MSBuildSDKsPath,
userOptionValue: options.MSBuildSDKsPath,
environmentValue: sdksPath);

globalProperties.AddPropertyIfNeeded(
logger,
PropertyNames.TargetFrameworkRootPath,
Expand Down
Loading