Skip to content

Feature/create and execute dll #315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 20, 2018

Conversation

Sharpiro
Copy link
Contributor

This feature continues with my previous publish to .exe PR #312 as well as Filip's POC e677cd6 to create and execute a .dll .

I made improvements to the way we were emitting the streams in ScriptEmitter:

  • Debug information is now embedded in the PeStream so we have 1 less file to worry about (and apparently I hear it might be more performant?).
  • If the publish option for -c release is supplied, then no debug information will be created.
  • It tuns out Filip was right and I did not need to actually rename the assembly to get the publishing working, so I removed that bit of code.

.dll generation considerations:

  • when the --dll flag is passed to the publish command, the script is outputted to a .dll in a publish directory in the working directory (configurable), along w/ any .dll's the script referenced via #r. Getting Nuget packages working was trickier. I elected to not move over the assembly files to the publish directory during a publish, instead moving 2 files from the "obj" folder, "project.assets.json", and "script.csproj.nuget.g.props" to determine the necessary nuget information when the generated .dll is executed. 1 caveat to doing this, is no nuget restore takes place at execution time. I figured this would be ok after I tested the dotnet test.dll command and saw that it does not restore nuget packages either. This does mean though that if you do a publish to dll, delete your nuget packages (or execute from a machine missing the packages), then try to execute the dll, you will get a missing reference error.
  • A dll is generated and named based upon the current working directory. This was not possible to do with .exe generation w/o some breaking changes.
  • After a dll has been generated, it can then be run through dotnet script via the exec command. This command calls the ScriptRunner, creates the dependency map from the obj information, runs the main script <Factory> method, and then resolves missing nuget references.

misc:

  • it seems d93a557 may have broken the Dotnet.Script.Desktop.Tests tests

Looking forward to your feedback. Thanks

@seesharper seesharper requested review from seesharper and filipw June 19, 2018 09:05
@@ -133,17 +133,20 @@ private static int Wain(string[] args)
c.Description = "Creates an executable from a script";
Copy link
Member

@filipw filipw Jun 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please update the description here (or DLL)

var publishDebugMode = c.Option(DebugFlagShort + " | " + DebugFlagLong, "Enables debug output.", CommandOptionType.NoValue);
c.OnExecute(() =>
{
var x = debugMode.HasValue();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's x? 😀

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate that visual studio didn't give a warning for this type of unused variable...

@@ -133,17 +133,20 @@ private static int Wain(string[] args)
c.Description = "Creates an executable from a script";
var fileNameArgument = c.Argument("filename", "The script file name");
var publishDirectoryOption = c.Option("-o |--output", "Directory where the published executable should be placed. Defaults to a 'publish' folder in the current directory.", CommandOptionType.SingleValue);
var dllOption = c.Option("--dll", "Publish to a .dll instead of a .exe", CommandOptionType.NoValue);
var commandConfig = c.Option("-c | --configuration <configuration>", "Configuration to use for running the script [Release/Debug] Default is \"Debug\"", CommandOptionType.SingleValue);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need an extra option instead of the already existing top-level var configuration = app.Option("-c | --configuration <configuration>"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad you mentioned this. I tested trying to access "app" level "options" when executing a sub "command", and those options were not coming through and required me to create new variables in order to access them at the "command" level.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am barely able to handle this argument parsing library 😀 so I now suspect this is happening because the publish is a command so it creates a new context and all the arguments are parsed within this context, not in the global one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that has been the assumption I went with as well.

@filipw
Copy link
Member

filipw commented Jun 19, 2018

Thanks a lot, great work! 🍻

Getting Nuget packages working was trickier. I elected to not move over the assembly files to the publish directory during a publish, instead moving 2 files from the "obj" folder, "project.assets.json", and "script.csproj.nuget.g.props" to determine the necessary nuget information when the generated .dll is executed.

I think this has certain problems and we will have to change it - like you mentioned, if the packages are gone, or if you move to a different machine where they are not there, or if you move to a different OS (then they might be there, just in different place).
Also, technically speaking, what I think should happen, is that we should move the DLLs that are not part of the .NET Core SDK (runtime package store).

That said, I think this is a reasonable 1st version though, this is more or less how it worked in scriptcs in the past too, and we can describe it as known limitation for now, and improve later.

Also, the way I'd view compile to exe and compile to dll is that compile to exe is to really export to a self contained app that can run elsewhere. Compile to dll is like a local cache for your script so that you keep running on the same machine, but with better performance for subsequent executions.

If the publish option for -c release is supplied, then no debug information will be created.

This is not a bad idea. I want debug info to always be there for standard scripting scenarios, but once we deal with exe/dll I think it makes sense to respect the configuration.

A dll is generated and named based upon the current working directory. This was not possible to do with .exe generation w/o some breaking changes.

why not generate the name of the DLL from the entry CSX file? dotnet script publish foo.csx should create foo.dll? I don't think the name of the folder matters here.

@Sharpiro
Copy link
Contributor Author

So for the generated DLL name, since the name of the script is usually less descriptive than the folder, I went with the folder. Using dotnet script init the intro script is always just "main.csx", whereas the folder might describe the script project. I don't have a strong opinion and can change this to just the script name if you'd like.

@filipw
Copy link
Member

filipw commented Jun 19, 2018

I think we should use the script name. Perhaps we can have another switch, something like -o | --output where we can override the name?

{
try
{
var emitResult = _scriptEmitter.Emit<int>(context, AssemblyName);
var emitResult = _scriptEmitter.Emit<int>(context);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove the PdbStream property from the emitResult?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea I already removed it since the debug information is embedded

@@ -16,30 +16,26 @@ public ScriptEmitter(ScriptConsole scriptConsole, ScriptCompiler scriptCompiler)
_scriptCompiler = scriptCompiler;
}

public virtual ScriptEmitResult Emit<TReturn>(ScriptContext context, string assemblyName = null)
public virtual ScriptEmitResult Emit<TReturn>(ScriptContext context)
{
try
{
var compilationContext = _scriptCompiler.CreateCompilationContext<TReturn, CommandLineScriptGlobals>(context);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that on other code paths (i.e. script execution) we support using custom host types. This is not very important but in the future the publish code should probably be extended with that

Copy link
Collaborator

@seesharper seesharper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work. LGTM

Copy link
Member

@filipw filipw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@filipw filipw merged commit 8e11235 into dotnet-script:master Jun 20, 2018
@Sharpiro Sharpiro deleted the feature/create_and_execute_dll branch June 20, 2018 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants