Compiling a dynamic framework with a statically linked library creates dependencies in ".swiftmodule" file

Steps to reproduce:

  1. Create a new project in Xcode with template Cocoa Touch Framework, and name it TestFramework.
  2. Add another target in this project with template Cocoa Touch Static Library, and name it TestLibrary.
  3. In the auto-generated file TestLibrary.swift, add a public interface like:
    public struct TestLibrary {
        public init() { }
        public let name = "static library"
    }
  1. In target TestFramework, link libTestLibrary.a.
  2. In target TestFramework, create a new file with the name TestFramework.swift.
  3. In TestFramework.swift, import TestLibrary and use the API it provides without exposing any symbol in public, like
    import TestLibrary
    public struct TestFramework {
        public init() { }
        public let library = TestLibrary().name
    }
  1. Build target TestFramework, and locate the product TestFramework.framework.
  2. Create a new project in Xcode with template Single View Application, and name it TestApplication.
  3. Drag the TestFramework.framework from step 7 into the Embedded Binaries build phase of TestApplication.
  4. In the file AppDelegate.swift of TestApplication, import TestFramework like
    import UIKit
    import TestFramework
  1. Run the app.
  2. At the line where TestFramework is imported, an error is prompted:

:exclamation: Missing required module 'TestLibrary'

  1. If you command-click on that import TestFramework, Xcode will generate the public interfaces of TestFramework, and it shows as:
    import Foundation
    import SwiftOnoneSupport
    import TestFramework
    import TestFramework.Swift
    import TestLibrary
    import UIKit
    ...

So this is where I got confused.

TestLibrary is statically linked with TestFramework, which means the binary of TestFramework has all the symbols from TestLibrary. Plus, TestFramework is not exposing any APIs from TestLibrary, but only using them. This means TestFramework is fully functional on its own regardless of TestLibrary being presented or not.

So why the .swiftmodule file of TestFramework creates an additional (probably unnecessary) dependency on TestLibrary?

As a result, when a user uses TestFramework to build an app, the app won't be able to compile because it can not find the TestLibrary, but it can run perfectly because it actually does not use TestLibrary directly if we can somehow bypass that dependency check.

So I am wondering if there is a way to remove a dependency from .swiftmodule file?
Or is there any compile/link flag I can pass in to prevent it generates any unnecessary dependency?

Just found another similar description of this problem while I was searching through the internet for a solution:
https://gist.github.com/briancroom/5d0f1b966fa9ef0ae4950e97f9d76f77

Terms of Service

Privacy Policy

Cookie Policy