I created test project - "TaoTester" and test package with C-library called "SwiftGit2".

After few days of work in package almost all works fine....

EXCEPT: I cannot link C-libraries files into the package using related paths.
It's work fine with absolute path's:

// swift-tools-version: 6.0

import PackageDescription

let package = Package(
    name: "SwiftGit2",
    platforms: [
        .macOS(.v12)
    ],
    products: [
        .library(
            name: "SwiftGit2",
            targets: ["SwiftGit2"]
        )
    ],
    dependencies: [
        .package(url: "https://github.com/apple/swift-collections.git", exact: "1.3.0"),
        .package(url: "https://github.com/pointfreeco/swift-parsing.git", exact: "0.10.0"),
        // --------
        .package(url: "https://github.com/Quick/Nimble.git", exact: "8.1.2"),
        .package(url: "https://github.com/Quick/Quick.git", exact: "2.2.1"),
    ],
    targets: [
        .target(
            name: "Clibgit2",
            path: "Sources/Clibgit2",
            publicHeadersPath: "include",
            cSettings: [
                .headerSearchPath("include")
            ],
            linkerSettings: [
                .unsafeFlags([
                    "/Users/User/TaoGitRepos_Empty/TestSG2/SwiftGit2P/Sources/Clibgit2/libgit2.a",
                    "/Users/User/TaoGitRepos_Empty/TestSG2/SwiftGit2P/Sources/Clibgit2/libssh2.a",
                    "/Users/User/TaoGitRepos_Empty/TestSG2/SwiftGit2P/Sources/Clibgit2/libssl.a",
                    "/Users/User/TaoGitRepos_Empty/TestSG2/SwiftGit2P/Sources/Clibgit2/libcrypto.a",
                ]),
                
                .linkedLibrary("z"),       // zlib
                .linkedLibrary("iconv"),   // iconv
            ]
        ),
        
        .target(
            name: "SwiftGit2",
            dependencies: [
                "Clibgit2",
                .product(name: "Collections", package: "swift-collections"),
                .product(name: "Parsing", package: "swift-parsing"),
            ]
        ),
        
        .testTarget(
            name: "SwiftGit2Tests",
            dependencies: [
                "SwiftGit2",
                .product(name: "Quick", package: "Quick"),
                .product(name: "Nimble", package: "Nimble")
            ]
        )
    ]
)

But doesn't work with relative paths:

.unsafeFlags([
    "Sources/Clibgit2/libgit2.a",
    "Sources/Clibgit2/libssh2.a",
    "Sources/Clibgit2/libssl.a",
    "Sources/Clibgit2/libcrypto.a",
]),

My Package have the following structure:

Xcode files structure

I have tried a lot of things but this is best solution that I have at the moment.
But still - absolute path to library is not good enough solution for me as project must be compiled on lot of computers.

Does anyone know how to use package with relative paths to attach "a"-library files?

6 Replies 6

Normally to export C APIs to swift, you need module maps. Please read this helpful link first: https://rderik.com/blog/making-a-c-library-available-in-swift-using-the-swift-package/

I have tried to use module map for this package, but didn't find proper solution that will work =( This is really the best I have got in a half of week that can be compilled without errors and with successful linked c-libraries. But I will read, thanks.

Forget about module map: it's fully managed by SPM.

You need add this libs as binaryTargets

@Cy-4AH as SwiftPM does not support adding ".a" files as binaryTargets, but supports "xcframeworks".

I did the following:

  1. As xcframeworks does not work with set of "a" libs - only with one: I did combine set of a-libs into one a-lib:
libtool -static -o libclibgit2_combined.a \
    libgit2.a \
    libssh2.a \
    libssl.a \
    libcrypto.a
  1. build xcframework:
xcodebuild -create-xcframework \
  -library libclibgit2_combined.a \
  -headers include \
  -output Clibgit2.xcframework
  1. in PackageSwift applied binaryTarget:
.binaryTarget(
            name: "Clibgit2",
            path: "Sources/Clibgit2/Clibgit2.xcframework"
        ),
  1. also there was required to manually create modulemap inside of xcframework:
module Clibgit2 {
    umbrella "."
    export *
    link "clibgit2"
}
  1. after this I rebuild project from scratch: did remove derived data, made "reset packages cache" and "cleared build files".

And looks like success.

Thanks a lot for all of help

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.