Making dependencies writable in Xcode package project

I'm using Xcode to develop an SPM-based executable, and I’ve run into a situation where I’d like to be able to edit the source code of one of my dependencies. Xcode conveniently lets me navigate to the dependency’s source files, but seems to make them read-only.

This particular dependency comes from Github. I’d like to fork that project and start adding to it, but it would be most useful if I could do it directly in Xcode, and have Xcode rebuild the dependency as needed each time I run.

Is this possible?

1 Like

Yes: make a local clone of the package you want to edit, and drag its folder into the project navigator on the side bar. Xcode will understand that it is an editable version of one of the packages listed in the project.

So, my package project doesn't have the typical project at the top of the Files & Groups view.

Oops. Did you try anything? Including checking the editing options provided by SPM itself? swift-package-manager/Usage.md at main · apple/swift-package-manager · GitHub

Oh, thanks for pointing that out, that's a helpful feature. Issuing swift package edit SDL --branch additions created a new Packages directory and put a copy of the dependency there, switched to the branch additions. Unfortunately, Xcode doesn't seem to see it, refusing to show the sources there (it still shows the sources down inside DerivedData/.../checkouts, but that's still read-only).

Note that the Packages entry in Xcode is a blue folder, which usually indicates a folder reference rather than a group, and which normally reflects its contents as on disk. However, in the inspector you can see that the path for that folder reference is …DerivedData/InfoDisplay-bbxdotrtztwikhbjrfwwtbkoypav/SourcePackages/checkouts/SDL, not $(PROJECT_DIR)/Packages. This seems like a bug to me.

(It also didn't change the Package.swift github URL to refer to the additions branch, but I'm not sure if it was supposed to or not.)

Xcode:

Finder:

08%20

The CLI driven workflow has good handling of this use-case. You can create your package with:

$ swift package init --type executable

Then add your dependencies, and make them editable

Now you can make your xcode project:

$ swift package generate-xcodeproj

And inside this xcode project, your dependency sources will appear as a group and the files will be editable.

It also works fine for local dependencies: i.e. if your dependency is declared with a relative path rather than a URL.

Just take care because the project is no longer portable: you'll have to make sure to push any changes you make in the dependency upstream.

That works, it creates an explicit Xcode project (unlike Xcode 11’s implicit project when opening a Pacakge.swift file), and it lets me edit the dependencies.

Is this, then, a bug in Xcode when looking at a non-pre-generated Package?

From what I gather from the WWDC videos, this is a deliberate design choice. For most uses of Xcode 11, Apple feels that imported packages by default should be read-only. You have to go through the process to make them editable.

I think there is a way to make a SPM project already added in Xcode as a dependency editable, but, I can't recall how right off the top of my head.

This seems like a poor choice. Now we have two subtly different kinds of Swift Package Xcode project, with all the attendant confusion (as this thread points out).

For future folks finding this thread on Google, you can accomplish what is desired here without the generate-xcodeproj, but it requires the creation of an empty xcworkspace. Full details in this blog post but the TLDR is:

The TLDR:

  1. Create an empty workspace
  2. Draft the containing folder of the Swift Package you want to work on
  3. Wait for packages to resolve
  4. Drag the containing folder of the dependency you want to edit. The name of that folder needs to match the name of the dependency as it appeared after step 3. And make sure that it is a folder where you have the dependency checked out or is editable.
  5. Wait for packages to resolve
  6. Edit your current package and the dependency all together.

Step #4 is tricky because you need to make sure to drag it to the root of the workspace and not into the package you added in #2. Xcode makes this hard.