Laptop with library and 0MQ

Let's Build a ZeroMQ Library

By Boris Ralchenko

Last week, I introduced you to ZeroMQ, a high-performance asynchronous messaging library, aimed at use in distributed or concurrent applications. Now, I’ll show you how to actually build a library from source code.

Building a Library from Source Code

Our best resource is http://zeromq.org/build:iphone with its instructions on how to build the library for iOS. Or not. The problem is that these instructions are outdated. For instance, the script asks for iOS 5.0 and XCode 4.3.3. The current iOS version is 11.3.1 and the latest version of XCode is 9.3. Clearly the information has not been updated for a number of years. In fact, the latest release of iOS 5.x was May 7, 2012. The Apple ecosystem has evolved significantly since then, including adding new devices like Apple Watch, new programming language, and new build tools.  

So what do we do? The answer is to check out this repository: https://github.com/azawawi/libzmq-ios. Thank you Ahmad Zawawi!

The ZeroMQ build procedure is based on configure script. We’ll have to set all the parameters properly, as well as paths, compilers, flags etc.  libzmq-ios repository contains Ruby script that does just that. This script is based on https://github.com/drewcrawford/libzmq-ios/blob/master/libzmq.sh, but we'll focus on the Ruby script. 

The first step is to edit it by specifying versions and configurations.

# ZeroMQ release version PKG_VER="4.2.5" // this is the version of ZeroMQ library that we are building, 4.2.5 is the latest,
# Minimum platform versions
IOS_VERSION_MIN = "9.0"
MACOS_VERSION_MIN = "10.11"
TVOS_VERSION_MIN = "9.0"
WATCHOS_VERSION_MIN = "2.0" </code>
LIBNAME="libzmq.a" // we build static library. iOS does not like shared libraries anyway
ROOTDIR=File.absolute_path(File.dirname(__FILE__))
LIBSODIUM_DIST=File.join(ROOTDIR, "dist")
VALID_ARHS_PER_PLATFORM = {
       "iOS" => ["armv7", "armv7s", "arm64", "i386", "x86_64"],
       "macOS" => ["x86_64"],
       "tvOS" => ["arm64", "x86_64"],
       "watchOS" => ["armv7k", "i386"],
} 

There’s the catch. So, instead of looking for compilers, linkers and SDKs on the filesystem, let’s ask XCode what it does support. This is a big thing as the Apple ecosystem is famous for its slick design and easy-to-use interface. Its healthy Unix core is there with all its glory. Command Line Tools are very much alive and kicking.

DEVELOPER = `xcode-select -print-path`.chomp
LIPO = `xcrun -sdk iphoneos -find lipo`.chomp

DEVELOPER screenshot

def find_sdks sdks=`xcodebuild -showsdks`.chomp sdk_versions = {} …….. return sdk_versions end

That’s how the output looks like on my computer.

Developer Output

Now we are all set with the script sets parameters and builds ZeroMQ libraries for all platforms and configurations. Here’s an example.

For one of the architectures:

when "iOS-arm64" # iOS 64-bit ARM (iPhone 5s and later) platform_name = "iPhoneOS" host = "arm-apple-darwin" base_dir = "#{DEVELOPER}/Platforms/#{platform_name}.platform/Developer" ENV["BASEDIR"] = base_dir isdk_root = "#{base_dir}/SDKs/#{platform_name}#{IOS_SDK_VERSION}.sdk" ENV["ISDKROOT"] = isdk_root ENV["CXXFLAGS"] = OTHER_CXXFLAGS ENV["CPPFLAGS"] = "-arch #{arch} -isysroot #{isdk_root} -mios-version-min=#{IOS_VERSION_MIN} #{other_cppflags}" ENV["LDFLAGS"] = "-mthumb -arch #{arch} -isysroot #{isdk_root}"

Then modify the path:

# Modify path to include Xcode toolchain path ENV["PATH"] = "#{DEVELOPER}/Toolchains/XcodeDefault.xctoolchain/usr/bin:" + "#{DEVELOPER}/Toolchains/XcodeDefault.xctoolchain/usr/sbin:#{ENV["PATH"]}"

Then configure the build:

puts "Configuring for #{build_type}..." FileUtils.cd(LIBDIR) configure_cmd = [ "./configure", "--prefix=#{build_arch_dir}", "--disable-shared", "--enable-static", "--host=#{host}", "--with-libsodium=#{LIBSODIUM_DIST}/#{platform}", ] exit 1 unless system(configure_cmd.join(" "))

Then build everything: 

puts "Building for #{build_type}..." exit 1 unless system("make clean") exit 1 unless system("make -j8 V=0") exit 1 unless system("make install")

And at the end script creates a universal library with all the architectures for the specific OS, “fat” library. That’s the LIPO utility that we were looking for. You may comment out this part of the script and use libraries per architecture, but I appreciate this feature. 

(Cautionary note: these snippets are just a parts of the entire script. Please clone the repository and read/use the complete script. I just pointed out to the interesting and remarkable fragments.)

ZeroMQ and Qt 

There were several attempts to integrate ZeroMQ with Qt. It would make perfect sense to integrate ZeroMQ events to the Qt event loop but the releases ceased at around 2014.The latest active effort can be found here: https://github.com/jonnydee/nzmqt (It is possible that it works with the latest ZeroMQ library, but I have not checked it yet. I’ll keep you posted.) 

ZeroMQ Release Github

Interested in learning more about ZeroMQ? I have a few more blogs on the topic in the pipeline so check back here regularly.