dotnet / corert

This repo contains CoreRT, an experimental .NET Core runtime optimized for AOT (ahead of time compilation) scenarios, with the accompanying compiler toolchain.
http://dot.net
MIT License
2.91k stars 508 forks source link

samples/WebApi doesn't work with .NET Core 2.1 #5720

Closed ThatRendle closed 6 years ago

ThatRendle commented 6 years ago

I encountered this on my own project, so I tried with the WebApi sample and got the same issue.

I tested before changing anything and everything worked.

I updated the csproj file to use 2.1 instead of 2.0, so it now looks like this:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <RdXmlFile Include="rd.xml" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="2.1.0-preview2-final" /> 
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.1.0-preview2-final" /> 
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.1.0-preview2-final" />     
    <PackageReference Include="Microsoft.DotNet.ILCompiler" Version="1.0.0-alpha-*" />
  </ItemGroup>
</Project>

I had to remove the Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv entry from rd.xml because 2.1-preview2 no longer uses libuv.

With those changes, when I ran dotnet publish -c Release -r win-x64 I got the following output:

λ  dotnet publish -c Release -r win-x64
Microsoft (R) Build Engine version 15.6.22.57775 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 52.32 ms for C:\Labs\dotnet\corert\samples\WebApi\SampleWebApi.csproj.
  SampleWebApi -> C:\Labs\dotnet\corert\samples\WebApi\bin\Release\netcoreapp2.1\win-x64\SampleWebApi.dll
  Generating native code
EXEC : warning : RD.XML processing will change before release (https://github.com/dotnet/corert/issues/5001) [C:\Labs\dotnet\corert\samples\WebApi\SampleWebApi.csproj]
EXEC : error : [TEMPORARY EXCEPTION MESSAGE] ClassLoadGeneral: System.Reflection.Emit.ILGenerator, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a [C:\Labs\dotnet\corert\samples\WebApi\SampleWebApi.csproj]
  Internal.TypeSystem.TypeSystemException+TypeLoadException: [TEMPORARY EXCEPTION MESSAGE] ClassLoadGeneral: System.Reflection.Emit.ILGenerator, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
     at Internal.TypeSystem.ThrowHelper.ThrowTypeLoadException(ExceptionStringID id, String typeName, String assemblyName)
     at Internal.TypeSystem.Ecma.EcmaModule.GetType(String nameSpace, String name, Boolean throwIfNotFound)
     at Internal.TypeSystem.Ecma.EcmaModule.GetType(String nameSpace, String name, Boolean throwIfNotFound)
     at Internal.TypeSystem.Ecma.EcmaModule.ResolveTypeReference(TypeReferenceHandle handle)
     at Internal.TypeSystem.Ecma.EcmaModule.EcmaObjectLookupHashtable.CreateValueFromKey(EntityHandle handle)
     at Internal.TypeSystem.LockFreeReaderHashtable`2.CreateValueAndEnsureValueIsInTable(TKey key)
     at Internal.TypeSystem.Ecma.EcmaModule.GetObject(EntityHandle handle)
     at Internal.TypeSystem.Ecma.EcmaModule.GetType(EntityHandle handle)
     at Internal.TypeSystem.Ecma.EcmaSignatureParser.ParseType(SignatureTypeCode typeCode)
     at Internal.TypeSystem.Ecma.EcmaSignatureParser.ParseFieldSignature()
     at Internal.TypeSystem.Ecma.EcmaField.InitializeFieldType()
     at Internal.TypeSystem.MetadataFieldLayoutAlgorithm.ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
     at Internal.TypeSystem.DefType.ComputeInstanceLayout(InstanceLayoutKind layoutKind)
     at ILCompiler.DependencyAnalysis.EETypeNode.CheckCanGenerateEEType(NodeFactory factory, TypeDesc type)
     at ILCompiler.DependencyAnalysis.NodeFactory.<CreateNodeCaches>b__36_1(TypeDesc type)
     at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
     at ILCompiler.Compilation.RootingServiceProvider.AddCompilationRoot(TypeDesc type, String reason)
     at ILCompiler.RdXmlRootProvider.RootType(IRootingServiceProvider rootProvider, TypeDesc type)
     at ILCompiler.RdXmlRootProvider.ProcessAssemblyDirective(IRootingServiceProvider rootProvider, XElement assemblyElement)
     at ILCompiler.RdXmlRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider)
     at ILCompiler.Compilation..ctor(DependencyAnalyzerBase`1 dependencyGraph, NodeFactory nodeFactory, IEnumerable`1 compilationRoots, DebugInformationProvider debugInformationProvider, DevirtualizationManager devirtualizationManager, Logger logger)
     at ILCompiler.ILScannerBuilder.ToILScanner()
     at ILCompiler.Program.Run(String[] args)
     at ILCompiler.Program.Main(String[] args)
C:\Users\mark\.nuget\packages\microsoft.dotnet.ilcompiler\1.0.0-alpha-26417-01\build\Microsoft.NETCore.Native.targets(172,5): error MSB3073: The command ""C:\Users\mark\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\1.0.0-alpha-26417-01\tools\ilc" @"obj\Release\netcoreapp2.1\win-x64\native\SampleWebApi.ilc.rsp"" exited with code 1. [C:\Labs\dotnet\corert\samples\WebApi\SampleWebApi.csproj]

Environment info

Windows 10 Pro 1709 Build 16299.371

$ dotnet --version
2.1.300-preview2-008530
jkotas commented 6 years ago

ASP.NET dependency injection introduced dependency on Reflection.Emit in https://github.com/aspnet/DependencyInjection/pull/630 unfortunately. It makes it incompatible with CoreRT.

We can make it functional in CoreRT AOT environment by introducing IL interpretter (https://github.com/dotnet/corert/issues/5011), but it would still perform poorly. The dependency injection framework is using Reflection.Emit on performance critical paths.

It would be really up to ASP.NET to provide AOT-friendly flavor that generates all code at build time instead of runtime to make this work well. It would likely help the startup without CoreRT as well.

ThatRendle commented 6 years ago

That's annoying. Thanks for the explanation though.

jkotas commented 6 years ago

It may be possible to workaround this by using netstandard2.0 build of DependencyInjection that does not have the dependency on Reflection.Emit: https://github.com/aspnet/DependencyInjection/pull/630/files#diff-499bed1ac3743837d217bcbe8bad072fR9

morganbr commented 6 years ago

It looks like ASP.NET might have also kept the expression-based DI engine based on ServiceProviderOptions.Mode (along with a couple other modes that might be faster than expressions while still AoT friendly). I'd suggest seeing if there's a way to control that from user code.

ThatRendle commented 6 years ago

Is there any way I can force the build to use the netstandard2.0 DLL over the netcoreapp one when my console application is targeting netcoreapp?

ThatRendle commented 6 years ago

Hmm... outside of the incredibly hacky "add a pre-build step to modify the project.assets.json file and change the compile and runtime entries on the target to netstandard2.0 instead of netcoreapp2.0" approach, that is.

I'm away from my project at the moment, but I'll try that when I get back to it.

davidfowl commented 6 years ago

If only we had this https://github.com/dotnet/corefx/issues/10470 😏

Fabi commented 6 years ago

Actually this also breaks some other projects that are not using Microsoft.AspNetCore* namespaces directly. This is a bit annoying^^

Btw: It also happens when using netcoreapp2.0

Fabi commented 6 years ago

This issue seems to be fixed? Just tested it and it works fine.

MichalStrehovsky commented 6 years ago

@Fabi according to a comment in aspnet/home#3079 we should really be fine for 2.1. Thanks for verifying this!

benaadams commented 6 years ago

Doesn't work for 2.1

davidfowl commented 6 years ago

Probably another issue

benaadams commented 6 years ago

Same issue

  Generating native code
EXEC : error : [TEMPORARY EXCEPTION MESSAGE] ClassLoadGeneral:
 System.Reflection.Emit.ILGenerator, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a [C:\....csproj]
  Internal.TypeSystem.TypeSystemException+TypeLoadException: [TEMPORARY EXCEPTION MESSAGE] ClassLoadGeneral: System.Reflection.Emit.ILGenerator, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
     at Internal.TypeSystem.ThrowHelper.ThrowTypeLoadException(ExceptionStringID id, String typeName, String assemblyName)
     at Internal.TypeSystem.Ecma.EcmaModule.GetType(String nameSpace, String name, Boolean throwIfNotFound)
     at Internal.TypeSystem.Ecma.EcmaModule.GetType(String nameSpace, String name, Boolean throwIfNotFound)
     at Internal.TypeSystem.Ecma.EcmaModule.ResolveTypeReference(TypeReferenceHandle handle)
     at Internal.TypeSystem.Ecma.EcmaModule.EcmaObjectLookupHashtable.CreateValueFromKey(EntityHandle handle)
     at Internal.TypeSystem.LockFreeReaderHashtable`2.CreateValueAndEnsureValueIsInTable(TKey key)
     at Internal.TypeSystem.Ecma.EcmaModule.GetObject(EntityHandle handle)
     at Internal.TypeSystem.Ecma.EcmaModule.GetType(EntityHandle handle)
     at Internal.TypeSystem.Ecma.EcmaSignatureParser.ParseType(SignatureTypeCode typeCode)
     at Internal.TypeSystem.Ecma.EcmaSignatureParser.ParseFieldSignature()
     at Internal.TypeSystem.Ecma.EcmaField.InitializeFieldType()
     at Internal.TypeSystem.MetadataFieldLayoutAlgorithm.ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
     at Internal.TypeSystem.DefType.ComputeInstanceLayout(InstanceLayoutKind layoutKind)
     at ILCompiler.DependencyAnalysis.EETypeNode.CheckCanGenerateEEType(NodeFactory factory, TypeDesc type)
     at ILCompiler.DependencyAnalysis.NodeFactory.<CreateNodeCaches>b__36_0(TypeDesc type)
     at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
     at ILCompiler.DependencyAnalysis.GenericCompositionNode.GetData(NodeFactory factory, Boolean relocsOnly)
     at ILCompiler.DependencyAnalysis.ObjectNode.GetStaticDependencies(NodeFactory factory)
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.GetStaticDependenciesImpl(DependencyNodeCore`1 node)
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ProcessMarkStack()
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ComputeMarkedNodes()
     at ILCompiler.ILScanner.ILCompiler.IILScanner.Scan()
     at ILCompiler.Program.Run(String[] args)
     at ILCompiler.Program.Main(String[] args)
davidfowl commented 6 years ago

I wonder if it's barfing at the reference itself. I would hope not...

benaadams commented 6 years ago

For what I'm trying to build the only use/reference of DI would be via WebHostBuilder with the indirect reference from Hosting

image

I'm trying to build the PlatformBenchmark with json and db stuff stripped out, so is very basic and doesn't use DI directly.

However I have updated the Sample to show the issue https://github.com/dotnet/corert/pull/5912

MichalStrehovsky commented 6 years ago

The compiler is crashing because the facade assemblies that CoreFX is generating for Ref.Emit are bogus.

I filed #5913 on the compiler crash (we shouldn't crash), but this would ideally be fixed by making the Ref.Emit behave like any other other API we don't currently support in CoreRT (i.e. a bunch of PlatformNotSupportedException-throwing methods instead of a bogus facade that doesn't have things in it).

MichalStrehovsky commented 6 years ago

The compiler is crashing because the facade assemblies that CoreFX is generating for Ref.Emit are bogus.

We're waiting for dotnet/corefx#30338 to get through. After that, we'll pick up the latest CoreFX and the problem with bogus Ref.Emit facades should be gone.

MichalStrehovsky commented 6 years ago

5953 has the fixes to CoreFX that should make this compile again.