ZeroMQ on iOS

In the current world of startups a common recipe is to have a site with REST API as well as various mobile applications for different platforms consuming said API. But sometimes that’s not enough. Sometimes you need real-time data pushed to you as soon as it becomes available on the service provider. Some of the examples might include stock exchange price changes, chat, or score changes for a match on sports website. Here’s where ZeroMQ comes to play. ZeroMQ is described as “intelligent transport layer” and is mostly used for distributed systems which have to do loads of processing and where pipelining of different tasks can greatly improve the overall performance of the system.

ZeroMQ can also be used for realtime messaging between iOS and any server that you’ve created (which, of course, employs zeromq). The only problem is that while googling for this possibility I became very dissapointed with search results. There was only one resource that actually presents what I need. And that very same has very misleading title .) I give you - Stack Overflow question about Cross-compiling ZeroMQ to ARM for use in a MonoTouch iPhone (mad props go to yourkshirespud).

Since I did not really enjoy writing everything into single line so I dropped this into one nice zsh script:

ZeroMQ configuration script for iOS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/env zsh

make clean &>>|/dev/null

BUILD_DIR=`pwd`/build

if [[ -d $BUILD_DIR ]]; then
  rm -fr $BUILD_DIR
fi

mkdir -p $BUILD_DIR

ZMQ_BUILD_LOG_FILE=$BUILD_DIR/build.log

echo "-- Configuring with prefix $BUILD_DIR"
SDK_ROOT="/Developer/Platforms/iPhoneOS.platform/Developer"
export CPP="cpp"
export CXXCPP="cpp"
export CXX="${SDK_ROOT}/usr/bin/arm-apple-darwin10-llvm-g++-4.2"
export CXXFLAGS="-O -isysroot $SDK_ROOT/SDKs/iPhoneOS5.0.sdk"
export CC="${SDK_ROOT}/usr/bin/arm-apple-darwin10-llvm-gcc-4.2"
export CFLAGS="-O -isysroot $SDK_ROOT/SDKs/iPhoneOS5.0.sdk"
export AR=$SDK_ROOT"/usr/bin/ar"
export AS=$SDK_ROOT"/usr/bin/as"
export LD=$SDK_ROOT"/usr/bin/ld"
export LDFLAGS="-lstdc++ -isysroot $SDK_ROOT/SDKs/iPhoneOS5.0.sdk"
export LIBTOOL=$SDK_ROOT"/usr/bin/libtool"
export STRIP=$SDK_ROOT"/usr/bin/strip"
export RANLIB=$SDKROOT"/usr/bin/ranlib"

./configure --disable-dependency-tracking --enable-static --disable-shared --host=arm-apple-darwin10 --prefix=$BUILD_DIR &>>| $ZMQ_BUILD_LOG_FILE

echo "-- Building"
make &>>| $ZMQ_BUILD_LOG_FILE

echo "-- Installing to $BUILD_DIR"
make install &>>| $ZMQ_BUILD_LOG_FILE

echo "-- Cleaning up"
make clean &>>| /dev/null

echo "-- Copying headers"
mkdir $BUILD_DIR/usr && cp -R include $BUILD_DIR/usr

Starting from the top - grab yourself a freshly baked, stable, ZeroMQ 2.1 source from ZeroMQ download page, unzip it, open terminal and create a script, with contents given above, in zeromq source directory. Run the script and once it’s completed - you should have libzmq.a static library file as well as usr directory with all include headers in build subdirectory ready for use in your own iOS application.

Linking with iOS project

To make ZeroMQ library actually work with your iOS project you have to add a few settings to the project. First and foremost - Framework search path. Create a Frameworks directory in your projects root directory (represented by $(SRCROOT) variable) drop the folder with libzmq.a and include headers into that directory. Then add $(SRCROOT)/Frameworks/{name_of_libzmq_folder} as a location where project should search for frameworks.

Next up - Header Search Path. Add the very same setting value to Header Search Path and don’t forget to tick the checkbox marking the path for recursive search.

And finally - add linker flag for standard C++ library. Find the Other Linker Flags setting and add -lstdc++ there. Otherwise, when linking, you’ll get loads of errors noting about unknown identifiers or symbols.

Caveats

The built library, according to SO post’s author, should be working for iOS4 and iOS5. If you paid attention - with a minor tweak you can have it working for iOS3 too.

Also - while linking it with iOS project you’ll get lots of warnings about CPU_SUBTYPE_ARM_ALL constant being deprecated. I was unsuccessful in finding fix for this warning, so in my iOS debug build I silenced it with -w option for linker (Other linker flags option in Project settings). If anyone by any chance will happen to know the solution for this (probably some linker flag) please don’t hesitate to write a solution for this in comments.

Comments