Swift frameworks and unmapped SDK libraries?

Over the course of Swift's existence I've had to take advantage of a number of workarounds (i.e., hacks) to compile a Swift framework that utilizes non-modular system code, e.g., CommonCrypto, sqlite3, etc.


These "solutions" have included:


  1. Renaming the umbrella header to be something different than the module name in order to exploit a bug that let frameworks compile with bridging headers, wherein the non-modular import happened:
    #import <CommonCrypto/CommonCrypto.h>
  2. Building a dummy, optional framework with a custom module map specifying the absolute path to an SDK header (relative SDK paths don't work):
    module CommonCrypto [system] [extern_c] {
        header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h"
        export *
    }
  3. Specifying a custom module map with an additional header specifying the absolute path to an SDK header:
    framework module MyCrypto {
        umbrella header "MyCrypto.h"
        header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h"
        export *
        module * { export * }
    }
  4. Using "@asmname" and linking to the dylib.
  5. Copying a version of the header and linking to the dylib.


None of these workarounds seem to work anymore. The bridging header hack appears to have been patched, and any attempt to use a module map, @asmname, or otherwise fails because an attempt to "link binary with [static] libraries" adds a ".tbd" file instead of a dylib, and not all of the symbols appear to make it over for the given architecture.


And so, I implore all that listen: is there any way to write a framework-level Swift wrapper over this kind of system-level code? And—if not—can we please have module maps with the next Xcode 7 beta? Please?

Replies

I found a way to get it working in this thread: https://forums.developer.apple.com/message/9176#9176

Did you ever figure out a workaround?

This is what I resorted to in order to get zlib working in my swift framework:


1) Under Target => Build Phases => Link Binary with Libraries: I added "libz.tbd"

2) In my "Umbrella Header File" (i.e. "MyFramework.h"), I copied and pasted relevant code from zlib.h (/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/zlib.h)

what is that "relevant code" you mentioned? having the same issue with libcommonCrypto.tbd

Was this ever figured out? I'm in need of CommonCrypto myself and about every StackOverflow / Google answer I've come across doesn't work. There has to be some way to do this -- I can't imagine Swift having much server-side / portable use without the ability to link to crypto libraries.


Anyone have a current answer for how to do this in Xcode 7.2 on El Capitan?


Thanks...

I had the same problem and I was missing the relative path to my bridging header file in Build Settings->Swift Compiler - Code Generation->Objective-C Bridging Header. Providing this fixed the problem.

I recently got this working for sqlite3 by adding a file called module.mappingmodule with content:


module SQLite3 [system] {
   header "/usr/include/sqlite3.h"
   link "sqlite3"
   export *
}


Then, in the Xcode Build Settings, "Swift Compiler - Search Paths", add a path to that file in "Import Paths".


Once this was done, I was able to do "import SQLite3" into my swift files and all was good with the world (until I tried to turn it into a CocoaPods module).


See also https://ind.ie/labs/blog/using-system-headers-in-swift/ for an example using

ifaddrs.h.


For future readers, hopefully this will be solved soon with Swift Package Manager's System Modules: https://github.com/apple/swift-package-manager/blob/master/Documentation/SystemModules.md