Carthage produces XCFrameworks instead of universal frameworks when is passed. (https://github.com/Carthage/Carthage/pull/3071). Thanks @elliottwilliams!
--use-xcframeworks
XCFrameworks contain multiple discrete framework bundles. Unlike universal frameworks (produced by lipo), an XCFramework can contain multiple versions of a framework which share the same processor architecture. Since Xcode 12 added Apple Silicon support to its simulator platforms, the device and simulator versions of a framework both build for arm64, hence requiring an XCFramework.
To build XCFrameworks into your app, run Carthage with --use-xcframeworks and drag the produced XCFrameworks into your Xcode target’s Embedded binaries section, without using a carthage copy-frameworks script phase. ﹡See the README﹡ for information on how to upgrade to XCFrameworks.
XCFrameworks are the only supported way to build Carthage frameworks for Apple Silicon-based Macs.
Known issues
--use-xcframeworks does not produce an XCFramework for github dependencies which download binaries.
Workaround: Pass --no-use-binaries to make Carthage rebuild the dependency from source, which will produce an XCFramework.
carthage archive does not archive built XCFrameworks, and --use-xcframeworks does not produce an xcframework for binary dependencies.
Under --use-xcframeworks, Carthage aims to accommodate something long relied upon: targets that 〈think about targets such as your dependencies ⋯ subdependencies ⋯ dependencies vended by others〉 …that link against «.framework»s in the directory of Carthage/Build ﹡as opposed to linking against «.framework»s in Per-configuration Build Products Path (CONFIGURATION_BUILD_DIR).﹡
Such targets will see Carthage extract — for each platform the target builds for — such-platform’s «.framework» bundles from all XCFrameworks, copying them into a temporary directory, and then — via build setting injection into FRAMEWORK_SEARCH_PATHS — allowing the xcodebuild run an at-the-end-of-FRAMEWORK_SEARCH_PATHS opportunity to link those extracted-into-temporary-directory «.framework»s (and fulfill a successful compilation).
Well, to be more precise…
〜 Well, to be more precise, any scheme where the Carthage-focused target with build setting value for FRAMEWORK_SEARCH_PATHS specifically containing a subdirectory of Carthage/Build will have the at-the-end-of-FRAMEWORK_SEARCH_PATHS opportunity.
This behavior works for framework targets in most cases, since they link against but generally do not embed their framework dependencies, but requires changes if any part of a target’s build process requires the exact path of the framework bundle. If you (or developers consuming your framework) encounter build errors when using carthage build --use-xcframeworks, you have a few options:
Update your project to link and embed XCFrameworks from Carthage/Build, then read the extracted framework from CONFIGURATION_BUILD_DIR. You won’t rely on the above ‘at-the-end-of-FRAMEWORK_SEARCH_PATHS opportunity’ behavior, but ﹡you will break compatibility with users who aren’t using the --use-xcframeworks flag﹡, so consider other options, proceed with caution, and consider versioning this as a breaking change.
If Carthage fails while building a scheme that contains non-framework targets, break it up into multiple schemes, so that Carthage only builds the framework targets.
Modify your build phases to parse the FRAMEWORK_SEARCH_PATHS build setting and search each directory in order to find a Carthage framework, rather than hard-coding its path to a Carthage/Build/<platform> directory.
If you’re struggling to figure out how Carthage focuses on a target…
〜 If you’re struggling to figure out how Carthage focuses on a target within a Xcode project/workspace within a repo and subsequently widens out to choose a scheme based on that, head to https://github.com/Carthage/Carthage/issues/new and attach the label «focused-target» or just mention «focused-target» in the issue’s body text; please make the body text detailed, and priority will be given to issues regarding open source repositories.
Acknowledgements
Thanks @olejnjak, @philipphofmann, and @daisuke-t-jp for their work on documenting the xcconfig workaround. More broadly, we appreciate the community of users who communicated about the problem, came up with a temporary workaround, and were patient while we architected a fix.
Thanks @tmspzz, @gjeck, @nighthawk, @chrisballinger, @renep, and @elliottwilliams for their work reviewing pull requests.