How to add local Swift Package as dependency?

I repeat from my earlier comment that using a URL and using a path have vastly different semantics. In addition, relative URLs do not work, so you run into trouble if you are part of a team or use CI: clone the project to another device and nothing will work. There is a time and place for local URLs, but they are not a replacement for relative paths.

If we are looking for what is “proper”, the very first answer upthread came from a rather authoritative source:

1 Like

Well, I came forward with that answer because it seemed to me some people had issues with dragging and dropping packages. And since the package integration system in Xcode is built around URLs I called the way when you in add a local package by typing in its URL "proper". I apologise if there is any confusion :blush:

2 Likes

Drag&Drop is not the same. It should be possible to add packages through SPM with relative paths as it works with Package.swift, but for Xcode's File -> Swift Packages -> Add Package Dependency... menu.

4 Likes

Your answer was super helpful and got me unblocked for local development. I still need to be able to write a CI test to make sure that the proper symbols are exposed etc... it's simply not enough to have a test that the package target itself will build. Are you aware of any ongoing work on adding proper pathing to Xcode so that we can have proper integration tests? Have you personally found a workaround for this?

Sorry, I don't think I understand your question. How to test that the package correctly exposes its symbols , like everything that has to be marked public is marked as such? Well, unit tests being compiled in separate module cannot access anything which is not exposed through public or not marked as @testable. Is that what you asking?

1 Like

I guess I mean as an integration test. Outside the context of a swift package. After I’ve created the package I want to run a smoke test with a separate project to make sure it can be consumed by that project as expected. This just means importing the libraries, making sure they compile in the context of an external app, and referencing some symbols as a sanity check.

The project I’m working with is sort of complex so it’s not a given that a consuming project will build the same way as the package on its own. I need to know that both are correct. :slightly_smiling_face:

Hmm I don't think I have ever though about implementing buildability test as something separate. technically one could create a separate test project which would be using all API types and calls that should be exposed by the package in question. And if this project builds the test passes. However, using CI implies that your package should already be deployed somewhere to be accessible via its URL by the build machine. So, it won't be local.

So the whole idea is that I could test it before it's deployed somewhere by using the local branch. I think this is still possible, just need to tool around with it a bit more.

I'm working on my libs by using them in my projects so I expect that my libs are connected locally so I can change their code on-the-fly. With Cocoapods I can do easily cause they put local pods to the specific folder named Development Pods and this is extremely useful.

I came here while trying to find out why dragging my Swift package into an Xcode project was not working. The package would show up in the project pane, but without the disclosure triangle, and the library it contained wouldn't show up when I tried to choose it with "Link Binary with Libraries".

The solution I found was to close the Xcode project after dropping the Swift package. On reopening the project, the disclosure triangle appeared, and everything else worked.

This is in Xcode 11.3 on MacOS 10.15.1. Hope this helps someone else.

2 Likes

If you're looking for a "development pods" type of experience, where you've got a local copy of the package source and you want to edit that source from inside the host project without having to commit and push your changes there's not currently a way to do that. However... I have found a hack that gets you halfway there. I'm using this approach in a sample project I include in one of my package's repositories.

Before proceeding, the following assumptions are made:

• you have your package repo cloned to your machine
• create a sample Xcode project in your Package repo

The root directory of your package repo should look like this, more or less:

Package.swift
Sources/
Tests/
SampleProject/

Then perform the following steps:

  1. Use the Xcode GUI to add your package to the sample project. You'll need to use the actual HTTPS URL to the repo origin. Specify a branch name to a branch you're comfortable working from regularly, e.g. a "develop" branch or something.

  2. Open the sample project's project.pbxproj file in a text editor.

  3. Find the XCRemoteSwiftPackageReference section.

  4. Edit the repositoryURL value so the line reads: repositoryURL = "../";

Now you should be able to build your sample project and run it normally.

The big caveat here is that it won't see any changes you haven't committed to the specified branch on your local clone. The good news is you don't have to push those changes to remote. Xcode resolves the ../ path to a local file URL and clones your local clone, not the remote branch.

3 Likes

This is the answer I was looking for, thank you. One small note is that latest committed changes are not made available immediately to the project, for that you need to select File > Swift Packages > Update

@Aciid As drag-n-drop approach does not seem to work for the case when application that uses the package is in the same folder with the package itself, can you consider it as a bug worth fixing? It seems to be a common scenario for libraries to provide a sample app along with the library itself.

Can you provide a sample project that isn't working?

For example this one https://github.com/ilyapuchka/SwiftNIOMock
It works with an approach described by @jaredsinclair but when dragging the package folder as you suggested first Xcode didn't resolve it (it only showed it as a package reference in the project structure). Now when I try to repeat this Xcode crashes so I can't make a screenshot, but I committed the change in the branch "local-spm". I can see that the project now has an entry that points to the package:

B506677E23EF674200EC3738 /* SwiftNIOMock */ = {isa = PBXFileReference; lastKnownFileType = folder; name = SwiftNIOMock; path = ..; sourceTree = "<group>"; };

Something else must be going on here. That general layout has never given me any issues on other projects.

But I can verify that doing the same thing on your project results in an Xcode workspace that crashes Xcode if you try to open it. Since this is an Xcode issue, I would talk to the Xcode folks over at the Feedback Assistant or the Developer Forums.

Submitted it as FB7570938

1 Like

Not sure if someone else already replied to this, but this is because you have two projects open at the same time, first one is your lib and second is your project you dropped your lib into. You have to close your lib project for it to work from the second project. ;)

2 Likes

This seems to be the best way of handling it. You can even modify the source code of the package from your main project, and it gets applied immediately.

With regard to the drag-and-drop approach, I've discovered that this works as long as only one project that uses the project is open at a time. As long as you do that, any project can edit, view, and import this package. Note, however, that this is not a true dependency. If you want that, you need to upload the package to a remote resource and serve it to yourself using the actual Add Package Dependency mechanism.

2 Likes
Terms of Service

Privacy Policy

Cookie Policy