Challenges Building a Swift Framework(C++, Objective C & Swift)

This talk focuses on the challenges of building a Swift framework. I will cover how we overcame these challenges, the experience we got from it, and the lessons learned. I hope it will help you understand how to build open source or third party software on mobile, and how you can do it right.

The main challenge is how to interface C++ with Swift.When we want to build something on top of something else from a library or source file. This was the case for us. You want to use yourself to build a wrapper on top of that.

A Viable Way to Distribute a Framework

Our first idea was to have just one big framework which contained another framework. Then, we would hide away the underlying Objective-C part that you don’t want to deal with if you start out building a new Swift app.

It turns out there were several difficulties with this approach. For one, you would have to mess around with build settings as a user. Even so, this was historically available for a long time on OSX.However, the App Store doesn’t allow this concept at all, with code signing, so it wasn’t usable for us because we want to allow our users to build real apps for the App Store.

Lets talk some thing new, Did you ever heard of modular framework ? or custom module map? if NO then lets deep dive into it for a minute to get basic idea.

What is a modular framework

A modular framework is a framework that contains a module map. This module map can either be generated from building the framework, or , not so-commonly, specified as a build settings in the framework project.

In order for Xcode to generate the module map file, a framework has to have an umbrella header with the same name of the framework and to have the Define Module (DEFINES_MODULE) build settings set to yes. When building this framework, Xcode will generate a framework bundle that contains a Modules director.

This Modules directory contains the generated modules map (module.modulemap) with the following content:

framework module MixModuleFramework {
umbrella header "
MixModuleFramework.h"
  export *
module * { export * }
}

Before deciphering the default module map file, lets roll our sleeves and write our own map file.

Custom module map

A framework can specify a custom map file by setting Module Map File (MODULEMAP_FILE) Xcode build setting to the map file path. Lets start by creating the simplest module map possible.

framework module MixModuleFramework {
umbrella header "MixModuleFramework.h"
}

In this module map we only specify the umbrella header file. This header is the header that imports all other headers.

For more details on module map, please refer this link http://clang.llvm.org/docs/Modules.html#module-map-file

Using C++ file in Swift Framework

Lets start with Objective C wrapper on C++ then include objective C file in Bridging header and try to use in swift file . OOPS Surprise!!

As convenient as the bridging header is, it has one key limitation — you can’t use it inside a framework project. The alternative is to use a module.

Let’s create a demo framework for Mix type (C++, ObjC and Swift)

I call this demo framework — MixModuleFramework. Open Xcode , select File ->New->Project-> Choose Cocoa Touch Framework in framework sections.

Press next and enter your framework name.

Once you are done with creating , empty framework project is ready to build.

When you build your framework, Xcode will generate a module map that includes the umbrella header. Here is the generated module map for a custom framework target which supports modules:

framework module MixModuleFramework {
umbrella header "MixModuleFramework.h"
  export *
module * { export * }
}

Now you can start adding your C++ files, Objective C wrappers and Swift files in it.

Few things to remember before building the framework, This demo framework gives TestCode class a interface to this framework , objective C or Swift based project can directly use it But as we earlier talk about modular framework, This TestCode module need to be modularized , Please make sure you make this file as public.

Error for non modular header
Solution to resolve above error

As i have written some private API which need not to be exposed, Please make sure you have created modular map file like below.

Please make sure that you have added import search path also in your project to avoid build error.

Once you are done with all the setting and importing your files into your framework project.

Its time to build the framework project and test it.

You can find the source code for this article https://github.com/charlieInDen/MixModuleFramework

For making your custom framework — Universal framework, Please read this article — https://medium.com/@nishantsamsung09/writing-custom-universal-framework-in-xcode-9-and-ios-11-7a63a2ce024a

Hope this article is useful for people looking to create custom swift based framework, Please ❤️ to recommend this post to others 😊. Let me know your feedback. :)

References:

  1. http://nsomar.com/modular-framework-creating-and-using-them/