Skip to content

Commit

Permalink
Merge pull request #1016 from DustinCampbell/fix-1.26.1-bugs
Browse files Browse the repository at this point in the history
Fix 1.26.1 bugs
  • Loading branch information
DustinCampbell authored Nov 10, 2017
2 parents 22f4fd9 + 23a85ec commit ff36173
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 20 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Changelog
All changes to the project will be documented in this file.

## [1.26.2] - 2017-11-09

* Fixed issue with discovering MSBuild under Mono even when it is missing. ([#1011](https://github.com/OmniSharp/omnisharp-roslyn/issues/1011))
* Fixed issue to not use Visual Studio 2017 MSBuild if it is from VS 2017 RTM. ([#1014](https://github.com/OmniSharp/omnisharp-roslyn/issues/1014))

## [1.26.1] - 2017-11-04

* Fixed issue with locating MSBuild when running OmniSharp on Mono on Windows. (PR: [#1001](https://github.com/OmniSharp/omnisharp-roslyn/pull/1001))
Expand Down
190 changes: 190 additions & 0 deletions src/OmniSharp.Abstractions/Utilities/Platform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
using System;
using System.IO;

namespace OmniSharp.Utilities
{
public enum OperatingSystem
{
Unknown,
Windows,
MacOS,
Linux
}

public enum Architecture
{
Unknown,
x86,
x64
}

public sealed class Platform
{
public static Platform Current { get; } = GetCurrentPlatform();

public OperatingSystem OperatingSystem { get; }
public Architecture Architecture { get; }
public Version Version { get; }
public string LinuxDistributionName { get; }

private Platform(
OperatingSystem os = OperatingSystem.Unknown,
Architecture architecture = Architecture.Unknown,
Version version = null,
string linuxDistributionName = null)
{
OperatingSystem = os;
Architecture = architecture;
Version = version ?? new Version(0, 0);
LinuxDistributionName = linuxDistributionName ?? string.Empty;
}

public override string ToString()
=> !string.IsNullOrEmpty(LinuxDistributionName)
? $"{LinuxDistributionName} {Version} ({Architecture})"
: $"{OperatingSystem} {Version} ({Architecture})";

private static Platform GetCurrentPlatform()
{
var os = OperatingSystem.Unknown;
var architecture = Architecture.Unknown;

// Simple check to see if this is Windows. Note: this check is derived from the fact that the
// System.PlatformID enum has six values (https://msdn.microsoft.com/en-us/library/3a8hyw88.aspx)
//
// * Win32 = 0
// * Win32Windows = 1
// * Win32NT = 2
// * WinCE = 3
// * Unix = 4
// * Xbox = 5
// * MacOSX = 6
//
// Essentially, we check to see if this is one of the "windows" values or Xbox. The other values
// can be a little unreliable, so we'll shell out to 'uname' for Linux and macOS.

var platformId = (int)Environment.OSVersion.Platform;
if (platformId <= 3 || platformId == 5)
{
os = OperatingSystem.Windows;

if (Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") == "x86" &&
Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432") == null)
{
architecture = Architecture.x86;
}
else
{
architecture = Architecture.x64;
}
}
else
{
// If this is not Windows, run 'uname' on Bash to get the OS name and architecture.
var output = RunOnBashAndCaptureOutput("uname", "-s -m");
if (string.IsNullOrEmpty(output))
{
return new Platform();
}

var values = output.Split(' ');
var osName = values[0];
var osArch = values[1];

os = osName.Equals("Darwin", StringComparison.OrdinalIgnoreCase)
? OperatingSystem.MacOS
: OperatingSystem.Linux;

if (osArch.Equals("x86", StringComparison.OrdinalIgnoreCase))
{
architecture = Architecture.x86;
}
else if (osArch.Equals("x86_64", StringComparison.OrdinalIgnoreCase))
{
architecture = Architecture.x64;
}
else
{
architecture = Architecture.Unknown;
}
}

switch (os)
{
case OperatingSystem.Windows:
return new Platform(os, architecture, Environment.OSVersion.Version);
case OperatingSystem.MacOS:
return new Platform(os, architecture, GetMacOSVersion());
case OperatingSystem.Linux:
ReadDistroNameAndVersion(out var distroName, out var version);
return new Platform(os, architecture, version, distroName);

default:
throw new NotSupportedException("Could not detect the current platform.");
}
}

private static Version GetMacOSVersion()
{
var versionText = RunOnBashAndCaptureOutput("sw_vers", "-productVersion");
return ParseVersion(versionText);
}

private static void ReadDistroNameAndVersion(out string distroName, out Version version)
{
// Details: https://www.freedesktop.org/software/systemd/man/os-release.html
var lines = File.ReadAllLines("/etc/os-release");

distroName = null;
version = null;

foreach (var line in lines)
{
var equalsIndex = line.IndexOf('=');
if (equalsIndex >= 0)
{
var key = line.Substring(0, equalsIndex).Trim();
var value = line.Substring(equalsIndex + 1).Trim();
value = value.Trim('"');

if (key == "ID")
{
distroName = value;
}
else if (key == "VERSION_ID")
{
version = ParseVersion(value);
}

if (distroName != null && version != null)
{
break;
}
}
}

if (distroName == null)
{
distroName = "Unknown";
}
}

private static Version ParseVersion(string versionText)
{
if (!versionText.Contains("."))
{
versionText += ".0";
}

if (Version.TryParse(versionText, out var version))
{
return version;
}

return null;
}

private static string RunOnBashAndCaptureOutput(string fileName, string arguments)
=> ProcessHelper.RunAndCaptureOutput("/bin/bash", $"-c '{fileName} {arguments}'");
}
}
52 changes: 41 additions & 11 deletions src/OmniSharp.Host/CompositionHostBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,13 @@ public CompositionHost Build()
var fileSystemWatcher = new ManualFileSystemWatcher();
var metadataHelper = new MetadataHelper(assemblyLoader);

var logger = loggerFactory.CreateLogger<CompositionHostBuilder>();

// We must register an MSBuild instance before composing MEF to ensure that
// our AssemblyResolve event is hooked up first.
var msbuildLocator = _serviceProvider.GetRequiredService<IMSBuildLocator>();
var instances = msbuildLocator.GetInstances();
var instance = instances.FirstOrDefault();
if (instance != null)
{
msbuildLocator.RegisterInstance(instance);
}
else
{
var logger = loggerFactory.CreateLogger<CompositionHostBuilder>();
logger.LogError("Could not locate MSBuild instance to register with OmniSharp");
}

RegisterMSBuildInstance(msbuildLocator, logger);

config = config
.WithProvider(MefValueProvider.From(_serviceProvider))
Expand All @@ -93,6 +86,43 @@ public CompositionHost Build()
return config.CreateContainer();
}

private static void RegisterMSBuildInstance(IMSBuildLocator msbuildLocator, ILogger logger)
{
MSBuildInstance instanceToRegister = null;
var invalidVSFound = false;

foreach (var instance in msbuildLocator.GetInstances())
{
if (instance.IsInvalidVisualStudio())
{
invalidVSFound = true;
}
else
{
instanceToRegister = instance;
break;
}
}


if (instanceToRegister != null)
{
// Did we end up choosing the standalone MSBuild because there was an invalid Visual Studio?
// If so, provide a helpful message to the user.
if (invalidVSFound && instanceToRegister.DiscoveryType == DiscoveryType.StandAlone)
{
logger.LogWarning(@"It looks like you have Visual Studio 2017 RTM installed.
Try updating Visual Studio 2017 to the most recent release to enable better MSBuild support.");
}

msbuildLocator.RegisterInstance(instanceToRegister);
}
else
{
logger.LogError("Could not locate MSBuild instance to register with OmniSharp");
}
}

private static IEnumerable<Type> SafeGetTypes(Assembly a)
{
try
Expand Down
13 changes: 13 additions & 0 deletions src/OmniSharp.Host/MSBuild/Discovery/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace OmniSharp.MSBuild.Discovery
{
internal static class Extensions
{
public static bool IsInvalidVisualStudio(this MSBuildInstance instance)
// MSBuild from Visual Studio 2017 RTM cannot be used.
=> instance.Version.Major == 15
&& instance.Version.Minor == 0
&& (instance.DiscoveryType == DiscoveryType.DeveloperConsole
|| instance.DiscoveryType == DiscoveryType.VisualStudioSetup);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,22 @@ public override ImmutableArray<MSBuildInstance> GetInstances()
return NoInstances;
}

// Look for Microsoft.Build.dll in the tools path. If it isn't there, this is likely a Mono layout on Linux
// where the 'msbuild' package has not been installed.
var microsoftBuildPath = Path.Combine(toolsPath, "Microsoft.Build.dll");
if (!File.Exists(microsoftBuildPath))
{
Logger.LogDebug($"Mono MSBuild could not be used because '{microsoftBuildPath}' does not exist.");

if (Platform.Current.OperatingSystem == Utilities.OperatingSystem.Linux)
{
Logger.LogWarning(@"It looks like you have Mono 5.2.0 or greater installed but MSBuild could not be found.
Try installing MSBuild into Mono (e.g. 'sudo apt-get install msbuild') to enable better MSBuild support.");
}

return NoInstances;
}

var propertyOverrides = ImmutableDictionary.CreateBuilder<string, string>(StringComparer.OrdinalIgnoreCase);

var localMSBuildPath = FindLocalMSBuildDirectory();
Expand Down
6 changes: 4 additions & 2 deletions src/OmniSharp.Http/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
using OmniSharp.Eventing;
using OmniSharp.Http.Middleware;
using OmniSharp.Options;
using OmniSharp.Roslyn;
using OmniSharp.Services;
using OmniSharp.Stdio.Services;
using OmniSharp.Utilities;

namespace OmniSharp.Http
{
Expand Down Expand Up @@ -52,6 +51,7 @@ public void Configure(
{
var workspace = _compositionHost.GetExport<OmniSharpWorkspace>();
var logger = loggerFactory.CreateLogger<Startup>();

loggerFactory.AddConsole((category, level) =>
{
if (HostHelpers.LogFilter(category, level, _environment)) return true;
Expand All @@ -64,6 +64,8 @@ public void Configure(
return false;
});

logger.LogInformation($"Starting OmniSharp on {Platform.Current}");

app.UseRequestLogging();
app.UseExceptionHandler("/error");
app.UseMiddleware<EndpointMiddleware>(_compositionHost);
Expand Down
Loading

0 comments on commit ff36173

Please sign in to comment.