Deterministic Ids in the Xcode generator to avoid unnecessary rebuilds

With stock CMake, adding a single file and rebuilding an Xcode project causes the build to start from scratch in Xcode as if it has just been cleaned. As this was causing a problem for us with build times, we looked into it, and it seems that the issue is that CMake’s Xcode generator creates random ids inside the Xcode project files it creates. We tweaked CMake’s Xcode generator to generate the Ids deterministically, and the problem went away with only the necessary files rebuilt upon regeneration of the Xcode project.

Precisely

  • In most cases, for most objects, our changes assign a monotically increasing integer, which given that the order of calls to this is deterministic, means those Ids are also deterministic
  • In cases where a name is available, for example a source path, our tweaked version hashes the path, and ensures those Ids are deterministic

A link to our changes can be seen here, however, we realise this is not ready for merging as we need to run clang-tidy on it and rebase to the latest to latest version of CMake, and move the repostitory to GitLab. We are getting in contact to get any feedback on the proposed changes, and if you would be interested in merging, before we do that rebase.

A potential issue with this is that some Ids are exported from the Xcode project file to the Xcode scheme file, so these changes respect the cached Ids where they exist. If the exported Ids are changed, then Xcode fails to load the source files. This would ensure that anyone upgrading would be able to leave the scheme files in place (although those are presumably generated by CMake in the first instance).

Duncan Steele

@duncanvv thanks. Your approach looks good to me. Please see CONTRIBUTING.rst for contribution instructions.

From a quick scroll through the changes:

  • Please use cmCryptoHash instead of a platform-specific API for the hash functions.
  • Please use {} or a default argument rather than a literal "" for empty hash key arguments.

Further review can be done in a merge request.

We will soon branch for the 3.19 release, and there have been many changes to the Xcode generator since 3.18. I think some more are coming soon. This may create conflicts with your work. It might be simpler to wait until the final 3.19.0 release is out (should be by mid-November) and then rebase on master for post-3.19 development.

@brad.king Thanks for replying. I hadn’t noticed the new Xcode build system work for 3.19, thanks for doing that. We’ll likely rebase our changes on top of that right away to start using it, and then rebase again and submit a pull request in November once 3.19 is out.

@duncanvv sounds good. Thanks for trying out the Xcode new build system support. If you have any problems with it, please open an issue.

Did this ever get merged?

I don’t think an MR ever got submitted.

We used a version where the object Ids were deterministic, and we were about to submit it when we noticed some other spurious builds. IIRC the problem was that the CMake generator was formatting lists of options slightly differently to Xcode, which triggered further builds, and so that would need to be changed in line with Xcode as well.

Around this time we upgraded machines and gave up on this, especially as it was unclear how much work would be required longterm to keep it in step with Xcode’s undocumented, and changing, preferences.

That said, if anyone is interested in it, I can bring it in line with the current version of CMake and submit an MR.

1 Like

As of version 3.24.2 this still has not been resolved. I’ve notices some MR where this was resolved for some script build phases, but generally build after reconfigure is still broken. Any plan to make this deterministic in near future so it won’t trigger full rebuild on each reconfigure? @brad.king

I don’t think there are plans at the moment beyond external contributions fixing the problem (which seems to at least be outlined in the first post here).