Today I would like to walk you through the process of compiling, running and debugging of .NET Core – that is the open source version of .NET environment. Let’s go to the answer to the simple question straight away…
What for?
In order to push the boat out. We got the source of .NET! Why do we need to compile it? In order to tamper, change, analyze, damage it – so that in the end up at Pull Request and record ourselves in Hall of Fame as our code will go to millions of computers all over the world!
Even if we don’t have such ambitious plans, isn’t it just fun to look inside .NET? Of course, it’s not the code of commercial .NET in one-to-one relation. However, the most of the inner part is the same, so there is plenty to play with. .NET foundation site states it plainly:
.NET Core has two major components. It includes a small runtime that is built from the same codebase as the .NET Framework CLR. The .NET Core runtime includes the same GC and JIT (RyuJIT), but doesn’t include features like Application Domains or Code Access Security. (…)
.NET Core also includes the base class libraries. These libraries are largely the same code as the .NET Framework class libraries, but have been factored (removal of dependencies) to enable us to ship a smaller set of libraries.
Therefore if something tells us to look inside the code of framework, which we have used for many years, we can do it now.
How?
It’s best to organize it in one folder, so that it is one next to the other. I called it C:\Projects\DotNetCore. Next, we have to compile two components, which are separate repositories on GitHub.
CoreCLR
First of them has the runtime alone in its splendor. It is written mainly in C++, with some assembler parts. Step by step:
- We perform fork dotnet/coreclr to perform our exceptional Pull Request in future, in my case it’s a fork https://github.com/kkokosa/coreclr
- Standard procedure, which means we add an additional source to our local repository indicating the main repository. Thanks to it we can synchronize with it:
1 2 |
$ git clone https://github.com/kkokosa/coreclr.git $ git remote add upstream https://github.com/dotnet/coreclr.git |
- From now on it is worth to perform such synchronization with a help of:
1 2 3 |
$ git fetch upstream $ git checkout master $ git merge upstream/master |
- Compiling – you have to go through the steps depicted in–https://github.com/dotnet/coreclr/blob/master/Documentation/building/windows-instructions.md
In a nutshell:
- We are installing Visual Studio 2015, can be Community version, should be Update 3 (currently in RC version) but mine has compiled also in Update 2 version.
- Install CMake – remember to choose an option to add proper environment variables during installation.
- Install Python – again we remember about an option with an environment variable addition.
- We make sure that we have PowerShell, which should occur.
I had to, for example, among others, install Visual Studio 2015 Update 3, Python and CMake.
- We go to the coreclr directory and perform command:
1 |
$ build clean |
Alternatively
1 |
$ build clean skiptests |
This should speed up the process.
As a reward we should obtain the following message:
1 2 3 4 5 |
BUILDTEST: Test build successful. BUILDTEST: Test binaries are available at c:\Projects\DotNetCore\coreclr\tests\..\bin\tests\Windows_NT.x64.Debug BUILD: Repo successfully built. BUILD: Product binaries are available at c:\Projects\CoreNet\coreclr\bin\Product\Windows_NT.x64.Debug BUILD: Test binaries are available at c:\Projects\CoreNet\coreclr\bin\tests\Windows_NT.x64.Debug |
Note – on my, quite good I believe, computer it took around 22 minutes together with the tests. Please notice that it is by default 64 bit version in Debug mode that is being compiled – just fine for debugging.
CoreFX
The second component is a set of standard libraries. We perform exactly the same as above but in the corefx folder
- Fork https://github.com/dotnet/corefx to our account https://github.com/kkokosa/corefx
- Git cloning and configuration:
12$ git clone https:<span class="rem">//github.com/kkokosa/corefx.git</span>$ git remote add upstream https://github.com/dotnet/corefx.git - Synchronization (for later use) as we’ve just cloned the main repository:
123$ git fetch upstream$ git checkout master$ git merge upstream/maste
In a case of changes remember about git push!
- We start the compilation by a command:
1$ build.cmd
If any tests go bad, don’t worry. It’s important that only errors come precisely from unsuccessful tests are not harmful.
Running
Congratulations! Probably you have both bricks complied. Now we need to put it together. Firstly, we need to copy some files into one place from the complied projects into the folder, where we make first testing software. There will be subfolders ref and runtime. The best solution is to make it via batch file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
copy coreclr\bin\Product\Windows_NT.x64.debug\clrjit.dll coreclr-demo\runtime copy coreclr\bin\Product\Windows_NT.x64.debug\CoreRun.exe coreclr-demo\runtime copy coreclr\bin\Product\Windows_NT.x64.debug\coreclr.dll coreclr-demo\runtime copy coreclr\bin\Product\Windows_NT.x64.debug\mscorlib.dll coreclr-demo\runtime copy coreclr\bin\Product\Windows_NT.x64.debug\System.Private.CoreLib.dll coreclr-demo\runtime copy corefx\bin\Windows_NT.AnyCPU.Debug\System.Console\System.Console.dll coreclr-demo\runtime copy corefx\bin\Windows_NT.AnyCPU.Debug\System.Diagnostics.Debug\System.Diagnostics.Debug.dll coreclr-demo\runtime copy corefx\bin\AnyOS.AnyCPU.Debug\System.IO\System.IO.dll coreclr-demo\runtime copy corefx\bin\AnyOS.AnyCPU.Debug\System.IO.FileSystem.Primitives\System.IO.FileSystem.Primitives.dll coreclr-demo\runtime copy corefx\bin\AnyOS.AnyCPU.Debug\System.Runtime\System.Runtime.dll coreclr-demo\runtime copy corefx\bin\AnyOS.AnyCPU.Debug\System.Runtime.InteropServices\System.Runtime.InteropServices.dll coreclr-demo\runtime copy corefx\bin\AnyOS.AnyCPU.Debug\System.Text.Encoding\System.Text.Encoding.dll coreclr-demo\runtime copy corefx\bin\AnyOS.AnyCPU.Debug\System.Text.Encoding.Extensions\System.Text.Encoding.Extensions.dll coreclr-demo\runtime copy corefx\bin\AnyOS.AnyCPU.Debug\System.Threading\System.Threading.dll coreclr-demo\runtime copy corefx\bin\AnyOS.AnyCPU.Debug\System.Threading.Tasks\System.Threading.Tasks.dll coreclr-demo\runtime copy corefx\bin\<span class="kwrd">ref</span>\System.Runtime\4.0.0.0\System.Runtime.dll coreclr-demo\<span class="kwrd">ref</span> copy corefx\bin\<span class="kwrd">ref</span>\System.Console\4.0.0.0\System.Console.dll coreclr-demo\<span class="kwrd">ref</span> |
This way the whole set of environment required for a simple program goes to runtime folder. A program itself we can prepare really simple:
1 2 3 4 5 6 7 8 9 10 |
using System; public class Program { public static void Main() { Console.WriteLine("Hello, Windows"); Console.WriteLine("Love from CoreCLR."); } } |
And respectively compile:
1 |
$ csc /nostdlib /noconfig /r:<span class="kwrd">ref</span>\System.Runtime.dll /r:<span class="kwrd">ref</span>\System.Console.dll /<span class="kwrd">out</span>:runtime\hello.exe hello.cs |
Finally (last step) by going to c:\Projects\DotNetCore\coreclr-demo\runtime we can run this program:
1 2 3 |
$ corerun hello.exe Hello, Windows Love from CoreCLR. |
Congratulations! Maybe it doesn’t look astonishing. Yet, we need to be aware what we have completed! We have compiled the whole .NET environment from scratch and run a normal console program on it compiled with a help of Visual Studio. And this is not the end yet!
Debugging
At this point, we can debug CLR. How to do it? In order to do so, we use project files, which are being created at CoreCLR compilation and are kept in the folder c:\Projects\DotNetCore\coreclr\bin\obj . We search for this which we need to use. By default, it is 64 bits Debug version.
- We open in Visual Studio c:\Projects\CoreNet\coreclr\bin\obj\Windows_NT.x64.Debug\CoreCLR.sln
- We set as StartUp project project INSTALL
- In Configuration Properties->Debugging settings of INSTALL project we enter:
- Comand as $(SolutionDir)..\..\product\Windows_NT.$(Platform).$(Configuration)\corerun.exe
- Command Arguments as hello.exe
- Working Directory in place where is our demo (that is a path to coreclr-demo\runtime)
- We start debugging through Step Into (F11) – we start from source of program CoreRun.exe:
- We can also set interesting breakpoints in the CoreCLR itself and run debugging simply by F5. I recommend starting from ceemain.cpp file and method EEStartup, in which many interesting things happen (basically with the help method of EEStartupHelper):
Note: It is highly probable that Visual Studio will state that it has old builds of some libraries and wants to compile it. It’s a waste of time since we have done the compilation already. I, therefore, recommend to choose Tools -> Options in section Projects and Solutions -> Build and Run for an option “On Run, when projects are out of date” value “Never build” or “Prompt to build“.
Now we can push the boat out. I, for example, have a lot of fun debugging code of Garbage Collector. However you may find something else equally interesting.
Tags: .net , .net core , coreclr
Hi, Konrad! Thank you for the amazing article. Did you try to debug CLR by attaching to the running process?
When I try to do it I see the “Crst Reentrancy violation” exception. I’ve created the issue ( https://github.com/dotnet/coreclr/issues/21139 ), but still have no ideas what goes wrong. Have you faced with the issue?