Call into project in .NET SDK to create deps.json files for tools instead of doing so directly
This commit is contained in:
parent
c8a6b7b97a
commit
fa51bb43fc
13 changed files with 337 additions and 195 deletions
|
@ -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);
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
src/Microsoft.DotNet.Cli.Utils/ForwardingAppImplementation.cs
Normal file
108
src/Microsoft.DotNet.Cli.Utils/ForwardingAppImplementation.cs
Normal 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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue