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

Generating native code with RyuJIT - linked native resource problem #6375

Closed
tokaplan opened this issue Sep 25, 2018 · 12 comments
Closed

Generating native code with RyuJIT - linked native resource problem #6375

tokaplan opened this issue Sep 25, 2018 · 12 comments

Comments

@tokaplan
Copy link

Following these instructions, I'm trying to generate a native executable from my .NET Core assembly which has a dependency on Grpc.Core nuget. I hit the following issue:

dotnet publish -r win-x64

Microsoft.LocalForwarder.ConsoleHost.obj : error LNK2001: unresolved external symbol grpcsharp_auth_context_property_iterator [D:\Git\ApplicationInsights-LocalForwarder\src\ConsoleHost\ConsoleHost.csproj]
... same error message for every exported function from grpc_csharp_ext.x64.dll (see below)

Turns out Grpc.Core's assembly uses a native DLL called grpc_csharp_ext.x64.dll. They invoke it via DllImport, but there's also some sort of static dependency in the metadata. This is how ILSpy shows it:

image

I've never seen this, but I'm guessing this is the sort of reference that -linkresource option creates as described here.

Regardless, the question is - what's the best course of action here? Should I be able to compile such assembly into native code? How do I proceed to fix this?

@jkotas
Copy link
Member

jkotas commented Sep 25, 2018

The problem is that the library is built for many platforms, including the platforms that require static linking.

__Internal is what's causing the problem actually. It is coming from here:

https://github.com/grpc/grpc/blob/618a3f561d4a93f263cca23abad086ed8f4d5e86/templates/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs.template#L187

The CoreRT compiler generates code for this static linking path and that's what causes the unresolved symbols during linking.

@MichalStrehovsky
Copy link
Member

@jkotas Should we maybe expose a command line option to stop treating __Internal as early bound import?

@tokaplan The easiest way to make this go away (barring recompiling the NuGet with the __Internal thing removed) is to do this (the things under FIX define is the fix):

using System;
using System.Runtime.InteropServices;

#if FIX
namespace System.Runtime.InteropServices
{
    [AttributeUsage(AttributeTargets.Method)]
    public sealed class NativeCallableAttribute : Attribute
    {
        public NativeCallableAttribute() { }
        public CallingConvention CallingConvention;
        public string EntryPoint;
    }
}
#endif

internal class Program
{
    [DllImport("__Internal")]
    static extern void DoSomething();

#if FIX
    [NativeCallable(EntryPoint = "DoSomething")]
    static void DoSomethingImpl() { }
#endif

    private static void Main(string[] args)
    {
        if (String.Empty.Length > 0)
            DoSomething();
    }
}

This assumes that the __Internal P/Invoke is not actually reached at runtime and we just need to supply something to make it link. The code not being reachable is a pretty safe assumption since on CoreCLR this would attempt to load __Internal.dll and likely throw a `DllNotFoundException.

@MichalStrehovsky
Copy link
Member

...or since you're building CoreRT from source and not using the ILCompiler NuGet package, you can just comment out this:

// Force link time symbol resolution for "__Internal" module for compatibility with Mono
if (importModule == "__Internal")
return false;

It's only for compatibility with Mono, but we don't rely on it for anything.

@jkotas
Copy link
Member

jkotas commented Sep 26, 2018

@jkotas Should we maybe expose a command line option to stop treating __Internal as early bound import?

We have the early bound import policy hardcoded in the compiler right now. Instead of having special option for just __Internal, we may want to think about how to make it fully configurable and move the hardcoded policy to the makefiles.

Or maybe we should have an option to force trim "bad" parts of the program/libraries (replace them with exception throwing). Kind of like inverse rd.xml. It would help us to deal with cases where the program has statically reachable part that you do not actually need, but that is causing problems.

@MichalStrehovsky
Copy link
Member

We have the early bound import policy hardcoded in the compiler right now.

Ah yes. #2454. We should have a policy class that can decide on the way to do the import given a method as the parameter. Then we can pipe that through command line switches or RD.XML or any other mechanism.

@tokaplan
Copy link
Author

I don’t have control over the Grpc nugets unfortunately, so I’ll try the CoreRT side fix Michal has proposed. Thank you, I will let you know if that helps.

@tokaplan
Copy link
Author

So it appears that the fix has worked (at least in a sense that I'm not receiving that error any more). It finishes fine, but here's what I see now:

As long as my Main() executes in the primary assembly, things work. However, when the code execution encounters a call to a different assembly - that call doesn't appear to get executed, but Main() continues to be executed successfully after that point.

I lack fundamental understanding of how this whole thing works, can you please explain how this is possible and what I might be doing wrong?

@tokaplan
Copy link
Author

Never mind, I got confused. Native library is generally working (I have issues with reflection, but that would be a different issue). The corert-side fix suggested above worked for me.
@MichalStrehovsky , @jkotas , do you think you'll be able to squeeze in whatever permanent solution you deem appropriate in the near future? I don't mind using my local change for now, but at some point I'd like it to be official.

Regardless, thank you very much.

@MichalStrehovsky
Copy link
Member

PInvoke policy is tracked in #2454

@szhaomsft
Copy link

is there an official fix?

or I have to still create my own build of corert?

how to publish a nuget in this case?

@jkotas
Copy link
Member

jkotas commented Feb 4, 2019

@szhaomsft The linked issue was not fixed as you can see. You are welcomed to submit PR with a proposed fix.

@szhaomsft
Copy link

attempt a fix
#6959

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

4 participants