I’m wrapping up here pieces of information that I used to setup a working native iOS project taking advantage of a library I wrote mainly using Qt. The library I wrote has nothing to do with GUI, it just helps me dealing with connectivity, REST API interaction, file system access, compression… Also, the library was born for the Desktop but the porting effort to mobile is feasible due to the lack of GUI interaction.
In particular, the following has been tested using Qt 5.3.
Despite the huge integration level now Qt has reached over the year even on the iOS platform, I still prefer having the UI developed using the native SDK. I’m a rather experienced Cocoa developer, not that experienced with Cocoa Touch, but I managed to have everything I needed working. Since the information I found is rather sparse regarding this topic, I thought it could be nice to have everything here in a blog post.
In the following post I’m assuming you want to link a native iOS Xcode project to a third party library written using C++ and Qt. I’m also assuming you are using statically linked Qt for this project (which is the default for the iOS solution).
So what we have:
- A native Xcode project for iOS: NativeHelloWorld.xcodeproj
- A static lib Qt project: FancyStaticLib.pro
What we are going to have
- FancyStaticLib.xcodeproj as a subproject to NativeHelloWorld
- Qt for iOS properly linked to make NativeHelloWorld run and use FancyStaticLib
Let’s get things started
So, first of all let’s instruct Xcode about where to find Qt on our system.
Go to Xcode -> Preferences -> Locations (Tab) -> Source Trees (Sub Tab).
Add the path to your Qt for iOS packages and name it as you wish. I just chose QTLIB_IOS.
I like setting my paths this way in order to keep my project as “exportable” as possible. This way, other devs can join my project pretty easily.
Now, if you haven’t already, you should create an Xcode project for your static library you want to link into your native iOS project.
In order to do so you have to run something like this:
/path/to/your/Qt/ios/bin/qmake -spec macx-xcode -r /path/to/FancyStaticLib.pro CONFIG+=staticlib CONFIG+=whatever_you_need
This will output
FancyStaticLib.xcodeproj file for your static library. You can drag it to your our
NativeHelloWorld.xcodeproj inside Xcode and add its product (the static lib) as a link dependency to your project.
NOTE: You will have to re-generate the
FancyStaticLib.xcodeproj each time you change your static library .pro file
Link to Qt
Now that we have the project feeling more like a completely native Xcode one we have to set a few things up in order to easily keep developing directly from Xcode through our
First of all, look for the Headers Search path section in the Build Settings section of your Xcode project:
We want to make it easy for Xcode to find Qt headers, and also our static lib headers.
Now the variable we previously defined through the Source Trees section in the Xcode preferences comes in handy.
Let’s add the following to the Headers Search Path section:
Now, the actual linker flags.
You will probably need to start your project inside the emulator. When doing so bare in mind that the simulator has a different architecture from your iOS device. Simulator runs an i386 architecture and we want to link our project both to the static Qt lib files compiled for such architecture and for arm. This way we will be able to run our project both in the simulator and on the native device.
Scroll down to the Other Linker Flags section: you should at least have a Debug section. Under Debug, as a child item, you should have Any iOS Simulator SDK. If you don’t, click the little “+” icon on the side of the Debug item and add Any iOS Simulator SDK as child item.
Our project dependencies are satisfied by the following modules:
The Debug section will host the option for running our app on a native device with debug symbols:
-L$(QTLIB_IOS)/lib -lQt5Core_debug -lQt5Gui_debug -lQt5Network_debug -lQt5Script_debug
Also, don’t forget to include proper platform support with:
-lQt5PlatformSupport_debug -L$(QTLIB_IOS)/plugins/ -lqios_debug
You’ll also need
-lz -lqtharfbuzzng_debug most probably.
Also, if you are taking advantage of the bearer plugin to handle connectivity, add the following:
Now the Any iOS Simulator SDK section:
Simply replace what you typed in the previous section changing “_debug” with “_iphonesimulator_debug” and you are good to go.
The last touch
Your Qt lib will most probably need an instance of QGuiApplication. This usually requires you to replace the default
main coming with your project template with a custom one that actually calls
QGuiApplication::exec(). Luckily, Qt has made things relatively easy and you won’t need a custom main body. Looks like the Qt guys are cool enough to inject their Qt Event Dispatcher inside the main CocoaTouch run loop making it easy to spawn QTimers and queued methods invocations from Objective-C(++).
Just make sure you initialize a QGuiApplication instance (but you won’t need to call .exec()).
We are going to add the following piece of code inside your application delegate
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions after having renamed the application delegate file from .m to .mm. Renaming to .mm enables Objective-C++ which helps us mix C++ and Objective-C in the same source.
This is pretty much what is needed to mix a native iOS project with a Qt library. If you encounter linker issues you should be able to easily address them by inspecting the .a symbols you can find inside your
Otherwise please post here your issues so that we can try address them together.
Leave a Reply