3

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).

4
  • Hmm, I think maybe I can dotnet add package Microsoft.DotNet.ILCompiler --version 7.0.14 Commented Dec 29, 2023 at 11:48
  • Can you explain why you don't want to use the dotnet command? Commented Dec 29, 2023 at 12:21
  • 3
    @PMF - Because in the fullness of time, I intend to use BFlat to compile it direct to machine code, avoiding installing the .Net SDK or .Net runtime, see: github.com/bflattened/bflat Commented Jan 1, 2024 at 17:14
  • 1
    Run dotnet publish with /bl . That will give you a binlog which you can dig into to see the various commands that are run which you can replicate manually? Commented Mar 5, 2024 at 23:07

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.