Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

LinkNative doesn't pull assemblies from Runtime Package Store #4444

Closed
markrendle opened this issue Sep 4, 2017 · 19 comments
Closed

LinkNative doesn't pull assemblies from Runtime Package Store #4444

markrendle opened this issue Sep 4, 2017 · 19 comments

Comments

@markrendle
Copy link

Before I start, I should say that I know the scenario I'm describing isn't remotely supported yet; I have just been exploring how unsupported it is. 😈

I'm working on a thing that will benefit greatly from CoreRT AOT compilation when it is ready, so I thought I'd try it and see how far it got. It's an ASP.NET Core 2.0 application that just uses Routing, Kestrel and various Extensions packages. No Controllers or Views whatsoever. I figured it might work a bit and I could provide feedback on any problems I encountered.

So here goes with the first one:

When I tried to build the shtik/cli console application with /t:/LinkNative it did actually produce a runnable shtik.exe file, but when I ran it it errored out with a Could not find assembly Microsoft.Extensions... message. Obviously it failed to pull the various assemblies from the ASP.NET Core runtime package store during the build.

As I say, I'm not expecting it to work, just flagging the issue for now.

Environment info:

Windows 10 x64
Visual Studio 2017.3 Native Tools command prompt
dotnet SDK 2.0.0
ASP.NET Core 2.0.0
CoreRT built from master branch as of about a week back.

@markrendle markrendle changed the title Doesn't pull assemblies from Runtime Package Store LinkNative doesn't pull assemblies from Runtime Package Store Sep 4, 2017
@jkotas
Copy link
Member

jkotas commented Sep 5, 2017

Could not find assembly Microsoft.Extensions... message

Looks like a dup of #2619.

cc @sergiy-k @nattress

@markrendle
Copy link
Author

I'll try the workaround mentioned in that issue and see what I get, will comment-and-close this if it resolves.

@sergiy-k
Copy link
Contributor

sergiy-k commented Sep 8, 2017

Hi @markrendle!
@nattress is working on improving dotnet cli integration and fixing the issue #2619. He should have something to share with you soon but, as you probably have discovered it by yourself, this is not going to be the biggest issue.
The main problem is that ASP.NET heavily uses a lot reflection to glue things together even in a simple MVC core application. At this point, the CoreRT compiler does not have such an advance analysis engine that exits in .NET Native for UWP so it cannot see all the types that are constructed dynamically and needed by the app. This is especially problematic for dynamically created generic instantiations. As a result, all these types have to be manually listed in an rd.xml file. Currently, this is one of the main difficulties in building ASP.NET apps with CoreRT.

Having said that, I did build a set of simple ASP.NET Core 2.0 apps with CoreRT a few month ago. So, in order to help you to start playing with CoreRT, I took liberty to adjust my rd.xml and some very basic build scripts for your app. I hope that you don’t mind me doing it. :) You can find my files here: sergiy-k@9edc6df. As you can see, my rd.xml file is quite large, in part because I simply accumulated entries in it that were needed for different applications and some of the entries were added to work around bugs that we had in CoreRT a few months ago (which I did not have a chance to clean up). You might not need everything in it but I would not worry much about that unless you want to make your final executable as small as possible. I also did not use dotnet cli to build my apps because it was not possible at all at that time. Instead I invoked the ILC compiler and linker using response file from 'x64 Native Tools Command Prompt for VS'.
The “Console.WriteLine(...)” line that I added in RyuJitCompilation.cs will help you to detect missing assembly references at compile time instead of getting an exception at runtime. @MichalStrehovsky, we should turn the TODO in there into a real compilation warning or error.

Long story short, I was able to build and run your application using these scripts. Of course, I don’t know if everything works as expected. :)

There were two small workarounds that I had to apply in your code to make the app start:

  1. Environment.GetFolderPath() that is used in Program.cs currently does not work on CoreRT (issue BlittableStructPtrMarshaller not implemented #4466). So it needs to be temporary replaced with something else (maybe GetEnvironmentVariable?)
  2. The code in SharpYaml.Serialization.Descriptors.DictionaryDescriptor tries to access the generic DictionaryDescriptor.GetGenericEnumerable<> method by its name via reflection. This eventually results in an exception at runtime because the CoreRT compiler did not see a call to this method and did not include it in compilation. Unfortunately, right now CoreRT has only very basic support for rd.xml syntax which does not yet allow expressing required generic methods. As a workaround, you can add the following piece of code anywhere in your app (I added it in Slides.cs):
    public static void ReflectionRoots()
    {
        SharpYaml.Serialization.Descriptors.DictionaryDescriptor.GetGenericEnumerable<string, object>(new Dictionary<string, object>());
    }

Here are the steps that I followed to build and run your app:

  1. Apply the two workarounds that I mentioned above in your app
  2. Publish it as a self-contained application
    dotnet publish -c release -r win-x64
    This will allow you to get all required assembly references from one place so you don’t have to find them in NuGet cache.
  3. Build release flavor of CoreRT
  4. Adjust the paths in my scripts to your local setup and build the app from 'x64 Native Tools Command Prompt for VS'
    cd corert\tests\src\MvcCoreTestApp
    build.cmd
  5. I also needed to copy slides.md, shtik.json from your sources and libuv.dll (from the app’s publish folder) next to the app binary produced by CoreRT
dir /b bin
libuv.dll
shtik.exe
shtik.json
shtik.pdb
slides.md
  1. Launch the app and open it in browser :)
cd bin
shtik.exe

Yeah, I know, it’s not pretty but that’s where we are at this point. :(
Please let me know if you have any questions. Hope this will help you to start playing with CoreRT or maybe even a bit more than that. ;-)

@morganbr
Copy link
Contributor

@markrendle , would you mind telling us more about how you expect AoT compilation to benefit shtik? We're definitely interested in gathering that kind of feedback to help us prioritize work.

@JensNordenbro
Copy link

@morganbr ; I did the same experiment as markrendl a while back. (not on shtik though but another ASP.NET Core MVC application we wanted to run on a custom ARM-board)
For me it was a way of getting a sense of what to expect from corert on ARM since ASP.NET Core on ARM has bad startup performance (due to (my understanding) no crossgen being available yet).

I guess having corert on asp.net core applications is a important since many practical workloads for .NET Core uses ASP.NET Core. Also this brings a new deployment/optimization model already available on competing stacks such as Go or Rust. I agree that probably in many scenarios a crossgened or even JIT:ed SCD is good enough, however being able to produce a single executable targeting a platform is a nice thing and would attract people not confortable with JIT:ing on resource constrained devices.

@JensNordenbro
Copy link

@sergiy-k, is number 1 workaround in your comment above still relevent, considering jkotas commit as contrib to #4466?

@MichalStrehovsky
Copy link
Member

@sergiy-k, is number 1 workaround in your comment above still relevent, considering jkotas commit as contrib to #4466?

I ran over Sergiy's steps yesterday and skipped the first workaround - it worked fine for me.

@markrendle
Copy link
Author

@sergiy-k You are a hero! Thank you for taking the time to do all that, I'll try it out right away.

@morganbr There are two main drivers for me wanting to AoT-compile Shtik:

  1. Distributing the application as a standalone executable will be much easier for end users to install, it becomes a simple $ download && copy to $PATH process. With a standalone-published dotnet application, you can't copy everything to, say, /usr/local/bin because of all the DLLs.
  2. I'm intending to add a full set of command line actions to the CLI application, like shtik new to create a new empty presentation, for example. So the startup time for the .exe becomes important in that situation.

The thing that I'm most excited about here is that my main reason for creating Shtik is that I can use it in my presentations on .NET Core, where it is both the presentation tool and the thing I'm talking about. And now I can add a whole section on CoreRT to my talks (which will definitely include a mention of how helpful you guys are 😄)

@xoofx
Copy link
Member

xoofx commented Oct 16, 2017

@markrendle , would you mind telling us more about how you expect AoT compilation to benefit shtik? We're definitely interested in gathering that kind of feedback to help us prioritize work.

@morganbr the most common scenario for me is to be able to release small/medium self contained single app/exe tools that I can redistribute easily. If you look at the Go language ecosystem, this platform has been very popular in the past years, and one of the reason being that it allows to compile to AoT natively. Nowadays, It is often the language/platform most commonly used for releasing useful executable without having to install a runtime (see projects like hugo... though I could have taken docker as a higher proof of benefit! 😉 ).

Extrapolating a bit from this, I believe that the lack of AoT in .NET is likely a reason for some companies to not adopt .NET and use a language like Go instead.

Typically yesterday, I tried to use a Go program to generate markdown TOC with links from a github markdown file (here derived from another self contained shell here) but it was buggy with some markdown files. I developed a small tool with markdig called mdtoc to do this. It works a lot more better. But I can't redistribute this easily (Same would go for a tool I released a few years ago - git-rocket-filter).. And I know that I'm missing lots of other opportunities...

By being able to release a similar .NET tool (but much better and solid!) that you can use easily on Windows or Linux or MacOSX, people would start to see .NET differently to develop these kind of little useful programs...

If I had time, I would lovely help CoreRT on this, but my OSS duty is already eating my whole spare time... so keep up this work on AoT, it is a fantastic opportunity for .NET!

@markrendle
Copy link
Author

@sergiy-k Finally found the time to do this, and IT WORKS! Thanks!

@sergiy-k
Copy link
Contributor

@markrendle, great to hear that it worked for you. If you'll have more time to play with it, then please let me know what are other issue that you'll find. We'll be happy to help.

@markrendle
Copy link
Author

markrendle commented Nov 7, 2017

@sergiy-k I'll be experimenting some more with it this week, including seeing if I can trim the rd.xml file. I'll also try the new rd.xml syntax from #4775 and see if I can replace that code reference hack-around with an up-to-date build. Anything I achieve will be pushed to the shtik/cli repo and I'll post in this thread.

@sergiy-k
Copy link
Contributor

sergiy-k commented Nov 7, 2017

@markrendle, sounds great! Please make sure you pick the following change up: #4884. It fixes this issue (#4860) that affects the entries in rd.xml. Thanks!

@A-And
Copy link
Contributor

A-And commented Nov 14, 2017

Hey, @markrendle. With #4870 , shtik/cli should be publishable out of the box (as long as you identify the correct rd.xml file in your .csproj)! Give it a try and let us know if you run into any issues.

@JensNordenbro
Copy link

JensNordenbro commented Nov 16, 2017

Hi @A-And ; since your changes that allow using dotnet-cli for building (Nice!!) I cannot get a simple
"dotnet web" project (Reference Project setup) to work any more.
It works nice with "dotnet console". Maybe I have missunderstood how to add the rd.xml or something else. Here is the output from running "dotnet publish -r linux-arm" on Ubuntu on Windows.
My final goal is to native compile a full "dotnet mvc" template and a couple of weeks ago I managed to at least compile "dotnet web" project using the previous more manual approach.
Do you have any suggestions?

@jkotas
Copy link
Member

jkotas commented Nov 16, 2017

The undefined reference to CryptoNative_* errors are caused by missing reference to https:/dotnet/corefx/tree/master/src/Native/Unix/System.Security.Cryptography.Native . We do not have yet .a file for this library available out of the box yet. You would have to build and reference it yourself for now. I am not sure how it could have ever worked.

@JensNordenbro
Copy link

@jkotas; checked my work-VM; turns out it built the "dotnet web" on Windows, not WSL. Never the less using the dotnet-tooling on this Windows environement I get:

Unhandled Exception: System.InvalidOperationException: A public method named 'ConfigureProduction' or 'Configure' could not be found in the 'web.Startup' type.
at web!+0x8cad9
at web!+0x8b8a3
at web!+0x8a62b
at Microsoft.AspNetCore.Hosting.WebHostBuilderExtensions.<>c__DisplayClass1_0.b__

..when trying to run the output exe after dotnet publish -r win-x64.

Maybe this is my rd.xml not configured the right way. @A-And is not explicit in how to define the "correct rd.xml" in his comment. I just added it as Content in my csproj but maybe this is not the correct way.

@MichalStrehovsky
Copy link
Member

Maybe this is my rd.xml not configured the right way. @A-And is not explicit in how to define the "correct rd.xml" in his comment. I just added it as Content in my csproj but maybe this is not the correct way.

The file name needs to be specified in the RdXmlFile property otherwise the compiler won't see it.

@MichalStrehovsky
Copy link
Member

I think all issues here have been fixed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants