100

I have a project with multiple targets, such as an iOS app, a watchOS app, and some frameworks. How can I assign the same Swift Package to all my targets? Xcode only let's me select one:

SPM1

If I try to add the Swift Package again so I can try assigning it to another target in my project, I get an error:

SPM2

What is the correct way to do this? Below is what the package manifest looks like in the Swift Package. Is there something to be done on that side or something I have to do different in Xcode?

import PackageDescription

let package = Package(
    name: "Alamofire",
    platforms: [
        .macOS(.v10_12),
        .iOS(.v10),
        .tvOS(.v10),
        .watchOS(.v3)
    ],
    products: [
        .library(
            name: "Alamofire",
            targets: ["Alamofire"])
    ],
    targets: [
        .target(
            name: "Alamofire",
            path: "Source")
    ],
    swiftLanguageVersions: [.v5]
)
TruMan1
  • 33,665
  • 59
  • 184
  • 335
  • 1
    My current workaround is to drag & drop add the Xcode project generated from the common Swift Package dependency as a subproject on the iOS and macOS top level projects. (... still on Xcode 10) ... some discussion of approach at [Vapor server and companion iOS app examples](https://stackoverflow.com/questions/47717355/vapor-server-and-companion-ios-app-examples/55368410#55368410). – marc-medley Aug 23 '19 at 20:49
  • 1
    This is a huge oversight on Apple's part. After two years, Swift Package Manager is still a non-starter in Xcode's _default_ project type - Multiplatform App. – Steve May 30 '21 at 11:18

6 Answers6

154

I had the same problem, and I only found this two solutions:

First, add the package to the first target:

Add package

Then, the first option is going to the other target, General tab, and in Frameworks, Libraries and Embedded Content press +, select the package and press Add:

Adding package in General tab

The other option is going to build Phases and repeat a similar way in Link Binary With Libraries:

Build Phases

Select package

At the moment, I only know this options, I hope in the future Apple could improve this with a multi-check, for example.

Diego Carrera
  • 2,245
  • 1
  • 13
  • 16
  • 7
    I'm getting an error: "Swift package product _ is linked as a static library ... This will result in duplication of library code". From what I can see, the only difference is that one of my targets is an Extension. – XmasRights Apr 06 '20 at 19:22
  • 1
    This will duplicate all your symbols in multiple targets. Not good. –  Feb 07 '21 at 08:06
  • 1
    I'm pretty sure the first option (General tab) is how you're supposed to do this - what gets generated there configuration-wise is identical to what gets generated when you do the initial target from the SPM setup tool – bplattenburg Jun 10 '21 at 19:49
  • @XmasRights I don't get that error, but when I try to upload the build to AppStoreConnect, it complains about duplicate CFBundleIdentifiers. – Rick Jan 12 '22 at 23:04
  • 2
    For me it doesn't work for Xcode 14.1, but works well for Xcode 14.0. – 2Grey Nov 10 '22 at 13:30
  • Although this should have worked for me (has worked for me in the past for other libs) but when I tried adding this framework it did not appear to choose from the list. The same library exists in one of the targets, but not for all the targets. To do this, I had to manually open the project file and add the copied line of the framework from the already added target to other targets. So what Brett mentioned it worked for me. (I am using Xcode 14.1) – learner Mar 16 '23 at 16:22
  • @ManishGupta Did you manage to find it without editing the project file? – BlackM Apr 05 '23 at 11:26
  • @BlackM - No I did not find any other way, I ended up modifying the project file manually. Please let me know if you find a way. Also, Is this a bug on Xcode or the creator of framework. I believe its Xcode. – learner Apr 10 '23 at 19:36
6

In addition to the solution diego-carrera gave I had to reset the swift package caches to have the package available for all targets in the framework dialog.

In Xcode: File -> Swift Packages -> Reset Package Caches

Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
Sanzaru
  • 101
  • 2
  • 4
4

I hit the same problem when trying to add the new Numerics package to my project which contains an iOS Target called CreativeCoding, and a Mac command line target called mandelbrot.

I added the package the normal way in Xcode to the first target. I then quit Xcode and opened up the project.pbxproj file in an editor (vi of course). I then went down to the / Begin PBXNativeTarget section / comment, found my CreativeCoding target and copied the 3 lines from the packageProductDependencies container with the new Numerics packages (Numerics, ComplexModule, RealModule) and pasted them into the packageProductDependencies container of my mandelbrot command line target.

/* Begin PBXNativeTarget section */
            8B083F4B24F0B40000A225C8 /* CreativeCoding */ = {
                    isa = PBXNativeTarget;
                    buildConfigurationList = 8B083F6024F0B40200A225C8 /* Build configuration list for PBXNativeTarget "CreativeCoding" */;
                    buildPhases = (
                            8B083F4824F0B40000A225C8 /* Sources */,
                            8B083F4924F0B40000A225C8 /* Frameworks */,
                            8B083F4A24F0B40000A225C8 /* Resources */,
                    );
                    buildRules = (
                    );
                    dependencies = (
                    );
                    name = CreativeCoding;
                    packageProductDependencies = (
                            8B22BD29263E328B00867530 /* ComplexModule */,
                            8B22BD2B263E328B00867530 /* RealModule */,
                            8B22BD2D263E328B00867530 /* Numerics */,
                    );
                    productName = CreativeCoding;
                    productReference = 8B083F4C24F0B40000A225C8 /* CreativeCoding.app */;
                    productType = "com.apple.product-type.application";
            };
            8BE83F4F26213D1C00663AC9 /* mandelbrot */ = {
                    isa = PBXNativeTarget;
                    buildConfigurationList = 8BE83F5626213D1D00663AC9 /* Build configuration list for PBXNativeTarget "mandelbrot" */;
                    buildPhases = (
                            8BE83F4C26213D1C00663AC9 /* Sources */,
                            8BE83F4D26213D1C00663AC9 /* Frameworks */,
                            8BE83F4E26213D1C00663AC9 /* CopyFiles */,
                    );
                    buildRules = (
                    );
                    dependencies = (
                    );
                    name = mandelbrot;
                    packageProductDependencies = (
                            8BB120942622CCB8008EDAB0 /* ArgumentParser */,
                            8B22BD29263E328B00867530 /* ComplexModule */,
                            8B22BD2B263E328B00867530 /* RealModule */,
                            8B22BD2D263E328B00867530 /* Numerics */,
                    );
                    productName = mandlebrot;

It may have been a little easier for me as I already had the ArgumentParser package on my second target that I just appended the 3 new lines to. However you could do the same and add a temporary package to your second target.

I then went in to Xcode and built the two targets like normal and it worked.

Brett
  • 1,647
  • 16
  • 34
2

For me it was the version of Xcode 14.2. I couldn't see the framework I wanted to add to the target, but updating to the latest Xcode 14.3.1 fixed the issue. I was able to see the Swift Package I wanted to add to the second target and added it successfully.

I used Diego's answer https://stackoverflow.com/a/58079416/2929892 to add the missing framework.

valbu17
  • 4,034
  • 3
  • 30
  • 41
1

If you add a new target after you added the dependency, then you will have to remove the dependency from the project and then add it back in again. Otherwise the library will not show up in the framework chooser.

It's annoying that the one reliable thing Xcode can do with Swift Package Manager is crash for me. So make sure you have a backup of the project because it can get to a state that just opening it will crash Xcode.

John Endres
  • 327
  • 3
  • 8
0

With Xcode 12 you just select second target and add dependency (swift package).

sabiland
  • 2,526
  • 1
  • 25
  • 24