Tom
Tom

Reputation: 1154

Undefined symbols for some architectures when creating OpenSSL Framework

I'm working on a Swift framework for OSX/iOS. I need to generate RSA keys and export them and the Security framework does not allow to do this neatly on iOS, so I'll use OpenSSL.

I retrieved a script that build OpenSSL for both platforms (https://gist.github.com/6710405). It works flawlessly and generates libcrypto.a, libssl.a and the corresponding headers for each platform.

I would like to put OpenSSL in its own framework and define a module to use it easily in Swift.

Let's restrict to OSX only for simplicity. I created a new framework project called OpenSSL. I linked the two libs and added all the headers (as public headers). I've also added a "Copy files" phase where I copy and sign the two libs. I've created a .modulemap file:

framework module OpenSSL {

   header "rc2.h"
   header "rc4.h"

   header "aes.h"
   […]
   header "x509v3.h"

   header "dtls1.h"

   export *
}

All the headers of OpenSSL are listed. I originally sorted the headers alphabetically, but some #undef were causing issues so I had to reorder a few headers and it compiles (I don't like that at all!).

Back in the original framework, I added my OpenSSL framework, imported the OpenSSL module and wrote a few lines:

import OpenSSL

func generateKeyPair() -> RSAKeyPair? {
    var exponent = BN_new();
    BN_set_word(exponent, 65537);
    var rsa = RSA_new()
    RSA_generate_key_ex(rsa, 2048, exponent, nil)
    […]
}

The code is completed by Xcode which sees the headers of the module. When I try to compile, it generates a few Undefined symbols for architecture x86_64: for some (but not all) OpenSSL's calls. For example, it complains for RSA_generate_key_ex but not for BN_set_word or RSA_new() (which is declared a couple of lines before RSA_generate_key_ex). It does not fails only for RSA_generate_key_ex and some other calls are failing with the same error later.

I've set up a playground to check this. Some calls to RSA_new() are returning things, but the playground fails to find a symbol for RSA_generate_key_ex.

I quickly set up a new Objective-C project, added the libs and headers the classical way and the same code (in ObjC) compiles and runs without issues. I'm thus sure that the libs are built with all the needed architectures (and I double checked with otool).

Something is wrong with my framework. I've tried to remove/add the "Copy files" phase without success. I'm not happy with the way I made the .modulemap file, but I don't see where it can cause such issues. I'm not an expert in framework crafting, so maybe someone knows what happens and how to fix it?

Upvotes: 3

Views: 911

Answers (1)

Tom
Tom

Reputation: 1154

Found the solution myself. As usual, the old -all_load flag was needed as "Other linker flags" in the framework.

Furthermore, the copy phase is not needed for the libraries. Linking them seems to be enough.

Upvotes: 2

Related Questions