From 3239c30a3187bd656218c431165142a950a24d74 Mon Sep 17 00:00:00 2001 From: Elliott Williams Date: Tue, 12 Jan 2021 22:06:21 -0800 Subject: [PATCH 1/5] Bump version to 0.37.0 --- Source/CarthageKit/CarthageKitVersion.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CarthageKit/CarthageKitVersion.swift b/Source/CarthageKit/CarthageKitVersion.swift index 23f6e7d605..a70ae0ded5 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)) } From 3302df2014df287920cac7d4cca408f8e5e413e8 Mon Sep 17 00:00:00 2001 From: Elliott Williams Date: Tue, 12 Jan 2021 23:38:28 -0800 Subject: [PATCH 2/5] Avoid FileManager.replaceItem so that replacements can happen across volumes --- Source/CarthageKit/Xcode.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/CarthageKit/Xcode.swift b/Source/CarthageKit/Xcode.swift index 39582070df..a0074d3e69 100644 --- a/Source/CarthageKit/Xcode.swift +++ b/Source/CarthageKit/Xcode.swift @@ -648,7 +648,8 @@ private func mergeIntoXCFramework(in directoryURL: URL, settings: BuildSettings) return .success(()) } return Result(at: xcframeworkURL) { url in - try fileManager.replaceItemAt(url, withItemAt: replacementURL) + try fileManager.removeItem(at: url) + try fileManager.copyItem(at: replacementURL, to: url) }.flatMap { _ in Result(at: temporaryDirectory) { try fileManager.removeItem(at: $0) } } From 3dfed084b0ff49549d85afbb870c2d07a1e78166 Mon Sep 17 00:00:00 2001 From: Elliott Williams Date: Fri, 22 Jan 2021 17:00:44 -0800 Subject: [PATCH 3/5] Add README section on migrating to XCFrameworks --- README.md | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e77d47c0f9..fd1465a7b3 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 From 0cec60aa78c423d58ecd93d227977df72ec29f58 Mon Sep 17 00:00:00 2001 From: Elliott Williams Date: Fri, 22 Jan 2021 17:54:07 -0800 Subject: [PATCH 4/5] Avoid using url(for:in:) and replaceItemAt APIs url(for:in:) is fragile because there's a systemwide limit to the number of temporary items that can be created: https://developer.apple.com/forums/thread/128927 replaceItemAt is only reliable when used with url(for:in:), because it requires the URLs to point to the same volume --- Source/CarthageKit/Xcode.swift | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/Source/CarthageKit/Xcode.swift b/Source/CarthageKit/Xcode.swift index a0074d3e69..fb3708d7a3 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,11 @@ 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.removeItem(at: url) + 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) } From 00a50cb9ed69fa4c6b5373249d38feca622b8e62 Mon Sep 17 00:00:00 2001 From: Elliott Williams Date: Fri, 29 Jan 2021 08:33:01 -0800 Subject: [PATCH 5/5] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fd1465a7b3..213acb86dc 100644 --- a/README.md +++ b/README.md @@ -92,12 +92,12 @@ We encourage using XCFrameworks as of version 0.37.0 (January 2021), and require 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. + - 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. + - 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.