Carthage: Opting out of Carthage's shared cache?

Created on 10 Mar 2016  路  13Comments  路  Source: Carthage/Carthage

I run a Jenkins server that executes its work on a slave machine that is set to build 4 concurrent jobs at once. At times, I get irritating race conditions that cause build failures and block PRs unnecessarily. Carthage stops with messages like the following:

fatal: Unable to create '/Users/chris/Library/Caches/org.carthage.CarthageKit/dependencies/Argo/index.lock': File exists.

Generally I invoke Carthage using carthage bootstrap --no-use-binaries --platform ios,mac for my cross-platform products, because using binaries simply doesn't work with Swift code and fast-moving Xcode releases. I generally don't use submodules in my projects, either, which likely exacerbates this issue.

I think it would be beneficial to supply either a command-line switch, or something in the Cartfile that would specify a local folder to use for Carthage's cache. For instance, you could default to a non-shared cache location of Carthage/Cache (alongside Carthage/Checkouts and Carthage/Build), or the user could choose to specify their own folder.

That way I could keep on doing what I'm doing without worrying about automated build checks failing randomly, etc.

To some extent this is related to #458, #459 (in that we can maintain per-project "carthage droppings"), and surely a few others.

Alternatively, Carthage could maintain a more sensible locking mechanism to avoid running concurrent git processes that target the same folder, however that seems quite delicate.

enhancement help wanted

Most helpful comment

We run into this problem as well (contention over index.lock files) when running CI builds. A configurable cache folder would be appreciated.

All 13 comments

I think catching that error and retrying the command would be a good first step. I'd rather see us prevent/fix the issue than create a workaround.

But if that's not enough to be workable, then I'd support adding a way to opt-out of the shared cache.

I too think I would prefer configuration (and/or command line parameters) that allowed users to choose from a couple different sets of behavior:

  1. Use the shared _Caches_ folder (default)
  2. Don't use a permanent _Caches_ folder (other than the _Carthage/Checkouts_ folder)
  3. Either

    1. Use a user-defined location for the _Caches_ folder

    2. Default to _Carthage/Caches_

We're also starting to run into the same issue as OP: concurrent jobs failing on getting a lock to the _Caches_ git repo. We don't really want to drop back to a single build executor... so yeah.

I don't know which approach is necessarily better re: allowing users to specify _Caches_ folders or gracefully handling lock errors. I feel like both might be a benefit, but doing one would likely solve most of our issues.

@stupergenius For what it's worth, life got a _lot_ better when I finally decided to stop using carthage for anything but a submodule resolver. In a nutshell, I did this:

  1. rm -rf Carthage
  2. carthage bootstrap --use-submodules --no-build
  3. (Update/create your Xcode workspace with all your dependencies' xcodeproj files added to it. See the ReactiveCocoa workspace for an example of this.)
  4. Update your build systems to just call git submodule update --init --recursive

Whenever you need to pick up new dependencies, you still use carthage update --use-submodules --no-build, specifying individual dependencies as needed.

So, what's the benefit of doing the above? For starters:

  1. Xcode's IDE builds _way_ faster overall, and does a better job resolving headers/symbols/docs/etc.
  2. Contributing back to the upstream repos is a lot easier, and you can experiment with library changes _in situ_ as you go.
  3. You will enjoy much faster, and hassle-free CI builds overall
  4. No worrying about using Carthage's copy-frameworks script/etc for submissions and all the weird issues that crop up during that workflow.

The downsides? I can think of a few, but these are probably the most common pain points:

  1. If you're not comfortable with git submodule and its related workflow then it could be awkward for a while. In general, don't commit anything in your parent repo if your submodules are dirty, and life will go fairly well for you.
  2. Building up a working xcworkspace can be a pain if you're not good with that sort of thing. Frankly I think it's a required skill for most developers to be able to construct & manage workspaces these days, so this is worthwhile to learn.

Anyway, hopefully this helps!

Thanks @liscio! I'd rather not deal with the separate set of headaches that are git submodules but thank you for the viable solution. I'll tinker with some of those strategies and see if there's anything workable for our use cases.

Does this resolve the concurrent index.lock error? Presumably because it's only keeping submodules checked out and not cloning separate repos?

@stupergenius I avoided this issue by just limiting my Jenkins remotes to run a single job at a time. It sucked big-time when I had a lot of builds that needed to get done, but it worked.

When I moved over to use submodules I could run many concurrent builds at once without incident.

YMMV, of course.

Once we get a stable Swift ABI, many of these problems will go away and we can return to building from the pre-built frameworks. But even when that happens I'll probably still maintain this workspace setup because of the ease of upstream work, and highly optimized workflow.

We run into this problem as well (contention over index.lock files) when running CI builds. A configurable cache folder would be appreciated.

Also running into this issue. Getting 'File exists' errors when running mutiple builds concurrently on both DerivedData as well as on Caches.

I am also blocked by this issue. Is there a manner to serialize git updates?

@liscio did you encounter any issues with using Carthage as submodule resolver? I'm aiming at exactly the same approach, as an upgrade from using plain submodules. I'm wondering if you had any learnings that could be useful? Thank you!

Just solved this in our fork with this pull request: https://github.com/nsoperations/Carthage/pull/4

@werner77 How has your guy's changes not been incorporated into Carthage yet. Carthage is practically unusable with large dependency graphs right now. It will literally eat up 800% of my iMac Pro's CPU when running. It's absurd to the point where it doesn't even make sense as a professional dependency manager.

Unfortunately we will not try to merge back into the main project anymore, our fork has diverged too much already. You can install it directly with homebrew as well though. See the README at https://github.com/nsoperations/Carthage

@werner77 how sad, hopefully SPM will gain capabilities for platform targets and version in the near future ;). That will avoid this hot mess.

Was this page helpful?
0 / 5 - 0 ratings