androidandroid-ndkstunturnlibnice

Compiling libnice for Android


I'm trying to compile libnice (v0.18 to be specific) for Android, but have run into some troubles. How can I compile libnice for Android? I have listed my attempts so far below.

1st Attempt

My first try was using a custom Android.mk makefile but I got an error stating AI_NUMERICHOST undeclared (adding #include <netdb.h> did not resolve this and I'm out of ideas here). See my Android.mk below

LOCAL_PATH  := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE        := glib
LOCAL_SRC_FILES     := lib/libglib-2.0.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE        := gobject
LOCAL_SRC_FILES     := lib/libgobject-2.0.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE        := gmodule
LOCAL_SRC_FILES     := lib/libgmodule-2.0.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE        := gio
LOCAL_SRC_FILES     := lib/libgio-2.0.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE        := gthread
LOCAL_SRC_FILES     := lib/libgthread-2.0.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE        := ffi
LOCAL_SRC_FILES     := lib/libffi.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE        := iconv
LOCAL_SRC_FILES     := lib/libiconv.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE        := intl
LOCAL_SRC_FILES     := lib/libintl.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE        := xml2
LOCAL_SRC_FILES     := lib/libxml2.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE        := z
LOCAL_SRC_FILES     := lib/libz.a
include $(PREBUILT_STATIC_LIBRARY)


include $(CLEAR_VARS)
NICE                := libnice-0.1.8
LOCAL_MODULE        := ice_jni
LOCAL_LDLIBS        := -llog 

LOCAL_STATIC_LIBRARIES  := glib gobject gmodule gio gthread ffi iconv intl xml2 z 

NICE_INCLUDES       := $(LOCAL_PATH)/include \
                        $(LOCAL_PATH)/lib/glib-2.0/include \
                        $(LOCAL_PATH)/lib/libffi-3.0.13/include \
                        $(wildcard $(LOCAL_PATH)/include/*) \
                        $(LOCAL_PATH)/$(NICE)/nice \
                        $(LOCAL_PATH)/$(NICE)/agent \
                        $(LOCAL_PATH)/$(NICE)/random \
                        $(LOCAL_PATH)/$(NICE)/socket \
                        $(LOCAL_PATH)/$(NICE)/stun

NICE_SRC            := $(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/$(NICE)/agent/*.c)) \
                        $(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/$(NICE)/random/*.c)) \
                        $(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/$(NICE)/socket/*.c)) \
                        $(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/$(NICE)/stun/*.c))

LOCAL_C_INCLUDES        := $(LOCAL_PATH) \
                            $(NICE_INCLUDES)

LOCAL_SRC_FILES         := ICE.cpp \
                            $(NICE_SRC)

include $(BUILD_SHARED_LIBRARY)

The static libraries are copied over from the gstreamer 1.4.1 debug version and are selected in accordance with the guide mentioned below.

2nd Attempt

I then tried to compile a static library referring to this guide, which is again causing trouble:

export PKG_CONFIG_PATH=`pwd`/../gstreamer/lib/pkgconfig  
export CFLAGS="--sysroot=`pwd`/../toolchain/sysroot"
./configure --prefix=`pwd`/../build --host=arm-linux-androideabi

This results in the error below. Adding -mthumb or -marm to CFLAGS yields a C compiler cannot create executables error during configure.

stunagent.c: Assembler messages:
stunagent.c:160: Error: no such instruction: `rev %eax,%eax'
stunagent.c:676: Error: no such instruction: `rev16 %ax,%ax'

The mentioned lines do not contain ASM but calls to htons and ntohl, so I guess I did something wrong...

I used make_standalone_toolchain from the NDK using various Android versions to create the toolchain.

Can anybody help? Thanks in advance! ~


Solution

  • FINALLY! This took me way too long. The problem was that libnice creates a config.h file during configure which defines some macros (HAVE_NETDB_H among others). Although I was not able to compile libnice with my toolchain I was able to generate a valid config.h which I could use. After this I had to make some additional adjustments to my Android.mk. I'll post both files below for others in search of answers.

    (Note: you still need glib. As my project uses gstreamer I was able to use the shared library created by the gstreamer build script which contains glib.)

    Cheers!

    ========================

    Android.mk

    LOCAL_PATH  := $(call my-dir)
    
    include $(CLEAR_VARS)
    NICE                    := libnice-0.1.8
    LOCAL_MODULE            := nice_jni
    LOCAL_LDLIBS            := -llog 
    
    LOCAL_SHARED_LIBRARIES  := gstreamer_android
    LOCAL_CFLAGS            += -DHAVE_CONFIG_H
    
    NICE_DIRS               := $(LOCAL_PATH)/$(NICE)/ \
                                $(LOCAL_PATH)/$(NICE)/agent/ \
                                $(LOCAL_PATH)/$(NICE)/nice/ \
                                $(LOCAL_PATH)/$(NICE)/random/ \
                                $(LOCAL_PATH)/$(NICE)/socket/ \
                                $(LOCAL_PATH)/$(NICE)/stun/ \
                                $(LOCAL_PATH)/$(NICE)/stun/usages/
    #                           $(LOCAL_PATH)/$(NICE)/stun/tools/ \
    
    NICE_INCLUDES           := $(NICE_DIRS)
    NICE_SRC                := $(filter-out %test.c, $(foreach dir, $(NICE_DIRS), $(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(addsuffix *.c, $(dir)))) ))
    
    LOCAL_C_INCLUDES        := $(NICE_INCLUDES) #add your own headers if needed
    
    LOCAL_SRC_FILES         := [YOUR_SRC_FILES] \
                                $(NICE_SRC)
    
    include $(BUILD_SHARED_LIBRARY)
    

    config.h

    (This should not differ across platforms and Android versions. I left the comments in it intentionally for future reference)

    /* config.h.  Generated from config.h.in by configure.  */
    /* config.h.in.  Generated from configure.ac by autoheader.  */
    
    /* Define to 1 if you have the <arpa/inet.h> header file. */
    #define HAVE_ARPA_INET_H 1
    
    /* Define to 1 if C supports variable-length arrays. */
    #define HAVE_C_VARARRAYS 1
    
    /* Define to 1 if you have the <dlfcn.h> header file. */
    #define HAVE_DLFCN_H 1
    
    /* Whether getifaddrs() is available on the system */
    /* #undef HAVE_GETIFADDRS */
    
    /* Have the GUPnP IGD library */
    /* #undef HAVE_GUPNP */
    
    /* Define to 1 if you have the <ifaddrs.h> header file. */
    /* #undef HAVE_IFADDRS_H */
    
    /* Define to 1 if you have the <inttypes.h> header file. */
    #define HAVE_INTTYPES_H 1
    
    /* Define to 1 if you have the <memory.h> header file. */
    #define HAVE_MEMORY_H 1
    
    /* Define to 1 if you have the <netdb.h> header file. */
    #define HAVE_NETDB_H 1
    
    /* Define to 1 if you have the <net/in.h> header file. */
    /* #undef HAVE_NET_IN_H */
    
    /* Define to 1 if you have the `poll' function. */
    #define HAVE_POLL 1
    
    /* Define to 1 if the system has the type `size_t'. */
    #define HAVE_SIZE_T 1
    
    /* Define to 1 if the system has the type `ssize_t'. */
    #define HAVE_SSIZE_T 1
    
    /* Define to 1 if stdbool.h conforms to C99. */
    #define HAVE_STDBOOL_H 1
    
    /* Define to 1 if you have the <stdint.h> header file. */
    #define HAVE_STDINT_H 1
    
    /* Define to 1 if you have the <stdlib.h> header file. */
    #define HAVE_STDLIB_H 1
    
    /* Define to 1 if you have the <strings.h> header file. */
    #define HAVE_STRINGS_H 1
    
    /* Define to 1 if you have the <string.h> header file. */
    #define HAVE_STRING_H 1
    
    /* Define to 1 if you have the <sys/stat.h> header file. */
    #define HAVE_SYS_STAT_H 1
    
    /* Define to 1 if you have the <sys/types.h> header file. */
    #define HAVE_SYS_TYPES_H 1
    
    /* Define to 1 if you have the <unistd.h> header file. */
    #define HAVE_UNISTD_H 1
    
    /* Define to 1 if the system has the type `_Bool'. */
    #define HAVE__BOOL 1
    
    /* Define to the sub-directory in which libtool stores uninstalled libraries.
       */
    #define LT_OBJDIR ".libs/"
    
    /* Define to 1 if assertions should be disabled. */
    /* #undef NDEBUG */
    
    /* Public library function implementation */
    #define NICEAPI_EXPORT 
    
    /* Name of package */
    #define PACKAGE "libnice"
    
    /* Define to the address where bug reports for this package should be sent. */
    #define PACKAGE_BUGREPORT ""
    
    /* Define to the full name of this package. */
    #define PACKAGE_NAME "libnice"
    
    /* Define to the full name and version of this package. */
    #define PACKAGE_STRING "libnice 0.1.8"
    
    /* Define to the one symbol short name of this package. */
    #define PACKAGE_TARNAME "libnice"
    
    /* Define to the home page for this package. */
    #define PACKAGE_URL ""
    
    /* Define to the version of this package. */
    #define PACKAGE_VERSION "0.1.8"
    
    /* Define to 1 if you have the ANSI C header files. */
    #define STDC_HEADERS 1
    
    /* Enable extensions on AIX 3, Interix.  */
    #ifndef _ALL_SOURCE
    # define _ALL_SOURCE 1
    #endif
    /* Enable GNU extensions on systems that have them.  */
    #ifndef _GNU_SOURCE
    # define _GNU_SOURCE 1
    #endif
    /* Enable threading extensions on Solaris.  */
    #ifndef _POSIX_PTHREAD_SEMANTICS
    # define _POSIX_PTHREAD_SEMANTICS 1
    #endif
    /* Enable extensions on HP NonStop.  */
    #ifndef _TANDEM_SOURCE
    # define _TANDEM_SOURCE 1
    #endif
    /* Enable general extensions on Solaris.  */
    #ifndef __EXTENSIONS__
    # define __EXTENSIONS__ 1
    #endif
    
    
    /* Version number of package */
    #define VERSION "0.1.8"
    
    /* Define to `2' to get GNU/libc warnings. */
    /* Only define if -O1 or more is enabled */
    #if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
    # define _FORTIFY_SOURCE 2
    #endif
    
    /* Define to 1 if on MINIX. */
    /* #undef _MINIX */
    
    /* Define to 2 if the system does not provide POSIX.1 features except with
       this defined. */
    /* #undef _POSIX_1_SOURCE */
    
    /* Define to 1 if you need to in order for `stat' and other things to work. */
    /* #undef _POSIX_SOURCE */
    
    /* Needed to get declarations for msg_control and msg_controllen on Solaris */
    /* #undef _XOPEN_SOURCE */
    
    /* Needed to get declarations for msg_control and msg_controllen on Solaris */
    #define __EXTENSIONS__ 1
    
    /* Define to the equivalent of the C99 'restrict' keyword, or to
       nothing if this is not supported.  Do not define if restrict is
       supported directly.  */
    #define restrict __restrict
    /* Work around a bug in Sun C++: it does not support _Restrict or
       __restrict__, even though the corresponding Sun C compiler ends up with
       "#define restrict _Restrict" or "#define restrict __restrict__" in the
       previous line.  Perhaps some future version of Sun C++ will work with
       restrict; if so, hopefully it defines __RESTRICT like Sun C does.  */
    #if defined __SUNPRO_CC && !defined __RESTRICT
    # define _Restrict
    # define __restrict__
    #endif