SwiftPM Using a System Library

Hello,

Please excuse me if this is obvious - but for the life of me I cannot get a system library as a target in a swift executable using the SwiftPM.

Initially I tried the method in the documentation here:

That method involves creating a whole separate package as a git repo then making that a dependency of the main package. Alas I couldn't get that to work and I noticed that that method was deprecated as noted in the compilation output.

So - this time I'm attempting the newer technique as described here:

My package manifest is as so:

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

import PackageDescription

let package = Package(
    name: "libNFCTest",
    dependencies: [
        // Dependencies declare other packages that this package depends on.
    ],
    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.
        .systemLibrary(
			name: "libnfc", 
			pkgConfig: "libnfc",
			providers: [
					.apt(["libnfc-dev"]), 
					.brew(["libnfc"]) ]),
        .target(
            name: "libNFCTest",
            dependencies: ["libnfc"]),
        .testTarget(
            name: "libNFCTestTests",
            dependencies: ["libNFCTest"]),
    ]
)

and my module.modulemap file is as so:

module cairo 
{
    umbrella header "libnfc.h"
    link "libnfc"
}

I have libnfc installed via Brew, but upon attempts to compile I get:

Compile Swift Module 'libNFCTest' (1 sources)

**/Users/diggory/Code/OpenSource/libNFCTest/Sources/libNFCTest/main.swift:1:8:** **error:** **no such module 'libnfc'**

import libnfc

**^**

**error:** terminated(1):

What am I getting wrong?
Thanks.

1 Like

Right -- I'm an idiot - I've just seen the copy/paste error that I made.

Actually - even with the corrected typo, I now get the same compilation error that I got with the previous technique.

The compiler appears to recognise the functions defined in the header file referenced (libnfc.h), but not the types defined in another header which is #included in that header (libnfc-types.h).

**main.swift:3:18:** **error:** **use of undeclared type 'nfc_context'**

var nfcContext : nfc_context

I think the nfc_context can not be found is normal behavior. The nfc-types.h file just declare the struct without the inner structure. Swift port it as OpaquePointer without a type. If you want to use the nfc_context. I think that's the proper way. (Maybe not due to not familiar with libnfc)

import Foundation
import CNfc


class NFCContext {
    let raw: OpaquePointer
    
    init(raw: OpaquePointer) {
        self.raw = raw
    }
    
    convenience init() {
        var raw: OpaquePointer?
        print(raw)
        nfc_init(&raw)
        print(raw)
        self.init(raw: raw!)
    }
    
    deinit {
        nfc_exit(raw)
        print("deinit")
    }
    
}

autoreleasepool {
    print(String(cString: nfc_version()))
    let context = NFCContext()
}

print("finish")

The output:

1.7.1
nil
Optional(0x000000010080c200)
deinit
finish
Program ended with exit code: 0
1 Like

Why then master branch has changed the document. This section has been deleted from the document. Confused. A similar post System target library: How to use them?

I still see the section in the documentation in the main branch, at swift-package-manager/Usage.md at main · apple/swift-package-manager · GitHub . System library targets are still supported, and should work as described there.

In SwiftPM 4.1 and earlier, system libraries used to require separate packages instead of just separate targets. That was changed in swift-evolution/0208-package-manager-system-library-targets.md at master · apple/swift-evolution · GitHub , but some write-ups on various web sites may refer to the older package-based functionality.

my brain chaos