.swiftinterface import

Hi community,

.swiftinterface includes imports to Foundation and Swift, and within custom framework dependencies, it adds related, for example import A. When I add the framework, compiler says 'No such module 'A'.

Which search paths does it refer to?

1 Like

It inherits the search paths of the module that is importing it, so if your framework needs A as a dependency, your client needs to provide search paths to find A as well.

A is already inside of a framework in Frameworks folder.

Is this a binary framework you're importing from someone else? This might be an Xcode build settings issue.

Here is .swiftinterface:

// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)
// swift-module-flags: -target x86_64-apple-ios13.2-simulator -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name FooFramework
import A
import Data
import Foundation

A is the dependency that is embedded in the FooFramework, when I embed it into any project, I get the error:

no such module 'A'

I need to specify in build Build Settings explicit path to inner dependency A of FooFramework or this is a bug?

When you say "embedded in the FooFramework", what folder structure do you mean?

Is it an umbrella framework, like this?

FooFramework.framework/
  Frameworks/
    A.framework/
      Modules/
        A.swiftmodule/
          x86_64-apple-ios13.2-simulator.swiftinterface
  Modules/
    FooFramework.swiftmodule/
      x86_64-apple-ios13.2-simulator.swiftinterface

If so, I'm pretty sure we've never supported umbrella frameworks, since they're pretty much unspecified.

Foo.framework/
  _CodeSignature/
    CodeResources
  Frameworks/
    A.framework/
      _CodeSignature/
        CodeResources
      A
      Info.plist
  Headers/
    Foo-Swift.h
    Foo.h
  Modules/
    Foo.swiftmodule/
      x86_64-apple-ios-simulator.swiftdoc
      x86_64-apple-ios-simulator.swiftinterface
      x86_64.swiftdoc
      x86_64.swiftinterface
  Foo
  Info.plist

If I put directly Foo.framework, not .xcframework, I get:

ld: warning: Could not find or use auto-linked framework 'A'

Where I should specify explicit path to it?
Tried Framework Search Paths and Library Search Paths – warning the same.

Does A.framework have a Modules directory?

No, I've provide the exact full structure.

Without a Modules directory, even with the correct search paths, the Swift compiler wouldn’t be able to load A.framework. Is it a binary framework you’ve gotten from someone else or one you’ve created yourself?

A also needs a .swiftinterface (or a .modulemap, if it’s an Objective-C framework) for Swift to be able to import it. Both of those live in the Modules directory

I've created it by xcodebuild with simple archive and -create-xcframework -framework commands.

If I make directly from xcodebuild archive, archive file contains two frameworks, A and Foo.
A has Headers and Modules folder as and Foo, but Foo also has Frameworks inside with duplication of A but with _CodeSignature, A and Info.plist.

Why does xcodebuild archive in this way?

Is A.framework a target in your project? I think Xcode (xcodebuild) archiving puts all the targets in the archive. So, you get an A.framework that can be used with any project, and a Foo.framework with A.framework embedded so you can use Foo.framework in any project.

Not a target, but a dependency as dylib of Foo.
A in Foo is not useful as framework, as it doesn't have Modules and Headers inside.

Where does A.framework come from? How is it built? The A.framework embedded in Foo.framework can't be used standalone, but the A.framework in the archive can.

A – is just dylib with simple enum, it's attached as dependency with sign & embed to Foo.
In code, Foo.swift has import to A, and Foo.init prints some case of enum from A.

When I build Foo.framework, inside of its Frameworks there aren't included Headers and Modules of A, in this case compiler cannot link with libraries to run the framework completely, regarding error with dynamic linking.

If you don’t want clients seeing your usage of A, then you can mark A’s import as @_implementationOnly import A inside Foo.

Good to know, thanks.
In my case, A should be public.

Then you’ll also need to make sure the Modules folder is installed in the resulting framework