Carthage: Swift ABI / Module Stability

Created on 6 Aug 2019  路  7Comments  路  Source: Carthage/Carthage

Hey,

As the maintainer of a few frameworks used internally at my company, I've been following Swift ABI & module stability quite closely. From my understanding, both are required before we'll be able to avoid the common issue of having to recompile all of a project's Swift dependencies when upgrading to a newer version of Xcode.

According to this blog post over on the Swift forums, ABI stability is present in Swift 5 now, but module stability is still being developed (and might be delivered with Swift 5.1 / Xcode 11). As such, when Xcode 10.3 dropped, I began the process of recompiling our internal frameworks and requesting a new build from the vendor of a closed-source framework that we use.

However, it seems that recompiling is not actually required to use these frameworks with Xcode 10.3. This is pretty easily demonstrable:

  1. Create a sample project in Xcode 10.3
  2. Set the Command Line Tools version to Xcode 10.2
  3. Add a Cartfile and reference any Swift framework that can be compiled with Xcode 10.2 (I used Alamofire to test with given its popularity)
  4. Run carthage update to build the framework with Xcode 10.2
  5. Link / import it into the sample project
  6. Build

Everything I've come to understand about ABI & module stability says that this shouldn't work, but it does (unless I'm missing something here). Can anyone tell me why I'm not getting a compile error or why it might be a bad idea to not recompile the framework with Xcode 10.3?

If not, it would seem to me that Carthage should be updated to reflect this capability, as an error is thrown when using Carthage to download binaries built with a different Swift version than what the Command Line Tools option is set to. I imagine that this behavior would have to only be updated for Swift 5+, though.

  • carthage install method: [x] .pkg, [] homebrew, [ ] source
  • which carthage: /usr/local/bin/carthage
  • carthage version: 0.33.0
  • xcodebuild -version: 10E125 / 10G8
  • Are you using --no-build? No
  • Are you using --no-use-binaries? No
  • Are you using --use-submodules? No
  • Are you using --cache-builds? No
  • Are you using --new-resolver? No

Cartfile

github "Alamofire/Alamofire" == 4.8.2
stale

Most helpful comment

There is a draft PR to add XCFramework support to Carthage (which includes module stability), but for now you can enable module stability for your Carthage-built frameworks as follows:

echo 'BUILD_LIBRARY_FOR_DISTRIBUTION=YES'>/tmp/config.xcconfig; XCODE_XCCONFIG_FILE=/tmp/config.xcconfig carthage build; rm /tmp/config.xcconfig

All 7 comments

Here is a previous related issue: https://github.com/Carthage/Carthage/issues/2794

From what I understand the issue is that binary stability does not give you any guarantees about module stability so it is unsafe to assume that linking against frameworks created with other versions of Swift will work properly.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

There is a draft PR to add XCFramework support to Carthage (which includes module stability), but for now you can enable module stability for your Carthage-built frameworks as follows:

echo 'BUILD_LIBRARY_FOR_DISTRIBUTION=YES'>/tmp/config.xcconfig; XCODE_XCCONFIG_FILE=/tmp/config.xcconfig carthage build; rm /tmp/config.xcconfig

Hey @jonathanellis

Can we use the example snippet you gave as:

echo 'BUILD_LIBRARY_FOR_DISTRIBUTION=YES'>/tmp/config.xcconfig; XCODE_XCCONFIG_FILE=/tmp/config.xcconfig carthage update --platform iOS --new-resolver --no-use-binaries --cache-builds; rm /tmp/config.xcconfig

Thanks

@b-onc Not sure I understand the question...

@jonathanellis
Instead of carthage build can we run carthage update --platform iOS --new-resolver --no-use-binaries --cache-builds in the snippet you've posted?

Despite providing the module stability workaround, I'm not much of a Carthage user...carthage update should be fine, the problem in your usage is going to be --cache-builds:

By default Carthage will rebuild a dependency regardless of whether it's the same resolved version as before. Passing the --cache-builds will cause carthage to avoid rebuilding a dependency if it can.

From the look of it, if it was already built without module stability, then you're going to end up with the cached version rather than the new build with module stability...

Was this page helpful?
0 / 5 - 0 ratings