Cocoapods: XCFramework created with static library is not working

Created on 9 Feb 2020  ยท  17Comments  ยท  Source: CocoaPods/CocoaPods

Report

What did you do?

I created a Swift+Objective-C static library and published it as xcframework via cocoapods.

What did you expect to happen?

I expected it to link with the host app. I could easily get a dynamic xcframework working with the host app, want to know whether static xcframework are currently supported by Cocoapods.

What happened instead?

I tried a lot of things but I couldn't get it to link with the host app. The host app fails to build with No such module XCFRAMEWORK_NAME

CocoaPods Environment

Stack

   CocoaPods : 1.9.0.beta.3
        Ruby : ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin18]
    RubyGems : 3.0.3
        Host : Mac OS X 10.14.5 (18F132)
       Xcode : 11.2.1 (11B500)
         Git : git version 2.21.0 (Apple Git-122.2)
Ruby lib dir : /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib
Repositories : master - git - https://github.com/CocoaPods/Specs.git @ 7a73a1f864b5d4abc0f520214dd14f0422746b6a

               trunk - CDN - https://cdn.cocoapods.org/

Installation Source

Executable Path: /usr/local/bin/pod

Plugins

cocoapods-deintegrate : 1.0.4
cocoapods-plugins     : 1.0.0
cocoapods-search      : 1.0.0
cocoapods-stats       : 1.0.0
cocoapods-trunk       : 1.4.1
cocoapods-try         : 1.1.0

Podfile

# Uncomment the next line to define a global platform for your project
platform :ios, '11.0'

target 'HostApp' do
#  use_frameworks!
  pod 'StaticXCFramework', :path => 'StaticXCFramework.podspec'
end

Project that demonstrates the issue

Static xcframework attached.
StaticXCFramework.xcframework.zip

moderate xcframeworks

All 17 comments

@amorde Please help.

Thanks for the report, will look into this when I can

This xcframework isn't in the expected format - did you create this with xcodebuild -create-xcframework or did you manually create the directory structure?

We are expecting something like this (regardless of static vs. dynamic linking):

$ tree CoconutLib.xcframework
CoconutLib.xcframework
โ”œโ”€โ”€ Info.plist
โ”œโ”€โ”€ ios-armv7_arm64
โ”‚   โ””โ”€โ”€ CoconutLib.framework
โ”‚       โ”œโ”€โ”€ CoconutLib
โ”‚       โ”œโ”€โ”€ Headers
โ”‚       โ”‚   โ”œโ”€โ”€ Coconut.h
โ”‚       โ”‚   โ””โ”€โ”€ CoconutLib.h
โ”‚       โ”œโ”€โ”€ Info.plist
โ”‚       โ””โ”€โ”€ Modules
โ”‚           โ””โ”€โ”€ module.modulemap
โ”œโ”€โ”€ ios-i386_x86_64-simulator
โ”‚   โ””โ”€โ”€ CoconutLib.framework
โ”‚       โ”œโ”€โ”€ CoconutLib
โ”‚       โ”œโ”€โ”€ Headers
โ”‚       โ”‚   โ”œโ”€โ”€ Coconut.h
โ”‚       โ”‚   โ””โ”€โ”€ CoconutLib.h
โ”‚       โ”œโ”€โ”€ Info.plist
โ”‚       โ”œโ”€โ”€ Modules
โ”‚       โ”‚   โ””โ”€โ”€ module.modulemap
โ”‚       โ””โ”€โ”€ _CodeSignature
โ”‚           โ””โ”€โ”€ CodeResources
โ”œโ”€โ”€ ios-x86_64-maccatalyst
โ”‚   โ””โ”€โ”€ CoconutLib.framework
โ”‚       โ”œโ”€โ”€ CoconutLib -> Versions/Current/CoconutLib
โ”‚       โ”œโ”€โ”€ Headers -> Versions/Current/Headers
โ”‚       โ”œโ”€โ”€ Modules -> Versions/Current/Modules
โ”‚       โ”œโ”€โ”€ Resources -> Versions/Current/Resources
โ”‚       โ””โ”€โ”€ Versions
โ”‚           โ”œโ”€โ”€ A
โ”‚           โ”‚   โ”œโ”€โ”€ CoconutLib
โ”‚           โ”‚   โ”œโ”€โ”€ Headers
โ”‚           โ”‚   โ”‚   โ”œโ”€โ”€ Coconut.h
โ”‚           โ”‚   โ”‚   โ””โ”€โ”€ CoconutLib.h
โ”‚           โ”‚   โ”œโ”€โ”€ Modules
โ”‚           โ”‚   โ”‚   โ””โ”€โ”€ module.modulemap
โ”‚           โ”‚   โ””โ”€โ”€ Resources
โ”‚           โ”‚       โ””โ”€โ”€ Info.plist
โ”‚           โ””โ”€โ”€ Current -> A

your example looks like this:

$ tree StaticXCFramework.xcframework                                                                                                                                                                                                  system
StaticXCFramework.xcframework
โ”œโ”€โ”€ Info.plist
โ”œโ”€โ”€ ios-arm64
โ”‚ย ย  โ”œโ”€โ”€ Headers
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ StaticXCFramework.h
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ module.modulemap
โ”‚ย ย  โ”œโ”€โ”€ libStaticXCFramework.a
โ”‚ย ย  โ””โ”€โ”€ module.modulemap
โ””โ”€โ”€ ios-x86_64-simulator
    โ”œโ”€โ”€ Headers
    โ”‚ย ย  โ”œโ”€โ”€ StaticXCFramework.h
    โ”‚ย ย  โ””โ”€โ”€ module.modulemap
    โ”œโ”€โ”€ libStaticXCFramework.a
    โ””โ”€โ”€ module.modulemap

I'm personally surprised that Xcode seems to handle this when manually adding it to a project

I also noticed the Info.plist is _very_ different than what we expected

<dict>
    <key>AvailableLibraries</key>
    <array>
        <dict>
            <key>HeadersPath</key>
            <string>Headers</string>
            <key>LibraryIdentifier</key>
            <string>ios-arm64</string>
            <key>LibraryPath</key>
            <string>libStaticXCFramework.a</string>
            <key>SupportedArchitectures</key>
            <array>
                <string>arm64</string>
            </array>
            <key>SupportedPlatform</key>
            <string>ios</string>
        </dict>
        <dict>
            <key>HeadersPath</key>
            <string>Headers</string>
            <key>LibraryIdentifier</key>
            <string>ios-x86_64-simulator</string>
            <key>LibraryPath</key>
            <string>libStaticXCFramework.a</string>
            <key>SupportedArchitectures</key>
            <array>
                <string>x86_64</string>
            </array>
            <key>SupportedPlatform</key>
            <string>ios</string>
            <key>SupportedPlatformVariant</key>
            <string>simulator</string>
        </dict>
    </array>
    <key>CFBundlePackageType</key>
    <string>XFWK</string>
    <key>XCFrameworkFormatVersion</key>
    <string>1.0</string>
</dict>
</plist>

This looks like something Xcode supports that we didn't know about ๐Ÿ˜ž

@amorde Thanks for looking into this. I did create this xcframework using xcodebuild -create-xcframework command and noticed that manual integration into host application worked naturally.
I had earlier tried the workaround that you have suggested above (creating the directory structure manually) but it only worked for iphoneos and it couldn't find the slice for simulator. I will give it a try once again and let you know.

I think this is something we'll need to support, but I don't think it will make it into the 1.9 release unfortunately.

For now, the workaround would be to create a framework target but change the MACHO_O_TYPE build setting to staticlib to create a static framework, and then pass that to xcodebuild -create-framework

If you're using CocoaPods to develop the library itself, you can use use s.static_framework = true in the Podspec

Hi! I have a very similar issue using xcframeworks. I made a post here.

In my case, the xcframework also works when adding by drag and drop to the proyect.
The difference I have with this issue is that I'm not using an static library and the error I get is:
ld: symbol(s) not found for architecture x86_64

@LFuryk that isn't a similar issue at all actually - could you open another issue?

@LFuryk that isn't a similar issue at all actually - could you open another issue?
Done! https://github.com/CocoaPods/CocoaPods/issues/9549

thanks!

I've started work on this, but running into an issue.

I've included each slice's Headers dir in HEADER_SEARCH_PATHS, but Xcode complains about multiple module map definitions. It's possible we can't support this with build settings alone, but will keep digging into it.

I've pushed my changes to the amorde/xcframework-libraries branch if you'd like to take a look

Hi @amorde, i've a similar problem with xcframework and static podspec.
When i extract an xcframework from my podspec and install in client app i receive:

    <unknown>:0: error: using bridging headers with module interfaces is unsupported
Command CompileSwiftSources failed with a nonzero exit code

this is my podspec (omitting name and other things):

    Pod::Spec.new do |s|
  s.version          = '0.2.1'
  s.platform = :ios
  s.ios.deployment_target = '10.0'
  s.swift_version = '5.0'

  s.default_subspecs = 'Firebase'
  s.requires_arc = true

  s.subspec 'Firebase' do |ss|
    ss.frameworks = 'Foundation'

    ss.dependency 'FirebaseAuth', '6.5.0'
    ss.dependency 'FirebaseDatabase', '6.1.4'
    ss.dependency 'FirebaseMessaging', '4.3.0'
    ss.dependency 'CodableFirebase', '0.2.1'

    ss.vendored_frameworks = 'Frameworks/iOS/Firebase/Framework.xcframework'
  end

  s.xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' }
  s.static_framework = true
end

If i extract directly an xcframework without firebase everything is fine, can you confirm this is a cocoapods issue at the moment?
I'm using cocoapods version 1.9.1 at the moment.

Thanks :)

I've started work on this, but running into an issue.

I've included each slice's Headers dir in HEADER_SEARCH_PATHS, but Xcode complains about multiple module map definitions. It's possible we can't support this with build settings alone, but will keep digging into it.

Take a look at conditionalizing build settings - https://nshipster.com/xcconfig/#conditionalizing-build-settings

@alessioarsuffi I'm facing exactly same issue now with my xcframework wrapping static library (with Firebase dependency)

:0: error: using bridging headers with module interfaces is unsupported
Command CompileSwiftSources failed with a nonzero exit code

Were you able to solve this? I'm on Cocoapods 1.9.3

@alessioarsuffi I'm facing exactly same issue now with my xcframework wrapping static library (with Firebase dependency)

:0: error: using bridging headers with module interfaces is unsupported
Command CompileSwiftSources failed with a nonzero exit code

Were you able to solve this? I'm on Cocoapods 1.9.3

@adamszeremeta unfortunately no! we are using as temporary workaround normal .framework.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Curtis-Halbrook picture Curtis-Halbrook  ยท  3Comments

pallaviMN picture pallaviMN  ยท  3Comments

sonu5 picture sonu5  ยท  3Comments

dawnnnnn picture dawnnnnn  ยท  3Comments

tlandsmancars picture tlandsmancars  ยท  3Comments