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

Allow creating native library (static or shared) #1285

Closed
DemiMarie opened this issue May 16, 2016 · 47 comments
Closed

Allow creating native library (static or shared) #1285

DemiMarie opened this issue May 16, 2016 · 47 comments
Milestone

Comments

@DemiMarie
Copy link

It should be possible to create a library (either static or dynamic) which exposes a C API, and which does not require callers to be aware that it is not written in C.

@jkotas
Copy link
Member

jkotas commented May 17, 2016

Thank you for talking a look at the project. First class support for building libraries like this is definitely something we would like to support in CoreRT eventually. This involves providing a different version of startup code (src\Native\Bootstrap) and build scripts.

@jkotas jkotas modified the milestone: December May 17, 2016
@jkotas
Copy link
Member

jkotas commented Jul 11, 2016

#1498 is one of the problems that needs to be fixed to make this work.

@MichalStrehovsky MichalStrehovsky added this to the Future milestone Oct 20, 2016
@MihaMarkic
Copy link

This is a great proposition and would be of immense value. Hopefully it will be implemented.

@allquixotic
Copy link

Now that #1498 is fixed, what is left to make this happen? Can any of the core devs give kind of a roadmap for how this could be implemented? Are there any known chunks of work besides #1498 that are pending before this can be implemented in a fairly straightforward way?

@jkotas
Copy link
Member

jkotas commented Jul 17, 2017

Here is what's needed to make this happen. For now, I would worry about RyuJIT codegen only for all of this.

  • Create clone of the bootstrap code for dlls: Copy src\Native\Bootstrap\base to src\Native\Bootstrap\dll, rename bootstrapper to bootstrapperdll in the CMakeLists.txt, add add_subdirectory(bootstrapperdll) to src\Native\Bootstrap\CMakeLists.txt to add it to the build.

  • Modify the bootstrap code for dlls to not have main method: Add add_definitions(-DCORERT_DLL) to src\Native\Bootstrap\dll\CMakeLists.txt and change src\Native\Bootstrap\main.cpp:

extern "C" void InitializeModules(void* osModule, void ** modules, int count, void ** pClasslibFunctions, int nClasslibFunctions);

#ifdef CORERT_DLL
#if defined(_WIN32)
#define wmain CoreRT_wmain
#else
#define main CoreRT_main
#endif
#endif
  • Change build scripts under https://github.com/dotnet/corert/tree/master/src/BuildIntegration to not produce native .exe, but produce native .dll instead when a new NativeDll msbuild property is set

Now, you should be able to produce native .dll out of managed .exe. This native .dll should have CoreRT_wmain entrypoint that you can use to run it. You should be also able to export extern "C" entrypoints from it using NativeCallable attribute that you can call afer the CoreRT_wmain have finished.

The next step is get rid of the fake main method and polish this so that you can actually build the native .dll from managed library:

@MichalStrehovsky Feel free to edit this post with anything else you can think of.

@tonerdo
Copy link
Contributor

tonerdo commented Jul 24, 2017

@jkotas I'd love to pick this up. I'd get started on it, right away

@jkotas
Copy link
Member

jkotas commented Jul 24, 2017

@tonerdo It's yours. Thanks!

@bazzilic
Copy link

@tonerdo thanks for working on that! Been looking for a way to produce native libraries for the last week -- with no useful results. Hope you can put a prototype together soon, I'd be happy to test it!

@tonerdo
Copy link
Contributor

tonerdo commented Jul 26, 2017

@bazzilic Yeah I saw your message in gitter, was going to respond. I've started working on it and will let you know once I got something

tonerdo added a commit to tonerdo/corert that referenced this issue Jul 30, 2017
tonerdo added a commit to tonerdo/corert that referenced this issue Jul 30, 2017
@tonerdo
Copy link
Contributor

tonerdo commented Aug 3, 2017

@jkotas I notice that when I add

#ifdef CORERT_DLL
#if defined(_WIN32)
#define wmain CoreRT_wmain
#else
#define main CoreRT_main
#endif
#endif

and I try to build a shared library. I get the below error at the linking stage

Undefined symbols for architecture x86_64:
    "_main", referenced from:
        _PalGetModuleFileName in libRuntime.a(PalRedhawkUnix.cpp.o)
       (maybe you meant: __Z11CoreRT_mainiPPc)
  ld: symbol(s) not found for architecture x86_64

Typically this error is thrown by the linker when it doesn't find a main method when it's trying to build an executable but that should be suppressed when the switch to build a library is used. Any ideas?

@jkotas
Copy link
Member

jkotas commented Aug 4, 2017

The problem is that PalGetModuleFileName is referencing the main method here:

if (moduleBase == NULL)

I think that the fix for this should be to get rid of this code, and always require PalGetModuleFileName to take non-null argument (on Unix at least).

tonerdo added a commit to tonerdo/corert that referenced this issue Aug 4, 2017
tonerdo added a commit to tonerdo/corert that referenced this issue Aug 4, 2017
@tonerdo
Copy link
Contributor

tonerdo commented Aug 4, 2017

@jkotas so from my tests I realize the we still need CoreRT_main/main method to setup and tear down the runtime. What does this mean for a native library in the context of dlopen/LoadLibrary if those main functions have to be called before any managed function can be executed?

@jkotas
Copy link
Member

jkotas commented Aug 4, 2017

Some of this is covered by "The next step is get rid of the fake main method and polish this" in my write up.

It is fine to have an option that initialize the runtime automatically when the library is loaded or when the first unmanaged method gets called. I would expect that this automatic options would be used by "simple" libraries. Folks complex programs will likely prefer the explicit initialization/shutdown methods.

It is not unusual for the "C" libraries to have initialize method that has to be called before anything else from the library is used.

tonerdo added a commit to tonerdo/corert that referenced this issue Aug 5, 2017
* Include nativelib switch for compiler
* suppress checking for entrypoint when -nativelib
tonerdo added a commit to tonerdo/corert that referenced this issue Aug 10, 2017
@tonerdo
Copy link
Contributor

tonerdo commented Aug 10, 2017

@jkotas adding NativeCallable works alright on Unix and checking the resulting .dylib/.so file for exported functions shows the methods that have that attribute applied. For Windows however doing a dumpbin /EXPORTS on the generated native dll doesn't display any method including those that have the NativeCallable attribute applied.

This happens when using both Cdecl and StdCall calling conventions. The native dll is generated with:

LINK.EXE /DLL /OUT:NATIVELIB.DLL NATIVEOBJECT.OBJ @NATIVELIBS.LIB

Any ideas?

@jkotas
Copy link
Member

jkotas commented Aug 10, 2017

On Windows, the methods have to be exported via .def file passed to the linker.

@tonerdo
Copy link
Contributor

tonerdo commented Aug 10, 2017

Aaah, forgot about that. Is there are provision in the compiler to automatically generate DEF files or is this something I need to add?

@jkotas
Copy link
Member

jkotas commented Aug 10, 2017

For now, you need to add it. It may be possible to auto generate it in future, but it should be separate issue.

@tonerdo
Copy link
Contributor

tonerdo commented Nov 12, 2017

@nattress after a bit of google searches I've been able to come to the conclusion that the static library that contains that symbol wasn't compiled with position independent code in mind. I should mention that after pulling the latest master the problem symbol is no longer __GetNonGCStaticBase_S_P_CoreLib_System_AppContext but now __NewArr1___Array<Object>.

Full error output:

/usr/bin/ld: obj/Debug/netstandard2.0/native/cslib.o: relocation R_X86_64_PC32 against symbol `__NewArr1___Array<Object>' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value

tonerdo added a commit to tonerdo/corert that referenced this issue Nov 21, 2017
tonerdo added a commit to tonerdo/corert that referenced this issue Nov 21, 2017
tonerdo added a commit to tonerdo/corert that referenced this issue Nov 21, 2017
tonerdo added a commit to tonerdo/corert that referenced this issue Nov 21, 2017
tonerdo added a commit to tonerdo/corert that referenced this issue Nov 21, 2017
tonerdo added a commit to tonerdo/corert that referenced this issue Nov 21, 2017
jkotas pushed a commit that referenced this issue Nov 21, 2017
* add bootstrapper for native libraries (#1285)

* overwrite main method when building library (#1285)

* add stub for native library startup method (#1285)

* Include nativelib switch for compiler

* suppress checking for entrypoint when -nativelib

* initialize runtime at start of reverse PInvoke, unix dlopen successful (#1285)

* don't run library initializers for Multi module build (#1285)

* update buildscript to build unix static library (#1285)

* update buildscript to build Windows static library (#1285)

* create and use NativeLibraryInitializerRootProvider (#1285)

* use "shared" linker arg on unix to build shared library (#1285)

* use system module to initialize NativeLibraryInitializerRootProvider (#1285)

* initialize runtime just before initializing the thread (#1285)

* move InitializeRuntime call to within TSF_Attached state check (#1285)

* use static struct constructor to set InitializeRuntime pointer (#1285)

* do not include main function in native library build (#1285)

* move runtime initialization check to thread init (#1285)

* use Thread* to determine whether to initialize runtime (#1285)

* handle race conditions when initializing runtime (#1285)
@jkotas
Copy link
Member

jkotas commented Nov 21, 2017

@tonerdo Could you open github issues on the followup up work items for this that you are aware of, and link them to this issue?

@tonerdo
Copy link
Contributor

tonerdo commented Nov 21, 2017

@jkotas will do 👍

@sgf
Copy link

sgf commented Mar 17, 2018

if could be create native lib,thats will be great !!!

@MichalStrehovsky
Copy link
Member

We now have small workitems tracking the remaining work here (see issues linking to this). Let's not have duplicate issues open.

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

No branches or pull requests