Skip to content
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

[feature request] Bindings to Roslyn csc.dll or example in docs of using Roslyn to compile a C# file or a code snippet in a string #2196

Closed
vadimkantorov opened this issue Jul 19, 2023 · 2 comments

Comments

@vadimkantorov
Copy link

vadimkantorov commented Jul 19, 2023

For .NET Core embedding into Python, it is useful in educational/hack scenarios to allow the user to allow the user to not compile the C# code beforehand. E.g. a solution would be a Python binding (or docs example) to Roslyn/csc.dll of calling it from python to compile a C# code file or code snippet (without saving it to a file). An alternative would be binding to CSharpScript technology of Roslyn.

Originally discussed at #2195

In my example there https://gist.github.com/vadimkantorov/c9ab97aff995ea01ea7f6248ddc733bc I first prepare the compilation string, then compile the csharp code in csharpfrompython.sh, and only then call clr.AddReference in the python code. It would be great to call the compiler directly from the python code and have nice bindings to even maybe not store the assembly on disk and add it to clr.AddReference directly.

Maybe the API could be clr.CompileAndAddAssembly(code files, code snippets, compiler options, reference assemblies and other csc options) or sth similar

@filmor
Copy link
Member

filmor commented Jul 20, 2023

This is out of scope for Python.NET.

@filmor filmor closed this as not planned Won't fix, can't repro, duplicate, stale Jul 20, 2023
@vadimkantorov
Copy link
Author

vadimkantorov commented Jul 20, 2023

An example in docs would be nice though even if you consider this not needed to add in the codebase :)

For instance, as you can see in https://gist.github.com/vadimkantorov/c9ab97aff995ea01ea7f6248ddc733bc#file-csharpfrompython-sh the path discovery is a beast:

DOTNETSDKVER=$("$DOTNET_ROOT/dotnet" --version)
DOTNETFWKVER=$("$DOTNET_ROOT/dotnet" --list-runtimes | grep Microsoft.NETCore.App | tail -n 1 | cut -d' ' -f2)
DOTNETLIBDIR="$DOTNET_ROOT/shared/Microsoft.NETCore.App/$DOTNETFWKVER"
"$DOTNET_ROOT/dotnet" "$DOTNET_ROOT/sdk/$DOTNETSDKVER/Roslyn/bincore/csc.dll" $(find "$DOTNETLIBDIR" -name "*.dll" -printf '-r:"%p" ')  -target:library -out:csharpfrompython.dll csharpfrompython.cs

If these paths are available somewhere under the clr module, calling the Roslyn compiler from pythonnet would be much simpler.

Here is a complete snippet:

output_path = os.path.abspath('foo.dll')
input_path = os.path.abspath('foo.cs')

os.environ['PYTHONNET_RUNTIME'] = 'coreclr'
os.environ['DOTNET_ROOT'] = os.path.expanduser('~/.dotnet')

import clr

DOTNETSDKVER=subprocess.check_output([os.path.join(os.environ['DOTNET_ROOT'], 'dotnet'), '--version']).decode().strip()
DOTNETFWKVER=[line.split()[1] for line in subprocess.check_output([os.path.join(os.environ['DOTNET_ROOT'], 'dotnet'), '--list-runtimes']).decode().splitlines() if 'Microsoft.NETCore.App' in line][-1].strip()
DOTNETLIBDIR=os.path.join(os.environ['DOTNET_ROOT'], 'shared', 'Microsoft.NETCore.App', DOTNETFWKVER)

csc_args_reference_assembly_paths = ['-r:' + os.path.join(dirname, basename) for dirname, dirs, basenames in os.walk(DOTNETLIBDIR) for basename in basenames if basename.endswith('.dll')]
csc_args_main = ['-target:library', '-out:' + output_path, input_path]
clr.AddReference(os.path.join(os.environ['DOTNET_ROOT'], 'sdk', DOTNETSDKVER, 'Roslyn', 'bincore', 'csc.dll'))
import Microsoft.CodeAnalysis.CSharp.CommandLine
Microsoft.CodeAnalysis.CSharp.CommandLine.Program.Main(csc_args_reference_assembly_paths + csc_args_main)

clr.AddReference(output_path)

Somewhat related on complete pipeline of using Roslyn + Assembly.Load: https://weblog.west-wind.com/posts/2022/Jun/07/Runtime-CSharp-Code-Compilation-Revisited-for-Roslyn - might be useful for other people looking to do this.

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

No branches or pull requests

2 participants