Packaging .a static C libraries in Swift Package Manager

Hello guys. I'm working on an iOS project and trying to add SPM support to it.
The problem is that one of the dependencies uses OpenSSL, a C static library which consists of
libcrypto.a, libssl.a and a bunch of header files respectively.

So what I've been trying to do is put the libcrypto.a, libssl.a and the headers inside the package and bundle them together to use this package as a dependency, so that others can easily integrate the openssl functionality.

Here's my setup:

Project structure:

    . 
    β”œβ”€β”€ Package.swift
    └── Sources 
        └── OpenSSL
        β”œβ”€β”€ include 
        | β”œβ”€β”€ openssl 
        | | └── aes.h, asn.h ... 
        | β”œβ”€β”€ module.modulemap
        | └── shim.h 
        β”œβ”€β”€ lib 
        | β”œβ”€β”€ libcrypto.a 
        | └── libssl.a 
        └── dummy.c

package.swift

// swift-tools-version:5.1
    
import PackageDescription
    
let package = Package(
    name: "OpenSSL",
    products: [
        .library(name: "OpenSSL", targets: ["OpenSSL"])
    ],
    targets: [
        .target(name: "OpenSSL"),
    ]
)

module.modulemap

module OpenSSL {
    umbrella header "shim.h"
    export *
    link "ssl"
    link "crypto"
}

shim.h

#include <openssl/bio.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/md4.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
...

The package builds, it can be added as a dependency, but that's about it.
I assume this is due to the package not being linked to the library.

This might do the trick, but it is stated that packages using unsafeFlags() cannot be added as dependencies.

.linkerSettings(LinkerSetting.unsafeFlags("-LSources/OpenSSL/lib"))

Is there some way I could achieve this?
I'm relatively new to this and could have missed something. Any help would be greatly appreciated.

Thanks!

There is no way to publish binaries yet, but much thought is going into making it possible:

That means you have three options:

  1. Depend on OpenSSL as source. Its GitHub repository is here. Fork it, add a Package.swift, tag a version, and depend on that. (And maybe submit your Package.swift back to them as a pull request.) Sometimes this strategy requires generating and checking in files the project normally leaves Git‐ignored.

  2. Distribute the binary separately, and instruct your clients to install it on the system first. (And your clients’ clients will have to do the same thing.) Once it is installed on the system, linkedLibrary should just work without needing unsafe flags.

  3. Use unsafeFlags and never release semantic versions, telling your clients to depend on branches instead. Branch dependencies allow unsafe flags, because they are only intended for development. The branches in the dependency tree will in turn prevent clients from release semantic versions too.

All these strategies see quite a lot of use, so which one you choose is up to you. (I’m partial to option 1.)

3 Likes

Thanks @SDGGiesbrecht, option 1 does seem to be the most viable in my case.
Cheers.

Terms of Service

Privacy Policy

Cookie Policy