[Embedded] swift auto linking of static libraries broken?

In our toolchain, we rely on automatic linking, so when a user imports a module, e.g. import AVR, our Makefile adds to the link command.

While lld may be able to do that fully automatically with the llvm metadata llvm.linker.options, we have had some issues in the past (plus at one point we gave the option of using gold or gnu ld instead of lld, which doesn't work with llvm metadata).

So to make this automatic linking work reliably, just before we invoke the link command, we scan all of the main object files in our link for the contents the sections .swift1_autolink_entries. Usually that contains something like -lAVR which Swift automatically creates, and we append those to the linker command. That has worked well for us for a few years.

However, if I turn on -enable-experimental-feature Embedded, this section seems to no longer be produced. And llvm.linker.options is empty, so lld doesn't automatically include the required static libraries in the link, we would have to find a way for users to manually specify them or something in every project, which is a bit of a nuisance.

I'm wondering, is this by design for the embedded mode?

If not, I can take a look through to find the bug, although probably other people will be far quicker than me?

Also, is there something I'm doing wrong that means the llvm.linker.options metadata is not being populated in our bitcode files? (That's something we've never had reliably so we've probably done something wrong there.)

Any help would be much appreciated!

Regards,
Carl

1 Like

Ive actually found the opposite to be the case; where if you define a package building a library the symbols get imported twice, once via linking, and once via inlining. The package-based-building is not yet fully finished so I chucked that into the "it isn't done yet bucket" but perhaps this is the same issue.

Are you building swiftmodules or static library archives? Auto-link does seem to work for the swift module side (perhaps too well).

In the case of the AVR module, I’m building both! It’s a hybrid C and swift module with a module map file that describes the C “underlying module”. In the final executable build I make sure both the swiftmodule and the module map files are visible to the swift compiler on the include path. And I link with a separate command as the final step using lld. For that step I make sure the static libraries are on the library search path. It all worked up to now…

Mostly the static library contains underlying C functions with just a small amount of compiled swift. Most of the swift code is dumb wrappers around the C functions which are the functional nutty core. The swift code is almost all just inlined via the swiftmodule in the swift build step. Very little is in the static library.

—-

What’s a bit odd is I don’t understand why anything would change when embedded mode is enabled. I’m being slightly lazy here asking you guys. I can probably look through the compiler source to see what the flag changes. :) I’ll try that tomorrow.