diff --git a/README.md b/README.md index e77d47c0f..213acb86d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ Carthage builds your dependencies and provides you with binary frameworks, but y - [Installing Carthage](#installing-carthage) - [Adding frameworks to an application](#adding-frameworks-to-an-application) - [Getting started](#getting-started) - - [Building platform-independent xcframeworks](#building-platform-independent-xcframeworks-xcode-12-and-above) + - [Building platform-independent XCFrameworks](#building-platform-independent-xcframeworks-xcode-12-and-above) + - [Migrating a project from framework bundles to XCFrameworks](#migrating-a-project-from-framework-bundles-to-xcframeworks) - [Building platform-specific framework bundles](#building-platform-specific-framework-bundles-default-for-xcode-11-and-below) - [If you're building for macOS](#if-youre-building-for-macos) - [If you're building for iOS, tvOS, or watchOS](#if-youre-building-for-ios-tvos-or-watchos) @@ -75,15 +76,34 @@ Once you have Carthage [installed](#installing-carthage), you can begin adding f ### Getting started -#### Building platform-independent xcframeworks (Xcode 12 and above) +#### Building platform-independent XCFrameworks (Xcode 12 and above) 1. Create a [Cartfile][] that lists the frameworks you’d like to use in your project. -1. Run `carthage update --use-xcframeworks`. This will fetch dependencies into a [Carthage/Checkouts][] folder and build each one or download a pre-compiled xcframework. -1. On your application targets’ _General_ settings tab, in the _Embedded Binaries_ section, drag and drop each xcframework you want to use from the [Carthage/Build][] folder on disk. +1. Run `carthage update --use-xcframeworks`. This will fetch dependencies into a [Carthage/Checkouts][] folder and build each one or download a pre-compiled XCFramework. +1. On your application targets’ _General_ settings tab, in the _Frameworks, Libraries, and Embedded Content_ section, drag and drop each XCFramework you want to use from the [Carthage/Build][] folder on disk. + +##### Migrating a project from framework bundles to XCFrameworks + +We encourage using XCFrameworks as of version 0.37.0 (January 2021), and require XCFrameworks when building on an Apple Silicon Mac. Switching from discrete framework bundles to XCFrameworks requires a few changes to your project: + +
+ Migration steps + +1. Delete your `Carthage/Build` folder to remove any existing framework bundles. +1. Build new XCFrameworks by running `carthage build --use-xcframeworks`. Any other arguments you build with can be provided like normal. +1. Remove references to the old frameworks in each of your targets: + - Delete references to Carthage frameworks from the target's _Frameworks, Libraries, and Embedded Content_ section and/or its _Link Binary with Libraries_ build phase. + - Delete references to Carthage frameworks from any _Copy Files_ build phases. + - Delete the target's `carthage copy-frameworks` build phase, if present. +1. Add references to XCFrameworks in each of your targets: + - For an application target: In the _General_ settings tab, in the _Frameworks, Libraries, and Embedded Content_ section, drag and drop each XCFramework you use from the [Carthage/Build][] folder on disk. + - For a framework target: In the _Build Phases_ tab, in a _Link Binary with Libraries_ phase, drag and drop each XCFramework you use from the [Carthage/Build][] folder on disk. + +
#### Building platform-specific framework bundles (default for Xcode 11 and below) -**Xcode 12+ incompatibility**: Multi-architecture platforms are not supported when building framework bundles in Xcode 12 and above. Prefer [building with xcframeworks](#building-platform-independent-xcframeworks-xcode-12-and-above). If you need to build discrete framework bundles, [use a workaround xcconfig file](Documentation/Xcode12Workaround.md). +**Xcode 12+ incompatibility**: Multi-architecture platforms are not supported when building framework bundles in Xcode 12 and above. Prefer [building with XCFrameworks](#building-platform-independent-xcframeworks-xcode-12-and-above). If you need to build discrete framework bundles, [use a workaround xcconfig file](Documentation/Xcode12Workaround.md). ##### If you're building for macOS diff --git a/Source/CarthageKit/CarthageKitVersion.swift b/Source/CarthageKit/CarthageKitVersion.swift index 23f6e7d60..a70ae0ded 100644 --- a/Source/CarthageKit/CarthageKitVersion.swift +++ b/Source/CarthageKit/CarthageKitVersion.swift @@ -4,5 +4,5 @@ import Foundation public struct CarthageKitVersion { public let value: SemanticVersion - public static let current = CarthageKitVersion(value: SemanticVersion(0, 36, 0)) + public static let current = CarthageKitVersion(value: SemanticVersion(0, 37, 0)) } diff --git a/Source/CarthageKit/Xcode.swift b/Source/CarthageKit/Xcode.swift index b26dc0ba1..767c72b7d 100644 --- a/Source/CarthageKit/Xcode.swift +++ b/Source/CarthageKit/Xcode.swift @@ -616,23 +616,16 @@ private func mergeIntoXCFramework(in directoryURL: URL, settings: BuildSettings) let buildDebugSymbols = buildDSYMs.concat(buildSymbolMaps).collect() let platformName = SignalProducer(result: settings.platformTripleOS) let fileManager = FileManager.default + let createTemporaryDirectory = fileManager.reactive.createTemporaryDirectoryWithTemplate("carthage-xcframework-XXXXXX") return SignalProducer.combineLatest( framework, buildDebugSymbols, platformName, - xcframework - ).flatMap(.concat) { frameworkURL, debugSymbols, platformName, xcframeworkURL -> SignalProducer in - // If xcframeworkURL doesn't exist yet (i.e. we're creating a new xcframework rather than merging into an existing - // one), creating temporaryDirectory will fail, we'll set outputURL to xcframeworkURL, and we'll skip the call to - // replaceItemAt(_:withItemAt:) below. - let temporaryDirectory = try? fileManager.url( - for: .itemReplacementDirectory, - in: .userDomainMask, - appropriateFor: xcframeworkURL, - create: true - ) - let outputURL = temporaryDirectory.map { $0.appendingPathComponent(xcframeworkURL.lastPathComponent) } ?? xcframeworkURL + xcframework, + createTemporaryDirectory + ).flatMap(.concat) { frameworkURL, debugSymbols, platformName, xcframeworkURL, temporaryDirectory -> SignalProducer in + let outputURL = temporaryDirectory.appendingPathComponent(xcframeworkURL.lastPathComponent) return mergeIntoXCFramework( xcframeworkURL, @@ -644,11 +637,12 @@ private func mergeIntoXCFramework(in directoryURL: URL, settings: BuildSettings) ) .mapError(CarthageError.taskError) .attempt { replacementURL in - guard let temporaryDirectory = temporaryDirectory, replacementURL != xcframeworkURL else { - return .success(()) - } return Result(at: xcframeworkURL) { url in - try fileManager.replaceItemAt(url, withItemAt: replacementURL) + if fileManager.fileExists(atPath: url.path) { + try fileManager.removeItem(at: url) + } + try fileManager.createDirectory(at: url.deletingLastPathComponent(), withIntermediateDirectories: true) + try fileManager.copyItem(at: replacementURL, to: url) }.flatMap { _ in Result(at: temporaryDirectory) { try fileManager.removeItem(at: $0) } }