Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Android] Support static linking of CoreCLR on Android #114629

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

Open
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

kotlarmilos
Copy link
Member

@kotlarmilos kotlarmilos commented Apr 14, 2025

Description

This PR adds support for static linking of CoreCLR on Android. It includes static libraries in the runtime pack and updates the APK builder to enable static linking of the sample app.

Changes

  • Added coreclr_static.a to the runtime pack
  • Updated the APK builder to support static linking

Validation

Added a functional test in the runtime pipeline to validate static linking.

Out-of-scope

Runtime modularization is tracked in #114737
CMake export module is tracked in #115362

@kotlarmilos kotlarmilos self-assigned this Apr 14, 2025
@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 14, 2025
@kotlarmilos kotlarmilos added area-Infrastructure-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Apr 14, 2025
@kotlarmilos kotlarmilos added this to the 10.0.0 milestone Apr 14, 2025
Copy link
Contributor

Tagging subscribers to this area: @hoyosjs
See info in area-owners.md if you want to be subscribed.

@@ -26,4 +26,4 @@ set (VXSORT_SOURCES
do_vxsort.h
)

add_library(gc_vxsort STATIC ${VXSORT_SOURCES})
add_library(gc_vxsort OBJECT ${VXSORT_SOURCES})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be nice to use the same style, either this one in src/coreclr/gc/unix/CMakeLists.txt or the other way around.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean to conditionally add gc_vxsort objects if android host?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That or change static to object in gc/unix as well.

Copy link
Member Author

@kotlarmilos kotlarmilos Apr 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added gc_vxsort_objects for the android host. I could also switch it from static to an object library, but I’m not sure if archive is actually being used in other scenarios.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need both, static and objects, for Android? If not, we can use an if-else block.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW: vxsort is a ton of code for relatively small performance gain. We may want to disable it on mobile. It is implemented on x64 only for now, but arm64 implementation is in the works #110692 .

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I'd prefer to switch from static to object library here instead of introducing the conditional object for Android. At least for gc_pal and gc_vxsort, since they are pretty isolated (used for coreclr and standalone gc) and I think the conditional object build makes it more complicated that just switching - as opposed to something like coreclrminipal, which would fit better as a separate change per #114629 (review).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I haven’t applied these changes to the other libraries in this PR, since I’m not sure whether they’re required as archives on other platforms.

Copy link
Member

@filipnavara filipnavara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable to me in the current incarnation. I assume we will eventually want to extend this to all mobile platforms but it's fine to do that separately.

@jkoritzinsky
Copy link
Member

I am curious, if we switch to using object files for in-tree linking instead of static archives, does that affect shipping, which currently produces and distributes .a files?

What was the error with linking static libs on Android? If we sort that out, we won't be needing this separate flavor.

I agree with @am11 here: I'd like to know what errors were being seen with the current system.

Also, for the various new "OBJECT" libraries, I'd like the "static library" flavors that are defined in the build system to be based on the object libraries (ie nativeresourcestring should gets its sources by linking to nativeresourcestring_objects).

My biggest concern with this work (and work in this general direction) is that the CMake scripts for Mono are extremely confusing today (even for me) and it's really difficult to iterate on them. I really don't want the scripting for CoreCLR to get that confusing as well.

@kotlarmilos
Copy link
Member Author

kotlarmilos commented May 2, 2025

I agree with @am11 here: I'd like to know what errors were being seen with the current system.

Below are the linking failures for the object libraries.

coreclrminipal_objects

ld.lld: error: undefined symbol: u16_strlen(char16_t const*)
>>> referenced by rwutil.cpp:27 (/Users/miloskotlar/dotnet/runtime/src/coreclr/md/enc/rwutil.cpp:27)
>>>               rwutil.cpp.o:(Unicode2UTF(char16_t const*, char*, int)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by eventpipehelpers.cpp:65 (eventpipe/eventpipehelpers.cpp:65)
>>>               eventpipehelpers.cpp.o:(WriteToBuffer(char16_t const*, unsigned char*&, unsigned long&, unsigned long&, bool&)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by sstring.inl:389 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/sstring.inl:389)
>>>               dllimport.cpp.o:(ILStubState::TruncateUnicodeString(SString&, unsigned int)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 149 more times
ld.lld: error: undefined symbol: u16_strtoui64(char16_t const*, char16_t**, int)
>>> referenced by gcenv.ee.cpp:1281 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/gcenv.ee.cpp:1281)
>>>               gcenv.ee.cpp.o:(GCToEEInterface::GetIntConfigValue(char const*, char const*, long*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by eventtracebase.h:385 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/eventtracebase.h:385)
>>>               eventtrace.cpp.o:(XplatEventLoggerConfiguration::Parse(char16_t*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by configuration.cpp:86 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/configuration.cpp:86)
>>>               configuration.cpp.o:(Configuration::GetKnobULONGLONGValue(char16_t const*, unsigned long)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 3 more times
ld.lld: error: undefined symbol: u16_strtoul(char16_t const*, char16_t**, int)
>>> referenced by eventtrace.cpp:843 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/eventtrace.cpp:843)
>>>               eventtrace.cpp.o:(ETW::TypeSystemLog::PostRegistrationInit()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by eeconfig.cpp:584 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/eeconfig.cpp:584)
>>>               eeconfig.cpp.o:(EEConfig::sync()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by threads.cpp:2087 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/threads.cpp:2087)
>>>               threads.cpp.o:(ParseDefaultStackSize(char16_t const*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 2 more times
ld.lld: error: undefined symbol: u16_strchr(char16_t const*, char16_t)
>>> referenced by eventtracebase.h:549 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/eventtracebase.h:549)
>>>               eventtrace.cpp.o:(XplatEventLogger::InitializeLogger()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by eventtracebase.h:358 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/eventtracebase.h:358)
>>>               eventtrace.cpp.o:(XplatEventLoggerConfiguration::Parse(char16_t*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by eventtracebase.h:358 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/eventtracebase.h:358)
>>>               eventtrace.cpp.o:(XplatEventLoggerConfiguration::Parse(char16_t*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 2 more times
ld.lld: error: undefined symbol: u16_strncpy_s(char16_t*, unsigned long, char16_t const*, unsigned long)
>>> referenced by eventtracebase.h:374 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/eventtracebase.h:374)
>>>               eventtrace.cpp.o:(XplatEventLoggerConfiguration::Parse(char16_t*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by eventtracebase.h:407 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/eventtracebase.h:407)
>>>               eventtrace.cpp.o:(XplatEventLoggerConfiguration::Parse(char16_t*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: u16_strcmp(char16_t const*, char16_t const*)
>>> referenced by nativelibrary.cpp:653 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/nativelibrary.cpp:653)
>>>               nativelibrary.cpp.o:((anonymous namespace)::LoadNativeLibraryBySearch(Assembly*, int, int, unsigned int, (anonymous namespace)::LoadLibErrorTracker*, char16_t const*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by ceesectionstring.cpp:73 (/Users/miloskotlar/dotnet/runtime/src/coreclr/md/ceefilegen/ceesectionstring.cpp:73)
>>>               ceesectionstring.cpp.o:(CeeSectionString::getEmittedStringRef(char16_t*, unsigned int*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by controller.cpp:8590 (/Users/miloskotlar/dotnet/runtime/src/coreclr/debug/ee/controller.cpp:8590)
>>>               controller.cpp.o:(DebuggerUserBreakpoint::IsFrameInDebuggerNamespace(FrameInfo*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 20 more times
ld.lld: error: undefined symbol: u16_strncmp(char16_t const*, char16_t const*, unsigned long)
>>> referenced by genanalysis.cpp:31 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/genanalysis.cpp:31)
>>>               genanalysis.cpp.o:(GenAnalysis::Initialize()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by emit.cpp:117 (/Users/miloskotlar/dotnet/runtime/src/coreclr/md/compiler/emit.cpp:117)
>>>               emit.cpp.o:(RegMeta::DefineMethod(unsigned int, char16_t const*, unsigned int, unsigned char const*, unsigned int, unsigned int, unsigned int, unsigned int*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by bundle.cpp:68 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/bundle.cpp:68)
>>>               bundle.cpp.o:(Bundle::Probe(SString const&, bool) const) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 3 more times
ld.lld: error: undefined symbol: u16_strrchr(char16_t const*, char16_t)
>>> referenced by eeconfig.cpp:369 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/eeconfig.cpp:369)
>>>               eeconfig.cpp.o:(EEConfig::sync()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: VMToOSInterface::CreateDoubleMemoryMapper(void**, unsigned long*)
>>> referenced by executableallocator.cpp:288 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/executableallocator.cpp:288)
>>>               executableallocator.cpp.o:(ExecutableAllocator::StaticInitialize(void (*)(unsigned int, char16_t const*))) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: VMToOSInterface::ReleaseRWMapping(void*, unsigned long)
>>> referenced by executableallocator.cpp:320 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/executableallocator.cpp:320)
>>>               executableallocator.cpp.o:(ExecutableAllocator::UpdateCachedMapping(ExecutableAllocator::BlockRW*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by executableallocator.cpp:320 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/executableallocator.cpp:320)
>>>               executableallocator.cpp.o:(ExecutableAllocator::Release(void*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by executableallocator.cpp:960 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/executableallocator.cpp:960)
>>>               executableallocator.cpp.o:(ExecutableAllocator::UnmapRW(void*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: VMToOSInterface::CommitDoubleMappedMemory(void*, unsigned long, bool)
>>> referenced by executableallocator.cpp:497 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/executableallocator.cpp:497)
>>>               executableallocator.cpp.o:(ExecutableAllocator::Commit(void*, unsigned long, bool)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: VMToOSInterface::ReleaseDoubleMappedMemory(void*, void*, unsigned long, unsigned long)
>>> referenced by executableallocator.cpp:551 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/executableallocator.cpp:551)
>>>               executableallocator.cpp.o:(ExecutableAllocator::Release(void*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: VMToOSInterface::ReserveDoubleMappedMemory(void*, unsigned long, unsigned long, void const*, void const*)
>>> referenced by executableallocator.cpp:681 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/executableallocator.cpp:681)
>>>               executableallocator.cpp.o:(ExecutableAllocator::ReserveWithinRange(unsigned long, void const*, void const*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by executableallocator.cpp:773 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/executableallocator.cpp:773)
>>>               executableallocator.cpp.o:(ExecutableAllocator::Reserve(unsigned long)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: VMToOSInterface::GetRWMapping(void*, void*, unsigned long, unsigned long)
>>> referenced by executableallocator.cpp:904 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/executableallocator.cpp:904)
>>>               executableallocator.cpp.o:(ExecutableAllocator::MapRW(void*, unsigned long, ExecutableAllocator::CacheableMapping)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: u16_strcpy_s(char16_t*, unsigned long, char16_t const*)
>>> referenced by assembly.cpp:1060 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/assembly.cpp:1060)
>>>               assembly.cpp.o:(Assembly::AddDiagnosticStartupHookPath(char16_t const*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by assembly.cpp:1066 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/assembly.cpp:1066)
>>>               assembly.cpp.o:(Assembly::AddDiagnosticStartupHookPath(char16_t const*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by assembly.cpp:1070 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/assembly.cpp:1070)
>>>               assembly.cpp.o:(Assembly::AddDiagnosticStartupHookPath(char16_t const*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 1 more times
ld.lld: error: undefined symbol: u16_strstr(char16_t const*, char16_t const*)
>>> referenced by stresslog.cpp:166 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/stresslog.cpp:166)
>>>               stresslog.cpp.o:(ReplacePid(char16_t const*, char16_t*, unsigned long)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a

eventprovider_objects

ld.lld: error: undefined symbol: FireEtXplatAllocationSampled
>>> referenced by clretwallmain.h:3718 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:3718)
>>>               gchelpers.cpp.o:(FireAllocationSampled(GC_ALLOC_FLAGS, unsigned long, unsigned long, Object*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatGCFinalizersBegin_V1
>>> referenced by clretwallmain.h:562 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:562)
>>>               finalizerthread.cpp.o:(FinalizerThread::FinalizeAllObjects()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatGCFinalizersEnd_V1
>>> referenced by clretwallmain.h:535 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:535)
>>>               finalizerthread.cpp.o:(FinalizerThread::FinalizeAllObjects()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolWorkerThreadStart
>>> referenced by clretwallmain.h:1183 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1183)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolWorkerThreadStart) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolWorkerThreadStop
>>> referenced by clretwallmain.h:1199 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1199)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolWorkerThreadStop) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolWorkerThreadWait
>>> referenced by clretwallmain.h:1303 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1303)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolWorkerThreadWait) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolMinMaxThreads
>>> referenced by clretwallmain.h:1337 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1337)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolMinMaxThreads) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolWorkerThreadAdjustmentSample
>>> referenced by clretwallmain.h:1246 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1246)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolWorkerThreadAdjustmentSample) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolWorkerThreadAdjustmentAdjustment
>>> referenced by clretwallmain.h:1263 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1263)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolWorkerThreadAdjustmentAdjustment) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolWorkerThreadAdjustmentStats
>>> referenced by clretwallmain.h:1287 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1287)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolWorkerThreadAdjustmentStats) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolIOEnqueue
>>> referenced by clretwallmain.h:1399 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1399)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolIOEnqueue) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolIODequeue
>>> referenced by clretwallmain.h:1415 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1415)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolIODequeue) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolWorkingThreadCount
>>> referenced by clretwallmain.h:1352 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1352)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolWorkingThreadCount) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatThreadPoolIOPack
>>> referenced by clretwallmain.h:1431 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1431)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogThreadPoolIOPack) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatContentionLockCreated
>>> referenced by clretwallmain.h:1741 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1741)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogContentionLockCreated) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by clretwallmain.h:1741 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1741)
>>>               syncblk.cpp.o:(AwareLock::EnterEpilogHelper(Thread*, int)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatContentionStart_V2
>>> referenced by clretwallmain.h:1694 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1694)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogContentionStart) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by clretwallmain.h:1694 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1694)
>>>               syncblk.cpp.o:(AwareLock::EnterEpilogHelper(Thread*, int)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatFailFast
>>> referenced by clretwallmain.h:7144 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:7144)
>>>               eepolicy.cpp.o:(EEPolicy::LogFatalError(unsigned int, unsigned long, char16_t const*, _EXCEPTION_POINTERS*, char16_t const*, char16_t const*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by clretwallmain.h:7144 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:7144)
>>>               eepolicy.cpp.o:(FireEtwFailFast(char16_t const*, void const*, unsigned int, unsigned int, unsigned short, minipal_guid__ const*, minipal_guid__ const*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by clretwallmain.h:7144 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:7144)
>>>               jithelpers.cpp.o:(DoJITFailFast) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 1 more times
ld.lld: error: undefined symbol: FireEtXplatContentionStop_V1
>>> referenced by clretwallmain.h:1725 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1725)
>>>               nativeeventsource.cpp.o:(NativeRuntimeEventSource_LogContentionStop) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by clretwallmain.h:1725 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:1725)
>>>               syncblk.cpp.o:(AwareLock::EnterEpilogHelper(Thread*, int)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatAllocRequest
>>> referenced by clretwallmain.h:7307 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:7307)
>>>               explicitcontrolloaderheap.cpp.o:(ExplicitControlLoaderHeap::AllocMemForCode_NoThrow(unsigned long, unsigned long, unsigned int, unsigned long)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by clretwallmain.h:7307 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:7307)
>>>               loaderheap.cpp.o:(UnlockedLoaderHeap::UnlockedAllocMem_NoThrow(unsigned long)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: undefined symbol: FireEtXplatEEStartupStart_V1
>>> referenced by clretwallmain.h:5330 (/Users/miloskotlar/dotnet/runtime/artifacts/obj/coreclr/android.x64.Release/inc/clretwallmain.h:5330)
>>>               ceemain.cpp.o:(EEStartupHelper()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
ld.lld: error: too many errors emitted, stopping now (use --error-limit=0 to see all errors)

nativeresourcestring_objects

>>> referenced by ccomprc.cpp:536 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/ccomprc.cpp:536)
>>>               ccomprc.cpp.o:(CCompRC::LoadString(CCompRC::ResourceCategory, unsigned int, char16_t*, int, int*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a

coreclrpal_objects

lld: error: undefined symbol: PAL_InitializeCoreCLR
>>> referenced by exports.cpp:265 (/Users/miloskotlar/dotnet/runtime/src/coreclr/dlls/mscoree/exports.cpp:265)
>>>               exports.cpp.o:(coreclr_initialize) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
lld: error: undefined symbol: MultiByteToWideChar
>>> referenced by exports.cpp:80 (/Users/miloskotlar/dotnet/runtime/src/coreclr/dlls/mscoree/exports.cpp:80)
>>>               exports.cpp.o:(StringToUnicode(char const*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by exports.cpp:86 (/Users/miloskotlar/dotnet/runtime/src/coreclr/dlls/mscoree/exports.cpp:86)
>>>               exports.cpp.o:(StringToUnicode(char const*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by fstring.cpp:188 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/fstring.cpp:188)
>>>               fstring.cpp.o:(FString::Utf8_Unicode_Length(char const*, bool*, unsigned int*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 46 more times
lld: error: undefined symbol: PAL_Shutdown
>>> referenced by exports.cpp:371 (/Users/miloskotlar/dotnet/runtime/src/coreclr/dlls/mscoree/exports.cpp:371)
>>>               exports.cpp.o:(coreclr_shutdown) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by exports.cpp:403 (/Users/miloskotlar/dotnet/runtime/src/coreclr/dlls/mscoree/exports.cpp:403)
>>>               exports.cpp.o:(coreclr_shutdown_2) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
lld: error: undefined symbol: _vsnprintf_s
>>> referenced by exports.cpp:504 (/Users/miloskotlar/dotnet/runtime/src/coreclr/dlls/mscoree/exports.cpp:504)
>>>               exports.cpp.o:(LogErrorToHost(char const*, ...)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by sstring.cpp:1743 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/sstring.cpp:1743)
>>>               sstring.cpp.o:(SString::VPrintf(char const*, __va_list_tag*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by sstring.cpp:1772 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/sstring.cpp:1772)
>>>               sstring.cpp.o:(SString::VPrintf(char const*, __va_list_tag*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 1 more times
lld: error: undefined symbol: RaiseException
>>> referenced by safecrt.h:327 (/Users/miloskotlar/dotnet/runtime/src/coreclr/pal/inc/rt/safecrt.h:327)
>>>               clrconfig.cpp.o:(CLRConfig::GetConfigValue(CLRConfig::ConfigStringInfo const&, char16_t**)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by safecrt.h:327 (/Users/miloskotlar/dotnet/runtime/src/coreclr/pal/inc/rt/safecrt.h:327)
>>>               clrconfig.cpp.o:((anonymous namespace)::EnvGetString(char16_t const*, CLRConfig::LookupOptions)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by safecrt.h:327 (/Users/miloskotlar/dotnet/runtime/src/coreclr/pal/inc/rt/safecrt.h:327)
>>>               clrconfig.cpp.o:((anonymous namespace)::EnvGetString(char16_t const*, CLRConfig::LookupOptions)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 73 more times
lld: error: undefined symbol: GetEnvironmentStringsW
>>> referenced by clrconfig.cpp:641 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/clrconfig.cpp:641)
>>>               clrconfig.cpp.o:(CLRConfig::Initialize()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by ep-rt-coreclr.h:1163 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h:1163)
>>>               unity_0_cxx.cxx.o:(ds_env_info_payload_init(_DiagnosticsEnvironmentInfoPayload*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by qcallentrypoints.cpp
>>>               qcallentrypoints.cpp.o:(s_QCall) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
lld: error: undefined symbol: FreeEnvironmentStringsW
>>> referenced by clrconfig.cpp:684 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/clrconfig.cpp:684)
>>>               clrconfig.cpp.o:(CLRConfig::Initialize()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by ep-rt-coreclr.h:1170 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h:1170)
>>>               unity_0_cxx.cxx.o:(ds_env_info_payload_init(_DiagnosticsEnvironmentInfoPayload*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by qcallentrypoints.cpp
>>>               qcallentrypoints.cpp.o:(s_QCall) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
lld: error: undefined symbol: PAL_GetNativeExceptionHolderHead
>>> referenced by pal.h:4216 (/Users/miloskotlar/dotnet/runtime/src/coreclr/pal/inc/pal.h:4216)
>>>               clrconfig.cpp.o:((anonymous namespace)::EnvGetString(char16_t const*, CLRConfig::LookupOptions)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by pal.h:4216 (/Users/miloskotlar/dotnet/runtime/src/coreclr/pal/inc/pal.h:4216)
>>>               codeversion.cpp.o:(CodeVersionManager::PublishNativeCodeVersion(MethodDesc*, NativeCodeVersion)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by pal.h:4216 (/Users/miloskotlar/dotnet/runtime/src/coreclr/pal/inc/pal.h:4216)
>>>               codeversion.cpp.o:(CodeVersionManager::GetOrCreateILCodeVersioningState(Module*, unsigned int, ILCodeVersioningState**)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 301 more times
lld: error: undefined symbol: SetLastError
>>> referenced by clrconfig.cpp:219 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/clrconfig.cpp:219)
>>>               clrconfig.cpp.o:((anonymous namespace)::EnvGetString(char16_t const*, CLRConfig::LookupOptions)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by clrhost.h:41 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/clrhost.h:41)
>>>               callcounting.cpp.o:(CallCountingManager::OnCallCountThresholdReached(TransitionBlock*, unsigned long)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by clrhost.h:41 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/clrhost.h:41)
>>>               callcounting.cpp.o:(CallCountingManager::OnCallCountThresholdReached(TransitionBlock*, unsigned long)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 34 more times
lld: error: undefined symbol: WideCharToMultiByte
>>> referenced by fstring.cpp:68 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/fstring.cpp:68)
>>>               fstring.cpp.o:(FString::Unicode_Utf8_Length(char16_t const*, bool*, unsigned int*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by fstring.cpp:134 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/fstring.cpp:134)
>>>               fstring.cpp.o:(FString::Unicode_Utf8(char16_t const*, bool, char*, unsigned int)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by stgpool.cpp:987 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/stgpool.cpp:987)
>>>               stgpool.cpp.o:(StgStringPool::AddStringW(char16_t const*, unsigned int*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 29 more times
lld: error: undefined symbol: GetLastError
>>> referenced by utilcode.h:615 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/utilcode.h:615)
>>>               fstring.cpp.o:(FString::Unicode_Utf8_Length(char16_t const*, bool*, unsigned int*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by utilcode.h:615 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/utilcode.h:615)
>>>               fstring.cpp.o:(FString::Unicode_Utf8(char16_t const*, bool, char*, unsigned int)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by utilcode.h:615 (/Users/miloskotlar/dotnet/runtime/src/coreclr/inc/utilcode.h:615)
>>>               fstring.cpp.o:(FString::Utf8_Unicode_Length(char const*, bool*, unsigned int*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 87 more times
lld: error: undefined symbol: GetACP
>>> referenced by sstring.cpp:43 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/sstring.cpp:43)
>>>               sstring.cpp.o:(SString::Startup()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
lld: error: undefined symbol: PAL_FreeExceptionRecords
>>> referenced by pal.h:3988 (/Users/miloskotlar/dotnet/runtime/src/coreclr/pal/inc/pal.h:3988)
>>>               callcounting.cpp.o:(CallCountingManager::OnCallCountThresholdReached(TransitionBlock*, unsigned long)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by pal.h:3988 (/Users/miloskotlar/dotnet/runtime/src/coreclr/pal/inc/pal.h:3988)
>>>               callcounting.cpp.o:(PAL_SEHException::operator=(PAL_SEHException&&)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by pal.h:3988 (/Users/miloskotlar/dotnet/runtime/src/coreclr/pal/inc/pal.h:3988)
>>>               callcounting.cpp.o:(PAL_SEHException::~PAL_SEHException()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 42 more times
lld: error: undefined symbol: FormatMessageW
>>> referenced by sstring.cpp:1847 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/sstring.cpp:1847)
>>>               sstring.cpp.o:(SString::FormatMessageW(unsigned int, void const*, unsigned int, unsigned int, SString const&, SString const&, SString const&, SString const&, SString const&, SString const&, SString const&, SString const&, SString const&, SString const&)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by sstring.cpp:1869 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/sstring.cpp:1869)
>>>               sstring.cpp.o:(SString::FormatMessageW(unsigned int, void const*, unsigned int, unsigned int, SString const&, SString const&, SString const&, SString const&, SString const&, SString const&, SString const&, SString const&, SString const&, SString const&)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by qcallentrypoints.cpp
>>>               qcallentrypoints.cpp.o:(s_QCall) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
lld: error: undefined symbol: FlushProcessWriteBuffers
>>> referenced by callcounting.cpp:1009 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/callcounting.cpp:1009)
>>>               callcounting.cpp.o:(CallCountingManager::StopAndDeleteAllCallCountingStubs()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by threadsuspend.cpp:3324 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/threadsuspend.cpp:3324)
>>>               threadsuspend.cpp.o:(ThreadSuspend::SuspendAllThreads()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by profilinghelper.cpp:211 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/profilinghelper.cpp:211)
>>>               profilinghelper.cpp.o:(CurrentProfilerStatus::Set(ProfilerStatus)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 5 more times
lld: error: undefined symbol: CloseHandle
>>> referenced by utsem.cpp:146 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/utsem.cpp:146)
>>>               utsem.cpp.o:(UTSemReadWrite::~UTSemReadWrite()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by utsem.cpp:149 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/utsem.cpp:149)
>>>               utsem.cpp.o:(UTSemReadWrite::~UTSemReadWrite()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by fstream.cpp:240 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/fstream.cpp:240)
>>>               fstream.cpp.o:(CFileStream::~CFileStream()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 33 more times
lld: error: undefined symbol: CreateSemaphoreExW
>>> referenced by utsem.cpp:170 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/utsem.cpp:170)
>>>               utsem.cpp.o:(UTSemReadWrite::Init()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by qcallentrypoints.cpp
>>>               qcallentrypoints.cpp.o:(s_QCall) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
lld: error: undefined symbol: CreateEventW
>>> referenced by utsem.cpp:173 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/utsem.cpp:173)
>>>               utsem.cpp.o:(UTSemReadWrite::Init()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by synch.cpp:29 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/synch.cpp:29)
>>>               synch.cpp.o:(CLREventBase::CreateAutoEvent(int)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by synch.cpp:29 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/synch.cpp:29)
>>>               synch.cpp.o:(CLREventBase::CreateAutoEventNoThrow(int)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 10 more times
lld: error: undefined symbol: WaitForSingleObjectEx
>>> referenced by utsem.cpp:255 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/utsem.cpp:255)
>>>               utsem.cpp.o:(UTSemReadWrite::LockRead()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by utsem.cpp:343 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/utsem.cpp:343)
>>>               utsem.cpp.o:(UTSemReadWrite::LockWrite()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by synch.cpp:372 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/synch.cpp:372)
>>>               synch.cpp.o:(CLREventBase::WaitEx(unsigned int, WaitMode, PendingSync*)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 3 more times
lld: error: undefined symbol: SetEvent
>>> referenced by utsem.cpp:414 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/utsem.cpp:414)
>>>               utsem.cpp.o:(UTSemReadWrite::UnlockRead()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by utsem.cpp:478 (/Users/miloskotlar/dotnet/runtime/src/coreclr/utilcode/utsem.cpp:478)
>>>               utsem.cpp.o:(UTSemReadWrite::UnlockWrite()) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced by synch.cpp:344 (/Users/miloskotlar/dotnet/runtime/src/coreclr/vm/synch.cpp:344)
>>>               synch.cpp.o:(CLREventBase::CreateMonitorEvent(unsigned long)) in archive /Users/miloskotlar/dotnet/runtime/artifacts/bin/AndroidSampleApp/x64/Release/android-x64/publish/libcoreclr_static.a
>>> referenced 18 more times
lld: error: too many errors emitted, stopping now (use --error-limit=0 to see all errors)

Also, for the various new "OBJECT" libraries, I'd like the "static library" flavors that are defined in the build system to be based on the object libraries (ie nativeresourcestring should gets its sources by linking to nativeresourcestring_objects).

Yes, I like that approach. I’ve updated the build files to define the static libraries based on the object files.

My biggest concern with this work (and work in this general direction) is that the CMake scripts for Mono are extremely confusing today (even for me) and it's really difficult to iterate on them. I really don't want the scripting for CoreCLR to get that confusing as well.

The object files are no longer conditioned on Android, they now always build the object files first, then package them into the .a archives. What did you have in mind here?

@am11
Copy link
Member

am11 commented May 2, 2025

ld.lld: error: undefined symbol: u16_strlen(char16_t const*)

These are due to missing coreclr minipal linkage (src/coreclr/minipal, which is different from cross-runtime src/native/minipal). So the static lib (.a) which contains coreclr minipal should be available in the final linkage.

ld.lld: error: undefined symbol: FireEtXplatAllocationSampled

These are due to missing event provider. Same solution, the archive containing dummy or LTTng etc. provider is missing in the final linkage.

If we can make archives link with NDK properly without modifying the output type (objects for Android vs. static lib for every other platform configuration..), that's a win.

@jkoritzinsky
Copy link
Member

My biggest concern with this work (and work in this general direction) is that the CMake scripts for Mono are extremely confusing today (even for me) and it's really difficult to iterate on them. I really don't want the scripting for CoreCLR to get that confusing as well.

The object files are no longer conditioned on Android, they now always build the object files first, then package them into the .a archives. What did you have in mind here?

Personally, I'd rather not move everything to object libraries and instead ship each of the static libs that we produce, as well as a listing of them in the correct link order (and then the Android tooling would grab all of them instead of just libcoreclr_static.a).

However, if we decide to use object libraries, I'm fine with the provided approach (linking into static libs and using target_link_libraries instead of target_sources($<TARGET_OBJECTS>). My problem with Mono is that the heavy usage of $<TARGET_OBJECTS> as well as having a wide variety of build configurations makes it exceedingly difficult to figure out the right place to add sources, libraries, etc.

@filipnavara
Copy link
Member

Personally, I'd rather not move everything to object libraries and instead ship each of the static libs that we produce, as well as a listing of them in the correct link order (and then the Android tooling would grab all of them instead of just libcoreclr_static.a).

My personal preference is to have single library. This is not going to be consumed just by Android but also by iOS workloads. We have to deal with at least 3 different linkers (lld, ld64, ld-prime) and any additional complexity is going to be PITA long term.

@am11
Copy link
Member

am11 commented May 2, 2025

My personal preference is to have single library.

We can use --start/end-group for that purpose (git grep START_LIBRARY_GROUP to see the existing usage).

cc -Wl,--start-group libone.a libtwo.a ... -Wl,--end-group

to get the combined libcoreclr_static.a without touching other targets.

@kotlarmilos
Copy link
Member Author

I’ve summarized the main differences to help us make an informed decision. Please share your thoughts so we can iterate fast toward a solution.

Option 1: Multiple static libs

Pros:

  • Modular and extensible per component
  • Easier to trace symbols

Cons:

  • More complex to consume in cross-platform toolchains
  • Requires maintaining correct link order manually?

Option 2: Single static lib via object libs

Pros:

  • Easier consumption
  • Better LTO?

Cons:

  • Harder to maintain due to multiple object files linked into single .a
  • Less modular, harder to isolate components

@kotlarmilos
Copy link
Member Author

Personally, I'd rather not move everything to object libraries and instead ship each of the static libs that we produce, as well as a listing of them in the correct link order (and then the Android tooling would grab all of them instead of just libcoreclr_static.a).

My personal preference is to have single library. This is not going to be consumed just by Android but also by iOS workloads. We have to deal with at least 3 different linkers (lld, ld64, ld-prime) and any additional complexity is going to be PITA long term.

Is there a limitation preventing this, or is it already set up this way? Is the complexity you're referring to on the consumer/ SDK side?

My take -- multiple static libraries with explicit link order offers better maintainability and modularity.

@filipnavara
Copy link
Member

Cons:

  • Harder to maintain due to multiple object files linked into single .a
  • Less modular, harder to isolate components

I fail to see how is this harder to maintain.

I am arguing against leaking the internal details of CoreCLR product composition to downstream consumers (dotnet/android and dotnet/macios). CoreCLR build system itself has to know these details already.

I am not arguing for never spliting any separate modules into their .a libraries, similar to MonoVM components. I think it's fine to split diagnostics, custom GC, event tracing or whatever else we see fit in the future. These splits should be meaningful though - ie. the downstream consumer makes a conscious decision about including or not including some component, possibly based on a user-facing option.

Is there a limitation preventing this, or is it already set up this way? Is the complexity you're referring to on the consumer/ SDK side?

The supported linkers are enforced by their respective platforms and their SDK versions. We need to support the three aforementioned linkers due to these constraints. I would very much prefer not to shift any complexity downstream.

@am11
Copy link
Member

am11 commented May 6, 2025

Harder to maintain due to multiple object files linked into single .a

I don't see how it would be harder with --start/end-group mentioned above? The main pro is it's a one liner change and single point of failure without spreading it across multiple files and multiple repos which would, otherwise, need to account for each archive separately.

@kotlarmilos
Copy link
Member Author

Harder to maintain due to multiple object files linked into single .a

We must ensure that the runtime includes the same source or object files in both the component libraries and the coreclr_static.a archive. This complexity has to be managed somewhere, and it depends on how we view the runtime: as a modular package that makes no decisions about linking, or as a complete archive bundling all components.

I am not arguing for never spliting any separate modules into their .a libraries, similar to MonoVM components. I think it's fine to split diagnostics, custom GC, event tracing or whatever else we see fit in the future. These splits should be meaningful though - ie. the downstream consumer makes a conscious decision about including or not including some component, possibly based on a user-facing option.

This sounds like reasonable tradeoff. Do we already have clear split? If yes, I suggest proceeding that way. If not, I suggest keeping the single archive file and working on modularization in the future.

@filipnavara
Copy link
Member

Do we already have clear split? If yes, I suggest proceeding that way. If not, I suggest keeping the single archive file and working on modularization in the future.

No, we don't have modularization in CoreCLR yet. At some point we will likely end up with base + JIT + interpreter libraries (both static and dynamic) where some workloads will optionally skip JIT, interpreter or both. I'd worry about it when we get there.

@am11
Copy link
Member

am11 commented May 6, 2025

We must ensure that the runtime includes the same source or object files in both the component libraries and the coreclr_static.a archive. This complexity has to be managed somewhere, and it depends on how we view the runtime: as a modular package that makes no decisions about linking, or as a complete archive bundling all components.

That needs to be ensured anyway regardless of single or multiple archives. The granularity for dynamic libs is:

% find '.dotnet/shared' -name '*so'
<prefix>/libmscordbi.so
<prefix>/libSystem.Native.so
<prefix>/libmscordaccore.so
<prefix>/libclrjit.so
<prefix>/libcoreclrtraceptprovider.so
<prefix>/libclrgcexp.so
<prefix>/libSystem.IO.Compression.Native.so
<prefix>/libcoreclr.so
<prefix>/libclrgc.so
<prefix>/libSystem.Security.Cryptography.Native.OpenSsl.so
<prefix>/libSystem.Globalization.Native.so
<prefix>/libhostpolicy.so
<prefix>/libSystem.Net.Security.Native.so

static libs can use the same to keep things self explanatory. Notice the two GC flavors, that's pretty much the customization needed for coreclr thus far (nativeaot has more options which is a separate discussion). The rest is internal detail.

@filipnavara
Copy link
Member

The granularity for dynamic libs is:

I think it's reaonable expectation to have the same granularity for static and dynamic libs, thus allowing the build scripts to just append .a or .so as appropriate. I think that dotnet/macios was historically using such approach.

@steveisok
Copy link
Member

Harder to maintain due to multiple object files linked into single .a

I don't see how it would be harder with --start/end-group mentioned above? The main pro is it's a one liner change and single point of failure without spreading it across multiple files and multiple repos which would, otherwise, need to account for each archive separately.

My vote is to produce one static lib using this approach.

@am11
Copy link
Member

am11 commented May 6, 2025

My vote is to produce one static lib using this approach.

I think it's almost the same suggestion as aligning it with shared framework. e.g. we can bundle libcoreclr.a and libclrjit.a, while keeping GC flavors separate; unless we don't want to support multiple flavors (ServerGC vs. WorkstationGC distinction), then we can merge that in libcoreclr as well. Then debugging components: libmscordbi.a and libmscordaccore.a could be bundled together. Eventing libcoreclrtraceptprovider.a can be skipped as LTTng-ust doesn't work in static mode (tries to dlopen liblttng-ust, which is also optional). Remaining libs are native shims for src/libraries or corehost related.

Singlefilehost uses coreclr_static today:

so this could also be a good point of reference in terms of precedence.

@elinor-fung
Copy link
Member

I'd vote for starting with just one static lib coreclr_static (I actually thought singlefilehost was pretty close to using this until this PR). And then aligning with the current dynamic lib granularity if necessary / desired for componentization.

I don't think anything we do for single coreclr_static makes any future separation or addition of shipping static libs more complicated.

  • coreclr and clrjit are already be bundled together for regular single-file
  • We don't use standalone GC by default. I think any separation of flavors would be a broader change that should be separate from this one. I believe the existing separation is clrgc uses segments and clrgcexp uses regions (and experimental features?)
  • Event provider functionality is rather interwoven in the runtime, so we have the dummy event provider - I think than means it already doesn't use coreclrtraceptprovider.
  • Debugging components are already / should stay separate from coreclr_static

@jkoritzinsky
Copy link
Member

Looking over the conversation and the code, I think I'm okay with one static lib. Here's my preferences for the CMake/infra side of it:

  • Limit usage of TARGET_OBJECTS as that breaks CMake's target interface system (good in this PR so far)
  • We should strongly consider putting all platforms on the same path for coreclr_static instead of making Android different. Having one platform that's different like this makes maintainability much more difficult.

The only alternative that I think would be worthwhile would be to use CMake exports to generate a CMake module that the AppleAppBuilder and AndroidAppBuilder templates would consume (and as such would allow the runtime to control the complexity and the various templates just say "link against this target"). With that option, we'd limit the amount of knowledge that consuming repos would need to have. As this is more work though, I'm fine with the single static-lib approach.

@steveisok
Copy link
Member

Thanks @elinor-fung @jkoritzinsky @am11 @filipnavara for chiming in. Seems like we have good alignment.

@steveisok
Copy link
Member

The only alternative that I think would be worthwhile would be to use CMake exports to generate a CMake module that the AppleAppBuilder and AndroidAppBuilder templates would consume (and as such would allow the runtime to control the complexity and the various templates just say "link against this target").

That's a pretty good idea for us to do at some point now that you mention it.

@kotlarmilos
Copy link
Member Author

The only alternative that I think would be worthwhile would be to use CMake exports to generate a CMake module that the AppleAppBuilder and AndroidAppBuilder templates would consume (and as such would allow the runtime to control the complexity and the various templates just say "link against this target"). With that option, we'd limit the amount of knowledge that consuming repos would need to have. As this is more work though, I'm fine with the single static-lib approach.

Created a tracking issue: #115362

@jkoritzinsky Are we good to proceed with the current changes?

@jkoritzinsky
Copy link
Member

Yes, we're good to proceed.

@kotlarmilos kotlarmilos requested a review from jkoritzinsky May 7, 2025 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

9 participants