SPM issue? Objective C code in Xcode project can't interact with @objc protocols in Swift Package

I'm trying to separate out some Swift @objc protocols from a mixed Swift/Obj.C framework "Utils" into a pure Swift local SPM package "Adapters", which declares a static library target that gets imported by the framework.

However, now the Obj. C code in Utils apparently doesn't recognize any of the @objc protocols that I moved into Adapters.

When the Swift @objc protocols were part of the same target as the Obj. C code itself, all I had to do is #import <Utils/Utils-Swift.h> in the Obj. C .m files and use forward declarations in the .h files.

Now that the Swift @objc protocols are part of the Swift Package however, I cannot simply replace #import <Utils/Utils-Swift.h> with @import Adapters. It won't compile, and I get confusing messages that make it seem like the Obj. C classes and properties no longer conform to the protocols that were moved into Adapters.

What am I doing wrong? Is there something else that I need to do in order to get forward declarations of @objc protocols from the Swift package to work?

I tried adding cSettings: [.define("OTHER_LDFLAGS"), to: "-ObjC")] to the Swift package, to no avail. It doesn't seem to matter if I declare the package's product as a dynamic or static library. I also tried adding @_exported import Adapters to a file in Utils, but it didn't help.

I've done quite a bit of googling, and found several cases of other people having similar sorts of issues, and I tried a variety of possible solutions. But so far nothing helped and I have not been able to find a workaround:

Any help or advice would be most welcome! Thanks


Note: The only workaround I found so far is to perform the following steps:

  1. Create an Xcode project from the Swift Package using swift package generate-xcodeproj
  2. Link Utils to the Adapters.framework defined by that Xcode project
  3. Add a Copy Headers build phase to Adapters framework
  4. Add a public header Adapters.h to the Adapters framework
  5. Add #import <Adapters/Adapters-Swift.h> to the public header Adapters.h

Now, the build succeeds. However my understanding of Swift packages is that you cannot have a mixed Swift & Obj.C SPM package. Even if you could, I don't know how to add the equivalent of a Headers build phase to a Swift package. Please advise, thanks!


Note 2: When I inspect the Adapters.framework that gets built from the Swift package, it's always missing a Headers folder, even if I add publicHeadersPath: "Headers" to Package.swift. This seems to be the reason that Obj. C in other modules is unable to see the compatibility header, but I don't know what to add to the Package.swift file to get Headers to be properly added to the framework.

3 Likes

OK just found that this issue is resolved in Xcode 12.5 / Swift Package Manager 5.4. The problem is that 5.3 and earlier does not create a Headers folder in the framework.

Do you have a link to the related issue resolution?

Nevermind, I was wrong. It's actually NOT resolved in 5.4. I just had neglected to clear my DerivedData folder after I switched one of our modules from being an Xcode project, to being a Swift package.

So yeah, SPM still can't make a Swift module that's visible to Obj. C. [SR-14575] Frameworks built from Swift packages lack a Headers folder · Issue #4430 · apple/swift-package-manager · GitHub

Do they have anyone at Apple who is actually testing SPM or working with it? Seems very much like an alpha version right now based on all the bugs we've been having with it. It's making me regret using it every day.