Question about LDC and --gc-sections

Joakim dlang at joakim.fea.st
Fri Oct 26 06:02:51 UTC 2018


On Thursday, 25 October 2018 at 17:19:05 UTC, H. S. Teoh wrote:
> I'm currently working on an Android project that has a 
> significant D component, and using LDC to cross-compile to ARM. 
> (Much thanks to Joakim, BTW, who wrote detailed instructions on 
> the wiki on how to set this up.)  Since Android requires a .so 
> file, I have to statically link everything into a single .so.  
> However, I'm finding that the resulting .so has tons of unused 
> symbols that bloat the size to about 5MB (~1.6MB after the 
> Android SDK tools compress everything, of which only about 
> 100KB is my actual D code).
>
> Since LDC's libdruntime.a and libphobos2.a already have every 
> function in its own section, technically the linker *ought* to 
> be able to strip out most of the unreferenced sections.  
> However, running the linker with --gc-sections doesn't seem to 
> reduce the file size significantly, and many unused sections 
> are still present.  Stripping the file with `strip` afterwards 
> still leaves over 10,000 symbols, far too many given the 
> current size of my D code, and clearly an indication of a ton 
> of stuff in druntime/phobos that I don't actually use. I 
> suspect it may be because the target is an .so rather than an 
> executable, so the linker may be leaving in all public symbols 
> as a precaution.
>
> How do I tell the linker (clang) to drop everything except the 
> small handful of entry points required by the Android API?

Apparently this is a problem for C++ too:

https://stackoverflow.com/questions/18115598/how-to-remove-all-unused-symbols-from-a-shared-library

I don't know if D provides some way to change symbol visibility 
in object files, not an issue I've looked at.

Btw, are you writing a mostly native app that calls some D code 
or a Java app that calls some native code? I ask because I ran 
into an issue before depending on how it's set up, though you 
won't hit this if you're using D in betterC mode.

The difference is that there are two ways of calling native code 
on Android:

1. You can have the Android Java runtime directly call native 
code on _startup_ if you provide some standard native functions 
that it expects:

https://developer.android.com/ndk/reference/group/native-activity#group___native_activity_1ga02791d0d490839055169f39fdc905c5e

2. You have your Java app call some native functions using JNI.

Both have been tried with D, but the latter may present some 
difficulty for initializing the D runtime and GC. When I tried 
the latter with a sample app, it seemed to be loading the D 
library _every time_ the D functions were called, so I had to add 
a call to rt_init every time the function was called:

https://github.com/joakim-noah/android/blob/master/samples/bitmap-plasma/jni/plasma.d#L357

I initially had that call inside the initialization check just 
below, and it wouldn't work. I never investigated further though, 
as I have no interest in using D that way, I could be completely 
off on my guess as to why it didn't work.

For the way I use D and test it, the rt_init is called once on 
startup, as noted on the wiki, so everything works:

https://wiki.dlang.org/Build_D_for_Android#Changes_for_Android

Of course, you can always call Java functions through JNI if you 
go this route, as the Teapot sample app demonstrates, just 
something to consider in how you call D code.


More information about the Digitalmars-d mailing list