Package Source Path Error

I have been having an issue with specifying a path for my source files in the Library I'm working on. I have most of the files under the Sources directory but the library is a mix of Objective-C and Swift code.

Here is the error that I get when running "swift build" error: the package does not contain a buildable target

Could someone advise me on a possible way to approach this or fix the error?

Thanks!

You cannot mix Objective‐C and Swift in the same target. The package needs to be composed of two (or more) distinct targets.

What does your Package.swift look like (so far), and what is the directory structure of your project?

The source code for the package is mostly Swift with a few files in Objective-C. The folder structure is
Sources
|_ _ Models
|_ _ Objc
|_ _ Subclasses
|_ _ Support Files
|_ _ UI
|_ _ Utils

If I fill in some placeholders according to what I understand you to mean, you have a directory structure like this:

Package.swift
Sources
    ↳ Models
        ↳ ModelA.swift
        ↳ ModelB.swift
    ↳ Objc
        ↳ include
            ↳ CMyModule.h
        ↳ ObjectiveCA.m
        ↳ ObjectiveCB.m
    ↳ Subclasses
        ↳ SubclassA.swift
        ↳ SubclassB.swift
    ↳ Support Files
        ↳ SupportA.swift
        ↳ SupportB.swift
    ↳ UI
        ↳ UIA.swift
        ↳ UIB.swift
    ↳ Utils
        ↳ UtilityA.swift
        ↳ UtilityB.swift

If that is the case, and you want all of the Swift sources to belong to one module, then your Package.swift could look something like this:

// swift-tools-version:5.1

import PackageDescription

let package = Package(
    name: "MyPackage",
    products: [
        .library(name: "MyLibrary", targets: [
            "MyModule",
            "CMyModule"
        ]),
    ],
    targets: [
        .target(
            name: "MyModule",
            dependencies: ["CMyModule"],
            path: "Sources",
            exclude: ["Objc"]),
        .target(
            name: "CMyModule",
            path: "Sources/Objc")
    ]
)

Once set‐up like that, the Swift files in MyModule can do this:

#if SWIFT_PACKAGE
import CMyModule
#endif

I wanted to give a bit more context. I tried to use a framework called Wormholy in a project by using it thru SPM via Xcode. I received the following error and I figured I'd try to fix it and submit a PR to the original developer.

After doing a bit of research, I tried to update the path for the source files in the manifest file but I came to the error I mentioned in my original post.

Here is my Manifest file:

// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "Wormholy",
    products: [
        // Products define the executables and libraries produced by a package, and make them visible to other packages.
        .library(
            name: "Wormholy",
            targets: ["Wormholy"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: /* package url */, from: "1.0.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages which this package depends on.
        .target(
            name: "Wormholy",
            dependencies: [],
            path: "Sources"),
        .testTarget(
            name: "WormholyTests",
            dependencies: ["Wormholy"]),
    ]
)

Here is the original error I receive that prompted me to reach out for help here :slight_smile:

➜  Wormholy git:(develop) swift build
'Wormholy' /Users/Vadym/Developer/projects/Wormholy: warning: Ignoring declared target(s) 'Wormholy, WormholyTests' in the system package
error: the package does not contain a buildable target

Here is the full folder structure.

Thank you for all the help thus far, hopefully this will provide enough information.

1 Like

The package URL was all I really needed.

To load the package successfully, I had to make these changes to the manifest:

With that, the Swift target builds just fine.

However, to get the Objective C one to build, I also needed to comment out an import that does not exist, and the two lines that use it:

m

With those changes both targets can be successfully imported by a client.

I assume the developer is accustomed to the missing header being generated automatically. It will have to be checked in to use it with SwiftPM.

Lastly, just because the targets can be imported does not necessarily mean they will work as intended. I see several interface builder files in there. None of those will be available to Wormholy in SwiftPM builds.

1 Like