Skip to content

Commit 130a73e

Browse files
committed
publish and execution of dll now functional
1 parent 2015425 commit 130a73e

File tree

8 files changed

+199
-37
lines changed

8 files changed

+199
-37
lines changed

src/Dotnet.Script.Core/ScriptCompiler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public ScriptCompiler(ScriptLogger logger, RuntimeDependencyResolver runtimeDepe
7171
public virtual ScriptOptions CreateScriptOptions(ScriptContext context, IList<RuntimeDependency> runtimeDependencies)
7272
{
7373
var scriptMap = runtimeDependencies.ToDictionary(rdt => rdt.Name, rdt => rdt.Scripts);
74-
var opts = ScriptOptions.Default.AddImports(ImportedNamespaces)
74+
var opts = ScriptOptions.Default.AddImports(ImportedNamespaces)
7575
.WithSourceResolver(new NuGetSourceReferenceResolver(new SourceFileResolver(ImmutableArray<string>.Empty, context.WorkingDirectory),scriptMap))
7676
.WithMetadataResolver(new NuGetMetadataReferenceResolver(ScriptMetadataResolver.Default.WithBaseDirectory(context.WorkingDirectory)))
7777
.WithEmitDebugInformation(true)
@@ -229,7 +229,7 @@ private string GetScriptCode(ScriptContext context)
229229
return code;
230230
}
231231

232-
private static Dictionary<string, RuntimeAssembly> CreateScriptDependenciesMap(RuntimeDependency[] runtimeDependencies)
232+
public static Dictionary<string, RuntimeAssembly> CreateScriptDependenciesMap(IEnumerable<RuntimeDependency> runtimeDependencies)
233233
{
234234
// Build up a dependency map that picks runtime assembly with the highest version.
235235
// This aligns with the CoreCLR that uses the highest version strategy.

src/Dotnet.Script.Core/ScriptEmitter.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,27 @@ public virtual ScriptEmitResult Emit<TReturn>(ScriptContext context, string asse
2121
try
2222
{
2323
var compilationContext = _scriptCompiler.CreateCompilationContext<TReturn, CommandLineScriptGlobals>(context);
24-
2524
var compilation = compilationContext.Script.GetCompilation();
2625
if (!string.IsNullOrEmpty(assemblyName))
2726
{
28-
var compilationOptions = compilationContext.Script.GetCompilation().Options
27+
var compilationOptions = compilation.Options
2928
.WithScriptClassName(assemblyName);
30-
compilation = compilationContext.Script.GetCompilation()
29+
compilation = compilation
3130
.WithOptions(compilationOptions)
3231
.WithAssemblyName(assemblyName);
3332
}
3433

3534
var peStream = new MemoryStream();
36-
var pdbStream = new MemoryStream();
37-
var result = compilation.Emit(peStream, pdbStream: pdbStream, options: new EmitOptions().
38-
WithDebugInformationFormat(DebugInformationFormat.PortablePdb));
35+
MemoryStream pdbStream = null;
36+
EmitOptions emitOptions = null;
37+
if (context.OptimizationLevel == Microsoft.CodeAnalysis.OptimizationLevel.Debug)
38+
{
39+
emitOptions = new EmitOptions()
40+
.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
41+
pdbStream = new MemoryStream();
42+
}
43+
44+
var result = compilation.Emit(peStream, pdbStream: pdbStream, options: emitOptions);
3945

4046
if (result.Success)
4147
{

src/Dotnet.Script.Core/ScriptPublisher.cs

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,49 @@ public class ScriptPublisher
1919
private readonly ScriptEmitter _scriptEmitter;
2020
private readonly ScriptConsole _scriptConsole;
2121
private readonly ScriptEnvironment _scriptEnvironment;
22+
private readonly ScriptLogger _logger;
2223

23-
public ScriptPublisher(ScriptProjectProvider scriptProjectProvider, ScriptEmitter scriptEmitter, ScriptConsole scriptConsole)
24+
public ScriptPublisher(ScriptProjectProvider scriptProjectProvider, ScriptEmitter scriptEmitter, ScriptConsole scriptConsole,
25+
ScriptLogger scriptLogger)
2426
{
2527
_scriptProjectProvider = scriptProjectProvider ?? throw new ArgumentNullException(nameof(scriptProjectProvider));
2628
_scriptEmitter = scriptEmitter ?? throw new ArgumentNullException(nameof(scriptEmitter));
2729
_scriptConsole = scriptConsole ?? throw new ArgumentNullException(nameof(scriptConsole));
2830
_scriptEnvironment = ScriptEnvironment.Default;
31+
_logger = scriptLogger;
2932
}
3033

31-
public ScriptPublisher(LogFactory logFactory, ScriptEmitter scriptEmitter)
34+
public ScriptPublisher(LogFactory logFactory, ScriptEmitter scriptEmitter, ScriptLogger scriptLogger)
3235
: this
3336
(
3437
new ScriptProjectProvider(logFactory),
3538
scriptEmitter,
36-
ScriptConsole.Default
39+
ScriptConsole.Default,
40+
scriptLogger
3741
)
3842
{
3943
}
4044

45+
public void CreateAssembly(ScriptContext context, LogFactory logFactory)
46+
{
47+
Directory.CreateDirectory(context.WorkingDirectory);
48+
49+
_logger.Verbose("Publishing dll");
50+
CreateScriptAssembly(context, context.WorkingDirectory);
51+
52+
var tempProjectPath = ScriptProjectProvider.GetPathToProjectFile(Path.GetDirectoryName(context.FilePath));
53+
var tempProjectDirecory = Path.GetDirectoryName(tempProjectPath);
54+
var sourceProjectAssetsPath = Path.Combine(tempProjectDirecory, "obj", "project.assets.json");
55+
var destinationProjectAssetsPath = Path.Combine(context.WorkingDirectory, "project.assets.json");
56+
File.Copy(sourceProjectAssetsPath, destinationProjectAssetsPath, overwrite: true);
57+
}
58+
4159
public void CreateExecutable(ScriptContext context, LogFactory logFactory)
4260
{
43-
var tempProjectPath = _scriptProjectProvider.CreateProjectForScriptFile(context.FilePath);
61+
var tempProjectPath = ScriptProjectProvider.GetPathToProjectFile(Path.GetDirectoryName(context.FilePath));
4462
var tempProjectDirecory = Path.GetDirectoryName(tempProjectPath);
4563

46-
var scriptAssemblyPath = CreateScriptAssembly(context, tempProjectDirecory);
64+
var scriptAssemblyPath = CreateScriptAssembly(context, tempProjectDirecory, true);
4765

4866
var projectFile = new ProjectFile(File.ReadAllText(tempProjectPath));
4967
projectFile.AddPackageReference(new PackageReference("Microsoft.CodeAnalysis.Scripting", ScriptingVersion, PackageOrigin.ReferenceDirective));
@@ -56,39 +74,43 @@ public void CreateExecutable(ScriptContext context, LogFactory logFactory)
5674

5775
var commandRunner = new CommandRunner(logFactory);
5876
// todo: may want to add ability to return dotnet.exe errors
77+
_logger.Verbose("Publishing exe");
5978
var exitcode = commandRunner.Execute("dotnet", $"publish \"{tempProjectPath}\" -c Release -r {runtimeIdentifier} -o {context.WorkingDirectory}");
6079
if (exitcode != 0) throw new Exception($"dotnet publish failed with result '{exitcode}'");
6180
}
6281

63-
private string CreateScriptAssembly(ScriptContext context, string tempProjectDirecory)
82+
private string CreateScriptAssembly(ScriptContext context, string outputDirectory, bool useAssemblyName = false)
6483
{
6584
try
6685
{
67-
var emitResult = _scriptEmitter.Emit<int>(context, AssemblyName);
86+
var emitResult = _scriptEmitter.Emit<int>(context, useAssemblyName ? AssemblyName : "");
6887
if (!emitResult.Success)
6988
{
7089
throw new CompilationErrorException("One or more errors occurred when emitting the assembly", emitResult.Diagnostics);
7190
}
7291

73-
var assemblyPath = Path.Combine(tempProjectDirecory, $"{AssemblyName}.dll");
92+
var assemblyPath = Path.Combine(outputDirectory, $"{AssemblyName}.dll");
7493
using (var peFileStream = new FileStream(assemblyPath, FileMode.Create))
7594
using (emitResult.PeStream)
7695
{
7796
emitResult.PeStream.WriteTo(peFileStream);
7897
}
7998

80-
var pdbPath = Path.Combine(tempProjectDirecory, $"{AssemblyName}.pdb");
81-
using (var pdbFileStream = new FileStream(pdbPath, FileMode.Create))
82-
using (emitResult.PdbStream)
99+
if (emitResult.PdbStream != null)
83100
{
84-
emitResult.PdbStream.WriteTo(pdbFileStream);
101+
var pdbPath = Path.Combine(outputDirectory, $"{AssemblyName}.pdb");
102+
using (var pdbFileStream = new FileStream(pdbPath, FileMode.Create))
103+
using (emitResult.PdbStream)
104+
{
105+
emitResult.PdbStream.WriteTo(pdbFileStream);
106+
}
85107
}
86108

87109
foreach (var reference in emitResult.DirectiveReferences)
88110
{
89111
if (reference.Display.EndsWith(".NuGet.dll")) continue;
90112
var refInfo = new FileInfo(reference.Display);
91-
var newAssemblyPath = Path.Combine(tempProjectDirecory, refInfo.Name);
113+
var newAssemblyPath = Path.Combine(outputDirectory, refInfo.Name);
92114
File.Copy(refInfo.FullName, newAssemblyPath, true);
93115
}
94116

src/Dotnet.Script.Core/ScriptRunner.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1+
using System;
2+
using System.IO;
3+
using System.Reflection;
14
using System.Threading.Tasks;
5+
using Dotnet.Script.DependencyModel.Context;
6+
using Dotnet.Script.DependencyModel.ProjectSystem;
7+
using Dotnet.Script.DependencyModel.Runtime;
28
using Microsoft.CodeAnalysis.CSharp.Scripting.Hosting;
39
using Microsoft.CodeAnalysis.Scripting;
410
using Microsoft.CodeAnalysis.Scripting.Hosting;
@@ -18,6 +24,53 @@ public ScriptRunner(ScriptCompiler scriptCompiler, ScriptLogger logger, ScriptCo
1824
ScriptConsole = scriptConsole;
1925
}
2026

27+
public async Task<TReturn> Execute<TReturn>(string dllPath)
28+
{
29+
var assembly = Assembly.LoadFrom(dllPath);
30+
var refs = assembly.GetReferencedAssemblies();
31+
//var tempProjectPath = ScriptProjectProvider.GetPathToProjectFile(Path.GetDirectoryName(dllPath));
32+
//var projectFile = new ProjectFile();
33+
34+
//foreach (var @ref in refs)
35+
//{
36+
// projectFile.AddPackageReference(new PackageReference("AutoMapper", "6.1.0", PackageOrigin.ReferenceDirective));
37+
//}
38+
//projectFile.Save(tempProjectPath);
39+
40+
//var deps = ScriptCompiler.RuntimeDependencyResolver.GetDependencies();
41+
//var @ref = Assembly.LoadFrom(@"C:\Users\u403598\Desktop\temp\nuget_testing\AutoMapper.dll");
42+
//AppDomain.CurrentDomain.Load(@ref.GetName());
43+
44+
var rootDir = Path.GetDirectoryName(dllPath);
45+
var temp = ScriptDependencyInfoProvider.ReadDependencyContextFromAssets(rootDir);
46+
var rootNuget = Path.Combine(Environment.GetEnvironmentVariable("userprofile"), ".nuget", "packages");
47+
var runtimeDeps = ScriptCompiler.RuntimeDependencyResolver.GetDependenciesCustom(rootDir, new string[] { rootNuget, @"C:\Program Files\dotnet\sdk\NuGetFallbackFolder" });
48+
var runtimeDepsMap = ScriptCompiler.CreateScriptDependenciesMap(runtimeDeps);
49+
50+
AppDomain.CurrentDomain.AssemblyResolve +=
51+
(sender, args) =>
52+
{
53+
var assemblyName = new AssemblyName(args.Name);
54+
var result = runtimeDepsMap.TryGetValue(assemblyName.Name, out RuntimeAssembly runtimeAssembly);
55+
if (!result) throw new Exception($"Unable to locate assembly '{assemblyName.Name}: {assemblyName.Version}");
56+
var loadedAssembly = Assembly.LoadFrom(runtimeAssembly.Path);
57+
return loadedAssembly;
58+
};
59+
60+
//foreach (var @ref in refs)
61+
//{
62+
// AppDomain.CurrentDomain.Load(@ref);
63+
//}
64+
65+
var type = assembly.GetType("Submission#0");
66+
var method = type.GetMethod("<Factory>", BindingFlags.Static | BindingFlags.Public);
67+
68+
var submissionStates = new object[2];
69+
submissionStates[0] = new CommandLineScriptGlobals(ScriptConsole.Out, CSharpObjectFormatter.Instance);
70+
var resultTask = method.Invoke(null, new[] { submissionStates }) as Task<TReturn>;
71+
return await resultTask;
72+
}
73+
2174
public Task<TReturn> Execute<TReturn>(ScriptContext context)
2275
{
2376
var globals = new CommandLineScriptGlobals(ScriptConsole.Out, CSharpObjectFormatter.Instance);

src/Dotnet.Script.DependencyModel/Context/ScriptDependencyInfoProvider.cs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Dotnet.Script.DependencyModel.Context
1111
/// Represents a class that is capable of providing
1212
/// the <see cref="DependencyContext"/> for a given project file (csproj).
1313
/// </summary>
14-
public class ScriptDependencyInfoProvider
14+
public class ScriptDependencyInfoProvider
1515
{
1616
private readonly IRestorer[] _restorers;
1717
private readonly Logger _logger;
@@ -28,13 +28,20 @@ public ScriptDependencyInfoProvider(IRestorer[] restorers, LogFactory logFactory
2828
/// <param name="pathToProjectFile">The path to the project file.</param>
2929
/// <returns>The <see cref="DependencyContext"/> for a given project file (csproj).</returns>
3030
public ScriptDependencyInfo GetDependencyInfo(string pathToProjectFile, string[] packagesSources)
31-
{
31+
{
3232
Restore(pathToProjectFile, packagesSources);
33-
var context = ReadDependencyContext(pathToProjectFile);
33+
var context = ReadDependencyContext(pathToProjectFile);
3434
var nugetPackageFolders = GetNuGetPackageFolders(pathToProjectFile);
3535
return new ScriptDependencyInfo(context, nugetPackageFolders);
3636
}
3737

38+
public ScriptDependencyInfo GetDependencyInfoFromAssetsFile(string directory)
39+
{
40+
var context = ReadDependencyContextFromAssets(directory);
41+
//var nugetPackageFolders = GetNuGetPackageFolders(pathToProjectFile);
42+
return new ScriptDependencyInfo(context, new string[0]);
43+
}
44+
3845
private void Restore(string pathToProjectFile, string[] packageSources)
3946
{
4047
foreach (var restorer in _restorers)
@@ -63,6 +70,20 @@ private DependencyContext ReadDependencyContext(string pathToProjectFile)
6370
}
6471
}
6572

73+
public static DependencyContext ReadDependencyContextFromAssets(string directory)
74+
{
75+
//_logger.Debug($"Reading dependency context from {pathToAssetsFile}");
76+
77+
using (FileStream fs = new FileStream(Path.Combine(directory, "project.assets.json"), FileMode.Open, FileAccess.Read))
78+
{
79+
// https://github.com/dotnet/core-setup/blob/master/src/managed/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs
80+
using (var contextReader = new DependencyContextJsonReader())
81+
{
82+
return contextReader.Read(fs);
83+
}
84+
}
85+
}
86+
6687
private string[] GetNuGetPackageFolders(string pathToProjectFile)
6788
{
6889
var pathToObjFolder = Path.Combine(Path.GetDirectoryName(pathToProjectFile), "obj");

src/Dotnet.Script.DependencyModel/ProjectSystem/ScriptProjectProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ private void CopyNuGetConfigFile(string targetDirectory, string pathToProjectFil
125125
}
126126
}
127127

128-
private static string GetPathToProjectFile(string targetDirectory)
128+
public static string GetPathToProjectFile(string targetDirectory)
129129
{
130130
var pathToProjectDirectory = FileUtils.CreateTempFolder(targetDirectory);
131131
var pathToProjectFile = Path.Combine(pathToProjectDirectory, "script.csproj");

0 commit comments

Comments
 (0)