Call into project in .NET SDK to create deps.json files for tools instead of doing so directly

This commit is contained in:
Daniel Plaisted 2017-04-18 18:48:53 -07:00
parent c8a6b7b97a
commit fa51bb43fc
13 changed files with 337 additions and 195 deletions

View file

@ -8,22 +8,14 @@ namespace Microsoft.DotNet.Cli.Utils
{ {
public interface IPackagedCommandSpecFactory public interface IPackagedCommandSpecFactory
{ {
CommandSpec CreateCommandSpecFromLibrary( // Code review TODO: Is it OK to make breaking changes to the CLI Utils API surface?
LockFileTargetLibrary toolLibrary,
string commandName,
IEnumerable<string> commandArguments,
IEnumerable<string> allowedExtensions,
string nugetPackagesRoot,
CommandResolutionStrategy commandResolutionStrategy,
string depsFilePath,
string runtimeConfigPath);
CommandSpec CreateCommandSpecFromLibrary( CommandSpec CreateCommandSpecFromLibrary(
LockFileTargetLibrary toolLibrary, LockFileTargetLibrary toolLibrary,
string commandName, string commandName,
IEnumerable<string> commandArguments, IEnumerable<string> commandArguments,
IEnumerable<string> allowedExtensions, IEnumerable<string> allowedExtensions,
IEnumerable<string> packageFolders, LockFile lockFile,
CommandResolutionStrategy commandResolutionStrategy, CommandResolutionStrategy commandResolutionStrategy,
string depsFilePath, string depsFilePath,
string runtimeConfigPath); string runtimeConfigPath);

View file

@ -26,5 +26,7 @@ namespace Microsoft.DotNet.Cli.Utils
NuGetFramework DotnetCliToolTargetFramework { get; } NuGetFramework DotnetCliToolTargetFramework { get; }
Dictionary<string, string> EnvironmentVariables { get; } Dictionary<string, string> EnvironmentVariables { get; }
string ToolDepsJsonGeneratorProject { get; }
} }
} }

View file

@ -92,6 +92,19 @@ namespace Microsoft.DotNet.Cli.Utils
} }
} }
public string ToolDepsJsonGeneratorProject
{
get
{
var generatorProject = _project
.AllEvaluatedProperties
.FirstOrDefault(p => p.Name.Equals("ToolDepsJsonGeneratorProject"))
?.EvaluatedValue;
return generatorProject;
}
}
public MSBuildProject( public MSBuildProject(
string msBuildProjectPath, string msBuildProjectPath,
NuGetFramework framework, NuGetFramework framework,

View file

@ -27,28 +27,7 @@ namespace Microsoft.DotNet.Cli.Utils
string commandName, string commandName,
IEnumerable<string> commandArguments, IEnumerable<string> commandArguments,
IEnumerable<string> allowedExtensions, IEnumerable<string> allowedExtensions,
string nugetPackagesRoot, LockFile lockFile,
CommandResolutionStrategy commandResolutionStrategy,
string depsFilePath,
string runtimeConfigPath)
{
return CreateCommandSpecFromLibrary(
toolLibrary,
commandName,
commandArguments,
allowedExtensions,
new List<string> { nugetPackagesRoot },
commandResolutionStrategy,
depsFilePath,
runtimeConfigPath);
}
public CommandSpec CreateCommandSpecFromLibrary(
LockFileTargetLibrary toolLibrary,
string commandName,
IEnumerable<string> commandArguments,
IEnumerable<string> allowedExtensions,
IEnumerable<string> packageFolders,
CommandResolutionStrategy commandResolutionStrategy, CommandResolutionStrategy commandResolutionStrategy,
string depsFilePath, string depsFilePath,
string runtimeConfigPath) string runtimeConfigPath)
@ -72,7 +51,7 @@ namespace Microsoft.DotNet.Cli.Utils
return null; return null;
} }
var commandPath = GetCommandFilePath(packageFolders, toolLibrary, toolAssembly); var commandPath = GetCommandFilePath(lockFile, toolLibrary, toolAssembly);
if (!File.Exists(commandPath)) if (!File.Exists(commandPath))
{ {
@ -89,21 +68,16 @@ namespace Microsoft.DotNet.Cli.Utils
commandArguments, commandArguments,
depsFilePath, depsFilePath,
commandResolutionStrategy, commandResolutionStrategy,
packageFolders, lockFile.GetNormalizedPackageFolders(),
runtimeConfigPath); runtimeConfigPath);
} }
private string GetCommandFilePath( private string GetCommandFilePath(
IEnumerable<string> packageFolders, LockFile lockFile,
LockFileTargetLibrary toolLibrary, LockFileTargetLibrary toolLibrary,
LockFileItem runtimeAssembly) LockFileItem runtimeAssembly)
{ {
var packageFoldersCount = packageFolders.Count(); var packageDirectory = lockFile.GetPackageDirectory(toolLibrary);
var userPackageFolder = packageFoldersCount == 1 ? string.Empty : packageFolders.First();
var fallbackPackageFolders = packageFoldersCount > 1 ? packageFolders.Skip(1) : packageFolders;
var packageDirectory = new FallbackPackagePathResolver(userPackageFolder, fallbackPackageFolders)
.GetPackageDirectory(toolLibrary.Name, toolLibrary.Version);
if (packageDirectory == null) if (packageDirectory == null)
{ {

View file

@ -120,15 +120,13 @@ namespace Microsoft.DotNet.Cli.Utils
var lockFile = project.GetLockFile(); var lockFile = project.GetLockFile();
var toolLibrary = GetToolLibraryForContext(lockFile, commandName, framework); var toolLibrary = GetToolLibraryForContext(lockFile, commandName, framework);
var normalizedNugetPackagesRoot =
PathUtility.EnsureNoTrailingDirectorySeparator(lockFile.PackageFolders.First().Path);
var commandSpec = _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( var commandSpec = _packagedCommandSpecFactory.CreateCommandSpecFromLibrary(
toolLibrary, toolLibrary,
commandName, commandName,
commandArguments, commandArguments,
allowedExtensions, allowedExtensions,
normalizedNugetPackagesRoot, lockFile,
s_commandResolutionStrategy, s_commandResolutionStrategy,
depsFilePath, depsFilePath,
runtimeConfigPath); runtimeConfigPath);

View file

@ -170,10 +170,8 @@ namespace Microsoft.DotNet.Cli.Utils
toolLibraryRange, toolLibraryRange,
toolPackageFramework, toolPackageFramework,
toolLockFile, toolLockFile,
depsFileRoot); depsFileRoot,
project.ToolDepsJsonGeneratorProject);
var packageFolders = toolLockFile.PackageFolders.Select(p =>
PathUtility.EnsureNoTrailingDirectorySeparator(p.Path));
Reporter.Verbose.WriteLine(string.Format( Reporter.Verbose.WriteLine(string.Format(
LocalizableStrings.AttemptingToCreateCommandSpec, LocalizableStrings.AttemptingToCreateCommandSpec,
@ -184,7 +182,7 @@ namespace Microsoft.DotNet.Cli.Utils
commandName, commandName,
args, args,
_allowedCommandExtensions, _allowedCommandExtensions,
packageFolders, toolLockFile,
s_commandResolutionStrategy, s_commandResolutionStrategy,
depsFilePath, depsFilePath,
null); null);
@ -281,7 +279,8 @@ namespace Microsoft.DotNet.Cli.Utils
SingleProjectInfo toolLibrary, SingleProjectInfo toolLibrary,
NuGetFramework framework, NuGetFramework framework,
LockFile toolLockFile, LockFile toolLockFile,
string depsPathRoot) string depsPathRoot,
string toolDepsJsonGeneratorProject)
{ {
var depsJsonPath = Path.Combine( var depsJsonPath = Path.Combine(
depsPathRoot, depsPathRoot,
@ -292,7 +291,7 @@ namespace Microsoft.DotNet.Cli.Utils
ProjectToolsCommandResolverName, ProjectToolsCommandResolverName,
depsJsonPath)); depsJsonPath));
EnsureToolJsonDepsFileExists(toolLockFile, framework, depsJsonPath, toolLibrary); EnsureToolJsonDepsFileExists(toolLockFile, framework, depsJsonPath, toolLibrary, toolDepsJsonGeneratorProject);
return depsJsonPath; return depsJsonPath;
} }
@ -301,11 +300,12 @@ namespace Microsoft.DotNet.Cli.Utils
LockFile toolLockFile, LockFile toolLockFile,
NuGetFramework framework, NuGetFramework framework,
string depsPath, string depsPath,
SingleProjectInfo toolLibrary) SingleProjectInfo toolLibrary,
string toolDepsJsonGeneratorProject)
{ {
if (!File.Exists(depsPath)) if (!File.Exists(depsPath))
{ {
GenerateDepsJsonFile(toolLockFile, framework, depsPath, toolLibrary); GenerateDepsJsonFile(toolLockFile, framework, depsPath, toolLibrary, toolDepsJsonGeneratorProject);
} }
} }
@ -313,7 +313,8 @@ namespace Microsoft.DotNet.Cli.Utils
LockFile toolLockFile, LockFile toolLockFile,
NuGetFramework framework, NuGetFramework framework,
string depsPath, string depsPath,
SingleProjectInfo toolLibrary) SingleProjectInfo toolLibrary,
string toolDepsJsonGeneratorProject)
{ {
Reporter.Verbose.WriteLine(string.Format( Reporter.Verbose.WriteLine(string.Format(
LocalizableStrings.GeneratingDepsJson, LocalizableStrings.GeneratingDepsJson,
@ -323,11 +324,52 @@ namespace Microsoft.DotNet.Cli.Utils
.Build(toolLibrary, null, toolLockFile, framework, null); .Build(toolLibrary, null, toolLockFile, framework, null);
var tempDepsFile = Path.GetTempFileName(); var tempDepsFile = Path.GetTempFileName();
using (var fileStream = File.Open(tempDepsFile, FileMode.Open, FileAccess.Write))
{
var dependencyContextWriter = new DependencyContextWriter();
dependencyContextWriter.Write(dependencyContext, fileStream); var args = new List<string>();
args.Add(toolDepsJsonGeneratorProject);
args.Add($"/p:ProjectAssetsFile=\"{toolLockFile.Path}\"");
args.Add($"/p:ToolName={toolLibrary.Name}");
args.Add($"/p:ProjectDepsFilePath={tempDepsFile}");
// Look for the .props file in the Microsoft.NETCore.App package, until NuGet
// generates .props and .targets files for tool restores (https://github.com/NuGet/Home/issues/5037)
var platformLibrary = toolLockFile.Targets
.FirstOrDefault(t => framework == t.TargetFramework)
?.GetPlatformLibrary();
if (platformLibrary != null)
{
string buildRelativePath = platformLibrary.Build.FirstOrDefault()?.Path;
var platformLibraryPath = toolLockFile.GetPackageDirectory(platformLibrary);
if (platformLibraryPath != null && buildRelativePath != null)
{
// Get rid of "_._" filename
buildRelativePath = Path.GetDirectoryName(buildRelativePath);
string platformLibraryBuildFolderPath = Path.Combine(platformLibraryPath, buildRelativePath);
var platformLibraryPropsFile = Directory.GetFiles(platformLibraryBuildFolderPath, "*.props").FirstOrDefault();
if (platformLibraryPropsFile != null)
{
args.Add($"/p:AdditionalImport={platformLibraryPropsFile}");
}
}
}
// Delete temporary file created by Path.GetTempFileName(), otherwise the GenerateBuildDependencyFile target
// will think the deps file is up-to-date and skip executing
File.Delete(tempDepsFile);
var result = new MSBuildForwardingAppWithoutLogging(args).Execute();
if (result != 0)
{
// TODO: Can / should we show the MSBuild output if there is a failure?
throw new GracefulException(string.Format(LocalizableStrings.UnableToGenerateDepsJson, toolDepsJsonGeneratorProject));
} }
try try

View file

@ -0,0 +1,33 @@
using Microsoft.DotNet.Tools.Common;
using NuGet.Packaging;
using NuGet.ProjectModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Microsoft.DotNet.Cli.Utils
{
static class LockFileExtensions
{
public static string GetPackageDirectory(this LockFile lockFile, LockFileTargetLibrary library)
{
var packageFolders = lockFile.GetNormalizedPackageFolders();
var packageFoldersCount = packageFolders.Count();
var userPackageFolder = packageFoldersCount == 1 ? string.Empty : packageFolders.First();
var fallbackPackageFolders = packageFoldersCount > 1 ? packageFolders.Skip(1) : packageFolders;
var packageDirectory = new FallbackPackagePathResolver(userPackageFolder, fallbackPackageFolders)
.GetPackageDirectory(library.Name, library.Version);
return packageDirectory;
}
public static IEnumerable<string> GetNormalizedPackageFolders(this LockFile lockFile)
{
return lockFile.PackageFolders.Select(p =>
PathUtility.EnsureNoTrailingDirectorySeparator(p.Path));
}
}
}

View file

@ -0,0 +1,108 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.Cli.Utils
{
/// <summary>
/// A class which encapsulates logic needed to forward arguments from the current process to another process
/// invoked with the dotnet.exe host.
/// </summary>
internal class ForwardingAppImplementation
{
private const string s_hostExe = "dotnet";
private readonly string _forwardApplicationPath;
private readonly IEnumerable<string> _argsToForward;
private readonly string _depsFile;
private readonly string _runtimeConfig;
private readonly string _additionalProbingPath;
private Dictionary<string, string> _environmentVariables;
private readonly string[] _allArgs;
public ForwardingAppImplementation(
string forwardApplicationPath,
IEnumerable<string> argsToForward,
string depsFile = null,
string runtimeConfig = null,
string additionalProbingPath = null,
Dictionary<string, string> environmentVariables = null)
{
_forwardApplicationPath = forwardApplicationPath;
_argsToForward = argsToForward;
_depsFile = depsFile;
_runtimeConfig = runtimeConfig;
_additionalProbingPath = additionalProbingPath;
_environmentVariables = environmentVariables;
var allArgs = new List<string>();
allArgs.Add("exec");
if (_depsFile != null)
{
allArgs.Add("--depsfile");
allArgs.Add(_depsFile);
}
if (_runtimeConfig != null)
{
allArgs.Add("--runtimeconfig");
allArgs.Add(_runtimeConfig);
}
if (_additionalProbingPath != null)
{
allArgs.Add("--additionalprobingpath");
allArgs.Add(_additionalProbingPath);
}
allArgs.Add(_forwardApplicationPath);
allArgs.AddRange(_argsToForward);
_allArgs = allArgs.ToArray();
}
public int Execute()
{
return GetProcessStartInfo().Execute();
}
public ProcessStartInfo GetProcessStartInfo()
{
var processInfo = new ProcessStartInfo
{
FileName = GetHostExeName(),
Arguments = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(_allArgs),
UseShellExecute = false
};
if (_environmentVariables != null)
{
foreach (var entry in _environmentVariables)
{
processInfo.Environment[entry.Key] = entry.Value;
}
}
return processInfo;
}
public ForwardingAppImplementation WithEnvironmentVariable(string name, string value)
{
_environmentVariables = _environmentVariables ?? new Dictionary<string, string>();
_environmentVariables.Add(name, value);
return this;
}
private string GetHostExeName()
{
return $"{s_hostExe}{FileNameSuffixes.CurrentPlatform.Exe}";
}
}
}

View file

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Microsoft.DotNet.Cli.Utils
{
internal class MSBuildForwardingAppWithoutLogging
{
private const string MSBuildExeName = "MSBuild.dll";
private const string SdksDirectoryName = "Sdks";
private readonly ForwardingAppImplementation _forwardingApp;
private readonly Dictionary<string, string> _msbuildRequiredEnvironmentVariables =
new Dictionary<string, string>
{
{ "MSBuildExtensionsPath", AppContext.BaseDirectory },
{ "CscToolExe", GetRunCscPath() },
{ "MSBuildSDKsPath", GetMSBuildSDKsPath() }
};
private readonly IEnumerable<string> _msbuildRequiredParameters =
new List<string> { "/m", "/v:m" };
public MSBuildForwardingAppWithoutLogging(IEnumerable<string> argsToForward, string msbuildPath = null)
{
_forwardingApp = new ForwardingAppImplementation(
msbuildPath ?? GetMSBuildExePath(),
_msbuildRequiredParameters.Concat(argsToForward.Select(Escape)),
environmentVariables: _msbuildRequiredEnvironmentVariables);
}
public virtual ProcessStartInfo GetProcessStartInfo()
{
return _forwardingApp
.GetProcessStartInfo();
}
public int Execute()
{
return GetProcessStartInfo().Execute();
}
private static string Escape(string arg) =>
// this is a workaround for https://github.com/Microsoft/msbuild/issues/1622
(arg.StartsWith("/p:RestoreSources=", StringComparison.OrdinalIgnoreCase)) ?
arg.Replace(";", "%3B")
.Replace("://", ":%2F%2F") :
arg;
private static string GetMSBuildExePath()
{
return Path.Combine(
AppContext.BaseDirectory,
MSBuildExeName);
}
private static string GetMSBuildSDKsPath()
{
var envMSBuildSDKsPath = Environment.GetEnvironmentVariable("MSBuildSDKsPath");
if (envMSBuildSDKsPath != null)
{
return envMSBuildSDKsPath;
}
return Path.Combine(
AppContext.BaseDirectory,
SdksDirectoryName);
}
private static string GetRunCscPath()
{
var scriptExtension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".cmd" : ".sh";
return Path.Combine(AppContext.BaseDirectory, "Roslyn", $"RunCsc{scriptExtension}");
}
}
}

View file

@ -4,7 +4,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
namespace Microsoft.DotNet.Cli namespace Microsoft.DotNet.Cli.Utils
{ {
internal static class ProcessStartInfoExtensions internal static class ProcessStartInfoExtensions
{ {

View file

@ -1,28 +1,14 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved. using Microsoft.DotNet.Cli.Utils;
// Licensed under the MIT license. See LICENSE file in the project root for full license information. using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.DotNet.Cli.Utils; using System.Text;
namespace Microsoft.DotNet.Cli namespace Microsoft.DotNet.Cli
{ {
/// <summary>
/// A class which encapsulates logic needed to forward arguments from the current process to another process
/// invoked with the dotnet.exe host.
/// </summary>
public class ForwardingApp public class ForwardingApp
{ {
private const string s_hostExe = "dotnet"; ForwardingAppImplementation _implementation;
private readonly string _forwardApplicationPath;
private readonly IEnumerable<string> _argsToForward;
private readonly string _depsFile;
private readonly string _runtimeConfig;
private readonly string _additionalProbingPath;
private Dictionary<string, string> _environmentVariables;
private readonly string[] _allArgs;
public ForwardingApp( public ForwardingApp(
string forwardApplicationPath, string forwardApplicationPath,
@ -32,77 +18,29 @@ namespace Microsoft.DotNet.Cli
string additionalProbingPath = null, string additionalProbingPath = null,
Dictionary<string, string> environmentVariables = null) Dictionary<string, string> environmentVariables = null)
{ {
_forwardApplicationPath = forwardApplicationPath; _implementation = new ForwardingAppImplementation(
_argsToForward = argsToForward; forwardApplicationPath,
_depsFile = depsFile; argsToForward,
_runtimeConfig = runtimeConfig; depsFile,
_additionalProbingPath = additionalProbingPath; runtimeConfig,
_environmentVariables = environmentVariables; additionalProbingPath,
environmentVariables);
var allArgs = new List<string>();
allArgs.Add("exec");
if (_depsFile != null)
{
allArgs.Add("--depsfile");
allArgs.Add(_depsFile);
}
if (_runtimeConfig != null)
{
allArgs.Add("--runtimeconfig");
allArgs.Add(_runtimeConfig);
}
if (_additionalProbingPath != null)
{
allArgs.Add("--additionalprobingpath");
allArgs.Add(_additionalProbingPath);
}
allArgs.Add(_forwardApplicationPath);
allArgs.AddRange(_argsToForward);
_allArgs = allArgs.ToArray();
}
public int Execute()
{
return GetProcessStartInfo().Execute();
} }
public ProcessStartInfo GetProcessStartInfo() public ProcessStartInfo GetProcessStartInfo()
{ {
var processInfo = new ProcessStartInfo return _implementation.GetProcessStartInfo();
{
FileName = GetHostExeName(),
Arguments = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(_allArgs),
UseShellExecute = false
};
if (_environmentVariables != null)
{
foreach (var entry in _environmentVariables)
{
processInfo.Environment[entry.Key] = entry.Value;
}
}
return processInfo;
} }
public ForwardingApp WithEnvironmentVariable(string name, string value) public ForwardingApp WithEnvironmentVariable(string name, string value)
{ {
_environmentVariables = _environmentVariables ?? new Dictionary<string, string>(); _implementation = _implementation.WithEnvironmentVariable(name, value);
_environmentVariables.Add(name, value);
return this; return this;
} }
private string GetHostExeName() public int Execute()
{ {
return $"{s_hostExe}{FileNameSuffixes.CurrentPlatform.Exe}"; return _implementation.Execute();
} }
} }
} }

View file

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.Tools namespace Microsoft.DotNet.Tools
{ {

View file

@ -10,6 +10,7 @@ using System.Runtime.InteropServices;
using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli.CommandLine;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.Tools.MSBuild namespace Microsoft.DotNet.Tools.MSBuild
{ {
@ -17,24 +18,9 @@ namespace Microsoft.DotNet.Tools.MSBuild
{ {
internal const string TelemetrySessionIdEnvironmentVariableName = "DOTNET_CLI_TELEMETRY_SESSIONID"; internal const string TelemetrySessionIdEnvironmentVariableName = "DOTNET_CLI_TELEMETRY_SESSIONID";
private const string MSBuildExeName = "MSBuild.dll"; private MSBuildForwardingAppWithoutLogging _forwardingAppWithoutLogging;
private const string SdksDirectoryName = "Sdks"; static IEnumerable<string> ConcatTelemetryLogger(IEnumerable<string> argsToForward)
private readonly ForwardingApp _forwardingApp;
private readonly Dictionary<string, string> _msbuildRequiredEnvironmentVariables =
new Dictionary<string, string>
{
{ "MSBuildExtensionsPath", AppContext.BaseDirectory },
{ "CscToolExe", GetRunCscPath() },
{ "MSBuildSDKsPath", GetMSBuildSDKsPath() }
};
private readonly IEnumerable<string> _msbuildRequiredParameters =
new List<string> { "/m", "/v:m" };
public MSBuildForwardingApp(IEnumerable<string> argsToForward, string msbuildPath = null)
{ {
if (Telemetry.CurrentSessionId != null) if (Telemetry.CurrentSessionId != null)
{ {
@ -42,7 +28,7 @@ namespace Microsoft.DotNet.Tools.MSBuild
{ {
Type loggerType = typeof(MSBuildLogger); Type loggerType = typeof(MSBuildLogger);
argsToForward = argsToForward return argsToForward
.Concat(new[] .Concat(new[]
{ {
$"/Logger:{loggerType.FullName},{loggerType.GetTypeInfo().Assembly.Location}" $"/Logger:{loggerType.FullName},{loggerType.GetTypeInfo().Assembly.Location}"
@ -53,57 +39,28 @@ namespace Microsoft.DotNet.Tools.MSBuild
// Exceptions during telemetry shouldn't cause anything else to fail // Exceptions during telemetry shouldn't cause anything else to fail
} }
} }
return argsToForward;
}
_forwardingApp = new ForwardingApp( public MSBuildForwardingApp(IEnumerable<string> argsToForward, string msbuildPath = null)
msbuildPath ?? GetMSBuildExePath(), {
_msbuildRequiredParameters.Concat(argsToForward.Select(Escape)), _forwardingAppWithoutLogging = new MSBuildForwardingAppWithoutLogging(
environmentVariables: _msbuildRequiredEnvironmentVariables); ConcatTelemetryLogger(argsToForward),
msbuildPath);
} }
public ProcessStartInfo GetProcessStartInfo() public ProcessStartInfo GetProcessStartInfo()
{ {
return _forwardingApp var ret = _forwardingAppWithoutLogging.GetProcessStartInfo();
.WithEnvironmentVariable(TelemetrySessionIdEnvironmentVariableName, Telemetry.CurrentSessionId)
.GetProcessStartInfo(); ret.Environment[TelemetrySessionIdEnvironmentVariableName] = Telemetry.CurrentSessionId;
return ret;
} }
public int Execute() public int Execute()
{ {
return GetProcessStartInfo().Execute(); return GetProcessStartInfo().Execute();
} }
private static string Escape(string arg) =>
// this is a workaround for https://github.com/Microsoft/msbuild/issues/1622
(arg.StartsWith("/p:RestoreSources=", StringComparison.OrdinalIgnoreCase)) ?
arg.Replace(";", "%3B")
.Replace("://", ":%2F%2F") :
arg;
private static string GetMSBuildExePath()
{
return Path.Combine(
AppContext.BaseDirectory,
MSBuildExeName);
}
private static string GetMSBuildSDKsPath()
{
var envMSBuildSDKsPath = Environment.GetEnvironmentVariable("MSBuildSDKsPath");
if (envMSBuildSDKsPath != null)
{
return envMSBuildSDKsPath;
}
return Path.Combine(
AppContext.BaseDirectory,
SdksDirectoryName);
}
private static string GetRunCscPath()
{
var scriptExtension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".cmd" : ".sh";
return Path.Combine(AppContext.BaseDirectory, "Roslyn", $"RunCsc{scriptExtension}");
}
} }
} }