I'm writing a bare-metal OS kernel in C#, and I would like to execute the .NET AOT compiler from the command line without using the dotnet
command, also avoiding the use of a .csproj file.
On searching my file system, I notice a copy of the ILC, the Native AOT compiler, stored in the following location on my local machine: C:\Users\frank\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.14"\tools
I can actually call it successfully, ilc <args>
, and it does perform the ahead of time compilation.
Unfortunately, I have no idea how it got there and I need a reliable way to setup a fresh build environment.
How can I deterministically install, and then run, the .NET AOT compiler? (either .NET version 7 or 8 is fine).
I've made a .NET tool wrapper to simplify this whole process. To install it, simply do:
dotnet tool install -g ilc
...then, you can invoke ilc
as if it was on your PATH
:
$ ilc --version
9.0.0-preview.6.24327.7+573461dc897731c11d6166574b77a8c3aabba220
It doesn't need any updating, since it automatically keeps track of .NET versions.
However, if you want to do it without the tool, see my previous answer below.
If you want to manually transform an IL assembly to native code via ILC, you'll have to add the corresponding NuGet package. The name of the package depends on the runtime identifier - it's in the format of runtime.<runtime identifier>.Microsoft.DotNet.ILCompiler
. After adding that package, it will appear in your global-packages
directory, in which you'll find ilc under the tools
directory.
If you don't have a .NET project (a *.csproj
), you'll have to create one to add a NuGet reference:
dotnet new classlib tmp-nuget
cd ./tmp-nuget
...add the package, for example, for x86-64 (AMD64) Linux:
dotnet add package runtime.linux-x64.Microsoft.DotNet.ILCompiler --version 8.0.6
Then, locate your global-packages
folder:
$ dotnet nuget locals global-packages -l
global-packages: /home/asc/.nuget/packages/
Then, putting it all together:
$ "/home/asc/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/8.0.6/tools/ilc" -v
8.0.6+3b8b000a0e115700b18265d8ec8c6307056dc94d
Don't forget to delete that temporary directory (if you did need to create it in the first place, of course):
cd ..
rm -rf tmp-nuget
Unfortunately, I couldn't find a way to directly install a NuGet package to the global packages directory (a'la npm
's -g
flag). I recommend using a temporary directory even if you already have a .NET project, because it will add a PackageReference
that may result in unforeseen consequences when using it with the .NET SDK.