-
Notifications
You must be signed in to change notification settings - Fork 90
Add support for Mono #82
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
Changes from all commits
376fa25
3ec1c84
4837872
e51852c
f9b158f
06b5deb
1c5c7bd
c5ba85c
5f95f03
ebe5226
3108a59
e02e0ed
241758e
7883586
f8eb71f
04a7fc1
b84259d
9794b5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
| // Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
|
||
| using System; | ||
radical marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| using System.Collections.Generic; | ||
| using System.ComponentModel; | ||
| using System.Diagnostics; | ||
| using System.IO; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace Microsoft.Build.Locator | ||
| { | ||
| public static partial class MSBuildLocator | ||
| { | ||
| private static readonly string s_monoMSBuildDll_Current_RelativePath = Path.Combine ("lib", "mono", "msbuild", "Current", "bin", "MSBuild.dll"); | ||
| private static readonly string s_monoMSBuildDll_15_0_RelativePath = Path.Combine ("lib", "mono", "msbuild", "15.0", "bin", "MSBuild.dll"); | ||
| private static readonly string s_monoOSXBasePath = "/Library/Frameworks/Mono.framework/Versions"; | ||
|
|
||
| internal static IEnumerable<VisualStudioInstance> GetMonoMSBuildInstances() | ||
| { | ||
| // $prefix/lib/mono/4.5/mscorlib.dll | ||
| var runningMonoFullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(typeof (object).Assembly.Location), "..", "..", "..")); | ||
| if (TryGetValidMonoVersion(runningMonoFullPath, out var version)) | ||
| { | ||
| yield return new VisualStudioInstance("Mono", runningMonoFullPath, version, DiscoveryType.Mono); | ||
| } | ||
|
|
||
| if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) | ||
| { | ||
| // Returning just one instance on !osx, because we cannot determine | ||
| // where other mono installations might be | ||
| yield break; | ||
| } | ||
|
|
||
| foreach(var dirPath in Directory.EnumerateDirectories(s_monoOSXBasePath)) | ||
| { | ||
| if (string.Equals(Path.GetFileName(dirPath), "Current") || // skip the `Current` symlink | ||
| string.Equals(Path.GetFullPath(dirPath), runningMonoFullPath)) // and the running mono version returned above | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| if (TryGetValidMonoVersion(dirPath, out version)) | ||
| { | ||
| yield return new VisualStudioInstance("Mono", dirPath + '/', version, DiscoveryType.Mono); | ||
| } | ||
| } | ||
|
|
||
| bool TryGetValidMonoVersion(string path, out Version ver) | ||
| { | ||
| ver = null; | ||
| if (!File.Exists(Path.Combine(path, s_monoMSBuildDll_Current_RelativePath)) && | ||
radical marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| !File.Exists(Path.Combine(path, s_monoMSBuildDll_15_0_RelativePath))) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| if (TryGetMonoVersionFromMonoBinary(path, out ver) || Version.TryParse(Path.GetFileName(path), out ver)) | ||
| { | ||
| return true; | ||
| } | ||
|
|
||
| // The path has a valid mono, but we can't find the version | ||
| // so, let's return the instance at least but with version 0.0.0 | ||
| ver = new Version(0, 0, 0); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure whether this is better or it's better to not return it. Users could find it separately and register it anyway. @rainersigwald, thoughts?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok to merge? Or are we waiting for this?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to wait for @rainersigwald's signoff. Also, would you mind adding the if-not-mono check discussed here?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added, and fixed a bug introduced in the nuget PR.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is probably ok, let's just listen for feedback. |
||
| return true; | ||
| } | ||
|
|
||
| bool TryGetMonoVersionFromMonoBinary(string monoPrefixPath, out Version ver) | ||
| { | ||
| ver = null; | ||
| try | ||
| { | ||
| using (var p = new Process()) | ||
| { | ||
| p.StartInfo = new ProcessStartInfo | ||
| { | ||
| FileName = Path.Combine(monoPrefixPath, "bin", "mono"), | ||
| Arguments = "--version=number", | ||
| UseShellExecute = false, | ||
| RedirectStandardOutput = true, | ||
| RedirectStandardError = true | ||
| }; | ||
|
|
||
| // Don't pollute caller's console | ||
| p.OutputDataReceived += (s, e) => {}; | ||
| p.ErrorDataReceived += (s, e) => {}; | ||
|
|
||
| p.Start(); | ||
| p.WaitForExit(); | ||
|
|
||
| var stdout_str = p.StandardOutput.ReadToEnd(); | ||
| return Version.TryParse(stdout_str, out ver); | ||
| } | ||
| } | ||
| catch (Win32Exception) | ||
| { } | ||
|
|
||
| return false; | ||
| } | ||
| } | ||
|
|
||
| // Taken from MSBuild/NativeMethodsShared | ||
| private static readonly object IsRunningOnMonoLock = new object(); | ||
|
|
||
| private static bool? _isRunningOnMono; | ||
|
|
||
| /// <summary> | ||
| /// Gets a flag indicating if we are running under MONO | ||
| /// </summary> | ||
| internal static bool IsRunningOnMono | ||
| { | ||
| get | ||
| { | ||
| if (_isRunningOnMono.HasValue) return _isRunningOnMono.Value; | ||
|
|
||
| lock (IsRunningOnMonoLock) | ||
| { | ||
| if (_isRunningOnMono == null) | ||
| { | ||
| // There could be potentially expensive TypeResolve events, so cache IsMono. | ||
| _isRunningOnMono = Type.GetType("Mono.Runtime") != null; | ||
| } | ||
| } | ||
|
|
||
| return _isRunningOnMono.Value; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ | |
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" /> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, this is unfortunate. I told you to do this! But . . . it's really nice that the Locator package has no dependencies so you can use it basically anywhere. Unfortunately, this type wasn't added to .NET Framework until 4.7.1, so this reference is required to call it in a straightforward way, which makes the package slightly less easy to use. I think we can call it via reflection instead to avoid that hard requirement--if the type/method is not available, it's not macOS! |
||
| <PackageReference Include="MicroBuild.Core" Version="0.3.0" PrivateAssets="all" /> | ||
| <Content Include="build\Microsoft.Build.Locator.props"> | ||
| <CopyToOutputDirectory>Never</CopyToOutputDirectory> | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.