Adding support for seeding the repl with a project context.
This commit is contained in:
parent
8bccd0b93b
commit
adc24fd301
2 changed files with 119 additions and 5 deletions
|
@ -33,5 +33,7 @@ namespace Microsoft.DotNet.Cli.Utils
|
|||
RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "osx.10.10-x64" : "ubuntu.14.04-x64";
|
||||
|
||||
public static readonly string StaticLibSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".lib" : ".a" ;
|
||||
|
||||
public static readonly string ResponseFileSuffix = ".rsp";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,14 @@
|
|||
// 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.IO;
|
||||
using System.Text;
|
||||
using Microsoft.Dnx.Runtime.Common.CommandLine;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.DotNet.ProjectModel;
|
||||
using NuGet.Frameworks;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Repl.Csi
|
||||
{
|
||||
|
@ -19,21 +24,128 @@ namespace Microsoft.DotNet.Tools.Repl.Csi
|
|||
app.FullName = "C# REPL";
|
||||
app.Description = "C# REPL for the .NET platform";
|
||||
app.HelpOption("-h|--help");
|
||||
var script = app.Argument("<SCRIPT>", "The .csx file to run. Defaults to interactive mode.");
|
||||
|
||||
app.OnExecute(() => Run(script.Value));
|
||||
var script = app.Argument("<SCRIPT>", "The .csx file to run. Defaults to interactive mode.");
|
||||
var framework = app.Option("-f|--framework <FRAMEWORK>", "Compile a specific framework", CommandOptionType.MultipleValue);
|
||||
var configuration = app.Option("-c|--configuration <CONFIGURATION>", "Configuration under which to build", CommandOptionType.SingleValue);
|
||||
var preserveTemporary = app.Option("-t|--preserve-temporary", "Keep the output's temporary directory around", CommandOptionType.NoValue);
|
||||
var project = app.Option("-p|--project <PROJECT>", "The path to the project to run. Can be a path to a project.json or a project directory", CommandOptionType.SingleValue);
|
||||
|
||||
app.OnExecute(() => Run(script.Value, framework.Values, (configuration.Value() ?? Constants.DefaultConfiguration), preserveTemporary.HasValue(), project.Value()));
|
||||
return app.Execute(args);
|
||||
}
|
||||
|
||||
private static int Run(string scriptOpt)
|
||||
private static ProjectContext GetProjectContext(IEnumerable<string> targetFrameworks, string projectPath)
|
||||
{
|
||||
var contexts = ProjectContext.CreateContextForEachFramework(projectPath);
|
||||
var context = contexts.First();
|
||||
|
||||
if (targetFrameworks.Any())
|
||||
{
|
||||
var framework = NuGetFramework.Parse(targetFrameworks.First());
|
||||
context = contexts.FirstOrDefault(c => c.TargetFramework.Equals(framework));
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
private static CommandResult CompileProject(ProjectContext projectContext, string configuration, out string tempOutputDir)
|
||||
{
|
||||
tempOutputDir = Path.Combine(projectContext.ProjectDirectory, "bin", ".dotnetrepl", Guid.NewGuid().ToString("N"));
|
||||
|
||||
Reporter.Output.WriteLine($"Compiling {projectContext.RootProject.Identity.Name.Yellow()} for {projectContext.TargetFramework.DotNetFrameworkName.Yellow()} to use with the {"C# REPL".Yellow()} environment.");
|
||||
|
||||
return Command.Create($"dotnet-compile", $"--output \"{tempOutputDir}\" --temp-output \"{tempOutputDir}\" --framework \"{projectContext.TargetFramework}\" --configuration \"{configuration}\" {projectContext.ProjectFile.ProjectDirectory}")
|
||||
.ForwardStdOut(onlyIfVerbose: true)
|
||||
.ForwardStdErr()
|
||||
.Execute();
|
||||
}
|
||||
|
||||
private static List<string> GetRuntimeDependencies(ProjectContext projectContext, string buildConfiguration)
|
||||
{
|
||||
var runtimeDependencies = new List<string>();
|
||||
|
||||
var projectExporter = projectContext.CreateExporter(buildConfiguration);
|
||||
var projectDependencies = projectExporter.GetDependencies();
|
||||
|
||||
foreach (var projectDependency in projectDependencies)
|
||||
{
|
||||
var runtimeAssemblies = projectDependency.RuntimeAssemblies;
|
||||
|
||||
foreach (var runtimeAssembly in runtimeAssemblies)
|
||||
{
|
||||
var runtimeAssemblyPath = runtimeAssembly.ResolvedPath;
|
||||
|
||||
if (!runtimeDependencies.Contains(runtimeAssemblyPath))
|
||||
{
|
||||
runtimeDependencies.Add(runtimeAssemblyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return runtimeDependencies;
|
||||
}
|
||||
|
||||
private static string CreateResponseFile(ProjectContext projectContext, string buildConfiguration, string tempOutputDir)
|
||||
{
|
||||
var outputFileName = projectContext.ProjectFile.Name;
|
||||
var outputFilePath = Path.Combine(tempOutputDir, $"{outputFileName}{Constants.DynamicLibSuffix}");
|
||||
var projectResponseFilePath = Path.Combine(tempOutputDir, $"dotnet-repl.{outputFileName}{Constants.ResponseFileSuffix}");
|
||||
|
||||
var runtimeDependencies = GetRuntimeDependencies(projectContext, buildConfiguration);
|
||||
|
||||
using (var fileStream = new FileStream(projectResponseFilePath, FileMode.Create))
|
||||
{
|
||||
var streamWriter = new StreamWriter(fileStream);
|
||||
|
||||
streamWriter.WriteLine($"/r:\"{outputFilePath}\"");
|
||||
|
||||
foreach (var projectDependency in runtimeDependencies)
|
||||
{
|
||||
streamWriter.WriteLine($"/r:\"{projectDependency}\"");
|
||||
}
|
||||
|
||||
streamWriter.Flush();
|
||||
}
|
||||
|
||||
return projectResponseFilePath;
|
||||
}
|
||||
|
||||
private static int Run(string script, IEnumerable<string> targetFrameworks, string buildConfiguration, bool preserveTemporaryOutput, string projectPath)
|
||||
{
|
||||
var corerun = Path.Combine(AppContext.BaseDirectory, Constants.HostExecutableName);
|
||||
var csiExe = Path.Combine(AppContext.BaseDirectory, "csi.exe");
|
||||
var csiArgs = string.IsNullOrEmpty(scriptOpt) ? "-i" : scriptOpt;
|
||||
var result = Command.Create(csiExe, csiArgs)
|
||||
var csiArgs = new StringBuilder();
|
||||
|
||||
var tempOutputDir = string.Empty;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(projectPath))
|
||||
{
|
||||
var projectContext = GetProjectContext(targetFrameworks, projectPath);
|
||||
|
||||
var compileResult = CompileProject(projectContext, buildConfiguration, out tempOutputDir);
|
||||
|
||||
if (compileResult.ExitCode != 0)
|
||||
{
|
||||
return compileResult.ExitCode;
|
||||
}
|
||||
|
||||
string responseFile = CreateResponseFile(projectContext, buildConfiguration, tempOutputDir);
|
||||
csiArgs.Append($"@\"{responseFile}\" ");
|
||||
}
|
||||
|
||||
csiArgs.Append(string.IsNullOrEmpty(script) ? "-i" : script);
|
||||
|
||||
var result = Command.Create(csiExe, csiArgs.ToString())
|
||||
.ForwardStdOut()
|
||||
.ForwardStdErr()
|
||||
.Execute();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(tempOutputDir) && !preserveTemporaryOutput)
|
||||
{
|
||||
Directory.Delete(tempOutputDir, recursive: true);
|
||||
}
|
||||
|
||||
return result.ExitCode;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue