ZeroMQ build for Android
Introduction : JeroMQ for Java
This page was originally helping to build and cross-compile JZMQ using a JNI bridge to the native library.
The process is risky, difficult, bad for code portability; only use it if you have very specific needs and strong reasons to do so.
For everybody using Java, especially with Android, it is STRONGLY recommended to use the pure-java implementation of ZeroMQ : JeroMQ instead.
According to many benchmarks it is also faster than using a JNI bridge.
Go download it : JeroMQ repository
Advanced users : Native build of JZMQ
This page will explain you how to build ZeroMQ along with Jzmq and its JAR, to be directly usable in Android and loaded into an APK file. It gives some preliminary solution for pyzmq as well.
The tutorial will be divided in two parts: one for ZeroMQ > 3.0 (where libuuid is no longer a dependency, thus making the whole process a lot easier) and another one, kept for reference, that will explain how to cope with older versions. For info where to put the final files in Eclipse, read the part Final thoughts at the end of the article.
General Prerequisites
Get Android NDK and use it to generate a standalone ARM toolchain.
cd /tmp
wget http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2
tar xvfj android-ndk-r8-linux-x86.tar.bz2
sudo ./android-ndk-r8/build/tools/make-standalone-toolchain.sh --install-dir=/opt/android-toolchain
export PATH=/opt/android-toolchain/bin:$PATH
The above sudo is only there to write into /opt, if you choose another folder it may not be necessary.
Export the desired output directory in a dedicated variable; a folder that is writable by you is preferred, or you'll face issues at install time.
export OUTPUT_DIR=/tmp/zeromq-android
ZeroMQ 4.x
Use the following command lines:
cd /tmp/
git clone https://github.com/zeromq/libzmq.git
cd libzmq/
./autogen.sh
./configure --enable-static --disable-shared --host=arm-linux-androideabi --prefix=$OUTPUT_DIR LDFLAGS="-L$OUTPUT_DIR/lib" CPPFLAGS="-fPIC -I$OUTPUT_DIR/include" LIBS="-lgcc"
make
make install
Now download Jzmq from Github.
cd /tmp/
git clone https://github.com/zeromq/jzmq.git
cd jzmq/
./autogen.sh
./configure --host=arm-linux-androideabi --prefix=$OUTPUT_DIR --with-zeromq=$OUTPUT_DIR CPPFLAGS="-fPIC -I$OUTPUT_DIR/include" LDFLAGS="-L$OUTPUT_DIR/lib" --disable-version LIBS="-lpthread -lrt"
make
make install
The disable-version, enable-static and disable-shared flags ensure you'll generate a single libjzmq.so binary without version information, which is required to embed it into an APK. On newer systems, the parameter 'LIBS="-lpthread -lrt"' produces errors and has to be omited, because these librarys are already included.
If you're having problem on java environment, which will cause the configure failed with 'configure: error: cannot find zmq.h' or similar jni.h not found error , try to export the JAVA_HOME into your PATH environment:
export PATH=$JAVA_HOME/bin:$PATH
please make sure you have JAVA_HOME environment variable setup first:
echo $(/usr/libexec/java_home)
/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home
Moreover, you'll have the zmq.jar archive that will help you use ZeroMQ directly. Here's the generated output :
[victor@Q]</tmp/jzmq> tree /tmp/zeromq-android/
/tmp/zeromq-android/
├── include
│ ├── zmq.h
│ └── zmq_utils.h
├── lib
│ ├── libjzmq.a
│ ├── libjzmq.la
│ ├── libjzmq.so
│ ├── libzmq.a
│ ├── libzmq.la
│ └── pkgconfig
│ └── libzmq.pc
└── share
├── java
│ └── zmq.jar
└── man
├── man3
└── man7
8 directories, 9 files
ZeroMQ < 3.0
Complexity is increased because of the libuuid dependency. Follow this carefully.
First, before anything, download libuuid, inside the e2fsprogs package.
cd /tmp/
git clone git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
cd e2fsprogs/
./configure --host=arm-linux-androideabi --prefix=$OUTPUT_DIR CFLAGS="-fPIC"
cd lib/uuid
make
make install
Then, download and build ZeroMQ itself.
cd /tmp/
tar xzf zeromq-2.2.0.tar.gz
cd zeromq-2.2.0/
./autogen.sh
./configure --enable-static --disable-shared --host=arm-linux-androideabi --prefix=$OUTPUT_DIR --with-uuid=$OUTPUT_DIR LDFLAGS="-L$OUTPUT_DIR/lib" CPPFLAGS="-fPIC -I$OUTPUT_DIR/include" LIBS="-lgcc"
make
make install
See, the configure line is quite a bit longer. Now with Jzmq:
cd /tmp/
git clone https://github.com/zeromq/jzmq.git
cd jzmq/
./autogen.sh
./configure --host=arm-linux-androideabi --prefix=$OUTPUT_DIR --with-zeromq=$OUTPUT_DIR CPPFLAGS="-fPIC -I$OUTPUT_DIR/include" LDFLAGS="-L$OUTPUT_DIR/lib" --disable-version LIBS="-luuid"
make
make install
And there you are.
[victor@Q]</tmp> tree zeromq-android/
zeromq-android/
├── include
│ ├── uuid
│ │ └── uuid.h
│ ├── zmq.h
│ ├── zmq.hpp
│ └── zmq_utils.h
├── lib
│ ├── libjzmq.a
│ ├── libjzmq.la
│ ├── libjzmq.so
│ ├── libuuid.a
│ ├── libzmq.a
│ ├── libzmq.la
│ └── pkgconfig
│ ├── libzmq.pc
│ └── uuid.pc
└── share
├── java
│ └── zmq.jar
└── man
├── man3
│ ├── uuid.3
│ ├── uuid_clear.3
│ ├── uuid_compare.3
│ ├── uuid_copy.3
│ ├── uuid_generate.3
│ ├── uuid_generate_random.3
│ ├── uuid_generate_time.3
│ ├── uuid_is_null.3
│ ├── uuid_parse.3
│ ├── uuid_time.3
│ ├── uuid_unparse.3
│ ├── zmq_bind.3
│ ├── zmq_close.3
│ ├── zmq_connect.3
│ ├── zmq_device.3
│ ├── zmq_errno.3
│ ├── zmq_getsockopt.3
│ ├── zmq_init.3
│ ├── zmq_msg_close.3
│ ├── zmq_msg_copy.3
│ ├── zmq_msg_data.3
│ ├── zmq_msg_init.3
│ ├── zmq_msg_init_data.3
│ ├── zmq_msg_init_size.3
│ ├── zmq_msg_move.3
│ ├── zmq_msg_size.3
│ ├── zmq_poll.3
│ ├── zmq_recv.3
│ ├── zmq_send.3
│ ├── zmq_setsockopt.3
│ ├── zmq_socket.3
│ ├── zmq_strerror.3
│ ├── zmq_term.3
│ └── zmq_version.3
└── man7
├── zmq.7
├── zmq_cpp.7
├── zmq_epgm.7
├── zmq_inproc.7
├── zmq_ipc.7
├── zmq_pgm.7
└── zmq_tcp.7
9 directories, 54 files
Final thoughts
You should only have to take the built zmq.jar, place it in your application's in the libs/ folder. Add it to your build path in Eclipse if you're using Eclipse; ant should detect it nicely.
Then take the libjzmq.so file and put it in the libs/armeabi/ folder of your application, if your target has been armeabi since the beginning. Some users may want to put it in the armeabi-v7e folder instead.
Build your project with Eclipse or Ant, and it should work fine.
Remember that you will often have to activate special permissions to your app, for instance the android.permission.INTERNET for ZeroMQ's tcp transport protocol.
As a last word, if the generated binary us too huge (between 2.3 and 2.7 Mb) a good move is to strio/optimize it. To be straightforward, that means at least running
arm-linux-androideabi-strip --strip-all libjzmq.so
which reduces the binary size to about 600Kb, but you can also gain a few more Kb if using -ffunction-sections -fdata-sections -Wl,—gc-sections as additionnal CPPFLAGS.
And if you ever want to try pyzmq on Android, have a look at https://github.com/zeromq/pyzmq/issues/227
Notes
Please get Jzmq code using a fresh github's clone, since code prior to 06/06/2012 doesn't embed the necessary configure flags. If ever you had to use prior versions, have a look at:
https://github.com/vperron/android-jzeromq
… which is a quick&dirty collection of scripts to build Jzmq+ZeroMQ the same way. Adapt them, it may be helpful in those special cases.