Swift – How to use Swift Package Manager with an existing macOS project

macosswiftxcode

I've been using Cocoapods to manage dependencies for my Swift project. I came across this package which is not listed at Cocoapods. Instead it suggests using Swift Package Manager. However, whenever I try to use Swift Package Manager to do basically anything, it ends up completely destroying my entire project.

So, in order to figure out how to actually use Swift Package Manager, I'm playing with it in a test project.

Here's what I've tried:

  1. Create a new project from Xcode

File -> New -> Project -> Cocoa App

Product Name: basic-ssh-test

This creates a basic application which loads a blank window when I hit "Run". Just for fun I added print("test") to the applicationDidFinishLaunching function in my AppDelegate so the debug window says "test" when I run the program.

Now I want to add the Shout package as a dependency.

  1. swift package init --type executable

This creates the following files:

Creating executable package: basic-ssh-test
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/basic-ssh-test/main.swift
Creating Tests/

Now I'm going to add the "Shout" dependency to my new Package.swift file:

// swift-tools-version:4.0
import PackageDescription

let package = Package(
    name: "basic-ssh-test",
    dependencies: [
        .package(url: "https://github.com/jakeheis/Shout", from: "0.2.0")
    ],
    targets: [
        .target(
            name: "basic-ssh-test",
            dependencies: ["Shout"]),
    ]
)

And I'll pull in the dependencies:

  1. swift package resolve

This results in the dependencies being pulled into the .build directory:

Fetching https://github.com/jakeheis/Shout
Fetching https://github.com/jakeheis/CSSH
Fetching https://github.com/IBM-Swift/BlueSocket
Cloning https://github.com/IBM-Swift/BlueSocket
Resolving https://github.com/IBM-Swift/BlueSocket at 0.12.91
Cloning https://github.com/jakeheis/CSSH
Resolving https://github.com/jakeheis/CSSH at 1.0.3
Cloning https://github.com/jakeheis/Shout
Resolving https://github.com/jakeheis/Shout at 0.3.0

Now I regenerate the xcodeproj file:

  1. swift package generate-xcodeproj

Now when I open the xcodeproj file there is a new group called Sources that has a single directory basic-ssh-test with a single swift file in it main.swift with print("Hello, world!").

The code that I'm actually interested in running is now in a blue folder called basic-ssh-test. All of the necessary files are still in there, but instead of running my application, Xcode is running the main.swift file. I can tell because the debug output is "Hello, world!" instead of "test".

I've read a couple of tutorials that claim that Swift Package Manager will move my source files and continue to build the same as before, but that's clearly not the case.

There's also no longer a "Main Interface" option in my Build Settings, so I can't select "MainMenu.xib" as my application starting point.

This is essentially the same thing that happens when I try to use Swift Project Manager with my existing project. It pulls in the dependencies, but it basically ignores my entire existing project and just runs the "hello world" code.

How do I use Swift Package Manager to add a dependency to an existing project without ignoring the existing codebase?

Best Answer

I think SPM is only compatible with Mac command line executables or libraries. This explicitly states SPM doesn't support iOS, watchOS, or tvOS platforms at all. But, since macOS AppKit/Cocoa application targets are very similar to iOS or tvOS Xcode targets, I would say this statement implies that SPM can't be used with macOS Cocoa applications out of the box either, which is what I think you're hoping for.

It looks like there is some work here on how to use it with iOS application targets which should largely translate to a macOS Cocoa target.