which carthage: /usr/local/bin/carthagecarthage version: 0.33.0xcodebuild -version: 10.2--no-build? no--no-use-binaries? yes--use-submodules? no--cache-builds? yes--new-resolver? yesCartfile
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseRemoteConfigBinary.json" == 5.20.0
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json" == 5.20.0
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseABTestingBinary.json" == 5.20.0
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebasePerformanceBinary.json" == 5.20.0
Carthage Output
*** Downloading binary-only framework FirebaseABTestingBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebaseABTestingBinary.json"
*** Downloading binary-only framework FirebasePerformanceBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebasePerformanceBinary.json"
*** Downloading binary-only framework FirebaseAnalyticsBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json"
*** Downloading binary-only framework FirebaseRemoteConfigBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebaseRemoteConfigBinary.json"
*** Downloading binary-only framework FirebaseABTestingBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebaseABTestingBinary.json"
*** xcodebuild output can be found in /var/folders/ny/mwt5zhw17cbdxg3d13rf22hrqtll8q/T/carthage-xcodebuild.77Rtd9.log
*** Downloading binary-only framework FirebaseAnalyticsBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json"
*** Downloading binary-only framework FirebasePerformanceBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebasePerformanceBinary.json"
*** Downloading binary-only framework FirebaseRemoteConfigBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebaseRemoteConfigBinary.json"
Failed to write to /Users/hrichardson/programming/native-ios-app/Carthage/Build/iOS/Protobuf.framework: Error Domain=NSCocoaErrorDomain Code=513 "âProtobuf.frameworkâ couldnât be removed because you donât have permission to access it." UserInfo={NSFilePath=/Users/me/app/Carthage/Build/iOS/Protobuf.framework, NSUserStringVariant=(
Remove
), NSUnderlyingError=0x7f999f55a270 {Error Domain=NSPOSIXErrorDomain Code=66 "Directory not empty"}}
Actual outcome
Carthage 'failed to write' to that folder and stops
Expected outcome
Carthage should handle dependencies of binary dependencies.
I managed a workaround by removing the FirebaseRemoteConfigBinary dependency line in the Cartfile, running the carthage update command, and then re-running carthage update. The binaries will get placed into the Build folder in the first command, and then when it's run again it doesn't have the problem with Protobuf.framework.
I see the issue was mentioned in this issue in the Firebase repo https://github.com/firebase/firebase-ios-sdk/issues/9
I don't believe it to be an issue solely for Firebase, it seems more because there are multiple binary dependencies that have a dependency on the same thing.
We have the same issue. I think the issue is on Googles side, because Carthage canât know which transitive dependencies exist when using the binary download in a Cartfile. However, I think Carthage should provide an option to overwrite or skip those duplicate dependcies.
Steps to reproduce:
Example Cartfile
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMessagingBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseRemoteConfigBinary.json"
The first time, carthage is run with this Cartfile will succeed if the carthage cache is clean. However, every subsequent run will fail with the output in the original issue description.
Workaround that works most of the times:
carthage bootstrap --platform ios --cache-builds \
|| rm -rvf ~/Library/Caches/org.carthage.CarthageKit/binaries/Firebase** \
&& carthage bootstrap --platform ios --cache-builds
Try this patch:
diff --git a/Source/CarthageKit/Project.swift b/Source/CarthageKit/Project.swift
index ae282c01..54e8a51c 100644
--- a/Source/CarthageKit/Project.swift
+++ b/Source/CarthageKit/Project.swift
@@ -8,6 +8,18 @@ import XCDBLD
import ReactiveTask
import struct SPMUtility.Version
+
+let dsp = {
+
+ return DispatchQueue.init(label: "serial.unzip.queue")
+
+// return DispatchQueue.init(label: "serial.unzip.queue"
+// , qos: .default
+// , attributes: .concurrent
+// , autoreleaseFrequency: .inherit
+// , target: nil)
+}()
+
/// Describes an event occurring to or with a project.
public enum ProjectEvent {
/// The project is beginning to clone.
@@ -638,6 +650,7 @@ public final class Project { // swiftlint:disable:this type_body_length
return SignalProducer<URL, CarthageError>(value: zipFile)
.flatMap(.concat, unarchive(archive:))
+ .observe(on: QueueScheduler.init(qos: .default, name: "issue-2777", targeting: dsp))
.flatMap(.concat) { directoryURL -> SignalProducer<URL, CarthageError> in
// For all frameworks in the directory where the archive has been expanded
return frameworksInDirectory(directoryURL)
@@ -1134,6 +1147,7 @@ public final class Project { // swiftlint:disable:this type_body_length
}
.flatMap(.concat) { (dependencies: [(Dependency, PinnedVersion)]) -> SignalProducer<(Dependency, PinnedVersion), CarthageError> in
return SignalProducer(dependencies)
+ // even removing the concurrecny still requires the dsp serial queue. why?
.flatMap(.concurrent(limit: 4)) { dependency, version -> SignalProducer<(Dependency, PinnedVersion), CarthageError> in
switch dependency {
case .git, .gitHub:
By applying this patch on top of your open PR (#2791) the original issue with the _Failed to write_ message is not occuring anymore. However, there still are some race conditions: only 4 of 10 runs executing carthage bootstrap --platform ios with the Cartfile from https://github.com/Carthage/Carthage/issues/2777#issuecomment-493464781 were successful.
3 of 10 runs:
shell task (/usr/bin/xcrun dwarfdump --uuid /Users/ffittschen/Development/GitHub/sixt-ios/Carthage/Build/iOS/Protobuf.framework/Protobuf) failed with exit code 1:
/Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework/Protobuf: No such file or directory
3 of 10 runs:
A shell task (/usr/bin/shasum -a 256 /Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework/Protobuf) failed with exit code 1:
shasum: /Users/ffittschen/Development/GitHub/sixt-ios/Carthage/Build/iOS/Protobuf.framework/Protobuf
Those two new error messages seem to be related to copying the dSYMs and creating the version file within the same method. According to my Xcode, the queue is not the issue-2777 queue when it stops at the breakpoint, but rather some other concurrent queue (see screenshot).

I might have found the cause: It is a race condition between copyItem and removeItem
Logs enriched with timestamps:
*** xcodebuild output can be found in /var/folders/ck/5xmkrjzs5dq00bkmckztm7j80000gn/T/carthage-xcodebuild.XlTsjV.log
*** Downloading binary-only framework FirebaseAnalyticsBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json"
*** Downloading binary-only framework FirebaseMessagingBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMessagingBinary.json"
*** Downloading binary-only framework FirebaseRemoteConfigBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebaseRemoteConfigBinary.json"
*** Downloading binary-only framework GoogleSymbolUtilities at "file:///Users/ffittschen/Code/demo-project/Carthage/BinaryFrameworkSchemes/GoogleSymbolUtilities.json"
[removeItem] 1558264279.818767 start file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/GoogleSymbolUtilities.framework/
[removeItem] 1558264279.818767 end file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/GoogleSymbolUtilities.framework/
[copyItem] 1558264279.819322 start file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/GoogleSymbolUtilities.framework/
[copyItem] 1558264279.819322 end file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/GoogleSymbolUtilities.framework/
*** Downloading binary-only framework GoogleTagManager at "file:///Users/ffittschen/Code/demo-project/Carthage/BinaryFrameworkSchemes/GoogleTagManager.json"
[removeItem] 1558264279.935039 start file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework/
[removeItem] 1558264279.935039 end file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework/
[copyItem] 1558264279.9450989 start file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework/
[removeItem] 1558264279.9583368 start file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/FirebaseMessaging.framework/
[removeItem] 1558264279.9583368 end file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/FirebaseMessaging.framework/
[copyItem] 1558264279.960733 start file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/FirebaseMessaging.framework/
[copyItem] 1558264279.960733 end file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/FirebaseMessaging.framework/
[removeItem] 1558264279.990279 start file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework/
[removeItem] 1558264279.990279 end file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework/
[copyItem] 1558264279.9990911 start file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework/
[copyItem] 1558264279.9450989 end file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework/
[copyItem] 1558264279.9990911 end file:///Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework/
Failed to read file or folder at /Users/ffittschen/Code/demo-project/Carthage/Build/iOS/Protobuf.framework
As you can see: While it is still copying the first instance of Protobuf.framework ([copyItem] 1558264279.9450989), it called [removeItem] 1558264279.990279 in between.
diff --git a/Source/CarthageKit/FrameworkExtensions.swift b/Source/CarthageKit/FrameworkExtensions.swift
index 93c41986..e4937116 100644
--- a/Source/CarthageKit/FrameworkExtensions.swift
+++ b/Source/CarthageKit/FrameworkExtensions.swift
@@ -329,11 +329,14 @@ extension FileManager: ReactiveExtensionsProvider {
try from.path.withCString { fromCStr in
try to.path.withCString { toCStr in
+ let timestamp = Date().timeIntervalSince1970
+ print("[copyItem] \(timestamp) start \(to)")
let state = copyfile_state_alloc()
// Can't use COPYFILE_NOFOLLOW. Restriction relaxed to COPYFILE_NOFOLLOW_SRC
// http://openradar.appspot.com/32984063
let status = copyfile(fromCStr, toCStr, state, UInt32(COPYFILE_ALL | COPYFILE_RECURSIVE | COPYFILE_NOFOLLOW_SRC))
copyfile_state_free(state)
+ print("[copyItem] \(timestamp) end \(to)")
if status < 0 {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno), userInfo: nil)
}
diff --git a/Source/CarthageKit/Xcode.swift b/Source/CarthageKit/Xcode.swift
index 68624f0a..6f30fed1 100644
--- a/Source/CarthageKit/Xcode.swift
+++ b/Source/CarthageKit/Xcode.swift
@@ -1054,8 +1054,13 @@ public func copyProduct(_ from: URL, _ to: URL) -> SignalProducer<URL, CarthageE
let createDirectory = { try manager.createDirectory(at: $0, withIntermediateDirectories: true) }
return result(allowingErrorCode: NSFileWriteFileExistsError, Result(at: to.deletingLastPathComponent(), attempt: createDirectory))
- .flatMap { _ in
- result(allowingErrorCode: NSFileNoSuchFileError, Result(at: to, attempt: manager.removeItem(at:)))
+ .flatMap { _ -> Result<(), CarthageError> in
+ let timestamp = Date().timeIntervalSince1970
+ print("[removeItem] \(timestamp) start \(to)")
+ defer {
+ print("[removeItem] \(timestamp) end \(to)")
+ }
+ return result(allowingErrorCode: NSFileNoSuchFileError, Result(at: to, attempt: manager.removeItem(at:)))
}
.flatMap { _ in
Result(at: to, attempt: { destination /* to */ in
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.
If it is not fixed anywhere, it should not be closed ;)
When will this be fixed and pushed into a release? Carthage has become unusable ever since we added binary dependencies, and some of these libraries don't have alternatives.
We are resorting to this command sequence any time we update, which is slow and painful:
rm -rf carthage
rm -rf ~/Library/Caches/org.carthage.CarthageKit
carthage update --platform iOS
@sjmueller It won't. The root of the problem hasn't been found.
However, maybe you can take a stab at it (since it's important for your work) and make a PR! There is enough information here to get started on the problem. Don't rely on this fixed by someone else, take action. This is how open source works.
Thanks for letting me know how open source works. If the core contributors canât find the problem, I certainly wouldnât be able to either.
As for relying on someone else â yes, we do rely on Carthage. Thatâs what happens when a project grows to this insane level of popularity amongst other bad/worse options. Thankfully Swift Package Manager and ABI stability are coming together nicely in iOS 13, maybe all this pressure on Carthage to be reliable will melt away.
Thanks for letting me know how open source works. If the core contributors canât find the problem, I certainly wouldnât be able to either.
Great! So you'll cover me and submit a patch right? đ€
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.
I am seeing this issue 6.7.0 version of Firebase frameworks on Carthage
Would love to know if someone has found a fix or workaround for it.
Still getting the error đ
*** Downloading binary-only framework FirebaseMessagingBinary at "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMessagingBinary.json"
A shell task (/usr/bin/xcrun dwarfdump --uuid /.../ios_app/Carthage/Build/iOS/Protobuf.framework/Protobuf) failed with exit code 1:
error: /.../ios_app/Carthage/Build/iOS/Protobuf.framework/Protobuf: Invalid data was encountered while parsing the file
If the issue is due to the race between multiple frameworks being extracted simultaneously, it should be able to work around by treating them one by one. Now my build script is like this:
carthage bootstrap --use-ssh --cache-builds --platform iOS FirebaseABTestingBinary &&
carthage bootstrap --use-ssh --cache-builds --platform iOS FirebaseAnalyticsBinary &&
carthage bootstrap --use-ssh --cache-builds --platform iOS FirebaseMessagingBinary &&
carthage bootstrap --use-ssh --cache-builds --platform iOS FirebasePerformanceBinary &&
carthage bootstrap --use-ssh --cache-builds --platform iOS FirebaseRemoteConfigBinary &&
carthage bootstrap --use-ssh --cache-builds --platform iOS # for other frameworks
@aYukiWatanabe solution also goes for any firebase race conditions when trying to carthage update --platform iOS --no-use-binaries on your project... I also attempted to comment all FirebaseBinary Frameworks and build 1 by 1 via carthage update --platform iOS - which worked too.... stupid race conditions!
When this error occurs, this workaround works 100% of the time for me:
--cache-builds flagMy current workaround is
until carthage build --platform iOS --cache-builds --no-use-binaries; do echo "carthage build failed. trying again"; done;
It retries to build dependencies until it succeeded. On TravisCI it sometimes does two or three iterations if cache was invalidated
Most helpful comment
If it is not fixed anywhere, it should not be closed ;)