sdk icon indicating copy to clipboard operation
sdk copied to clipboard

[feature request] A way to compile and run raw `.cs` files from CLI (maybe extending `dotnet run`) in one-shot command

Open vadimkantorov opened this issue 1 year ago • 2 comments

I'm proposing to extend dotnet run (or introduce a new command) to compile and run passed .cs files (along with a way to pass dll's and so to be referenced) - so very similar to python myscript.py and go run myscript.go. By default it should be able to discover the assemblies stored in the selected SDK (or allowing to override the .NET version with a passed command-line switch), and also consider any passed .dll/.so search paths (and it can fail and ask user to add further command-line options like package references e.g. if it fails to discover some projects - like it is for python: if some module is not detected, python fails, requires the user to pip-install it and try again, so all essential csproj config options should be passable as command-line options). The working directory should be the current directory, and if any temp assemblies/binaries are created, their assembly location should be the current directory and not some ./bin/Debug/x64 - as this can break loading the .so files.

I think it would be a great addition to the https://github.com/dotnet/interactive direction and make .NET / C# stronger in the scripting (I also think it's time to also include a built-in REPL tool) and educational domains. This would make C# closer to the familiar-to-many python and go CLI workflow which do not require XML/JSON configs to just run a code snippet from CLI. Currently .NET tooling seems oriented to projects and having other tools (like Visual Studio) to prepare various configs, but for trying things out from CLI this can be almost insarmountably hard...

Currently dotnet run forces one to have a .csproj file which requires usage of other tools or knowledge of MSBuild intricacies (and its syntax is quite dated too). An alternative avenue is trying to use csc.dll directly, but it failed for me (if interested, please see context below) and is quite nasty to discover its path:

DOTNET_ROOT="$HOME/.dotnet"
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:my.dll my.cs

# and for running the executable, it also requires manually adding `.runtimeconfig.json`

Context:

I was trying to run a CppSharp which for some advanced setups asks to write+compile+run a small C# snippet which needs to reference the compiled CppSharp .dll's including some native .so files.

As a newbie in the CLI world of .NET I found it currently quite convoluted. I ended up with something like this: https://github.com/vadimkantorov/tritonservercppsharp/blob/master/.github/workflows/tritonservercppsharp.yml#L36 which dumps a csproj file (I had a lot of troubles figuring out how to disable implicit source discovery and so on). Prior to that I was having problems with .runtimeconfig.json https://github.com/mono/CppSharp/issues/1860#issuecomment-2297062617 and with not being able to run a csc.dll-produced binary along with libraries built with dotnet build: https://github.com/mono/CppSharp/issues/1860#issuecomment-2297058536 it was failing to load the runtime and then scanned 10 different ICU data libraries to format the error.

vadimkantorov avatar Aug 29 '24 15:08 vadimkantorov

https://github.com/dotnet/roslyn/issues/17666 perhaps related.

KalleOlaviNiemitalo avatar Aug 29 '24 16:08 KalleOlaviNiemitalo

@KalleOlaviNiemitalo Yes, there are quite a few third-party solutions like csi command (https://visualstudiomagazine.com/articles/2021/06/14/csharp-scripting.aspx, https://github.com/dotnet/roslyn/issues/17666), https://github.com/dotnet-script/dotnet-script and plenty of others. IMO this fragmentation is an indicator it's time to add a built-in script running tool (and hopefully a REPL tool) being able to reasonably handle .cs extension without a need for .csx.

Another argument for having a built-in official tool for these scripting run-and-forget, projectfile/configfile-less needs is that relying on third-party tools for this can expose to supply-chain attacks, especially if a github repo isn't actively supported, someone can try to send a PR there with some malicious update.

vadimkantorov avatar Aug 29 '24 16:08 vadimkantorov

I'm drafting a dotnet tool, maybe you can have a try https://github.com/WeihanLi/dotnet-exec

Install the dotnet-tool

dotnet tool update -g dotnet-execute

then you could try dotnet-exec simpleScript.cs

WeihanLi avatar Dec 11 '24 03:12 WeihanLi

IMO such a basic command should come in core / be supported officially and not require a third-party install...

vadimkantorov avatar Dec 11 '24 10:12 vadimkantorov

Is this now released https://x.com/davidfowl/status/1925348132113817735 ?

@davidfowl

vadimkantorov avatar May 24 '25 08:05 vadimkantorov

Yeah, it's supported in .NET 10 Preview 4 now

Is this now released https://x.com/davidfowl/status/1925348132113817735 ?

WeihanLi avatar May 24 '25 09:05 WeihanLi

Does it have a story for providing search paths for .so files / .dll files? At least it should be able to use the current directory for this

vadimkantorov avatar May 24 '25 09:05 vadimkantorov

seems no support so far, but should be on the list maybe, see the spec file here https://github.com/dotnet/sdk/blob/main/documentation/general/dotnet-run-file.md

WeihanLi avatar May 24 '25 09:05 WeihanLi

Why they didn't use already existing .csx file extension that is used for C# Script that is executed by csi? It feels like having a separate file extension is a good feature that helps to distinguish C# files that can be executed directly.

Having a separate file extension also opens the door to executing .csx files directly without manually typing dotnet run prefix every time, similar to C# Script files with shebang on Linux.

vrubleg avatar May 24 '25 09:05 vrubleg

Really hope proper support for explicitly specifying search paths (for native .so libs and for managed .dll) gets implemented

This is important for testing out DllImport bindings

vadimkantorov avatar May 24 '25 12:05 vadimkantorov

duplicate of https://github.com/dotnet/sdk/issues/9778

JoeRobich avatar Jun 13 '25 17:06 JoeRobich