"Who" defines / influences the linker invocation in a SwiftPM build of a swift target?

As described here I am hoping to get a statically-linked dynamic library of our Android app to reduce size and loading overhead.

Long story short, I've identified three things that I'd like to change in the Android linker invocation when running swift build --static-swift-stdlib, but I've never really worked on the compiler before so I don't know where to start:

  1. Currently the wrong library search path is being set (we want -L${SDK}/usr/lib/**swift_static**/android, not -L${SDK}/usr/lib/swift/android)
  2. We need to always add -lDispatchStubs to static builds to avoid runtime link errors.
  3. (Bonus) I noticed when running swift build --static-swift-stdlib on a lonesome C target, libswiftCore.so is still being dynamically linked. I'm pretty sure that makes no sense for two reasons. That may be more difficult to understand/fix, but I'd be interested to try.

Can anyone give me a pointer about where to look for this kind of thing? The Android build uses ldd, but I'm also not sure how/why that is set either.

Have you tried passing -v flag to swift build --static-swift-stdlib? Looking at the sequence of commands exposed by that flag is where I'd start.

I did indeed :) That's how I established the changes I need to make. Now I need to figure out how to change the compiler/frontend/SwiftPM (I don't know which) so it produces the right invocation – that's what I'd need an initial pointer on (just knowing which one of those places to change would already be a big help) :pray:

As Max points out, simply running SPM in verbose mode gives you a lot of info. I just tried your SPM command with some Swift packages, both compiling natively for linux and natively on my Android phone, and both produced the right lib/swift_static/ directory. If you look at that output, SPM simply passes the -static-stdlib flag to the Swift compiler, though it only does so for executables and snippets, not for dynamic libraries.

As for DispatchStubs, this line added it automatically a couple years ago, but if you stopped using Dispatch and Foundation, I guess you'll have to add it back manually, probably here.

1 Like

To answer my original question, "who" turns out to be "us": In our SwiftPM destination.json, we are setting the -resource-dir to ${TOOLCHAIN}/usr/lib/swift.

From what I can tell, there is some machinery in the compiler to -use-static-resource-dir when the -static-stdlib option is applied (which FYI does appear to be sent to the compiler, even when building a shared library). That said, I couldn't immediately figure out what the former option actually does and whether it does anything at all wrt the linker invocation. It doesn't appear to be applied or be relevant here – I couldn't see it being passed on, and I couldn't figure out "whom" to pass it to to test the option manually (swiftc and swift -frontend both seem to reject the flag).

For our purposes, I found that it was enough to simply change the -resource-dir in destination.json to .../usr/lib/swift_static. That alone fixes all three issues listed above, including the seemingly unrelated one whereby libswiftCore.so was being linked for non-swift targets.

It would be really great to have some kind of automatic recognition that -resource-dir is just the base directory, and that --static-swift-stdlib would add _static to that path automatically. But I suspect doing so might break other workflows, so for now I will just leave this as is.

2 Likes