jl303
jl303

Reputation: 1599

How to Incorporate Swift Package Manager to an Existing Xcode Project?

I already have a working Xcode project for a MacOS App. However, I would like to add a Swift framework from Github using Swift Package Manager.

I ran "swift package init" inside the project folder. Then I updated Package.swift file. Then I ran "swift package resolve".

However, it still complains no such module when I try to build.

Since I already have a working project, if I run "swift package generate-xcodeproj", it messes up the folder structure as well as removing the storyboard.

How can I tell Xcode to use the module that swift package manager downloaded into the project?

Thank you!

Upvotes: 4

Views: 6109

Answers (4)

Brianna Doubt
Brianna Doubt

Reputation: 699

All the answers here are real old and outdated so I decided to add some modern context in case anyone comes across this like I did.

Apple has done some seriously awesome upgrades to Xcode to natively support Swift Package Manager out of the box. The following image shows my local package (that I build and maintain) incorporated with the demo project included in the git repo. Navigating to this page (3) and clicking the + button (4) will open a dialogue to add remote packages from git repositories. This can be done with any .xcproj file.

Xcode Swift Package Manager Support

Apple also has a lot of wonderful documentation on how to build and support Swift Packages yourself, or how to incorporate them into your app.

It's very good practice to organize your code into local package dependancies per the documentation:

Swift packages are a convenient and lightweight solution for creating a modular app architecture and reusing code across your apps or with other developers. Over time, you may want to develop your published Swift package in tandem with your app, or create a sample app to showcase its features. To develop a Swift package in tandem with an app, you can leverage the behavior whereby a local package overrides a package dependency with the same name:

  1. Add the Swift package to your app as a package dependency instead of a local package, as described in Editing a Package Dependency as a Local Package.

  2. Develop your app and your Swift package in tandem, and push changes to their repositories.

  3. If you release a new version of your Swift package or want to stop using the local package, remove it from the project to use the package dependency again.

See Apple's official Swift Package Manager Documentation for more up-to-date information.

Many loves! <3

Upvotes: 3

samwize
samwize

Reputation: 27353

The generated Xcode project from SPM is different from your app's Xcode project/workspace.

You should generate that Xcode project in another directory eg. "Dependencies".

Then drag it into your app's, and add the linked framework. I have written a full step-by-step.

Upvotes: 3

Alex
Alex

Reputation: 1565

Steps to achieve Swift Package Manager and XCode integration in 2019:

1) Create Dependencies.swift file /yourproject/Dependencies/Sources/Dependencies.swift

(empty file)

2) Create macos.xcconfig file /yourproject/Dependencies/Sources/macos.xcconfig

MACOSX_DEPLOYMENT_TARGET = 10.14

3) Create Package.swift file /yourproject/Dependencies/Package.swift

// swift-tools-version:4.2
import PackageDescription

let package = Package(
    name: "Dependencies",
    products: [
        .library(name: "Dependencies", type: .static, targets: ["Dependencies"])
    ],
    dependencies: [
        .package(url: "https://github.com/YourDependency/here.git", .upToNextMinor(from: "0.1.0"))
    ],
    targets: [
        .target(name: "Dependencies", dependencies: ["YourDependency"])
    ]
)

4) Generate Dependencies.xcodeproj and drag-and-drop into your existing project

swift package generate-xcodeproj --xcconfig-overrides Sources/macos.xcconfig

5) Import your dependency

import YourDependency

This is enough to make it work but you can make your life a bit easier with a few extra steps.

Additional (optional) steps:

6) Create ios.xcconfig file /yourproject/Dependencies/Sources/ios.xcconfig

SDKROOT = iphoneos
SUPPORTED_PLATFORMS = iphonesimulator iphoneos
IPHONEOS_DEPLOYMENT_TARGET = 10.0

ARCHS = $(ARCHS_STANDARD)
VALID_ARCHS = $(ARCHS_STANDARD)

VALIDATE_PRODUCT = YES
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks
TARGETED_DEVICE_FAMILY = 1, 2

7) Add Pre-build action to your main project's iOS and macOS Schemes

iOS

echo "Building SPM Dependencies"
BASE_DIR="${PROJECT_DIR}/Dependencies"
cd ${BASE_DIR}

rm -fr Dependencies.xcodeproj
swift package update
swift package generate-xcodeproj --xcconfig-overrides Sources/ios.xcconfig

sleep 3

until [ -d "Dependencies.xcodeproj" ]
do
echo "File not found"
sleep 0.1
done
echo "File found"
exit

macOS

echo "Building SPM Dependencies"
BASE_DIR="${PROJECT_DIR}/Dependencies"
cd ${BASE_DIR}

rm -fr Dependencies.xcodeproj
swift package update
swift package generate-xcodeproj --xcconfig-overrides Sources/macos.xcconfig

sleep 3

until [ -d "Dependencies.xcodeproj" ]
do
echo "File not found"
sleep 0.1
done
echo "File found"
exit

8) Run your project and enjoy :)

Upvotes: 1

Caleb Kleveter
Caleb Kleveter

Reputation: 11484

macOS, iOS, tvOS, and watchOS do not support the Swift Package Manger at the time of this writing (Dec 2017). Instead, you will have to add the files from the package directly to your project.

I would suggest creating a Dependencies group in your project and a group below that with the package name:

enter image description here

Then add the files to the group:

enter image description here

enter image description here

I was unable to get this to work if I added folders, so you should add all the files to groups if you want to maintain structure of the package. I might have done this the wrong way though.

You can then access the code as you usually would when you write it yourself. No imports.

enter image description here

Upvotes: 1

Related Questions