swiftxcodeopensslllvm-clangmodule-map

Non-modular headers of OpenSSL library when using modulemap for Swift framework


I'm trying to link statically OpenSSL library to my Swift framework, using XCode. Most approaches mentioned online are not correct, because they suggest using Import path (SWIFT_INCLUDE_PATHS). As a result, the framework binary is locked to a specific location in the file system and the binary itself is not portable. While this is not end of the world, I'd still like to be able to distribute the binary via Carthage for example and following above-mentioned approach doesn't enable that.

I have attempted to create my own module map with an umbrella header file for the framework and including OpenSSL library as an explicit module, following approaches described in articles like these: https://badootech.badoo.com/bundling-c-library-in-swift-framework-3d9dae950774

This is my modulemap file, path of which I inserted into MODULEMAP_FILE build config variable.

framework module MyFramework {
    umbrella header "MyFramework.h"
    requires objc

    export *
    module * { export * }

    module COpenSSL [system] {
        header "shim.h"
        link "ssl"
        link "crypto"
        export *
    }
}

where shim.h file is a header file that looks like this:

#ifndef __COPENSSL_SHIM_H__
#define __COPENSSL_SHIM_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>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/ripemd.h>
#include <openssl/pkcs12.h>
#include <openssl/x509v3.h>

__attribute__((swift_name("SSL_set_tlsext_host_name(_:_:)")))
static inline int shim_SSL_set_tlsext_host_name(const SSL *s, const char *name) {
    return SSL_set_tlsext_host_name(s, name);
};

#endif

The problem here is, that I get errors when trying to compile the project about including non-modular headers.

I've attempted to include all the header files to the XCode project as public header files (conf.h, evp.h, etc, all of them). But the problem still persists, presumably because it's unable to work with the syntax of the header inclusion #include <openssl/conf.h>. Changing inclusions to #include "conf.h" etc. works, but then the same style of header inclusion is used with conf.h and all the other header files that come from the Open SSL library, so that doesn't really help.

I really don't want to modify every single header file from the OpenSSL library just to make it work, it seems like there must be some easier way out of this.

Is there any way to not have to include these headers to the XCode project so that they still work with the original syntax of #include <openssl/conf.h>?

I've tried setting HEADER_SEARCH_PATHS to a path from which the relative path to each header is openssl/conf.h etc., but that it didn't help at all.

Thanks.


Solution

  • In the end I couldn't find any better solution than listing all necessary headers into module map and rewriting include macros of the SSL library files from <> syntax to just plain include. I used this little shell script to help me with that:

    sed -E -i '' 's/#[[:space:]]*include <openssl\/(.*).h>/#include \"\1\.h"/' $SCRIPT_DIR/../Libraries/openssl/include/openssl/*.h