Make runtime resolution more robust

This commit is contained in:
Mikayla Hutchinson 2020-12-03 21:55:14 -05:00
Родитель 34f73d7699
Коммит d1cd9cce4d
2 изменённых файлов: 59 добавлений и 61 удалений

Просмотреть файл

@ -7,6 +7,7 @@
<RepositoryUrl>https://github.com/mono/t4</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageOutputPath>$(MSBuildThisFileDirectory)packages\$(Configuration)</PackageOutputPath>
<LangVersion>9.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="all" />

Просмотреть файл

@ -27,6 +27,8 @@
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
namespace Mono.TextTemplating.CodeCompilation
{
@ -49,30 +51,28 @@ namespace Mono.TextTemplating.CodeCompilation
public string CscPath { get; private set; }
public bool IsValid => Error == null;
public string RefAssembliesDir { get; private set; }
public string RuntimeFacadesDir { get; internal set; }
public static RuntimeInfo GetRuntime ()
{
var monoFx = GetMonoRuntime ();
if (monoFx.IsValid) {
return monoFx;
if (Type.GetType ("Mono.Runtime") != null)
{
return GetMonoRuntime ();
}
var netFx = GetNetFrameworkRuntime ();
if (netFx.IsValid) {
return netFx;
else if (RuntimeInformation.FrameworkDescription.StartsWith (".NET Framework"))
{
return GetNetFrameworkRuntime ();
}
var coreFx = GetDotNetCoreRuntime ();
if (coreFx.IsValid) {
return coreFx;
else
{
return GetDotNetCoreSdk ();
}
return FromError (RuntimeKind.Mono, "Could not find any valid runtime" );
}
public static RuntimeInfo GetMonoRuntime ()
static RuntimeInfo GetMonoRuntime ()
{
if (Type.GetType ("Mono.Runtime") == null) {
return FromError (RuntimeKind.Mono, "Current runtime is not Mono" );
}
var runtimeDir = Path.GetDirectoryName (typeof (int).Assembly.Location);
var runtimeDir = Path.GetDirectoryName (typeof (object).Assembly.Location);
var csc = Path.Combine (runtimeDir, "csc.exe");
if (!File.Exists (csc)) {
return FromError (RuntimeKind.Mono, "Could not find csc in host Mono installation" );
@ -80,52 +80,70 @@ namespace Mono.TextTemplating.CodeCompilation
return new RuntimeInfo (RuntimeKind.Mono) {
CscPath = csc,
RuntimeDir = runtimeDir
RuntimeDir = runtimeDir,
RuntimeFacadesDir = Path.Combine (runtimeDir, "Facades"),
};
}
public static RuntimeInfo GetNetFrameworkRuntime ()
static RuntimeInfo GetNetFrameworkRuntime ()
{
var runtimeDir = Path.GetDirectoryName (typeof (int).Assembly.Location);
var runtimeDir = Path.GetDirectoryName (typeof (object).Assembly.Location);
var csc = Path.Combine (runtimeDir, "csc.exe");
if (!File.Exists (csc)) {
return FromError (RuntimeKind.NetFramework, "Could not find csc in host .NET Framework installation");
}
return new RuntimeInfo (RuntimeKind.NetFramework) {
CscPath = csc,
RuntimeDir = runtimeDir
RuntimeDir = runtimeDir,
RuntimeFacadesDir = runtimeDir,
};
}
static string FindDotNetRoot ()
static bool TryParseVersionIgnoringSuffix(string versionString, out Version version)
{
string dotnetRoot;
bool DotnetRootIsValid () => !string.IsNullOrEmpty (dotnetRoot) && (File.Exists (Path.Combine (dotnetRoot, "dotnet")) || File.Exists (Path.Combine (dotnetRoot, "dotnet.exe")));
var dashIdx = versionString.IndexOf (';');
if (dashIdx > -1) {
versionString = versionString.Substring (0, dashIdx);
}
return Version.TryParse (versionString, out version);
}
string FindInPath (string name) => (Environment.GetEnvironmentVariable ("PATH") ?? "")
.Split (new [] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries)
.Select (p => Path.Combine (p, name))
.FirstOrDefault (File.Exists);
static RuntimeInfo GetDotNetCoreSdk ()
{
static bool DotnetRootIsValid (string root) => !string.IsNullOrEmpty (root) && (File.Exists (Path.Combine (root, "dotnet")) || File.Exists (Path.Combine (root, "dotnet.exe")));
dotnetRoot = Environment.GetEnvironmentVariable ("DOTNET_ROOT");
if (DotnetRootIsValid ()) {
return dotnetRoot;
// this should get us something like /usr/local/share/dotnet/shared/Microsoft.NETCore.App/5.0.0
var runtimeDir = Path.GetDirectoryName (typeof (object).Assembly.Location);
var dotnetRoot = Path.GetDirectoryName (Path.GetDirectoryName (Path.GetDirectoryName (runtimeDir)));
if (!DotnetRootIsValid (dotnetRoot)) {
// this may happen on single file deployments
return FromError (RuntimeKind.NetCore, "Not a valid .NET Core host");
}
// this should get us something like /usr/local/share/dotnet/shared/Microsoft.NETCore.App/2.1.2/System.Runtime.dll
var runtimeDir = Path.GetDirectoryName (typeof (int).Assembly.Location);
dotnetRoot = Path.GetDirectoryName (Path.GetDirectoryName (Path.GetDirectoryName (runtimeDir)));
if (DotnetRootIsValid ()) {
return dotnetRoot;
var hostVersion = Environment.Version;
if (hostVersion.Major < 5)
{
var versionPathComponent = Path.GetFileName (runtimeDir);
if (!TryParseVersionIgnoringSuffix (versionPathComponent, out hostVersion))
{
return FromError (RuntimeKind.NetCore, "Could not determine host runtime version");
}
}
dotnetRoot = Path.GetDirectoryName (FindInPath (Path.DirectorySeparatorChar == '\\' ? "dotnet.exe" : "dotnet"));
if (DotnetRootIsValid ()) {
return dotnetRoot;
string MakeCscPath (string d) => Path.Combine (d, "Roslyn", "bincore", "csc.dll");
var sdkDir = FindHighestVersionedDirectory (Path.Combine (dotnetRoot, "sdk"), d => File.Exists (MakeCscPath (d)));
if (sdkDir == null) {
return FromError (RuntimeKind.NetCore, "Could not find csc.dll in any .NET Core SDK");
}
return null;
// it's ok if this is null, we may be running on an older SDK that didn't support packs
var refAssembliesDir = FindHighestVersionedDirectory (
Path.Combine (dotnetRoot, "packs", "Microsoft.NETCore.App.Ref"),
d => File.Exists (Path.Combine (d, $"net{hostVersion.Major}.{hostVersion.Minor}", "System.Runtime.dll"))
);
return new RuntimeInfo (RuntimeKind.NetCore) { RuntimeDir = runtimeDir, RefAssembliesDir = refAssembliesDir, CscPath = MakeCscPath (sdkDir) };
}
static string FindHighestVersionedDirectory (string parentFolder, Func<string, bool> validate)
@ -143,26 +161,5 @@ namespace Mono.TextTemplating.CodeCompilation
}
return bestMatch;
}
public static RuntimeInfo GetDotNetCoreRuntime ()
{
var dotnetRoot = FindDotNetRoot ();
if (dotnetRoot == null) {
return FromError (RuntimeKind.NetCore, "Could not find .NET Core installation" );
}
string MakeCscPath (string d) => Path.Combine (d, "Roslyn", "bincore", "csc.dll");
var sdkDir = FindHighestVersionedDirectory (Path.Combine (dotnetRoot, "sdk"), d => File.Exists (MakeCscPath (d)));
if (sdkDir == null) {
return FromError (RuntimeKind.NetCore, "Could not find csc.dll in any .NET Core SDK" );
}
var runtimeDir = FindHighestVersionedDirectory (Path.Combine (dotnetRoot, "shared", "Microsoft.NETCore.App"), d => File.Exists (Path.Combine (d, "System.Runtime.dll")));
if (runtimeDir == null) {
return FromError (RuntimeKind.NetCore, "Could not find System.Runtime.dll in any .NET shared runtime" );
}
return new RuntimeInfo (RuntimeKind.NetCore) { RuntimeDir = runtimeDir, CscPath = MakeCscPath (sdkDir) };
}
}
}