Search code examples
iosswiftxcframework

How to add modulemap file to XCFramework manually?


I have an XCFramework which has the following directory structure:

.
└── WechatOpenSDK-XCFramework.xcframework
    ├── Info.plist
    ├── README.txt
    ├── ios-arm64_armv7
    │   ├── Headers
    │   │   ├── WXApi.h
    │   │   ├── WXApiObject.h
    │   │   └── WechatAuthSDK.h
    │   ├── Modules
    │   │   └── module.modulemap
    │   └── libWechatOpenSDK.a
    └── ios-arm64_i386_x86_64-simulator
        ├── Headers
        │   ├── WXApi.h
        │   ├── WXApiObject.h
        │   └── WechatAuthSDK.h
        ├── Modules
        │   └── module.modulemap
        └── libWechatOpenSDK.a

I added the Modules directory and the module.modulemap file manually. The XCFramework did not originally contain these.

For the module.modulemap file, I tried defining it as:

framework module WechatOpenSDK {
  umbrella header "WXApi.h"

  export *
  module * { export * }
}

I also tried defining it as:

framework module WechatOpenSDK {
  header "WXApi.h"
  header "WXApiObject.h"
  header "WechatAuthSDK.h"

  export *
}

However, when I drag the XCFramework into another project, regardless of how I define the module.modulemap file, I can't get import WechatOpenSDK to work.

I also tried modifying the contents of the top-level Info.plist file in the XCFramework. I removed the HeadersPath property which had a value of Headers.

My question is: Is there a way to manually add modulemap support to this XCFramework?


Solution

  • There is no functional difference between a manually packed XCFramework and one generated by Xcode. However, some manually packed frameworks may fail to work as expected.

    After some experimentation, I discovered that placing the modulemap file under the Headers folder allows Xcode to pick it up correctly. This resolves many issues related to module visibility and compatibility.

    Following is the folder structure of the xcframework

    └── WechatOpenSDK.xcframework
        ├── Info.plist
        └── ios-arm64
            ├── Headers
            │   └── WechatOpenSDK
            │       ├── WXApi.h
            │       ├── WXApiObject.h
            │       ├── WechatAuthSDK.h
            │       └── module.modulemap
            └── libWechatOpenSDK.a
    

    Important Caveat: Do not place the modulemap file directly at the root of the Headers folder. If you import two XCFrameworks with the same layout, they will collide, resulting in errors like: "Multiple commands produce … module.modulemap"

    To avoid this, ensure the modulemap file is placed in a subdirectory within the Headers folder, or use a unique naming convention for the module.

    For reference, I’ve shared my working setup for the WechatOpenSDK XCFramework here: WechatOpenSDK. Feel free to check it out if you’re facing similar issues.