Cannot access USB serial port via binary target within a package

My Swift app accesses the USB serial port via a C++ API built as a universal dylib. When the dylib is added as a framework via "Frameworks, Libraries, and Embedded Content", it works fine. When instead the dylib is included as a binary target within an xcframework inside a Package, I get an error indicating a permissions issue.

The package looks like this:

// swift-tools-version:5.3
import PackageDescription

let package = Package(
    name: "BrainFlow",
    platforms: [
        .macOS(.v10_14)
    ],
    products: [
        .library(
            name: "BrainFlow",
            targets: ["BrainFlow", "BoardController", "BrainBitLib", "DataHandler",
                      "GanglionLib", "MLModule", "MuseLib"])
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
    ],
    targets: [
        .target(
            name: "BrainFlow"
        ),
        .binaryTarget(
            name: "BoardController",
            path: "BoardController.xcframework"
        ),
        .binaryTarget(
            name: "BrainBitLib",
            path: "BrainBitLib.xcframework"
        ),
        .binaryTarget(
            name: "DataHandler",
            path: "DataHandler.xcframework"
        ),
        .binaryTarget(
            name: "GanglionLib",
            path: "GanglionLib.xcframework"
        ),
        .binaryTarget(
            name: "MLModule",
            path: "MLModule.xcframework"
        ),
        .binaryTarget(
            name: "MuseLib",
            path: "MuseLib.xcframework"
        ),
        .testTarget(
            name: "BrainFlowTests",
            dependencies: ["BrainFlow"]
        )
    ]
)

I get an error indicating a permissions issue.

I’d like more details about that. Is this permissions error reported when you run the code? If so, what system call reports the error? And what error is it? EPERM?

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

Hi Quinn! Thanks so much for replying.

Yes the error is reported when I run the code. The system call is:

The return value is -1 (I added a debug print statement, not shown above.) The open_serial_port function is called here:

which then prints the error message at line 37:

"Make sure you provided correct port name and have permissions to open it(run with "
"sudo/admin). Also, close all other apps using this port."

macOS Apps are by default sandboxed and need a special USB entitlement to be able to access USB devices. Because you said that it works with a universal dylib but not as an XCFramework, you probably already have the right settings but it may be worth double checking. At least I run into this issue when I first tried to access a serial device: Always Getting failedToOpen Error · Issue #9 · yeokm1/SwiftSerial · GitHub
The screenshot that shows how to add the entitlement is quite old and the tab for it is now called "Signing & Capabilities". Everything else looks quite similar.

I also see that you have a test target BrainFlowTests. AFAIK, SwiftPM tests run in a sandbox too and I don't think you can change the entitlement for it. Therefore you will not be able to access any device from this test target.

Thanks David. I already tried your suggestion but it did not help. It did however prompt me to revisit my Xcode project and target settings, and to retry embedding the dylib directly as a framework instead of via the Package (I removed the Package from the project entirely.) Much to my chagrin I get the same error. So now the issue seems no longer related to the Package.

I have another project where the open() call is working via embedded framework. I am now comparing the project and target settings between that project and my non-working project, to see where I went wrong.

1 Like

I scoured my project and target settings but could not find a setting that made any difference. So I made a copy of my working project and then, in the copy, replaced the embedded frameworks with the Package. The copy is working fine, hence it is definitely not a package issue.

My working project was created more than 1 year ago using an older 12.x version of Xcode. The non-working project I created a few days ago using the latest version of Xcode. Therefore I suspected it might be an issue with Info.plist being generated automatically in Xcode 13, so I tried copying the Info.plist from working to non-working and updating the appropriate build settings, but still no luck.

I will start from scratch, creating a new project using the App template for macOS. Any tips or suggestions would be most welcome.

1 Like

It is indeed an entitlements issue. I disabled App Sandbox via the Entitlements File, and now it works.

This is not a Swift issue. I apologize for posting it to this forum. Thanks Quinn and David for your help.

1 Like