Hiya,

I've got a module I'm building that is half C and half Swift, I'm trying to link it into a program with all swift compiled in embedded mode. I used to do import AVR (the module is called AVR rather confusingly) in my programs and the object file would contain a swift1_autolink_entries that listed linker commands for the static libraries I needed, like -lAVR. So I could adapt my tooling to read this and add it to the link.

(side note: Given I'm using llvm, it should have been possible via llvm metadata, but that might be a limitation of linking ELF rather than macho.)

But either way, the issue is since I turned on embedded mode on the compiler, this section doesn't seem to be emitted any more. And I've no way of automatically getting the static libraries required to put into the link now.

Looking at the code in IRGenModule.cpp it looks like perhaps this might be the trouble...

void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) {
  // The debugger gets the autolink information directly from
  // the LinkLibraries of the module, so there's no reason to
  // emit it into the IR of debugger expressions.
  if (Context.LangOpts.DebuggerSupport)
    return;

  if (Context.LangOpts.hasFeature(Feature::Embedded))
    return;
...

...as I read this, in embedded mode, auto linking is automatically disabled. Is there a reason this has to be the case? Is there perhaps another mechanism I should be using?

Regards,
Carl

1 Like

Embedded Swift currently doesn't link Swift libraries in the traditional way, instead library code is "pulled" into the client module's build as needed (this is somewhat documented at https://github.com/swiftlang/swift/blob/main/docs/EmbeddedSwift/UserManual.md#libraries-and-modules-in-embedded-swift). So I'd expect that in many cases you won't need to link the .a files for libraries at all (that is the case e.g. for the stdlib). That's the reason why autolinking is disabled for Embedded Swift.

Do you actually need to link your libraries? What are they, can you explain your setup?

1 Like

Ok, makes sense. I see.

This might be somewhat me using the compiler in a somewhat unintended way.

Our main hardware module, which I call “AVR” is hybrid. Most of the logic is written in C and the functions e.g. “_digitalWrite” that then have small Swift “shims” over the top like “digitalWrite” that mostly just act as a pass through, creating slightly nicer Swift interfaces and calling the underlying C function.

Both the C and the Swift code end up in the same module and the same standard library. I have a modulemap file that defines the AVR module with headers for the C functions and a link clause for the static library.

The swift files are compiled with “import-underlying-library” then the object files compiled from the swift source and the object files compiled from the C source code are all collated into one static library.

Before embedded Swift, importing this library into a Swift program would result in linking the static library and it all worked.

I’m thinking there are a few ways forward.

Probably the obvious think to do is separate these files into two modules. One is written in embedded Swift and it imports the other which is a classic C module. That’s probably a bit more canonical. I think hybrid modules are odd. And I think they’re not well supported by SPM when we manage to get that working.