SwiftPM Framework not found for C library

1k views Asked by At

I am working on creating a Swift wrapper for an existing C library, using Swift Package Manager. I think i have structured everything properly, but I am getting an error when create and build an Xcode project. I have tried everything I could find, with no luck. Officially leaving me stumped.

Here is a link to the project in its current state: https://github.com/JKcompute/Camiitool/tree/stackpost

Here is my Package.swift

// swift-tools-version:5.3
import PackageDescription

let package = Package(
    name: "CamiitoolPackage",
    products: [
        .library(name: "Camiitool", targets: ["Camiitool"]),
        .library(name: "amiitoolSwift", targets: ["amiitoolSwift"]),
    ],
    dependencies: [
    ],
    targets: [
        .target(
            name: "amiitoolSwift",
            dependencies: [ 
               "Camiitool"
            ],
            path: "./Sources/amiitoolSwift"
        ),

        .target(
            name: "Camiitool",
            dependencies: [ 
                "mbedtls"
            ],
            path: "./Sources/Camiitool",
            exclude: [
                "mbedtls",
                "LICENSE"
            ],
            resources: [
                .copy("."),
            ]
        ),
        .target(
            name: "mbedtls",
            dependencies: [],
            path: "./Sources/Camiitool/mbedtls",
            exclude: [
                "./mbedtls/yotta",
                "./mbedtls/visualc",
                "LICENSE"
            ],
            resources: [
                .copy("."),
            ]
        ),  

        .testTarget(
            name: "amiitoolSwiftTests",
            dependencies: ["amiitoolSwift"]
        )
    ]
)

So what I have here is Camiitool is the C library Amiitool. Amiitool depends on mbedtls. So i have a target for mbedtls, Camiitool, and then i also have one for amiitoolSwift, which i plan on having my swift API.

Here is my swift file from the amiitoolSwift target. Note: its very basic right now, just for testing.

import Foundation
import Camiitool

public class Amii {
    var someString = "test"

    public init() {
        someString = "initialized"
    }
    
    public func printTest() {
        print(someString)
    }

     public func methodJustForTesting() {
        print(someString)

        let cString: UnsafePointer<CChar> = Camiitool.nfc3d_version_fork()

       print(String(cString: cString))
     }
}

The issue is that when i build, i am getting a Framework Not Found Error for Camiitool.

> Ld /Users/ME/Library/Developer/Xcode/DerivedData/CamiitoolPackage-fjhqfruljmetilfuiykpzwhzobkc/Build/Products/Debug/amiitoolSwift.framework/Versions/A/amiitoolSwift normal (in target 'amiitoolSwift' from project 'CamiitoolPackage')
cd /Users/ME/GIT/PERSONAL/Amiibo/backup-wip/Camiitool
/Applications/Xcode_12.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -target x86_64-apple-macos10.10 -dynamiclib -isysroot /Applications/Xcode_12.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -L/Users/ME/Library/Developer/Xcode/DerivedData/CamiitoolPackage-fjhqfruljmetilfuiykpzwhzobkc/Build/Products/Debug -F/Users/ME/Library/Developer/Xcode/DerivedData/CamiitoolPackage-fjhqfruljmetilfuiykpzwhzobkc/Build/Products/Debug -F/Applications/Xcode_12.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -filelist /Users/ME/Library/Developer/Xcode/DerivedData/CamiitoolPackage-fjhqfruljmetilfuiykpzwhzobkc/Build/Intermediates.noindex/CamiitoolPackage.build/Debug/amiitoolSwift.build/Objects-normal/x86_64/amiitoolSwift.LinkFileList -install_name @rpath/amiitoolSwift.framework/Versions/A/amiitoolSwift -Xlinker -rpath -Xlinker /usr/lib/swift -Xlinker -rpath -Xlinker /Applications/Xcode_12.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -Xlinker -object_path_lto -Xlinker /Users/ME/Library/Developer/Xcode/DerivedData/CamiitoolPackage-fjhqfruljmetilfuiykpzwhzobkc/Build/Intermediates.noindex/CamiitoolPackage.build/Debug/amiitoolSwift.build/Objects-normal/x86_64/amiitoolSwift_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -fobjc-link-runtime -L/Applications/Xcode_12.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -L/usr/lib/swift -Xlinker -add_ast_path -Xlinker /Users/ME/Library/Developer/Xcode/DerivedData/CamiitoolPackage-fjhqfruljmetilfuiykpzwhzobkc/Build/Intermediates.noindex/CamiitoolPackage.build/Debug/amiitoolSwift.build/Objects-normal/x86_64/amiitoolSwift.swiftmodule -framework Camiitool -framework mbedtls -Xlinker -dependency_info -Xlinker /Users/ME/Library/Developer/Xcode/DerivedData/CamiitoolPackage-fjhqfruljmetilfuiykpzwhzobkc/Build/Intermediates.noindex/CamiitoolPackage.build/Debug/amiitoolSwift.build/Objects-normal/x86_64/amiitoolSwift_dependency_info.dat -o /Users/ME/Library/Developer/Xcode/DerivedData/CamiitoolPackage-fjhqfruljmetilfuiykpzwhzobkc/Build/Products/Debug/amiitoolSwift.framework/Versions/A/amiitoolSwift

ld: framework not found Camiitool clang: error: linker command failed with exit code 1 (use -v to see invocation)

Anything i have tried to fix the issue just seems to create some different version of the same error. For example "Module not found Camiitool", or i have had Camiitool found, but then i get errors on the method call (nfc3d_version_fork), that the method does not exist.

One last note: the current state of my project is based on this example i found: https://github.com/RoaringBitmap/SwiftRoaring Which is basically the same thing i am doing, except without a submodule. I have pulled this project and i am able to build and run it just fine. I have compared all the settings between the projects and i can not notice any differences. Which lead me to finally post here.

Running MacOS 10.15.7, Xcode 12.0

1

There are 1 answers

0
Johnathon Karcz On BEST ANSWER

So I figured this one out.

First i noticed that even though the .framework file was being generated, it was mostly empty. This clearly did not seem right, so I started working on a separate project to make sure i was not missing any steps. I was able to get another project to work, so I went back to this one and made some changes.

Looks like it was an issue with my setup for version 5.3. I went back to 5.1 and was getting errors for duplicate symbols. Once i cleared those out by excluding the c files that were not needed. I was able to get it to work on 5.1

In order to go back to 5.1, I needed to remove resources.copy parameters I had in my original manifest. So when I went back to 5.3, I was getting a bunch of warnings about unhandled resources:

warning: found 424 file(s) which are unhandled; explicitly declare them as resources or exclude from the target

I received this warning before, and that was the reason i added the resource.copy(".") in the first place. I decided to take a different approach this time, and exclude everything that was not needed, and see if I needed to specifically include anything once i was done. Turns out I did not need to include any resources, and exclude solved all my errors and warnings.

here is my manifest updated.

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

import PackageDescription

let package = Package(
    name: "CamiitoolPackage",
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(name: "Camiitool", targets: ["Camiitool"]),
        .library(name: "amiitoolSwift", targets: ["amiitoolSwift"]),
        .library(name: "amiitoolSwiftDynamic", type: .dynamic,  targets: ["amiitoolSwift"]),
    ],
    dependencies: [
    ],
    targets: [
        .target(
            name: "amiitoolSwift",
            dependencies: [ 
               "Camiitool"
            ],
            path: "./Sources/amiitoolSwift"
        ),
        .target(
            name: "Camiitool",
            dependencies: [ 
                "mbedtls"
            ],
            path: "./Sources/Camiitool",
            exclude: [
                "./mbedtls",
                "./mbedtls/yotta",
                "./mbedtls/visualc",
                "./LICENSE",
                "./amiitool.c",
                "./README.md",
                "./Makefile"
            ]
        ),
        .target(
            name: "mbedtls",
            dependencies: [],
            path: "./Sources/Camiitool/mbedtls",
            exclude: [
                "./yotta",
                "./visualc",
                "./LICENSE",
                "./programs",
                "./tests",
                "./scripts",
                "./include/CMakeLists.txt",
                "./DartConfiguration.tcl",
                "./doxygen",
                "./library/Makefile",
                "./apache-2.0.txt",
                "./Makefile",
                "./README.md",
                "./ChangeLog",
                "./CMakeLists.txt",
                "./circle.yml",
                "./configs/README.txt",
                "./library/CMakeLists.txt"
            ]
        ),  
        .testTarget(
            name: "amiitoolSwiftTests",
            dependencies: ["amiitoolSwift"]
        )
    ]
)

Now it builds, generates no warnings or errors, and my .framework files are complete, as expected. I think there might be a bug here that I was not getting a better error, since xcode would show my Camiitool.framework building as successful. Even though it was clearly not.

I was able to then test my package with the following executable package setup, and this worked as well.

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

import PackageDescription

let package = Package(
    name: "packageTester",

    dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(name: "CamiitoolPackage", path: "../Camiitool"),
    ],
    targets: [
        .target(
            name: "packageTester",
            dependencies: [
                .product(name: "amiitoolSwift", package: "CamiitoolPackage")
            ]
        ),
        .testTarget(
            name: "packageTesterTests",
            dependencies: ["packageTester"]),
    ]
)