2015-11-20 19:00:56 -08:00
|
|
|
|
// 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.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using Microsoft.DotNet.Cli.Utils;
|
2016-04-28 16:30:32 -07:00
|
|
|
|
using Microsoft.DotNet.InternalAbstractions;
|
2015-11-27 16:19:54 -08:00
|
|
|
|
using Microsoft.DotNet.ProjectModel;
|
2015-11-20 19:00:56 -08:00
|
|
|
|
using NuGet.Frameworks;
|
|
|
|
|
|
|
|
|
|
namespace Microsoft.DotNet.Tools.Run
|
|
|
|
|
{
|
2016-01-30 21:47:50 -08:00
|
|
|
|
public partial class RunCommand
|
2015-11-20 19:00:56 -08:00
|
|
|
|
{
|
|
|
|
|
public string Framework = null;
|
|
|
|
|
public string Configuration = null;
|
|
|
|
|
public string Project = null;
|
|
|
|
|
public IReadOnlyList<string> Args = null;
|
|
|
|
|
|
2016-05-12 10:24:57 -05:00
|
|
|
|
private readonly ICommandFactory _commandFactory;
|
|
|
|
|
private ProjectContext _context;
|
|
|
|
|
private List<string> _args;
|
|
|
|
|
private BuildWorkspace _workspace;
|
|
|
|
|
|
2016-04-25 13:53:02 -07:00
|
|
|
|
public static readonly string[] DefaultFrameworks = new[]
|
|
|
|
|
{
|
|
|
|
|
FrameworkConstants.FrameworkIdentifiers.NetCoreApp,
|
|
|
|
|
FrameworkConstants.FrameworkIdentifiers.NetStandardApp,
|
|
|
|
|
};
|
|
|
|
|
|
2016-05-12 10:24:57 -05:00
|
|
|
|
public RunCommand()
|
|
|
|
|
: this(new RunCommandFactory())
|
|
|
|
|
{
|
|
|
|
|
}
|
2016-04-25 13:53:02 -07:00
|
|
|
|
|
2016-05-12 10:24:57 -05:00
|
|
|
|
public RunCommand(ICommandFactory commandFactory)
|
|
|
|
|
{
|
|
|
|
|
_commandFactory = commandFactory;
|
|
|
|
|
}
|
2015-11-20 19:00:56 -08:00
|
|
|
|
|
|
|
|
|
public int Start()
|
|
|
|
|
{
|
2015-11-23 16:31:27 -08:00
|
|
|
|
if (IsInteractive())
|
2015-11-20 19:00:56 -08:00
|
|
|
|
{
|
|
|
|
|
return RunInteractive(Project);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return RunExecutable();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-23 16:31:27 -08:00
|
|
|
|
private bool IsInteractive()
|
2015-11-20 19:00:56 -08:00
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(Project))
|
|
|
|
|
{
|
2015-11-23 16:31:27 -08:00
|
|
|
|
if (File.Exists(Project) && (Path.GetExtension(Project).ToLowerInvariant() == ".csx"))
|
2015-11-20 19:00:56 -08:00
|
|
|
|
{
|
2015-11-23 16:31:27 -08:00
|
|
|
|
return true;
|
2015-11-20 19:00:56 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-11-23 16:31:27 -08:00
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CalculateDefaultsForNonAssigned()
|
|
|
|
|
{
|
2015-11-23 19:58:11 -08:00
|
|
|
|
if (string.IsNullOrWhiteSpace(Project))
|
|
|
|
|
{
|
|
|
|
|
Project = Directory.GetCurrentDirectory();
|
|
|
|
|
}
|
2015-11-20 19:00:56 -08:00
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(Configuration))
|
|
|
|
|
{
|
|
|
|
|
Configuration = Constants.DefaultConfiguration;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-29 15:46:16 -05:00
|
|
|
|
var frameworkContexts = _workspace.GetProjectContextCollection(Project)
|
|
|
|
|
.EnsureValid(Project)
|
|
|
|
|
.FrameworkOnlyContexts;
|
2016-04-22 15:01:56 -07:00
|
|
|
|
|
2016-04-28 16:30:32 -07:00
|
|
|
|
var rids = RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers();
|
2016-02-19 15:12:04 -08:00
|
|
|
|
|
2016-04-25 13:53:02 -07:00
|
|
|
|
ProjectContext frameworkContext;
|
2015-11-20 19:00:56 -08:00
|
|
|
|
if (Framework == null)
|
|
|
|
|
{
|
2016-04-22 15:01:56 -07:00
|
|
|
|
if (frameworkContexts.Count() == 1)
|
2016-02-19 15:12:04 -08:00
|
|
|
|
{
|
2016-04-25 13:53:02 -07:00
|
|
|
|
frameworkContext = frameworkContexts.Single();
|
2016-02-19 15:12:04 -08:00
|
|
|
|
}
|
|
|
|
|
else
|
2016-02-03 10:57:25 -08:00
|
|
|
|
{
|
2016-04-25 13:53:02 -07:00
|
|
|
|
frameworkContext = frameworkContexts.FirstOrDefault(c => DefaultFrameworks.Contains(c.TargetFramework.Framework));
|
2016-02-03 10:57:25 -08:00
|
|
|
|
}
|
2015-11-20 19:00:56 -08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-04-25 13:53:02 -07:00
|
|
|
|
frameworkContext = frameworkContexts.FirstOrDefault(c => Equals(c.TargetFramework, NuGetFramework.Parse(Framework)));
|
2015-11-20 19:00:56 -08:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-25 13:53:02 -07:00
|
|
|
|
if (frameworkContext == null)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidOperationException($"Couldn't find target to run. Possible causes:" + Environment.NewLine +
|
|
|
|
|
"1. No project.lock.json file or restore failed - run `dotnet restore`" + Environment.NewLine +
|
|
|
|
|
Framework == null ?
|
|
|
|
|
$"2. project.lock.json has multiple targets none of which is in default list ({string.Join(", ", DefaultFrameworks)})" :
|
|
|
|
|
$"2. The project does not support the desired framework: {Framework}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_context = _workspace.GetRuntimeContext(frameworkContext, rids);
|
|
|
|
|
|
2015-11-20 19:00:56 -08:00
|
|
|
|
if (Args == null)
|
|
|
|
|
{
|
|
|
|
|
_args = new List<string>();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_args = new List<string>(Args);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int RunExecutable()
|
|
|
|
|
{
|
2016-04-22 15:01:56 -07:00
|
|
|
|
// Set up the workspace
|
2016-05-02 11:32:24 -07:00
|
|
|
|
_workspace = new BuildWorkspace(ProjectReaderSettings.ReadFromEnvironment());
|
2016-04-22 15:01:56 -07:00
|
|
|
|
|
2015-11-23 19:58:11 -08:00
|
|
|
|
CalculateDefaultsForNonAssigned();
|
|
|
|
|
|
2015-11-20 19:00:56 -08:00
|
|
|
|
// Compile to that directory
|
2016-02-03 12:04:09 -08:00
|
|
|
|
var result = Build.BuildCommand.Run(new[]
|
2016-02-04 19:12:02 -08:00
|
|
|
|
{
|
|
|
|
|
$"--framework",
|
|
|
|
|
$"{_context.TargetFramework}",
|
|
|
|
|
$"--configuration",
|
2016-02-03 10:57:25 -08:00
|
|
|
|
Configuration,
|
2016-02-04 19:12:02 -08:00
|
|
|
|
$"{_context.ProjectFile.ProjectDirectory}"
|
2016-05-02 11:32:24 -07:00
|
|
|
|
}, _workspace);
|
2015-11-20 19:00:56 -08:00
|
|
|
|
|
2016-02-03 12:04:09 -08:00
|
|
|
|
if (result != 0)
|
2015-11-20 19:00:56 -08:00
|
|
|
|
{
|
2016-02-03 12:04:09 -08:00
|
|
|
|
return result;
|
2015-11-20 19:00:56 -08:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-07 20:50:44 -07:00
|
|
|
|
List<string> hostArgs = new List<string>();
|
2016-07-26 13:20:23 -05:00
|
|
|
|
if (!_context.TargetFramework.IsDesktop() && _context.LockFile != null)
|
2016-03-31 09:00:25 -07:00
|
|
|
|
{
|
2016-07-26 13:20:23 -05:00
|
|
|
|
// Add Nuget Packages Probing Paths
|
|
|
|
|
const string probingPathArg = "--additionalprobingpath";
|
|
|
|
|
|
|
|
|
|
foreach (var packageFolder in _context.LockFile.PackageFolders)
|
|
|
|
|
{
|
|
|
|
|
hostArgs.Insert(0, packageFolder.Path);
|
|
|
|
|
hostArgs.Insert(0, probingPathArg);
|
|
|
|
|
}
|
2016-03-31 09:00:25 -07:00
|
|
|
|
}
|
2016-03-14 16:34:02 -07:00
|
|
|
|
|
2015-11-20 19:00:56 -08:00
|
|
|
|
// Now launch the output and give it the results
|
2016-03-15 11:50:14 -07:00
|
|
|
|
var outputPaths = _context.GetOutputPaths(Configuration);
|
|
|
|
|
var outputName = outputPaths.RuntimeFiles.Executable;
|
2016-01-26 06:39:13 -08:00
|
|
|
|
|
2015-11-20 19:00:56 -08:00
|
|
|
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
|
|
{
|
|
|
|
|
if (_context.TargetFramework.IsDesktop())
|
|
|
|
|
{
|
|
|
|
|
// Run mono if we're running a desktop target on non windows
|
2016-01-26 06:39:13 -08:00
|
|
|
|
_args.Insert(0, outputName);
|
2015-11-20 19:00:56 -08:00
|
|
|
|
|
|
|
|
|
if (string.Equals(Configuration, "Debug", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
// If we're compiling for the debug configuration then add the --debug flag
|
|
|
|
|
// other options may be passed using the MONO_OPTIONS env var
|
|
|
|
|
_args.Insert(0, "--debug");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outputName = "mono";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-12 10:24:57 -05:00
|
|
|
|
ICommand command;
|
2016-03-15 11:50:14 -07:00
|
|
|
|
if (outputName.EndsWith(FileNameSuffixes.DotNet.DynamicLib, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
// The executable is a ".dll", we need to call it through dotnet.exe
|
2016-03-14 16:34:02 -07:00
|
|
|
|
var muxer = new Muxer();
|
|
|
|
|
|
2016-05-12 10:24:57 -05:00
|
|
|
|
command = _commandFactory.Create(muxer.MuxerPath, Enumerable.Concat(
|
2016-04-07 20:50:44 -07:00
|
|
|
|
Enumerable.Concat(new string[] { "exec" }, hostArgs),
|
|
|
|
|
Enumerable.Concat(new string[] { outputName }, _args)));
|
2016-03-15 11:50:14 -07:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-05-12 10:24:57 -05:00
|
|
|
|
command = _commandFactory.Create(outputName, Enumerable.Concat(hostArgs, _args));
|
2016-03-15 11:50:14 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = command
|
2016-02-03 12:04:09 -08:00
|
|
|
|
.Execute()
|
|
|
|
|
.ExitCode;
|
2015-12-13 22:40:11 -08:00
|
|
|
|
|
2016-02-03 12:04:09 -08:00
|
|
|
|
return result;
|
2015-11-20 19:00:56 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int RunInteractive(string scriptName)
|
|
|
|
|
{
|
2016-03-15 11:50:14 -07:00
|
|
|
|
var command = Command.CreateDotNet($"repl-csi", new[] { scriptName })
|
2015-11-20 19:00:56 -08:00
|
|
|
|
.ForwardStdOut()
|
|
|
|
|
.ForwardStdErr();
|
|
|
|
|
var result = command.Execute();
|
|
|
|
|
return result.ExitCode;
|
|
|
|
|
}
|
2016-05-12 10:24:57 -05:00
|
|
|
|
|
|
|
|
|
private class RunCommandFactory : ICommandFactory
|
|
|
|
|
{
|
|
|
|
|
public ICommand Create(string commandName, IEnumerable<string> args, NuGetFramework framework = null, string configuration = "Debug")
|
|
|
|
|
{
|
|
|
|
|
return Command.Create(commandName, args, framework, configuration);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-11-20 19:00:56 -08:00
|
|
|
|
}
|
|
|
|
|
}
|