rules_apple icon indicating copy to clipboard operation
rules_apple copied to clipboard

Bug: When Static XCFramework depends on objc_library importing XCFramework fails to build

Open sanju-naik opened this issue 1 year ago • 6 comments

What's the issue

I have a static xcframework which is consumed using rule apple_static_xcframework_import and this xcfraemwork depends on an objc_library. Importing this XCFramework inside swift classes of ios_application fails to build with following error

/private/var/tmp/_bazel_sanju/e107e611dd65132537122ef1dabd8e89/execroot/__main__/TimeManager/TImeManager.xcframework/ios-arm64_x86_64-simulator/TImeManager.framework/Modules/TImeManager.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface:6:8: error: no such module 'GCDTimeManager'
import GCDTimeManager
       ^
BazelDemo/ViewController.swift:9:8: error: failed to build module 'TImeManager'; this SDK is not supported by the compiler (the SDK is built with 'Apple Swift version 5.8.1 (swiftlang-5.8.0.124.5 clang-1403.0.22.11.100)', while this compiler is 'Apple Swift version 5.8 (swiftlang-5.8.0.124.2 clang-1403.0.22.11.100)'). Please select a toolchain which matches the SDK.
import TImeManager

How to reproduce

Clone this repository - https://github.com/sanju-naik/Bazel-Example and checkout xcframework-error branch . then running this command bazel build --config=Debug --ios_multi_cpus=sim_arm64 --verbose_failures BazelDemo throws the error.

sanju-naik avatar Sep 18 '23 17:09 sanju-naik

Your prebuilt library is depending on a source-built library, but they're compiled with different compilers. This is not possible with Swift. You need to use the same version of Xcode that was used to build the xcframework.

Closing since this is not a bug of rules_apple.

thii avatar Sep 19 '23 23:09 thii

Your prebuilt library is depending on a source-built library, but they're compiled with different compilers. This is not possible with Swift. You need to use the same version of Xcode that was used to build the xcframework.

Yeah you were right on this, XCFramework was generated using Xcode 14.3.1 and I was building ios_application using Xcode 14.3

Now I built the app using Xcode 14.3.1 and it throws this error

/private/var/tmp/_bazel_sanju/e107e611dd65132537122ef1dabd8e89/execroot/__main__/TimeManager/TImeManager.xcframework/ios-arm64_x86_64-simulator/TImeManager.framework/Modules/TImeManager.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface:6:8: error: no such module 'GCDTimeManager'
import GCDTimeManager
       ^
BazelDemo/ViewController.swift:9:8: error: failed to build module 'TImeManager' for importation due to the errors above; the textual interface may be broken by project issues or a compiler bug
import TImeManager
       ^
<module-includes>:3:9: note: in file included from <module-includes>:3:
#import "../../../../TimeManager/TImeManager.xcframework/ios-arm64_x86_64-simulator/TImeManager.framework/Modules/TImeManager.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface"

So for some reason, the client app is not able to recognize the underlying Objective C module, even though the objc_library is added as a dependency on the underlying swift_library of ios_application.

sanju-naik avatar Sep 20 '23 03:09 sanju-naik

the textual interface may be broken by project issues or a compiler bug

I was able to build it by removing import GCDTimeManager from the swiftinterface files. It failed with linker errors though it seems like a problem with the framework.

duplicate symbol '_OBJC_IVAR_$_GCDTimer._timer' in:
    TimeManager/TImeManager.xcframework/ios-arm64_x86_64-simulator/TImeManager.framework/TImeManager(GCDTimer.o)
    bazel-out/ios-sim_arm64-min12.0-applebin_ios-ios_sim_arm64-dbg-ST-acb08275552e/bin/GCDTimeManager/libGCDTimeManager.a(GCDTimer.o)
duplicate symbol '_OBJC_CLASS_$_GCDTimer' in:
    TimeManager/TImeManager.xcframework/ios-arm64_x86_64-simulator/TImeManager.framework/TImeManager(GCDTimer.o)
    bazel-out/ios-sim_arm64-min12.0-applebin_ios-ios_sim_arm64-dbg-ST-acb08275552e/bin/GCDTimeManager/libGCDTimeManager.a(GCDTimer.o)
duplicate symbol '_OBJC_METACLASS_$_GCDTimer' in:
    TimeManager/TImeManager.xcframework/ios-arm64_x86_64-simulator/TImeManager.framework/TImeManager(GCDTimer.o)
    bazel-out/ios-sim_arm64-min12.0-applebin_ios-ios_sim_arm64-dbg-ST-acb08275552e/bin/GCDTimeManager/libGCDTimeManager.a(GCDTimer.o)

thii avatar Sep 20 '23 13:09 thii

@sanju-naik Does it solve your issue?

thii avatar Sep 29 '23 00:09 thii

@thii When I tried by manually removing import GCDTimeManager from .swiftinterface file, it did throw same duplicate symbol error as you shared, however same xcframework works fine on Xcode build system though.

Also manually removing import GCDTimeManager from swiftinterface file seems like more of workaround, any idea why its throwing this error

BazelDemo/ViewController.swift:9:8: error: failed to build module 'TImeManager' for importation due to the errors above; the textual interface may be broken by project issues or a compiler bug import TImeManager

Also any idea when an XCFramework can have .private.swiftinterface file? in other xcframeworks I have just seen .swiftinterface file, in this framework, there is a private.swiftinterface file and the textual interface broken error is coming from this private interface file only.

sanju-naik avatar Sep 29 '23 12:09 sanju-naik

however same xcframework works fine on Xcode build system though

Do you have a repro?

BazelDemo/ViewController.swift:9:8: error: failed to build module 'TImeManager' for importation due to the errors above; the textual interface may be broken by project issues or a compiler bug

I would ask the framework vendor about the broken module interface. If you built that yourself, a repro would be helpful.

The duplicate symbol error is because you're linking the same thing twice, which you will have to fix in your code.

thii avatar Sep 29 '23 14:09 thii