-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Linking Native AOT for android complains about -fPIC #109341
Comments
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas |
Tagging subscribers to 'arch-android': @vitek-karas, @simonrozsival, @steveisok, @akoeplinger |
Do you have more detailed repro steps? I tried:
This linked fine. I also tried adding an UnmanagedCallersOnly method and it still linked fine. |
Well, you are using dotnet all the way, whereas I only use Dotnet NativeAOT to produce static libraries. I'll see if I can get a 100% small example later, but these are the steps I take:
The error message suggests that the libRuntime.WorkstationGC.a is not compiled using |
As far as I know, we compile everything with fPIC in this repo: runtime/eng/native/configureplatform.cmake Line 494 in 1557f12
You should be able to double check with something like readelf: https://stackoverflow.com/questions/1340402/how-can-i-tell-with-something-like-objdump-if-an-object-file-has-been-built-wi The (unsupported) instructions for building with static libraries suggest to replicate the entire command line that is used by native AOT E2E. So my recommendation would be to capture the command line that is used in the workflow from #109341 (comment) and make sure the switches match when linking the static library. |
The error message is about this line in the handwritten asm code:
|
Thanks for the info.
Well, I work under the assumption that this will work (and be supported) in the end, as per discussions in our private chat (ping @steveisok @jbevain). As for the technical part, the linking requirements of the final shared library for the Android platform, should really be the deciding factor, not the library per se. I'll try to make a small repro case tomorrow.
I posted the linking step in the OP, the main factor seem to be if I pass "-shared" or not to the linker. |
We do pass
|
Thanks for the info. I've boiled it down to a minimal repro case here.
Prerequisites:
I build under x86_64 Linux (an Ubuntu 20.04 docker container) For full details, check the To compile: $ SDK=/opt/platformsdk/android/android-sdk-linux/ NDK=/opt/platformsdk/android/android-ndk-r25b/ ./scripts/compile.sh android In the zip I included the full source and script, as well as the build log and the aot.binlog. GIven the error:
I suspect that the libNativeLibrary.a that dotnet generates isn't actually built using the |
We don't pass I tried to modify my repro steps (#109341 (comment)) and added:
to the project. I confirmed |
Afaik, the So, you added a flag to the linker, is it possible to add a flag to building the library? Since you mention my environment, I outlined the setup above. I can of course try to look further. May I ask under which environment and Andorid tools you use for comparison? |
The error in your repro is triggered by missing The linker command line used by The problem is that the handwritten assembly code assumes the existence of the version script. We may be able to tweak the handwritten assembly code to remove this assumption and make it work even without the version script.
We do that. The PIC flag has no effect on hand-written assembly code. The hand-written assembly code has to follow specific patterns to be compatible with PIC. It is why you see the linker error only for the one symbol defined in the handwritten assembly code. If we were missing the PIC flag when compiling C/C++ code, you would see the error for many more symbols. |
I have noticed that there are more linker command line options missing in your repro compared to what |
I think this would make it work jkotas@97a36a2 (untested). The change makes the hand-written code a bit less efficient. However, fixing your linker command line options to better match what's used by |
Hi @jkotas
Just to clarify so that we're on the same page. The executable is linked as a shared library.
Possibly, I'll try to see if that works. |
Right. The static libraries produced by NativeAOT are not ordinary static libraries like what you get from C/C++. They have to be linked into the final binary in a specific way. It is why @MichalStrehovsky suggested in #109341 (comment) to replicate the command line used by
We are not aware of any issues with this approach on the intended platforms. If you run into any issues, we will be happy to take a look. |
Ok, are these flags documented anywhere? Or do I need to check the output of dotnet cli tool (and how do I do that). As for future obstacles, I know of one popular vendor that requires their own tools for creating the object files. (Sorry, I can't be more specific as I'm under NDA) |
Run We do not have the linker command line switches explicitly documented. Such documentation would be duplicating the build targets that I have linked. It would be difficult to keep it up to date.
You would need IL to C transpiler (like Unity IL2CPP) to satisfy this requirement. We do not maintain transpiler like that in this repo currently. |
Back after some more testing. While the linker error goes away, it also seems to remove the other functions that should be exported.
And it doesn't take into consideration e.g. However, it then presents a problem of our users adding other extensions. How to know which symbols they want/need to add or not? We've never before needed this .exports file, and I wonder if it's actually needed now? Fyi, I tried this generic approach:
But then it's back to square one, when it complains about fPIC. |
It is the opposite problem: We do make all symbols show up by default, but it does not work for some symbols like The fix that I have suggested in #109341 (comment) should make it work. Are you able to validate that this change makes it work? |
The compiler will update the exports file to export any UnmanagedCallersOnly methods. That way only the actual necessary public surface area will be exported. I assume without this you're getting .NET implementation details such as @JCash can you remind me why you need a static library? Why can't you let dotnet publish build a .so file for you? |
@jkotas How would I get access to that dotnet build? I'm currently using dotnet 9 rc2
@MichalStrehovsky We need it because the Defold Game Engine is a C++ application, with a static library eco system (for plugin creators). I know for a fact that other engine(s) are looking to use NativeAOT this way as well. For more info, I refer to @steveisok and @jbevain who are also involved in this effort. |
From what I can gather here, you currently have:
What makes following setup not feasible:
|
Typically, all these are separate static libs fed to the build system, enabling modular builds and predictable dependencies (which game engines are sensitive to). In a balanced world view, static libs will always have a place. |
@MichalStrehovsky Not sure what you mean? Example of our engine running with C# support on an Android phone: |
Any suggestion on how to install the dotnet version with the fix, using |
You run |
@JCash, since #109617 is still in PR stage, it will require building the runtime by yourself: #109538 (comment): # shallow clone
git clone https://github.com/dotnet/runtime --single-branch --depth 1
cd runtime
# apply Jan's patch
curl -sSL https://github.com/dotnet/runtime/pull/109617.patch | git apply -
# install build dependencies (if you haven't already)
./eng/common/native/install-dependencies.sh
# build and follow Michal's instructions on <IlcSdkPath>
./build.sh clr.aot -c Release |
There's no builds until the PR is merged and an official .NET 10 build with it produced. You'd need to follow repo instructions to build it yourself: https://github.com/dotnet/runtime/blob/main/docs/workflow/building/coreclr/nativeaot.md |
Right, thanks then I'll wait until the build is available via the install scripts. |
Good point. It sounds like a better fix would be to mark the exports from system module as hidden. It would be an extension of what we do here:
|
Maybe I'm missing something - would that require the compiler knowing the list of all publics within the unmanaged runtime? Based on this, it could also be done with a linker flag ( |
WhIle I haven't tried "exclude-libs" flag, I do worry when a single library enforces linker flags for all other libraries in the same executable. I.e. will it work for all future libraries that we add? E.g. all the ads networks and their shared libraries etc. Imho, a library should be as self contained as possible, so if we can avoid extra linker flags, that's my advice. |
The fix that I had in mind would change: runtime/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.cs Line 432 in 7ee5b7d
to be (logically) All publics in CoreLib should have hidden visibility on Unix. We do not want any of them to ever participate in the process-global symbol unification. We achieve that via the linker script today, but we should be able to achieve the same effect by setting the right flags on the symbols. We can also make this configurable via command line switches so that this is not hardcoded to SystemModule. |
Should fix dotnet#109341. We currently rely on the linkerscript not exporting these, now it's a per-assembly compiler switch.
Should fix dotnet#109341. We currently rely on the linkerscript not exporting these, now it's a per-assembly compiler switch.
Description
I'm linking our executable, and I get this error:
Reproduction Steps
I compile for android (linux-bionic-arm64), and link a shared library for android mobile.
The toolchain requires -fPIC to link a shared executable for android, which is supplied on the command line.
However, if the "-shared" flag is omitted, the command succeeds. So it's nothing wrong with our setup (our builds work for macOS/iOS/Windows).
Expected behavior
I expect to be able to link a shared executable (.so) for the Android poatform.
Actual behavior
I get a linker error complaining about the library not being built with -fPIC (/tmp/.nuget/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/native/libRuntime.WorkstationGC.a)
Regression?
No response
Known Workarounds
I don't know of a workaround unfortunately, so this is a blocker.
Configuration
No response
Other information
No response
The text was updated successfully, but these errors were encountered: