Reputation: 10375
I'm trying to generate a wrapper around a C library for Swift but when I import it into my Xcode project I'm getting an error that
Missing required module 'Clibsodium'
I'm not sure where it's trying to get that name from. My wrapper has this for the Package.swift
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "Sodium",
pkgConfig: "libsodium",
providers: [
.brew(["libsodium"]),
.apt(["libsodium-dev"])
]
)
And then my module.modulemap looks like so:
module Sodium [system] {
header "shim.h"
link "sodium"
export *
}
and shim.h just includes the proper header:
#ifndef CLIB_SWIFT_SODIUM
#define CLIB_SWIFT_SODIUM
#ifdef __APPLE__
#include "/usr/local/include/sodium.h"
#else
#include "/usr/include/sodium.h"
#endif
#endif
On my mac, if I run pkg-config --libs libsodium
it says this:
-L/usr/local/Cellar/libsodium/1.0.16/lib -lsodium
Upvotes: 1
Views: 443
Reputation: 1373
I fixed the defining the Clibsodium lib as an explicit module. Doing that you can import it via the Sodium framework like import Sodium.Clibsodium and fixing with that the missing Missing required module 'Clibsodium'
I inspired my solution on:
In order to import C library into Swift, it first need to be be declared as a module. Declaration takes the form of a module map — a file describing headers to import and static libraries to link with. The resulting module may be imported into Swift (natively) and Objective-C (using @import keyword).
This way of embedding C library into a framework will work for you in most cases (learn more about this approach here and there). It is totally legit as long as you’re developing some internal framework or simply modularising your application into separate parts. However, it doesn’t work well when you need to ship your library to external users via Carthage, Cocoapods or as a binary. The main reason being that the resulting framework is not portable between computers. When undergoing compilation, your resulting framework is bound to the current location of headers and libraries from module map on your computer. You can use it right away in your project but should you try to send it to somebody else they will not be able to link it to a project because files referenced by module map are no longer accessible.
from this article where you can find step by step how to achieve it with the advantage and disadvantage of this approach.
Basically what you need to do is:
Inside Sodium.modulemap you can define the Clibsodium library as an explicit module like:
framework module Sodium {
umbrella header "Sodium.h"
explicit module Clibsodium {
private header "version.h"
private header "crypto_pwhash_argon2id.h"
private header "export.h"
private header "core.h"
private header "crypto_aead_aes256gcm.h"
private header "crypto_aead_chacha20poly1305.h"
private header "crypto_aead_xchacha20poly1305.h"
private header "crypto_auth.h"
private header "crypto_auth_hmacsha256.h"
private header "crypto_auth_hmacsha512.h"
private header "crypto_auth_hmacsha512256.h"
private header "crypto_box.h"
private header "crypto_box_curve25519xsalsa20poly1305.h"
private header "crypto_core_hsalsa20.h"
private header "crypto_core_hchacha20.h"
private header "crypto_core_salsa20.h"
private header "crypto_core_salsa2012.h"
private header "crypto_core_salsa208.h"
private header "crypto_generichash.h"
private header "crypto_generichash_blake2b.h"
private header "crypto_hash.h"
private header "crypto_hash_sha256.h"
private header "crypto_hash_sha512.h"
private header "crypto_kdf.h"
private header "crypto_kdf_blake2b.h"
private header "crypto_kx.h"
private header "crypto_onetimeauth.h"
private header "crypto_onetimeauth_poly1305.h"
private header "crypto_pwhash.h"
private header "crypto_pwhash_argon2i.h"
private header "crypto_scalarmult.h"
private header "crypto_scalarmult_curve25519.h"
private header "crypto_secretbox.h"
private header "crypto_secretbox_xsalsa20poly1305.h"
private header "crypto_secretstream_xchacha20poly1305.h"
private header "crypto_shorthash.h"
private header "crypto_shorthash_siphash24.h"
private header "crypto_sign.h"
private header "crypto_sign_ed25519.h"
private header "crypto_stream.h"
private header "crypto_stream_chacha20.h"
private header "crypto_stream_salsa20.h"
private header "crypto_stream_xsalsa20.h"
private header "crypto_verify_16.h"
private header "crypto_verify_32.h"
private header "crypto_verify_64.h"
private header "randombytes.h"
private header "randombytes_internal_random.h"
private header "randombytes_sysrandom.h"
private header "runtime.h"
private header "utils.h"
}
export *
module * { export * }
}
Sodium.modulemap should not be added to any target and must be specified in Build Settings — Packaging — Module Map (MODULEMAP_FILE) = $SRCROOT/GifSwift/GifSwift.modulemap
Now you can use the Sodium framework in any project without having the missing module error because Sodium will look for the library inside the .framework container
Upvotes: 1