Using a `.swiftmodule inside` `Package.swift`

Hello!

I have a peculiar problem when trying to build a swift package, that has a shared library as a dependency.

I'm using Uniffi, to build rust to swift bindings, as part of a project.

Using swiftc, I can build an importable swiftmodule, and use it in a file:

  • swiftc -emit-module -module-name bf -o libbf.so -emit-library -Xcc -fmodule-map-file=/home/dresden/fuzzing/baby_fuzzer/out/baby_fuzzerFFI.modulemap -I . -L . -lbaby_fuzzer baby_fuzzer.swift helps me create a bf.swiftmodule, from the corresponding modulemap and shared library.

Then I can:

  • swift -I . -L . -lbf -Xcc -fmodule-map-file=/home/dresden/fuzzing/baby_fuzzer/out/baby_fuzzerFFI.modulemap test.swift , run this to use the module inside the test.swift file, which contains:
import bf

<code>

Now, I want to use this module inside another package. I can't emulate this inside that however. Contents of Package.swift:

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

import PackageDescription

let package = Package(
    name: "BabyFuzzer",
    products: [
        // Products define the executables and libraries a package produces, making them visible to other packages.
        .executable(
            name: "BabyFuzzer",
            targets: ["BabyFuzzer"]),
    ],
    targets: [
        .executableTarget(
            name: "BabyFuzzer",
            dependencies: [],
            path: "Sources/BabyFuzzer",
            //publicHeadersPath: "include",
            swiftSettings: [
                .unsafeFlags(["-I/home/dresden/fuzzing/baby_fuzzer/out/bindings","-Xcc","-fmodule-map-file=/home/dresden/fuzzing/baby_fuzzer/out/bindings/baby_fuzzerFFI.modulemap"]),  // Adjust paths as necessary
            ],
            linkerSettings: [
                .unsafeFlags(["-L/home/dresden/fuzzing/baby_fuzzer/out/bindings", "-lbf"]),
                  // Adjust paths as necessary
            ]
        )
    ]
)

Current directory structure:

├── bindings
│   ├── baby_fuzzerFFI.h
│   ├── baby_fuzzerFFI.modulemap
│   ├── baby_fuzzer.swift
│   ├── bf.swiftdoc
│   ├── bf.swiftmodule
│   ├── bf.swiftsourceinfo
│   ├── libbaby_fuzzer.so
│   └── libbf.so
├── Package.swift
└── Sources
    └── BabyFuzzer
        └── main.swift

When I try to swift run:

swift run
Building for debugging...
[1/1] Write swift-version--1BFCD5C06E9F820A.txt
Build complete! (0.18s)
.build/x86_64-unknown-linux-gnu/debug/BabyFuzzer: error while loading shared libraries: libbf.so: cannot open shared object file: No such file or directory

main.swift has the same code as test.swift earlier.

Is there a method to solve this issue? (Without the system library concept)

Appreciate any help on this matter :smile:

Copying the libraries to /usr/lib seems to solve the issue. How do I specify the bindings folder as the path to swift though? :smile:

Looks like it does build, your issue is that the dynamic linker can't find the file when you try to run the resulting executable. You can use the LD_LIBRARY_PATH environment variable to tell it where to look. It already looks in /usr/lib which is why it works when you copy the library there.

LD_LIBRARY_PATH=/home/dresden/fuzzing/baby_fuzzer/out/bindings <executable to run>

If you want to learn more, this article explains things pretty well: Shared Libraries: Understanding Dynamic Loading

1 Like