Possible bug: generate-xcodeproj incompatible with resolve from Swift 4.2 on

I am not sure if it is a bug or not, but Swift 4.2 has destroyed my use of swift package generate-xcodeproj.

Here is how I use it:

  1. I generate an xcodeproj with swift package generate-xcodeproj.
  2. I share the xcodeproj on a repository with other developers. I don't share .build/checkouts on this repo.
  3. Other developers pull the repo, run swift package resolve to get the dependencies.
  4. From Swift 4.2 on, this doesn't work anymore.

The reason for that is the following: the <project>.xcodeproj/project.pbxproj file contains references to the dependencies (e.g. path = "/private/tmp/grpc-swift/.build/checkouts/Commander.git--6986935687834931528/Package.swift";). With Swift before 4.2, the number was created in a deterministic way. From 4.2 on, it is not anymore. And because swift package resolve doesn't (and can't possibly) update the generated xcodeproj, it results in a non-working xcodeproj.

In other words, with Swift 4.2, you cannot remove .build and run swift package resolve without breaking the project generated by swift package generate-xcodeproj.

A consequence of that is that it makes it considerably more difficult to support a SwiftPM project from Carthage (as noted here).

Is there a reason for this change in Swift 4.2? Or was it a bad idea to depend on an xcodeproj generated by the SwiftPM from Carthage, in the first place?

It seems to me that the main benefit of SPM is actually to not share the xcodeproj but instead the Package.swift file and the sources code + tests.

This way, you can always generate a new xcodeproj when you clone the repo. The source of truth being the actual code and not what Xcode might do or not do.

And that's actually why swift package init creates a .gitignore excluding xcodeproj from git.

I do understand that, and I really like the idea of not depending on the cryptic xcodeproj.

I am just trying to find a way to deal with the different package managers until SPM possibly takes over (but that would require support for platforms like iOS, and it doesn't seem like it is coming anytime soon). Maybe my way wasn't right.

Still, I find it a bit weird to be able to break a build by cleaning the dependencies and running swift package resolve instead of running swift package generate-xcodeproj again. For me, it was more consistent the way it was in swift 4.1.2, which is why I was wondering if there was a reason for breaking that :slight_smile:.

I guess for security reasons. And maybe the bug is that is was working in the first place. While using SPM, the xcodeproj is actually a side product, an artefact of the tool if you want to use Xcode for writing the code. But you could use anything else, TextEdit, SublimeText, VSCode, or even Vim. With the new LSP, it's gonna be even easier.

If you're developing an iOS/macOS app with graphical components, SPM is clearly not the way to go.

You're better off using something else, be it Cocoapods, Carthage, or just plain ol' submodules.

Good packages/libraries will often provide you with the 3 ways of incorporating them in your project.

One day, I hope, SPM will take over and we'll be able to do all of that from the command line without relying on Xcode.

I'm exactly trying to bring Carthage support to such a library (grpc-swift) :wink:.

I am not, but people who do may want to use a library that's relying on SPM. Hence the need to bridge between SPM and Carthage, for instance.

If SPM never goes into supporting iOS/macOS apps with graphical components, it means that those apps will always rely on Carthage/Cocoapods, which means that developers of libraries will always have to deal with Cocoapods, Carthage and (now) SwiftPM. So I don't see the xcodeproj leaving the repositories anytime soon, unfortunately.

Making an SPM library Cocoapods compatible is pretty easy.

See my example here: SwiftEventCenter/SwiftEventCenter.podspec at develop · ladislas/SwiftEventCenter · GitHub

But I can't help you with carthage :(

1 Like

You shouldn't rely on the structure of .build directory. Almost everything is an implementation detail and can change over time. Also, the generated Xcode project is not meant to be portable since it may contain absolute path references. There are other subtle things that can easily break if you share the generated project. For e.g., umbrella directory style generated modulemaps.

2 Likes

Right. That's good to know. I'll find another way, then ;-). There is @ladislas suggestion above, and @stephencelis' one about XcodeGen here.

Thanks a lot for the answers!

1 Like