Skip to content
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

Closed
JCash opened this issue Oct 29, 2024 · 34 comments · Fixed by #110152
Closed

Linking Native AOT for android complains about -fPIC #109341

JCash opened this issue Oct 29, 2024 · 34 comments · Fixed by #110152
Labels
area-NativeAOT-coreclr in-pr There is an active PR which will close this issue when it is merged os-android
Milestone

Comments

@JCash
Copy link

JCash commented Oct 29, 2024

Description

I'm linking our executable, and I get this error:

ld.lld: error: relocation R_AARCH64_ADR_PREL_PG_HI21 cannot be used against symbol 'RhpCidResolve'; recompile with -fPIC
>>> defined in /tmp/job17052320106867802331/build/libExtensionCSharp_3.a(libExtensionCSharp_3.o)
>>> referenced by StubDispatch.S:114 (/__w/1/s/src/coreclr/nativeaot/Runtime/arm64/StubDispatch.S:114)
>>>               StubDispatch.S.o:(RhpInterfaceDispatchSlow) in archive /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

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).

/opt/platformsdk/android/android-ndk-r25b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++ -fuse-ld=/opt/platformsdk/android/android-ndk-r25b/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld -O2 -g -isysroot=/opt/platformsdk/android/android-ndk-r25b/toolchains/llvm/prebuilt/linux-x86_64/sysroot -static-libstdc++ build/main_tmp4.o  -o build/libdmengine.so -Wl,-soname=libdmengine.so -DDLIB_LOG_DOMAIN="UNKNOWN" -DDDF_EXPOSE_DESCRIPTORS -DDM_PLATFORM_ANDROID -D__aarch64__ -DDM_RELEASE  -Wl,--build-id=uuid  -fpic /tmp/.nuget/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/native/libbootstrapperdll.o /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 /tmp/.nuget/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/native/libeventpipe-enabled.a /tmp/.nuget/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/native/libstandalonegc-enabled.a /tmp/.nuget/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/native/libSystem.IO.Compression.Native.a /tmp/.nuget/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/native/libSystem.Globalization.Native.a /tmp/.nuget/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/native/libSystem.Native.a -Wl,--no-undefined -Wl,-z,noexecstack -landroid -z text -L/tmp/job17052320106867802331/build  -L/dynamo_home//lib/arm64-android -L/dynamo_home//ext/lib/arm64-android -L/tmp/.nuget/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/native  -Wl,-Bstatic -Wl,--start-group -lc++_static -lengine_release -lengine_service_null -lprofile_null -lremotery_null -lprofilerext_null  -lExtensionCSharp_3 -lExtensionCPP_2  -lmbedtls -lzip -lrecord_null -lgameobject -lddf -lresource -lgamesys -lgamesys_model -lgamesys_rig -lscript_box2d -lgraphics -lgraphics_transcoder_basisu -lbasis_transcoder -lphysics -lBulletDynamics -lBulletCollision -lplatform -lLinearMath -lBox2D -lrender -lscript -lluajit-5.1 -lextension -lhid -linput -lparticle -lrig -ldlib -limage -ldmglfw -lgui -lcrashext -lsound -ltremolo -lliveupdate -lunwind  -Wl,--end-group -Wl,-Bdynamic  -lEGL -lGLESv1_CM -lGLESv2 -lOpenSLES -lm -llog -lc  -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -shared

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

@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Oct 29, 2024
Copy link
Contributor

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

Tagging subscribers to 'arch-android': @vitek-karas, @simonrozsival, @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.

@MichalStrehovsky
Copy link
Member

Do you have more detailed repro steps? I tried:

dotnet new classlib -o droidlib 
cd droidlib
set PATH=C:\Programs\android-ndk-r26\toolchains\llvm\prebuilt\windows-x86_64\bin;%PATH% 
dotnet publish -r linux-bionic-arm64 -p:PublishAot=true -p:DisableUnsupportedError=true -p:PublishAotUsingRuntimePack=true

This linked fine. I also tried adding an UnmanagedCallersOnly method and it still linked fine.

@JCash
Copy link
Author

JCash commented Oct 30, 2024

Well, you are using dotnet all the way, whereas I only use Dotnet NativeAOT to produce static libraries.
Then I link them using android's clang. For many platforms, the -fPIC is required.

I'll see if I can get a 100% small example later, but these are the steps I take:

  1. Create static library for Android using NativeAOT (I don't think this libr is the problematic one, but is it generated using fPIC?)
  2. Link the (C++) engine with clang: android-clang++ -lMyNativeAOT.a -lRuntime.WorkstationGC.a -shared (simplified ofc)

The error message suggests that the libRuntime.WorkstationGC.a is not compiled using -fPIC, can you verify this?

@MichalStrehovsky
Copy link
Member

As far as I know, we compile everything with fPIC in this repo:

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

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.

@jkotas
Copy link
Member

jkotas commented Oct 30, 2024

The error message suggests that the libRuntime.WorkstationGC.a is not compiled using -fPIC, can you verify this?

The error message is about this line in the handwritten asm code:

PREPARE_EXTERNAL_VAR RhpCidResolve, xip0
. The problem is likely caused by combination of how this asm code is written and how you are linking your library.

@JCash
Copy link
Author

JCash commented Oct 30, 2024

Thanks for the info.

The (unsupported) instructions for building with static libraries suggest to replicate the entire command line that is used by native AOT E2E.

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.

. The problem is likely caused by combination of how this asm code is written and how you are linking your library.

I posted the linking step in the OP, the main factor seem to be if I pass "-shared" or not to the linker.
No "shared", then it links, with "shared" then it fails with the error I posted in the OP.

@MichalStrehovsky
Copy link
Member

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 -shared in the shared library configuration as well:

"clang" "obj\Release\net9.0\linux-bionic-arm64\native\droidlib.o" -o "bin\Release\net9.0\linux-bionic-arm64\native\droidlib.so" -Wl,--version-script=obj\Release\net9.0\linux-bionic-arm64\native\droidlib.exports -Wl,--export-dynamic -gz=zlib -fuse-ld=lld C:\Users\michals\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64\9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/\native\libbootstrapperdll.o C:\Users\michals\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64\9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/\native\libRuntime.WorkstationGC.a C:\Users\michals\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64\9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/\native\libeventpipe-disabled.a C:\Users\michals\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64\9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/\native\libstandalonegc-disabled.a C:\Users\michals\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64\9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/\native\libstdc++compat.a C:\Users\michals\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64\9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/\native\libSystem.Native.a C:\Users\michals\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64\9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/\native\libSystem.Globalization.Native.a C:\Users\michals\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64\9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/\native\libSystem.IO.Compression.Native.a C:\Users\michals\.nuget\packages\microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64\9.0.0-rc.2.24473.5/runtimes/linux-bionic-arm64/\native\libSystem.Security.Cryptography.Native.OpenSsl.a --target=aarch64-linux-android21 -g -Wl,-rpath,"$ORIGIN" -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e,0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,-z,max-page-size=16384 -Wl,--discard-all -Wl,--gc-sections -Wl,-T,"obj\Release\net9.0\linux-bionic-arm64\native\sections.ld"

@JCash
Copy link
Author

JCash commented Oct 31, 2024

Thanks for the info.

I've boiled it down to a minimal repro case here.

  1. I create a static library using NativeAOT (libNativeLibrary.a)
  2. I link this library with a C++ main.cpp into a shared exe, using -shared and -fPIC

Prerequisites:

  • Set the DOTNET_CLI_HOME
  • Install android sdk+ndk

I build under x86_64 Linux (an Ubuntu 20.04 docker container)

For full details, check the scripts/compile.sh

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.

android_repro.zip

GIven the error:

ld: error: relocation R_AARCH64_ADD_ABS_LO12_NC cannot be used against symbol 'RhpCidResolve'; recompile with -fPIC
>>> defined in ./build/android/libNativeLibrary.a(libNativeLibrary.o)

I suspect that the libNativeLibrary.a that dotnet generates isn't actually built using the -fPIC flag?

@MichalStrehovsky
Copy link
Member

We don't pass -fPIC when linking the shared library. Is there something broken at runtime if you don't pass -fPIC to the linker invocation?

I tried to modify my repro steps (#109341 (comment)) and added:

  <ItemGroup>
    <LinkerArg Include="-fPIC" />
  </ItemGroup>

to the project. I confirmed -fPIC is passed to the clang invocation by inspecting msbuild binlog. It still built without any problems. This looks specific to your build environment/command line.

@JCash
Copy link
Author

JCash commented Nov 1, 2024

Afaik, the PIC flag should be passed to both the compiler as well as the linker (if it wasn't a linker flag, it would complain)

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?
Since you modified the "LinkerArg", it seems you are still trying to reproduce this using dotnet?
I'm more thinking that since dotnet generates the .o files, and also does the linking, it doesn't conform to static library building?
I might be off ofc.

@jkotas
Copy link
Member

jkotas commented Nov 1, 2024

The error in your repro is triggered by missing -Wl,--version-script command line option for the linker.

The linker command line used by dotnet publish when building shared libraries includes -Wl,--version-script=obj/Release/net9.0/linux-bionic-arm64/native/libNativeLibrary.exports option. This option is missing in your repro. When I add this option to your repro, the error disappears. You can try to workaround the linker error by creating a version script that is similar to the one used by dotnet when building shared libraries.

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.

the PIC flag should be passed to both the compiler as well as the linker

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.

@jkotas
Copy link
Member

jkotas commented Nov 1, 2024

I have noticed that there are more linker command line options missing in your repro compared to what dotnet publish uses when publishing shared libraries. It can lead to more non-obvious issues.

@jkotas
Copy link
Member

jkotas commented Nov 1, 2024

We may be able to tweak the handwritten assembly code to remove this assumption

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 dotnet publish is probably a better fix.

@JCash
Copy link
Author

JCash commented Nov 2, 2024

Hi @jkotas
Thanks for the info.

The linker command line used by dotnet publish when building shared libraries includes

Just to clarify so that we're on the same page.
I use NativeAOT to generate a static library, not a shared library.

The executable is linked as a shared library.

The error in your repro is triggered by missing -Wl,--version-script command line option for the linker.

I have noticed that there are more linker command line options missing in your repro compared to what dotnet publish uses

Possibly, I'll try to see if that works.
But also with "works", we're also subject to the verification of each vendor, e.g. app stores for Android/iOS, so I'm a little reluctant to add linker commands just like that. Each vendor may have very different requirements/restrictions, so I just want to make sure that your recommendations are supported on each platform.
E.g. is that approach working and verified on all the intended platforms? E.g. iOS, Android and all the rest?

@jkotas
Copy link
Member

jkotas commented Nov 2, 2024

I use NativeAOT to generate a static library, not a shared library.

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 dotnet publish when publishing a shared library.

is that approach working and verified on all the intended platforms? E.g. iOS, Android and all the rest?

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.

@JCash
Copy link
Author

JCash commented Nov 3, 2024

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.
E.g. they wouldn't let me use Zig to create object files directly, instead requires me to generate an intermediate .c file and then compile that using their tools.
I'd imagine they would have similar objections regarding your library files as well then.

(Sorry, I can't be more specific as I'm under NDA)

@jkotas
Copy link
Member

jkotas commented Nov 3, 2024

Or do I need to check the output of dotnet cli tool (and how do I do that).

Run dotnet publish /v:diag > log.txt on project that publishes a shared library and look for the linker command in log.txt. Alternatively, you can go through LinkerArgs in https://github.com/dotnet/runtime/blob/main/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets .

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.

they wouldn't let me use Zig to create object files directly, instead requires me to generate an intermediate .c file and then compile that using their tools.

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.

@JCash
Copy link
Author

JCash commented Nov 7, 2024

Back after some more testing.

While the linker error goes away, it also seems to remove the other functions that should be exported.
Your .exports file looks like:

V1.0 { 
    global: 
        DotNetRuntimeDebugHeader; 
    local: *; 
};

And it doesn't take into consideration e.g. ANativeActivity_onCreate or Java_com_dynamo_android_DefoldActivity ....
I can add ANativeActivity* and Java_com_dynamo_android_DefoldActivity*, and the app finally works (yay!).

However, it then presents a problem of our users adding other extensions. How to know which symbols they want/need to add or not?
The workflow seems quite unruly tbh.

We've never before needed this .exports file, and I wonder if it's actually needed now?
Is it possible to fix on your side, by setting an attribute on your symbol so that it shows up by default?

Fyi, I tried this generic approach:

V1.0 { 
    global: 
        DotNetRuntimeDebugHeader; 
        *;
    local: *; 
};

But then it's back to square one, when it complains about fPIC.

@jkotas
Copy link
Member

jkotas commented Nov 7, 2024

Is it possible to fix on your side, by setting an attribute on your symbol so that it shows up by default?

It is the opposite problem: We do make all symbols show up by default, but it does not work for some symbols like RhpCidResolve.

The fix that I have suggested in #109341 (comment) should make it work. Are you able to validate that this change makes it work?

@dotnet-policy-service dotnet-policy-service bot added the in-pr There is an active PR which will close this issue when it is merged label Nov 7, 2024
@MichalStrehovsky
Copy link
Member

And it doesn't take into consideration e.g. ANativeActivity_onCreate or Java_com_dynamo_android_DefoldActivity ....

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 RhpCidResolve exported and Unix it means they can also be overriden by anything else with the same name in the process. Linker complains because the code cannot handle RhpCidResolve being overriden. But we don't want that.

@JCash can you remind me why you need a static library? Why can't you let dotnet publish build a .so file for you?

@JCash
Copy link
Author

JCash commented Nov 8, 2024

The fix that I have suggested in #109341 (comment) should make it work. Are you able to validate that this change makes it work?

@jkotas How would I get access to that dotnet build? I'm currently using dotnet 9 rc2

can you remind me why you need a static library? Why can't you let dotnet publish build a .so file for you?

@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.

@MichalStrehovsky
Copy link
Member

@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:

  • game.so that contains the C++ Defold engine, native AOT-compiled managed code, and third party code

What makes following setup not feasible:

  • game.so that contains the C++ Defold engine, and third party code
  • game.managed.so that contains native AOT-compiled managed code

@am11
Copy link
Member

am11 commented Nov 8, 2024

C++ Defold engine, native AOT-compiled managed code, and third party code

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.

@JCash
Copy link
Author

JCash commented Nov 8, 2024

What makes following setup not feasible:

game.so that contains the C++ Defold engine, and third party code
game.managed.so that contains native AOT-compiled managed code

@MichalStrehovsky Not sure what you mean?
I can link and run the executable on Android using the static library approach, using NativeAOT.
My workaround was to alter the *.exports file like I mentioned.
I'd ofc like to try the fix @jkotas mentioned, if I can get hold of that runtime version.

Example of our engine running with C# support on an Android phone:
Image

@JCash
Copy link
Author

JCash commented Nov 8, 2024

Any suggestion on how to install the dotnet version with the fix, using dotnet-install.sh?

@MichalStrehovsky
Copy link
Member

@MichalStrehovsky Not sure what you mean?

You run dotnet publish to produce a static lib (.a file) that you then statically link into a .so file with other code. Why not run dotnet publish to produce a dynamic lib (.so file) and then link that to the other code dynamically? Where does the "put everything into single a .so file and no dynamic linking" requirement comes from? E.g. I'm looking a Microsoft Flight simulator now that has a single 180 MB EXE and then another 170 MB spread around in 37 dynamic libraries. Why cannot there be dynamic libraries in Defold on Android?

@am11
Copy link
Member

am11 commented Nov 8, 2024

@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

@MichalStrehovsky
Copy link
Member

Any suggestion on how to install the dotnet version with the fix, using dotnet-install.sh?

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

@JCash
Copy link
Author

JCash commented Nov 8, 2024

Right, thanks then I'll wait until the build is available via the install scripts.

@jkotas
Copy link
Member

jkotas commented Nov 8, 2024

you're getting .NET implementation details such as RhpCidResolve exported and Unix it means they can also be overriden by anything else with the same name in the process. Linker complains because the code cannot handle RhpCidResolve being overriden. But we don't want that.

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:

=> _methods.AddRange(methods.Where(m => m.Module != _context.SystemModule));

@MichalStrehovsky
Copy link
Member

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 (-Wl,--exclude-libs,ALL), without having to maintain a list of all public APIs from the unmanaged runtime.

@JCash
Copy link
Author

JCash commented Nov 11, 2024

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.

@jkotas
Copy link
Member

jkotas commented Nov 11, 2024

would that require the compiler knowing the list of all publics within the unmanaged runtime?

The fix that I had in mind would change:

to be (logically) global: n.Module != context.SystemModule. We do not have Module information available at this layer, so the flag would have to be passed in through the layers.

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.

@agocke agocke modified the milestones: 10.0.0, Future Nov 18, 2024
@agocke agocke removed the untriaged New issue has not been triaged by the area owner label Nov 18, 2024
MichalStrehovsky added a commit to MichalStrehovsky/runtime that referenced this issue Nov 25, 2024
Should fix dotnet#109341. We currently rely on the linkerscript not exporting these, now it's a per-assembly compiler switch.
mikelle-rogers pushed a commit to mikelle-rogers/runtime that referenced this issue Dec 10, 2024
Should fix dotnet#109341. We currently rely on the linkerscript not exporting these, now it's a per-assembly compiler switch.
@github-actions github-actions bot locked and limited conversation to collaborators Dec 26, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-NativeAOT-coreclr in-pr There is an active PR which will close this issue when it is merged os-android
Projects
Archived in project
6 participants