diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs b/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs
index 7134320d58e584b2a6016d4f353444121d11e877..ce6583c34651f905cc20d6a9e9b0ea8ffaef2e55 100644
--- a/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs
@@ -1373,7 +1373,7 @@ private void ConfirmModuleAttributePresentAndAddingToAssemblyResultsInSignedOutp
//confirm file does not claim to be signed
Assert.Equal(0, (int)(flags & CorFlags.StrongNameSigned));
- var corlibName = CoreClrShim.IsRunningOnCoreClr ? "netstandard" : "mscorlib";
+ var corlibName = RuntimeUtilities.IsCoreClrRuntime ? "netstandard" : "mscorlib";
EntityHandle token = metadata.Module.GetTypeRef(metadata.Module.GetAssemblyRef(corlibName), "System.Runtime.CompilerServices", "AssemblyAttributesGoHere");
Assert.False(token.IsNil); //could the type ref be located? If not then the attribute's not there.
var attrInfos = metadata.Module.FindTargetAttributes(token, expectedModuleAttr);
diff --git a/src/Compilers/CSharp/csc/csc.csproj b/src/Compilers/CSharp/csc/csc.csproj
index aae3403699da11554a3fb8c734ec6762b0538222..b48d639273a12d3aca928848417775766e51692d 100644
--- a/src/Compilers/CSharp/csc/csc.csproj
+++ b/src/Compilers/CSharp/csc/csc.csproj
@@ -27,6 +27,7 @@
+
BuildClient.cs
diff --git a/src/Compilers/Core/MSBuildTask/ManagedToolTask.cs b/src/Compilers/Core/MSBuildTask/ManagedToolTask.cs
index 24cecfc222abd8cff26b1bd9e96911d8ef96a4a6..9ef17a319d5d62973278c96da2c8d8efbcc20cc7 100644
--- a/src/Compilers/Core/MSBuildTask/ManagedToolTask.cs
+++ b/src/Compilers/Core/MSBuildTask/ManagedToolTask.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. 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.Build.Utilities;
namespace Microsoft.CodeAnalysis.BuildTasks
@@ -17,6 +18,8 @@ public abstract class ManagedToolTask : ToolTask
protected abstract string PathToManagedTool { get; }
+ protected string PathToManagedToolWithoutExtension => Path.ChangeExtension(PathToManagedTool, string.Empty);
+
///
/// Note: "Native" here does not necessarily mean "native binary".
/// "Native" in this context means "native invocation", and running the executable directly.
@@ -31,14 +34,9 @@ public abstract class ManagedToolTask : ToolTask
protected sealed override string GenerateCommandLineCommands()
{
var commandLineArguments = ToolArguments;
- if (IsManagedTool && IsCliHost(out string pathToDotnet))
+ if (IsManagedTool)
{
- var pathToTool = PathToManagedTool;
- if (pathToTool is null)
- {
- Log.LogErrorWithCodeFromResources("General_ToolFileNotFound", ToolName);
- }
- commandLineArguments = PrependFileToArgs(pathToTool, commandLineArguments);
+ (_, commandLineArguments, _) = RuntimeHostInfo.GetProcessInfo(PathToManagedToolWithoutExtension, commandLineArguments);
}
return commandLineArguments;
@@ -51,21 +49,9 @@ protected sealed override string GenerateCommandLineCommands()
///
protected sealed override string GenerateFullPathToTool()
{
- if (IsManagedTool)
- {
- if (IsCliHost(out string pathToDotnet))
- {
- return pathToDotnet;
- }
- else
- {
- return PathToManagedTool;
- }
- }
- else
- {
- return PathToNativeTool;
- }
+ return IsManagedTool
+ ? RuntimeHostInfo.GetProcessInfo(PathToManagedToolWithoutExtension, string.Empty).ProcessFilePath
+ : PathToNativeTool;
}
protected abstract string ToolNameWithoutExtension { get; }
@@ -80,37 +66,6 @@ protected sealed override string GenerateFullPathToTool()
/// as the implementation of IsManagedTool calls this property. See the comment in
/// .
///
- protected sealed override string ToolName => $"{ToolNameWithoutExtension}.{ToolExtension}";
-
- private static string ToolExtension =>
-#if NETCOREAPP2_1
- "dll";
-#elif NET472
- "exe";
-#else
-#error Unrecognized framework
-#endif
-
- private static bool IsCliHost(out string pathToDotnet)
- {
-#if NETCOREAPP2_1
- pathToDotnet = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH");
- return !string.IsNullOrEmpty(pathToDotnet);
-#elif NET472
- pathToDotnet = null;
- return false;
-#else
-#error Unrecognized framework
-#endif
- }
-
- private static string PrependFileToArgs(string pathToTool, string commandLineArgs)
- {
- var builder = new CommandLineBuilderExtension();
- builder.AppendFileNameIfNotNull(pathToTool);
- builder.AppendTextUnquoted(" ");
- builder.AppendTextUnquoted(commandLineArgs);
- return builder.ToString();
- }
+ protected sealed override string ToolName => $"{ToolNameWithoutExtension}.{RuntimeHostInfo.ToolExtension}";
}
}
diff --git a/src/Compilers/Core/MSBuildTask/Microsoft.Build.Tasks.CodeAnalysis.csproj b/src/Compilers/Core/MSBuildTask/Microsoft.Build.Tasks.CodeAnalysis.csproj
index 75946d58471c841d5e2c87df089eb8d8cf77d9f0..1343d67962b68d8fc5d61d83990c3f3fd51ebfcd 100644
--- a/src/Compilers/Core/MSBuildTask/Microsoft.Build.Tasks.CodeAnalysis.csproj
+++ b/src/Compilers/Core/MSBuildTask/Microsoft.Build.Tasks.CodeAnalysis.csproj
@@ -35,19 +35,11 @@
-
- BuildServerConnection.cs
-
-
- CoreClrShim.cs
-
+
+
-
- CommandLineUtilities.cs
-
-
- CompilerOptionParseUtilities.cs
-
+
+
IReadOnlySet.cs
diff --git a/src/Compilers/Core/MSBuildTask/Utilities.cs b/src/Compilers/Core/MSBuildTask/Utilities.cs
index f361a1ede68631509595981d63c38f8d06511f55..52121df8d2d45cdd6d2014a6b64c0ec9c9ed8078 100644
--- a/src/Compilers/Core/MSBuildTask/Utilities.cs
+++ b/src/Compilers/Core/MSBuildTask/Utilities.cs
@@ -191,49 +191,17 @@ internal static string TryGetAssemblyPath(Assembly assembly)
}
///
- /// Try to get the directory this assembly is in. Returns null if assembly
- /// was in the GAC or DLL location can not be retrieved.
+ /// Generate the full path to the tool that is deployed with our build tasks.
///
- public static string GenerateFullPathToTool(string toolName)
+ internal static string GenerateFullPathToTool(string toolName)
{
- string toolLocation = null;
-
var buildTask = typeof(Utilities).GetTypeInfo().Assembly;
- var assemblyPath = TryGetAssemblyPath(buildTask);
-
- if (assemblyPath != null)
- {
- var assemblyDirectory = Path.GetDirectoryName(assemblyPath);
- var desktopToolLocalLocation = Path.Combine(assemblyDirectory, toolName);
- var cliToolLocalLocation = Path.Combine(assemblyDirectory, "bincore", toolName);
-
- if (File.Exists(desktopToolLocalLocation))
- {
- toolLocation = desktopToolLocalLocation;
- }
- else if (File.Exists(cliToolLocalLocation))
- {
- toolLocation = cliToolLocalLocation;
- }
- }
-
- if (toolLocation == null)
- {
- // Roslyn only deploys to the 32Bit folder of MSBuild, so request this path on all architectures.
- var pathToBuildTools = ToolLocationHelper.GetPathToBuildTools(ToolLocationHelper.CurrentToolsVersion, DotNetFrameworkArchitecture.Bitness32);
-
- if (pathToBuildTools != null)
- {
- var toolMSBuildLocation = Path.Combine(pathToBuildTools, MSBuildRoslynFolderName, toolName);
-
- if (File.Exists(toolMSBuildLocation))
- {
- toolLocation = toolMSBuildLocation;
- }
- }
- }
+ var assemblyPath = buildTask.Location;
+ var assemblyDirectory = Path.GetDirectoryName(assemblyPath);
- return toolLocation;
+ return RuntimeHostInfo.IsDesktopRuntime
+ ? Path.Combine(assemblyDirectory, toolName)
+ : Path.Combine(assemblyDirectory, "bincore", toolName);
}
}
}
diff --git a/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj b/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj
index 4438a5ea232bbdc1134dc9242e474c951fb5ac46..535e940b0442acf5484ab57820527f19d16bbe52 100644
--- a/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj
+++ b/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj
@@ -36,7 +36,6 @@
-
DesktopShim.cs
diff --git a/src/Compilers/Server/VBCSCompiler/VBCSCompiler.csproj b/src/Compilers/Server/VBCSCompiler/VBCSCompiler.csproj
index c1dc3a824d91283de72fa1584d150f3181c5afab..51d2cbb235c7ec3224bf59345ef8ff198eddf3b5 100644
--- a/src/Compilers/Server/VBCSCompiler/VBCSCompiler.csproj
+++ b/src/Compilers/Server/VBCSCompiler/VBCSCompiler.csproj
@@ -28,6 +28,7 @@
+
BuildClient.cs
diff --git a/src/Compilers/Server/VBCSCompilerTests/CompilerServerTests.cs b/src/Compilers/Server/VBCSCompilerTests/CompilerServerTests.cs
index 6a2493d856bc29b22ad76d145635c74ff4564e37..32d17693c5bebc0e8ae348b50cd856c57fc15416 100644
--- a/src/Compilers/Server/VBCSCompilerTests/CompilerServerTests.cs
+++ b/src/Compilers/Server/VBCSCompilerTests/CompilerServerTests.cs
@@ -223,7 +223,7 @@ private static DisposableFile GetResultFile(TempDirectory directory, string resu
private static void RunCompilerOutput(TempFile file, string expectedOutput)
{
- if (!CoreClrShim.IsRunningOnCoreClr)
+ if (RuntimeHostInfo.IsDesktopRuntime)
{
var result = ProcessUtilities.Run(file.Path, "", Path.GetDirectoryName(file.Path));
Assert.Equal(expectedOutput.Trim(), result.Output.Trim());
diff --git a/src/Compilers/Shared/BuildClient.cs b/src/Compilers/Shared/BuildClient.cs
index 7280f557f13efdf3798e6ed4ae16ccb76674f055..a278febb5c6d2135466a9dd4f8fc3de7d07ff692 100644
--- a/src/Compilers/Shared/BuildClient.cs
+++ b/src/Compilers/Shared/BuildClient.cs
@@ -14,6 +14,7 @@
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
+using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CommandLine
{
@@ -48,14 +49,9 @@ internal abstract class BuildClient
///
public static string GetSystemSdkDirectory()
{
- if (CoreClrShim.IsRunningOnCoreClr)
- {
- return null;
- }
- else
- {
- return RuntimeEnvironment.GetRuntimeDirectory();
- }
+ return RuntimeHostInfo.IsCoreClrRuntime
+ ? null
+ : RuntimeEnvironment.GetRuntimeDirectory();
}
///
@@ -236,12 +232,12 @@ private static bool UseNativeArguments()
return false;
}
- if (Type.GetType("Mono.Runtime") != null)
+ if (PlatformInformation.IsRunningOnMono)
{
return false;
}
- if (CoreClrShim.IsRunningOnCoreClr)
+ if (RuntimeHostInfo.IsCoreClrRuntime)
{
// The native invoke ends up giving us both CoreRun and the exe file.
// We've decided to ignore backcompat for CoreCLR,
diff --git a/src/Compilers/Shared/BuildServerConnection.cs b/src/Compilers/Shared/BuildServerConnection.cs
index 097c7b3f196ea33cf72a828ff47de972323aa627..40e5f5e6317b932dfec95c514251dac4a41011ef 100644
--- a/src/Compilers/Shared/BuildServerConnection.cs
+++ b/src/Compilers/Shared/BuildServerConnection.cs
@@ -56,9 +56,6 @@ internal BuildPathsAlt(string clientDir, string workingDir, string sdkDir, strin
internal sealed class BuildServerConnection
{
- internal const string ServerNameDesktop = "VBCSCompiler.exe";
- internal const string ServerNameCoreClr = "VBCSCompiler.dll";
-
// Spend up to 1s connecting to existing process (existing processes should be always responsive).
internal const int TimeOutMsExistingProcess = 1000;
@@ -374,30 +371,13 @@ internal static bool IsCompilerServerSupported(string tempPath)
internal static bool TryCreateServerCore(string clientDir, string pipeName)
{
- string expectedPath;
- string processArguments;
-#if NETCOREAPP2_1
- // The server should be in the same directory as the client
- var expectedCompilerPath = Path.Combine(clientDir, ServerNameCoreClr);
- expectedPath = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? "dotnet";
- processArguments = $@"""{expectedCompilerPath}"" ""-pipename:{pipeName}""";
-
- if (!File.Exists(expectedCompilerPath))
- {
- return false;
- }
-#elif NET472
- // The server should be in the same directory as the client
- expectedPath = Path.Combine(clientDir, ServerNameDesktop);
- processArguments = $@"""-pipename:{pipeName}""";
+ var serverPathWithoutExetnsion = Path.Combine(clientDir, "VBCSCompiler");
+ var serverInfo = RuntimeHostInfo.GetProcessInfo(serverPathWithoutExetnsion, $"-pipename:{pipeName}");
- if (!File.Exists(expectedPath))
+ if (!File.Exists(serverInfo.ToolFilePath))
{
return false;
}
-#else
-#error Unrecognized configuration
-#endif
if (PlatformInformation.IsWindows)
{
@@ -415,9 +395,9 @@ internal static bool TryCreateServerCore(string clientDir, string pipeName)
PROCESS_INFORMATION processInfo;
- Log("Attempting to create process '{0}'", expectedPath);
+ Log("Attempting to create process '{0}'", serverInfo.ProcessFilePath);
- var builder = new StringBuilder($@"""{expectedPath}"" {processArguments}");
+ var builder = new StringBuilder($@"""{serverInfo.ProcessFilePath}"" {serverInfo.CommandLineArguments}");
bool success = CreateProcess(
lpApplicationName: null,
@@ -449,8 +429,8 @@ internal static bool TryCreateServerCore(string clientDir, string pipeName)
{
var startInfo = new ProcessStartInfo()
{
- FileName = expectedPath,
- Arguments = processArguments,
+ FileName = serverInfo.ProcessFilePath,
+ Arguments = serverInfo.CommandLineArguments,
UseShellExecute = false,
WorkingDirectory = clientDir,
RedirectStandardInput = true,
diff --git a/src/Compilers/Shared/CoreClrAnalyzerAssemblyLoader.cs b/src/Compilers/Shared/CoreClrAnalyzerAssemblyLoader.cs
index 2ecb0a6922862af2408a75b3d9604649fc158305..ccf3220ee4cbc1f7c0f6841edcacf7b90c3c0205 100644
--- a/src/Compilers/Shared/CoreClrAnalyzerAssemblyLoader.cs
+++ b/src/Compilers/Shared/CoreClrAnalyzerAssemblyLoader.cs
@@ -1,6 +1,6 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-#if NETCOREAPP1_1 || NETCOREAPP2_1
+#if NETCOREAPP2_1
using System.Diagnostics;
using System.Reflection;
diff --git a/src/Compilers/Shared/DesktopBuildClient.cs b/src/Compilers/Shared/DesktopBuildClient.cs
index abb8217643fb820405c76a2692433418925fc397..e2587836d2ec898d2c8a201dd296ef1a370c5260 100644
--- a/src/Compilers/Shared/DesktopBuildClient.cs
+++ b/src/Compilers/Shared/DesktopBuildClient.cs
@@ -29,7 +29,7 @@ internal DesktopBuildClient(RequestLanguage language, CompileFunc compileFunc, I
internal static int Run(IEnumerable arguments, RequestLanguage language, CompileFunc compileFunc, IAnalyzerAssemblyLoader analyzerAssemblyLoader)
{
var sdkDir = GetSystemSdkDirectory();
- if (CoreClrShim.IsRunningOnCoreClr)
+ if (RuntimeHostInfo.IsCoreClrRuntime)
{
// Register encodings for console
// https://github.com/dotnet/roslyn/issues/10785
diff --git a/src/Compilers/Shared/RuntimeHostInfo.cs b/src/Compilers/Shared/RuntimeHostInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0be41945b41bd18d67aef24a9de7a2677cfb880c
--- /dev/null
+++ b/src/Compilers/Shared/RuntimeHostInfo.cs
@@ -0,0 +1,89 @@
+// Copyright (c) Microsoft. 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.Diagnostics;
+using System.IO.Pipes;
+
+namespace Microsoft.CodeAnalysis
+{
+ ///
+ /// This type provides information about the runtime which is hosting application. It must be included in a concrete
+ /// target framework to be used.
+ ///
+ internal static class RuntimeHostInfo
+ {
+ internal static bool IsCoreClrRuntime => !IsDesktopRuntime;
+
+ internal static string ToolExtension => IsCoreClrRuntime ? "dll" : "exe";
+
+ ///
+ /// This gets information about invoking a tool on the current runtime. This will attempt to
+ /// execute a tool as an EXE when on desktop and using dotnet when on CoreClr.
+ ///
+ internal static (string ProcessFilePath, string CommandLineArguments, string ToolFilePath) GetProcessInfo(string toolFilePathWithoutExtension, string commandLineArguments)
+ {
+ Debug.Assert(!toolFilePathWithoutExtension.EndsWith(".dll") && !toolFilePathWithoutExtension.EndsWith(".exe"));
+
+ var toolFilePath = $"{toolFilePathWithoutExtension}.{ToolExtension}";
+ if (IsDotnetHost(out string pathToDotNet))
+ {
+ commandLineArguments = $@"exec ""{toolFilePath}"" {commandLineArguments}";
+ return (pathToDotNet, commandLineArguments, toolFilePath);
+ }
+ else
+ {
+ return (toolFilePath, commandLineArguments, toolFilePath);
+ }
+ }
+
+#if NET472
+ internal static bool IsDesktopRuntime => true;
+
+ internal static bool IsDotnetHost(out string pathToDotnet)
+ {
+ pathToDotnet = null;
+ return false;
+ }
+
+ internal static NamedPipeClientStream CreateNamedPipeClient(string serverName, string pipeName, PipeDirection direction, PipeOptions options) =>
+ new NamedPipeClientStream(serverName, pipeName, direction, options);
+
+#elif NETCOREAPP2_1
+ internal static bool IsDesktopRuntime => false;
+
+ internal static string DotnetHostPathEnvironmentName = "DOTNET_HOST_PATH";
+
+ internal static bool IsDotnetHost(out string pathToDotnet)
+ {
+ pathToDotnet = GetDotnetPathOrDefault();
+ return true;
+ }
+
+ ///
+ /// Get the path to the dotnet executable. This will throw in the case it is not properly setup
+ /// by the environment.
+ ///
+ internal static string GetDotnetPath()
+ {
+ var pathToDotnet = Environment.GetEnvironmentVariable(DotnetHostPathEnvironmentName);
+ if (string.IsNullOrEmpty(pathToDotnet))
+ {
+ throw new InvalidOperationException($"{DotnetHostPathEnvironmentName} is not set");
+ }
+ return pathToDotnet;
+ }
+
+ ///
+ /// Get the path to the dotnet executable. In the case the host did not provide this information
+ /// in the environment this will return simply "dotnet".
+ ///
+ internal static string GetDotnetPathOrDefault()
+ {
+ var pathToDotnet = Environment.GetEnvironmentVariable(DotnetHostPathEnvironmentName);
+ return pathToDotnet ?? "dotnet";
+ }
+#else
+#error Unsupported configuration
+#endif
+ }
+}
diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
index 2dc674cb156392482e16a927efaae4a26580203b..ae2f31e1c55516d08685a25fe17274378431a444 100644
--- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
+++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
@@ -891,7 +891,7 @@ public static SyntaxTree ParseWithRoundTripCheck(string text, CSharpParseOptions
string assemblyName = "",
string sourceFileName = "")
{
- IEnumerable allReferences = CoreClrShim.IsRunningOnCoreClr
+ IEnumerable allReferences = RuntimeUtilities.IsCoreClrRuntime
? TargetFrameworkUtil.NetStandard20References
: TargetFrameworkUtil.Mscorlib461ExtendedReferences.Add(TestReferences.Net461.netstandardRef);
diff --git a/src/Compilers/VisualBasic/vbc/vbc.csproj b/src/Compilers/VisualBasic/vbc/vbc.csproj
index 4811cc462a5ff264f6871c7e4e7b209e17d8d90c..dbfeccd6356a1d178c9f52606aef13ba7c2b22c7 100644
--- a/src/Compilers/VisualBasic/vbc/vbc.csproj
+++ b/src/Compilers/VisualBasic/vbc/vbc.csproj
@@ -26,6 +26,7 @@
+
BuildClient.cs
diff --git a/src/Scripting/Core/Microsoft.CodeAnalysis.Scripting.csproj b/src/Scripting/Core/Microsoft.CodeAnalysis.Scripting.csproj
index 6e95d46a7234eeaadeecb86f4890715af94f64fc..415542e7415ef7e0d5de6870f96cbaa5fa296797 100644
--- a/src/Scripting/Core/Microsoft.CodeAnalysis.Scripting.csproj
+++ b/src/Scripting/Core/Microsoft.CodeAnalysis.Scripting.csproj
@@ -34,6 +34,7 @@
+
Hosting\Resolvers\RelativePathResolver.cs
diff --git a/src/Test/Utilities/Portable/Assert/ConditionalFactAttribute.cs b/src/Test/Utilities/Portable/Assert/ConditionalFactAttribute.cs
index 0ef2f28409fd4fdbf057624472415a9e381d7626..f4bb7d54e8c0213de1747b70140a6870e270ef4f 100644
--- a/src/Test/Utilities/Portable/Assert/ConditionalFactAttribute.cs
+++ b/src/Test/Utilities/Portable/Assert/ConditionalFactAttribute.cs
@@ -137,7 +137,7 @@ public static class ExecutionConditionUtil
{
public static bool IsWindows => Path.DirectorySeparatorChar == '\\';
public static bool IsUnix => !IsWindows;
- public static bool IsDesktop => CoreClrShim.AssemblyLoadContext.Type == null;
+ public static bool IsDesktop => RuntimeUtilities.IsDesktopRuntime;
public static bool IsWindowsDesktop => IsWindows && IsDesktop;
public static bool IsMonoDesktop => Type.GetType("Mono.Runtime") != null;
public static bool IsCoreClr => !IsDesktop;