Decompose Crossgen, remove CleanPublishOutput, replace ExtractArchive with *FileExtractToDirectory (#3927)
* Eliminate CleanPublishOutput * Decompose Crossgen Task * WiP * TarGzFileExtractToDirectory * FixModeFlags --> CHMod Also various eliminations of dead code * Tasks cleanup Move all tasks to .tasks file. There is little value in keepint them in each source file as they are already being used assumptively by files that happen to get executed later. Also eliminating uses of <Exec> for DotNet invocations * Move to BuildTools implementation of TarGzCreateFromDirectory * Eliminate Command.cs and helpers * Remove dead code * Revert TarGz from BuildTools Latest build tools package has not picked up the task, though it is checked in. * Disable ChMod on Windows * Windows bug fix * PR Feedback * Finish changing Chmod caps
This commit is contained in:
parent
ee8a01b8d6
commit
5ebc6a1ceb
50 changed files with 827 additions and 1645 deletions
|
@ -1,206 +0,0 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.DotNet.Cli.Build.Framework
|
||||
{
|
||||
public static class ArgumentEscaper
|
||||
{
|
||||
/// <summary>
|
||||
/// Undo the processing which took place to create string[] args in Main,
|
||||
/// so that the next process will receive the same string[] args
|
||||
///
|
||||
/// See here for more info:
|
||||
/// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
public static string EscapeAndConcatenateArgArrayForProcessStart(IEnumerable<string> args)
|
||||
{
|
||||
return string.Join(" ", EscapeArgArray(args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Undo the processing which took place to create string[] args in Main,
|
||||
/// so that the next process will receive the same string[] args
|
||||
///
|
||||
/// See here for more info:
|
||||
/// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
public static string EscapeAndConcatenateArgArrayForCmdProcessStart(IEnumerable<string> args)
|
||||
{
|
||||
return string.Join(" ", EscapeArgArrayForCmd(args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Undo the processing which took place to create string[] args in Main,
|
||||
/// so that the next process will receive the same string[] args
|
||||
///
|
||||
/// See here for more info:
|
||||
/// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<string> EscapeArgArray(IEnumerable<string> args)
|
||||
{
|
||||
var escapedArgs = new List<string>();
|
||||
|
||||
foreach (var arg in args)
|
||||
{
|
||||
escapedArgs.Add(EscapeArg(arg));
|
||||
}
|
||||
|
||||
return escapedArgs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This prefixes every character with the '^' character to force cmd to
|
||||
/// interpret the argument string literally. An alternative option would
|
||||
/// be to do this only for cmd metacharacters.
|
||||
///
|
||||
/// See here for more info:
|
||||
/// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<string> EscapeArgArrayForCmd(IEnumerable<string> arguments)
|
||||
{
|
||||
var escapedArgs = new List<string>();
|
||||
|
||||
foreach (var arg in arguments)
|
||||
{
|
||||
escapedArgs.Add(EscapeArgForCmd(arg));
|
||||
}
|
||||
|
||||
return escapedArgs;
|
||||
}
|
||||
|
||||
private static string EscapeArg(string arg)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
var quoted = ShouldSurroundWithQuotes(arg);
|
||||
if (quoted) sb.Append("\"");
|
||||
|
||||
for (int i = 0; i < arg.Length; ++i)
|
||||
{
|
||||
var backslashCount = 0;
|
||||
|
||||
// Consume All Backslashes
|
||||
while (i < arg.Length && arg[i] == '\\')
|
||||
{
|
||||
backslashCount++;
|
||||
i++;
|
||||
}
|
||||
|
||||
// Escape any backslashes at the end of the arg
|
||||
// This ensures the outside quote is interpreted as
|
||||
// an argument delimiter
|
||||
if (i == arg.Length)
|
||||
{
|
||||
sb.Append('\\', 2 * backslashCount);
|
||||
}
|
||||
|
||||
// Escape any preceding backslashes and the quote
|
||||
else if (arg[i] == '"')
|
||||
{
|
||||
sb.Append('\\', (2 * backslashCount) + 1);
|
||||
sb.Append('"');
|
||||
}
|
||||
|
||||
// Output any consumed backslashes and the character
|
||||
else
|
||||
{
|
||||
sb.Append('\\', backslashCount);
|
||||
sb.Append(arg[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (quoted) sb.Append("\"");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepare as single argument to
|
||||
/// roundtrip properly through cmd.
|
||||
///
|
||||
/// This prefixes every character with the '^' character to force cmd to
|
||||
/// interpret the argument string literally. An alternative option would
|
||||
/// be to do this only for cmd metacharacters.
|
||||
///
|
||||
/// See here for more info:
|
||||
/// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private static string EscapeArgForCmd(string argument)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
var quoted = ShouldSurroundWithQuotes(argument);
|
||||
|
||||
if (quoted) sb.Append("^\"");
|
||||
|
||||
foreach (var character in argument)
|
||||
{
|
||||
|
||||
if (character == '"')
|
||||
{
|
||||
|
||||
sb.Append('^');
|
||||
sb.Append('"');
|
||||
sb.Append('^');
|
||||
sb.Append(character);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append("^");
|
||||
sb.Append(character);
|
||||
}
|
||||
}
|
||||
|
||||
if (quoted) sb.Append("^\"");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepare as single argument to
|
||||
/// roundtrip properly through cmd.
|
||||
///
|
||||
/// This prefixes every character with the '^' character to force cmd to
|
||||
/// interpret the argument string literally. An alternative option would
|
||||
/// be to do this only for cmd metacharacters.
|
||||
///
|
||||
/// See here for more info:
|
||||
/// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool ShouldSurroundWithQuotes(string argument)
|
||||
{
|
||||
// Don't quote already quoted strings
|
||||
if (argument.StartsWith("\"", StringComparison.Ordinal) &&
|
||||
argument.EndsWith("\"", StringComparison.Ordinal))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only quote if whitespace exists in the string
|
||||
if (argument.Contains(" ") || argument.Contains("\t") || argument.Contains("\n"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.DotNet.Cli.Build.Framework
|
||||
{
|
||||
public static class BuildHelpers
|
||||
{
|
||||
public static int ExecInSilent(string workingDirectory, string command, params string[] args) => ExecInSilent(workingDirectory, command, (IEnumerable<string>)args);
|
||||
public static int ExecInSilent(string workingDirectory, string command, IEnumerable<string> args) => ExecCore(command, args, workingDirectory, silent: true, env: null);
|
||||
|
||||
public static int ExecIn(string workingDirectory, string command, params string[] args) => ExecIn(workingDirectory, command, (IEnumerable<string>)args);
|
||||
public static int ExecIn(string workingDirectory, string command, IEnumerable<string> args) => ExecCore(command, args, workingDirectory, silent: false, env: null);
|
||||
|
||||
public static int ExecSilent(string command, params string[] args) => ExecSilent(command, (IEnumerable<string>)args);
|
||||
public static int ExecSilent(string command, IEnumerable<string> args) => ExecSilent(command, args, env: null);
|
||||
public static int ExecSilent(string command, IEnumerable<string> args, IDictionary<string, string> env) => ExecCore(command, args, workingDirectory: null, silent: true, env: env);
|
||||
|
||||
public static int Exec(string command, params string[] args) => Exec(command, (IEnumerable<string>)args);
|
||||
public static int Exec(string command, IEnumerable<string> args) => ExecCore(command, args, workingDirectory: null, silent: false, env: null);
|
||||
|
||||
public static Command Cmd(string command, params string[] args) => Cmd(command, (IEnumerable<string>)args);
|
||||
public static Command Cmd(string command, IEnumerable<string> args)
|
||||
{
|
||||
return Command.Create(command, args);
|
||||
}
|
||||
|
||||
internal static int ExecCore(string command, IEnumerable<string> args, string workingDirectory, bool silent, IDictionary<string, string> env)
|
||||
{
|
||||
var cmd = Cmd(command, args);
|
||||
if (!string.IsNullOrEmpty(workingDirectory))
|
||||
{
|
||||
cmd.WorkingDirectory(workingDirectory);
|
||||
}
|
||||
|
||||
if (silent)
|
||||
{
|
||||
cmd.CaptureStdErr().CaptureStdOut();
|
||||
}
|
||||
|
||||
var result = cmd.Environment(env).Execute();
|
||||
|
||||
result.EnsureSuccessful();
|
||||
return result.ExitCode;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,331 +0,0 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.DotNet.Cli.Build.Framework
|
||||
{
|
||||
public class Command
|
||||
{
|
||||
private Process _process;
|
||||
|
||||
private StringWriter _stdOutCapture;
|
||||
private StringWriter _stdErrCapture;
|
||||
|
||||
private Action<string> _stdOutForward;
|
||||
private Action<string> _stdErrForward;
|
||||
|
||||
private Action<string> _stdOutHandler;
|
||||
private Action<string> _stdErrHandler;
|
||||
|
||||
private bool _running = false;
|
||||
private bool _quietBuildReporter = false;
|
||||
|
||||
private Command(string executable, string args)
|
||||
{
|
||||
// Set the things we need
|
||||
var psi = new ProcessStartInfo()
|
||||
{
|
||||
FileName = executable,
|
||||
Arguments = args
|
||||
};
|
||||
|
||||
_process = new Process()
|
||||
{
|
||||
StartInfo = psi
|
||||
};
|
||||
}
|
||||
|
||||
public static Command Create(string executable, params string[] args)
|
||||
{
|
||||
return Create(executable, ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args));
|
||||
}
|
||||
|
||||
public static Command Create(string executable, IEnumerable<string> args)
|
||||
{
|
||||
return Create(executable, ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args));
|
||||
}
|
||||
|
||||
public static Command Create(string executable, string args)
|
||||
{
|
||||
ResolveExecutablePath(ref executable, ref args);
|
||||
|
||||
return new Command(executable, args);
|
||||
}
|
||||
|
||||
private static void ResolveExecutablePath(ref string executable, ref string args)
|
||||
{
|
||||
foreach (string suffix in Constants.RunnableSuffixes)
|
||||
{
|
||||
var fullExecutable = Path.GetFullPath(Path.Combine(
|
||||
AppContext.BaseDirectory, executable + suffix));
|
||||
|
||||
if (File.Exists(fullExecutable))
|
||||
{
|
||||
executable = fullExecutable;
|
||||
|
||||
// In priority order we've found the best runnable extension, so break.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// On Windows, we want to avoid using "cmd" if possible (it mangles the colors, and a bunch of other things)
|
||||
// So, do a quick path search to see if we can just directly invoke it
|
||||
var useCmd = ShouldUseCmd(executable);
|
||||
|
||||
if (useCmd)
|
||||
{
|
||||
var comSpec = System.Environment.GetEnvironmentVariable("ComSpec");
|
||||
|
||||
// cmd doesn't like "foo.exe ", so we need to ensure that if
|
||||
// args is empty, we just run "foo.exe"
|
||||
if (!string.IsNullOrEmpty(args))
|
||||
{
|
||||
executable = (executable + " " + args).Replace("\"", "\\\"");
|
||||
}
|
||||
args = $"/C \"{executable}\"";
|
||||
executable = comSpec;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ShouldUseCmd(string executable)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
var extension = Path.GetExtension(executable);
|
||||
if (!string.IsNullOrEmpty(extension))
|
||||
{
|
||||
return !string.Equals(extension, ".exe", StringComparison.Ordinal);
|
||||
}
|
||||
else if (executable.Contains(Path.DirectorySeparatorChar))
|
||||
{
|
||||
// It's a relative path without an extension
|
||||
if (File.Exists(executable + ".exe"))
|
||||
{
|
||||
// It refers to an exe!
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search the path to see if we can find it
|
||||
foreach (var path in System.Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator))
|
||||
{
|
||||
var candidate = Path.Combine(path, executable + ".exe");
|
||||
if (File.Exists(candidate))
|
||||
{
|
||||
// We found an exe!
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It's a non-exe :(
|
||||
return true;
|
||||
}
|
||||
|
||||
// Non-windows never uses cmd
|
||||
return false;
|
||||
}
|
||||
|
||||
public Command Environment(IDictionary<string, string> env)
|
||||
{
|
||||
if (env == null)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
foreach (var item in env)
|
||||
{
|
||||
_process.StartInfo.Environment[item.Key] = item.Value;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Command Environment(string key, string value)
|
||||
{
|
||||
_process.StartInfo.Environment[key] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Command QuietBuildReporter()
|
||||
{
|
||||
_quietBuildReporter = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandResult Execute()
|
||||
{
|
||||
ThrowIfRunning();
|
||||
_running = true;
|
||||
|
||||
if (_process.StartInfo.RedirectStandardOutput)
|
||||
{
|
||||
_process.OutputDataReceived += (sender, args) =>
|
||||
{
|
||||
ProcessData(args.Data, _stdOutCapture, _stdOutForward, _stdOutHandler);
|
||||
};
|
||||
}
|
||||
|
||||
if (_process.StartInfo.RedirectStandardError)
|
||||
{
|
||||
_process.ErrorDataReceived += (sender, args) =>
|
||||
{
|
||||
ProcessData(args.Data, _stdErrCapture, _stdErrForward, _stdErrHandler);
|
||||
};
|
||||
}
|
||||
|
||||
_process.EnableRaisingEvents = true;
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
ReportExecBegin();
|
||||
|
||||
_process.Start();
|
||||
|
||||
if (_process.StartInfo.RedirectStandardOutput)
|
||||
{
|
||||
_process.BeginOutputReadLine();
|
||||
}
|
||||
|
||||
if (_process.StartInfo.RedirectStandardError)
|
||||
{
|
||||
_process.BeginErrorReadLine();
|
||||
}
|
||||
|
||||
_process.WaitForExit();
|
||||
|
||||
var exitCode = _process.ExitCode;
|
||||
|
||||
ReportExecEnd(exitCode);
|
||||
|
||||
return new CommandResult(
|
||||
_process.StartInfo,
|
||||
exitCode,
|
||||
_stdOutCapture?.GetStringBuilder()?.ToString(),
|
||||
_stdErrCapture?.GetStringBuilder()?.ToString());
|
||||
}
|
||||
|
||||
public Command WorkingDirectory(string projectDirectory)
|
||||
{
|
||||
_process.StartInfo.WorkingDirectory = projectDirectory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Command EnvironmentVariable(string name, string value)
|
||||
{
|
||||
_process.StartInfo.Environment[name] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Command CaptureStdOut()
|
||||
{
|
||||
ThrowIfRunning();
|
||||
_process.StartInfo.RedirectStandardOutput = true;
|
||||
_stdOutCapture = new StringWriter();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Command CaptureStdErr()
|
||||
{
|
||||
ThrowIfRunning();
|
||||
_process.StartInfo.RedirectStandardError = true;
|
||||
_stdErrCapture = new StringWriter();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Command OnOutputLine(Action<string> handler)
|
||||
{
|
||||
ThrowIfRunning();
|
||||
_process.StartInfo.RedirectStandardOutput = true;
|
||||
if (_stdOutHandler != null)
|
||||
{
|
||||
throw new InvalidOperationException("Already handling stdout!");
|
||||
}
|
||||
_stdOutHandler = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Command OnErrorLine(Action<string> handler)
|
||||
{
|
||||
ThrowIfRunning();
|
||||
_process.StartInfo.RedirectStandardError = true;
|
||||
if (_stdErrHandler != null)
|
||||
{
|
||||
throw new InvalidOperationException("Already handling stderr!");
|
||||
}
|
||||
_stdErrHandler = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
private string FormatProcessInfo(ProcessStartInfo info, bool includeWorkingDirectory)
|
||||
{
|
||||
string prefix = includeWorkingDirectory ?
|
||||
$"{info.WorkingDirectory}> {info.FileName}" :
|
||||
info.FileName;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(info.Arguments))
|
||||
{
|
||||
return prefix;
|
||||
}
|
||||
|
||||
return prefix + " " + info.Arguments;
|
||||
}
|
||||
|
||||
private void ReportExecBegin()
|
||||
{
|
||||
if (!_quietBuildReporter)
|
||||
{
|
||||
Console.WriteLine($"[> EXEC] {FormatProcessInfo(_process.StartInfo, includeWorkingDirectory: false)}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ReportExecEnd(int exitCode)
|
||||
{
|
||||
if (!_quietBuildReporter)
|
||||
{
|
||||
bool success = exitCode == 0;
|
||||
|
||||
var message = $"{FormatProcessInfo(_process.StartInfo, includeWorkingDirectory: !success)} exited with {exitCode}";
|
||||
|
||||
Console.WriteLine("[< EXEC] {message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ThrowIfRunning([CallerMemberName] string memberName = null)
|
||||
{
|
||||
if (_running)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to invoke {memberName} after the command has been run");
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessData(string data, StringWriter capture, Action<string> forward, Action<string> handler)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (capture != null)
|
||||
{
|
||||
capture.WriteLine(data);
|
||||
}
|
||||
|
||||
if (forward != null)
|
||||
{
|
||||
forward(data);
|
||||
}
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
handler(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
// 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;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.DotNet.Cli.Build.Framework
|
||||
{
|
||||
public struct CommandResult
|
||||
{
|
||||
public static readonly CommandResult Empty = new CommandResult();
|
||||
|
||||
public ProcessStartInfo StartInfo { get; }
|
||||
public int ExitCode { get; }
|
||||
public string StdOut { get; }
|
||||
public string StdErr { get; }
|
||||
|
||||
public CommandResult(ProcessStartInfo startInfo, int exitCode, string stdOut, string stdErr)
|
||||
{
|
||||
StartInfo = startInfo;
|
||||
ExitCode = exitCode;
|
||||
StdOut = stdOut;
|
||||
StdErr = stdErr;
|
||||
}
|
||||
|
||||
public void EnsureSuccessful(bool suppressOutput = false)
|
||||
{
|
||||
if(ExitCode != 0)
|
||||
{
|
||||
StringBuilder message = new StringBuilder($"Command failed with exit code {ExitCode}: {StartInfo.FileName} {StartInfo.Arguments}");
|
||||
|
||||
if (!suppressOutput)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(StdOut))
|
||||
{
|
||||
message.AppendLine($"{Environment.NewLine}Standard Output:{Environment.NewLine}{StdOut}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(StdErr))
|
||||
{
|
||||
message.AppendLine($"{Environment.NewLine}Standard Error:{Environment.NewLine}{StdErr}");
|
||||
}
|
||||
}
|
||||
|
||||
throw new BuildFailureException(message.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,15 +9,5 @@ namespace Microsoft.DotNet.Cli.Build.Framework
|
|||
{
|
||||
//public static readonly string ProjectFileName = "project.json";
|
||||
public static readonly string ExeSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
|
||||
|
||||
// Priority order of runnable suffixes to look for and run
|
||||
public static readonly string[] RunnableSuffixes = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||
? new string[] { ".exe", ".cmd", ".bat" }
|
||||
: new string[] { string.Empty };
|
||||
|
||||
public static readonly string DynamicLibPrefix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "" : "lib";
|
||||
|
||||
public static readonly string DynamicLibSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".dll" :
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? ".dylib" : ".so";
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue