Project

General

Profile

Installing Wt on Android » History » Revision 3

Revision 2 (Wim Dumon, 09/07/2010 04:36 PM) → Revision 3/4 (Wim Dumon, 09/07/2010 04:41 PM)

{{toc}} 

 h1. Installing Wt on Android 

 Warning: Installation of Wt on Android is a bit more complex than it should be. The dependencies (NDK, boost) don't support this platform perfectly, and thus you must be prepared to patch these if you encounter problems. This page describes how I made my first Wt on Android build. 

 h2. Installing the Cross Compilation Tools cross tools 

 At the time of writing, Google's NDK C++ support is insufficient to compile boost or Wt. Use the crystax NDK, a fork of the official Google NDK, instead. Download the prebuilt tools for your platform and install them somewhere. 

 h2. Cross Compiling Boost for Android boost 

 I used boost 1.44.0. Download and unpack it somewhere. 

 Run the bootstrap script to compile bjam. 

 Edit the boost_1_44_0/project-config.jam file to add some defaults. I made the following changes: 
 <pre> 
 # Python configuration 
 #using python : 2.6 : /usr ; 

 libraries = --with-date_time --with-filesystem --with-program_options --with-regex --with-signals --with-system --with-thread ;  

 # These settings are equivivalent to corresponding command-line 
 # options. 
 option.set prefix : /home/wim/project/android/boost ; 
 option.set exec-prefix : /home/wim/project/android/boost ; 
 option.set libdir : /home/wim/project/android/boost/lib ; 
 option.set includedir : /home/wim/project/android/boost/include ; 
 </pre> 

 In boost_1_44_0/tools/build/v2/user-config.jam, add the following lines (modify paths to your NDK installation directory as needed): 
 <pre> 
 using gcc : arm : /home/wim/project/android/android-ndk-r4-crystax/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/arm-eabi-c++ : 
 <compileflags>-I/home/wim/project/android/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/include/ 
 <compileflags>-fpic 
 <compileflags>-mthumb-interwork 
 <compileflags>-ffunction-sections 
 <compileflags>-funwind-tables 
 <compileflags>-fstack-protector 
 <compileflags>-fno-short-enums 
 <compileflags>-D__ARM_ARCH_5__ 
 <compileflags>-D__ARM_ARCH_5T__ 
 <compileflags>-D__ARM_ARCH_5E__ 
 <compileflags>-D__ARM_ARCH_5TE__ 
 <compileflags>-Wno-psabi 
 <compileflags>-march=armv5te 
 <compileflags>-mtune=xscale 
 <compileflags>-msoft-float 
 <compileflags>-mthumb 
 <compileflags>-Os 
 <compileflags>-fomit-frame-pointer 
 <compileflags>-fno-strict-aliasing 
 <compileflags>-finline-limit=64 
 <compileflags>-DANDROID 
 <compileflags>-D__ANDROID__ 
 <compileflags>-Wa,--noexecstack 
 # 'official' android flags stop here 
 <architecture>arm 
 <compileflags>-fvisibility=hidden 
 <compileflags>-fvisibility-inlines-hidden 
 <compileflags>-fdata-sections 
 <cxxflags>-DBOOST_THREAD_LINUX 
 <cxxflags>-DBOOST_HAS_PTHREADS 
 <cxxflags>-D__arm__ 
 <cxxflags>-D_REENTRANT 
 <cxxflags>-D_GLIBCXX__PTHREADS 
 <cxxflags>-DBOOST_HAS_GETTIMEOFDAY 
 ; 

 </pre> 

 You'll need to patch boost. This is a diff of my patched boost against an original one: 
 <pre> 
 diff -ru orig/boost_1_44_0/boost/asio/detail/fenced_block.hpp boost_1_44_0/boost/asio/detail/fenced_block.hpp 
 --- orig/boost_1_44_0/boost/asio/detail/fenced_block.hpp 	 2010-07-12 01:42:34.000000000 +0200 
 +++ boost_1_44_0/boost/asio/detail/fenced_block.hpp 	 2010-09-02 10:43:21.000000000 +0200 
 @@ -25,14 +25,14 @@ 
  # include <boost/asio/detail/macos_fenced_block.hpp> 
  #elif defined(__sun) 
  # include <boost/asio/detail/solaris_fenced_block.hpp> 
 -#elif defined(__GNUC__) && defined(__arm__) 
 +#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) 
  # include <boost/asio/detail/gcc_arm_fenced_block.hpp> 
  #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) 
  # include <boost/asio/detail/gcc_hppa_fenced_block.hpp> 
  #elif defined(__GNUC__) \ 
    && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ 
    && !defined(__INTEL_COMPILER) && !defined(__ICL) \ 
 -    && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) 
 +    && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) && !defined(ANDROID) 
  # include <boost/asio/detail/gcc_sync_fenced_block.hpp> 
  #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) 
  # include <boost/asio/detail/gcc_x86_fenced_block.hpp> 
 @@ -54,14 +54,14 @@ 
  typedef macos_fenced_block fenced_block; 
  #elif defined(__sun) 
  typedef solaris_fenced_block fenced_block; 
 -#elif defined(__GNUC__) && defined(__arm__) 
 +#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) 
  typedef gcc_arm_fenced_block fenced_block; 
  #elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) 
  typedef gcc_hppa_fenced_block fenced_block; 
  #elif defined(__GNUC__) \ 
    && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ 
    && !defined(__INTEL_COMPILER) && !defined(__ICL) \ 
 -    && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) 
 +    && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) && !defined(ANDROID) 
  typedef gcc_sync_fenced_block fenced_block; 
  #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) 
  typedef gcc_x86_fenced_block fenced_block; 
 diff -ru orig/boost_1_44_0/boost/asio/detail/socket_types.hpp boost_1_44_0/boost/asio/detail/socket_types.hpp 
 --- orig/boost_1_44_0/boost/asio/detail/socket_types.hpp 	 2010-06-09 11:40:46.000000000 +0200 
 +++ boost_1_44_0/boost/asio/detail/socket_types.hpp 	 2010-09-01 19:10:27.000000000 +0200 
 @@ -121,7 +121,11 @@ 
  typedef int socket_type; 
  const int invalid_socket = -1; 
  const int socket_error_retval = -1; 
 +#ifdef INET_ADDRSTRLEN 
  const int max_addr_v4_str_len = INET_ADDRSTRLEN; 
 +#else 
 +const int max_addr_v4_str_len = 16; 
 +#endif 
  #if defined(INET6_ADDRSTRLEN) 
  const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; 
  #else // defined(INET6_ADDRSTRLEN) 
 diff -ru orig/boost_1_44_0/boost/asio/ip/impl/address_v6.ipp boost_1_44_0/boost/asio/ip/impl/address_v6.ipp 
 --- orig/boost_1_44_0/boost/asio/ip/impl/address_v6.ipp 	 2010-06-09 11:40:46.000000000 +0200 
 +++ boost_1_44_0/boost/asio/ip/impl/address_v6.ipp 	 2010-09-01 19:10:27.000000000 +0200 
 @@ -11,6 +11,23 @@ 
  #ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP 
  #define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP 
 
 +#ifndef IN6_IS_ADDR_MULTICAST  
 +#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) 
 +#endif 
 + 
 +#ifndef IN6_IS_ADDR_MC_NODELOCAL 
 +#define IN6_IS_ADDR_MC_NODELOCAL(a) \ 
 +          (IN6_IS_ADDR_MULTICAST(a)                                               \ 
 +           && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) 
 +#endif 
 + 
 +#ifndef IN6_IS_ADDR_MC_GLOBAL 
 +#define IN6_IS_ADDR_MC_GLOBAL(a) \ 
 +          (IN6_IS_ADDR_MULTICAST(a)                                               \ 
 +           && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) 
 +#endif 
 + 
 + 
  #if defined(_MSC_VER) && (_MSC_VER >= 1200) 
  # pragma once 
  #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 
 Only in boost_1_44_0/: bootstrap.log 
 diff -ru orig/boost_1_44_0/libs/filesystem/v2/src/v2_operations.cpp boost_1_44_0/libs/filesystem/v2/src/v2_operations.cpp 
 --- orig/boost_1_44_0/libs/filesystem/v2/src/v2_operations.cpp 	 2010-08-10 22:00:09.000000000 +0200 
 +++ boost_1_44_0/libs/filesystem/v2/src/v2_operations.cpp 	 2010-09-02 17:38:22.000000000 +0200 
 @@ -58,14 +58,16 @@ 
 
  # else // BOOST_POSIX_API 
  #     include <sys/types.h> 
 -#     if !defined(__APPLE__) && !defined(__OpenBSD__) 
 +#     if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(ANDROID) 
  #       include <sys/statvfs.h> 
  #       define BOOST_STATVFS statvfs 
  #       define BOOST_STATVFS_F_FRSIZE vfs.f_frsize 
  #     else 
 -#ifdef __OpenBSD__ 
 -#       include <sys/param.h> 
 -#endif 
 +#       ifdef __OpenBSD__ 
 +#         include <sys/param.h> 
 +#       elif defined(ANDROID) 
 +#         include <sys/vfs.h> 
 +#       endif 
  #       include <sys/mount.h> 
  #       define BOOST_STATVFS statfs 
  #       define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>( vfs.f_bsize ) 
 @@ -1262,7 +1264,20 @@ 
          if ( max == 0 ) 
          { 
            errno = 0; 
 +#ifdef ANDROID 
 +            long tmp = 4096; // is it? 
 +#if 0 
 +            { 
 +              int fd = open( "/", O_RDONLY ); 
 +              if (fd >= 0) { 
 +                tmp = ::fpathconf( fd, _PC_NAME_MAX ); 
 +                close(fd); 
 +              } 
 +            } 
 +#endif 
 +#else 
            long tmp = ::pathconf( "/", _PC_NAME_MAX ); 
 +#endif 
            if ( tmp < 0 ) 
            { 
              if ( errno == 0 ) // indeterminate 
 Only in boost_1_44_0/libs/filesystem/v2/src: v2_operations.cpp~ 
 diff -ru orig/boost_1_44_0/libs/filesystem/v3/src/operations.cpp boost_1_44_0/libs/filesystem/v3/src/operations.cpp 
 --- orig/boost_1_44_0/libs/filesystem/v3/src/operations.cpp 	 2010-08-10 22:00:09.000000000 +0200 
 +++ boost_1_44_0/libs/filesystem/v3/src/operations.cpp 	 2010-09-01 19:10:27.000000000 +0200 
 @@ -66,13 +66,15 @@ 
  # ifdef BOOST_POSIX_API 
 
  #     include <sys/types.h> 
 -#     if !defined(__APPLE__) && !defined(__OpenBSD__) 
 +#     if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(ANDROID) 
  #       include <sys/statvfs.h> 
  #       define BOOST_STATVFS statvfs 
  #       define BOOST_STATVFS_F_FRSIZE vfs.f_frsize 
  #     else 
  #       ifdef __OpenBSD__ 
  #       include <sys/param.h> 
 +#       elif defined(ANDROID) 
 +#         include <sys/vfs.h> 
  #       endif 
  #       include <sys/mount.h> 
  #       define BOOST_STATVFS statfs 
 @@ -193,7 +195,19 @@ 
           || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) 
  #     define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) 
  #     define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) 
 +#ifndef ANDROID 
  #     define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) 
 +#else 
 +int BOOST_RESIZE_FILE(const char *path, off_t size) 
 +{ 
 +    int retval = -1; 
 +    int fd = open(path, O_WRONLY); 
 +    if (fd != -1) 
 +      retval = ftruncate(fd, size); 
 +    close(fd); 
 +    return retval; 
 +} 
 +#endif 
 
  #     define BOOST_ERROR_NOT_SUPPORTED ENOSYS 
  #     define BOOST_ERROR_ALREADY_EXISTS EEXIST 
 diff -ru orig/boost_1_44_0/tools/build/v2/tools/gcc.jam boost_1_44_0/tools/build/v2/tools/gcc.jam 
 --- orig/boost_1_44_0/tools/build/v2/tools/gcc.jam 	 2010-04-20 14:05:14.000000000 +0200 
 +++ boost_1_44_0/tools/build/v2/tools/gcc.jam 	 2010-09-01 16:37:36.000000000 +0200 
 @@ -935,8 +935,8 @@ 
              } 
              case * : 
              { 
 -                  option = -pthread ; 
 -                  libs = rt ; 
 +#                  option = -pthread ; 
 +#                  libs = rt ; 
              } 
          } 
     
 diff -ru orig/boost_1_44_0/tools/build/v2/tools/gcc.py boost_1_44_0/tools/build/v2/tools/gcc.py 
 --- orig/boost_1_44_0/tools/build/v2/tools/gcc.py 	 2009-10-28 08:47:51.000000000 +0100 
 +++ boost_1_44_0/tools/build/v2/tools/gcc.py 	 2010-09-01 16:36:22.000000000 +0200 
 @@ -672,12 +672,14 @@ 
          # BeOS has no threading options, don't set anything here. 
          pass 
      elif host_os_name.endswith('BSD'): 
 -          flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread']) 
 +          #flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread']) 
          # there is no -lrt on BSD 
 +          pass 
      elif host_os_name == 'DragonFly': 
 -          flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread']) 
 +          #flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread']) 
          # there is no -lrt on BSD - DragonFly is a FreeBSD variant, 
          # which anoyingly doesn't say it's a *BSD. 
 +          pass 
      elif host_os_name == 'IRIX': 
          # gcc on IRIX does not support multi-threading, don't set anything here. 
          pass 
 @@ -685,8 +687,9 @@ 
          # Darwin has no threading options, don't set anything here. 
          pass 
      else: 
 -          flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread']) 
 -          flags('gcc', 'FINDLIBS-SA', [], ['rt']) 
 +          #flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread']) 
 +          #flags('gcc', 'FINDLIBS-SA', [], ['rt']) 
 +          pass 
 
  def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None): 
      #FIXME: for some reason this fails.    Probably out of date feature code 

 </pre> 

 Now invoke bjam, and you should have a nice boost installation in the path that you specified in project-config.jam. 
 <pre> 
 ./bjam link=static threading=multi --layout=versioned install 
 </pre> 

 h2. Preparing Cmake for Cross Compilation to Android cmake 

 Create a toolchain file. Call it ~/toolchain-android.cmake 
 <pre> 
 SET(ANDROID_DIR /home/wim/project/android/) 
 SET(ANDROID_NDK_DIR ${ANDROID_DIR}/android-ndk-r4-crystax/) 
 SET(STAGING_DIR ${ANDROID_NDK_DIR}/build/prebuilt/linux-x86/arm-eabi-4.4.0/) 
 SET(TARGET_CC ${STAGING_DIR}/bin/arm-eabi-gcc) 
 SET(TARGET_CXX ${STAGING_DIR}/bin/arm-eabi-c++) 

 SET(CMAKE_SYSTEM_NAME Android) 
 SET(CMAKE_SYSTEM_VERSION 1) 

 SET(CMAKE_SYSTEM_PROCESSOR arm-elf) 
 SET(CMAKE_C_COMPILER ${TARGET_CC}) 
 SET(CMAKE_CXX_COMPILER ${TARGET_CXX}) 

 SET(CMAKE_FIND_ROOT_PATH    ${ANDROID_DIR}) 

 # search for programs in the build host directories 
 SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 
 # for libraries and headers in the target directories 
 SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 
 SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 
 </pre> 

 Create a platform file. Put it in a file called cmake/Platform/Android.cmake 
 <pre> 
 SET(ANDROID true) 
 SET(ANDROID_OPTION_LIST 
     -I/home/wim/project/android/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/include 
     -fpic 
     -mthumb-interwork 
     -ffunction-sections 
     -funwind-tables 
     -fstack-protector 
     -fno-short-enums 
     -D__ARM_ARCH_5__ 
     -D__ARM_ARCH_5T__ 
     -D__ARM_ARCH_5E__ 
     -D__ARM_ARCH_5TE__ 
     -Wno-psabi 
     -march=armv5te 
     -mtune=xscale 
     -msoft-float 
     -mthumb 
     -Os 
     -fomit-frame-pointer 
     -fno-strict-aliasing 
     -finline-limit=64 
     -DANDROID 
     -Wa,--noexecstack 
 #more options 
     -fvisibility=hidden 
     -fvisibility-inlines-hidden 
     -fdata-sections 
     -DBOOST_THREAD_LINUX 
     -DBOOST_HAS_PTHREADS 
     -D_REENTRANT 
     -D_GLIBCXX__PTHREADS 
     -DANDROID 
     -D__ANDROID__ 
     -DBOOST_HAS_GETTIMEOFDAY 
     -DSQLITE_OMIT_LOAD_EXTENSION 
 ) 

 foreach(arg ${ANDROID_OPTION_LIST}) 
   set(ANDROID_COMPILE_FLAGS "${ANDROID_COMPILE_FLAGS} ${arg}") 
 endforeach(arg ${ANDROID_OPTION_LIST}) 


 SET(CMAKE_CXX_COMPILE_OBJECT "<CMAKE_CXX_COMPILER>    <DEFINES> <FLAGS> ${ANDROID_COMPILE_FLAGS} -o <OBJECT> -c <SOURCE>") 
 SET(CMAKE_C_COMPILE_OBJECT "<CMAKE_C_COMPILER>    <DEFINES> <FLAGS> ${ANDROID_COMPILE_FLAGS} -o <OBJECT> -c <SOURCE>") 

 SET(ANDROID_NDK_PREFIX "/home/wim/project/android/android-ndk-r4-crystax/") 
 SET(ANDROID_LINK_EXE_FLAGS 
     "-nostdlib -Bdynamic -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc" 
     ) 
 SET(ANDROID_CRT_PRE 
     "${ANDROID_NDK_PREFIX}/build/platforms/android-3/arch-arm/usr/lib/crtbegin_dynamic.o" 
    ) 
 SET(ANDROID_CRT_POST_LIST 
     "${ANDROID_NDK_PREFIX}/build/platforms/android-3/arch-arm/usr/lib/libmissing.a" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a" 
     "${ANDROID_NDK_PREFIX}/build/platforms/android-3/arch-arm/usr/lib/libc.so" 
     "${ANDROID_NDK_PREFIX}/build/platforms/android-3/arch-arm/usr/lib/libm.so" 
     "-Wl,--no-undefined" 
     "-Wl,-z,noexecstack" 
     "-L${ANDROID_NDK_PREFIX}/build/platforms/android-3/arch-arm/usr/lib" 
     "-llog" 
     "-Wl,-rpath-link=${ANDROID_NDK_PREFIX}/build/platforms/android-3/arch-arm/usr/lib" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a" 
     "${ANDROID_NDK_PREFIX}/build/platforms/android-3/arch-arm/usr/lib/crtend_android.o" 
    ) 
 foreach(arg ${ANDROID_CRT_POST_LIST}) 
   set(ANDROID_CRT_POST "${ANDROID_CRT_POST} ${arg}") 
 endforeach(arg ${ANDROID_CRT_POST_LIST}) 
 SET(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_C_COMPILER>    ${ANDROID_LINK_EXE_FLAGS} <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> ${ANDROID_CRT_PRE} <OBJECTS>    -o <TARGET> <LINK_LIBRARIES> ${ANDROID_CRT_POST}") 
 SET(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER>    ${ANDROID_LINK_EXE_FLAGS} <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> ${ANDROID_CRT_PRE} <OBJECTS>    -o <TARGET> <LINK_LIBRARIES> ${ANDROID_CRT_POST}") 

 SET(ANDROID_LINK_SHARED_FLAGS 
     "-nostdlib -Wl,-soname,<TARGET> -Wl,-shared,-Bsymbolic" 
     ) 
 SET(ANDROID_LINK_SHARED_LIBS_LIST 
     "-Wl,--whole-archive" 
     "-Wl,--no-whole-archive" 
     "${ANDROID_NDK_PREFIX}/build/platforms/android-8/arch-arm/usr/lib/libmissing.a" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a" 
     "${ANDROID_NDK_PREFIX}/build/platforms/android-8/arch-arm/usr/lib/libc.so" 
     "${ANDROID_NDK_PREFIX}/build/platforms/android-8/arch-arm/usr/lib/libm.so" 
     "-Wl,--no-undefined" 
     "-Wl,-z,noexecstack" 
     "-Wl,-rpath-link=${ANDROID_NDK_PREFIX}/build/platforms/android-8/arch-arm/usr/lib" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a" 
     "${ANDROID_NDK_PREFIX}/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a" 
    ) 
 foreach(arg ${ANDROID_LINK_SHARED_LIBS_LIST}) 
   set(ANDROID_LINK_SHARED_LIBS "${ANDROID_LINK_SHARED_LIBS} ${arg}") 
 endforeach(arg ${ANDROID_LINK_SHARED_LIBS_LIST}) 
 SET(CMAKE_CXX_CREATE_SHARED_LIBRARY 
     "<CMAKE_C_COMPILER> ${ANDROID_LINK_SHARED_FLAGS} <CMAKE_SHARED_LIBRARY_CXX_FLAGS><LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES> ${ANDROID_LINK_SHARED_LIBS}" 
     ) 
 </pre> 

 Disclaimer: I'm not a specialist in writing platform files, I was looking for something that works. With this platform file, you can build both executables and shared objects (and .a files of course). 

 h2. Cross Build Wt 

 Adjust paths as necessary. The CMAKE_MODULE_PATH is the directory where you put your Android platform file. 

 <pre> 
 mkdir wt-build 
 cd wt-build 
 cmake -DCMAKE_TOOLCHAIN_FILE=~/toolchain-android.cmake -DBOOST_PREFIX=~/project/android/boost/ -DBOOST_VERSION=1_44 -DBOOST_COMPILER=gcc -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MODULE_PATH=/home/wim/project/android/cmake -DSHARED_LIBS=OFF ~/project/android/wt 
 </pre> 

 Android doesn't have libdl, so omit it while compiling the sqlite3 backend: 
 <pre> 
 diff --git a/src/Wt/Dbo/backend/CMakeLists.txt b/src/Wt/Dbo/backend/CMakeLists.txt 
 index f268223..a915db2 100644 
 --- a/src/Wt/Dbo/backend/CMakeLists.txt 
 +++ b/src/Wt/Dbo/backend/CMakeLists.txt 
 @@ -16,7 +16,7 @@ MESSAGE("** Wt::Dbo: building SQLite3 backend.") 
  TARGET_LINK_LIBRARIES(wtdbosqlite3 wtdbo ${SQLITE3_LIBRARIES} ${BOOST_WT_DT_LIB}) 

  IF(NOT WIN32) 
 -    TARGET_LINK_LIBRARIES(wtdbosqlite3 dl) 
 +    TARGET_LINK_LIBRARIES(wtdbosqlite3) 
  ENDIF(NOT WIN32) 

  INSTALL(TARGETS wtdbosqlite3 
 </pre> 

 Now compile Wt: 
 <pre> 
 make -j 8 
 cd examples 
 make -j 8 -k 
 </pre> 

 Examples that use crypt will fail to build. 

 h2. Deploying and running Wt on Android 

 Log in on your android device and make a temporary directory: 
 <pre> 
 $ adb shell 
 # mkdir /data/tmp 
 # cd /data/tmp 
 </pre> 

 Copy your executable (and all dependency files, such as the resources directory, if necessary) to the temporary directory: 
 <pre> 
 $ adb shell push hello.wt /data/tmp/hello.wt 
 </pre> 

 Run the executable: 
 <pre> 
 $ adb shell 
 # cd /data/tmp 
 # chmod 755 hello.wt 
 # ./hello.wt --docroot=. --http-address=0.0.0.0 --http-port=8080 
 </pre> 

 Set up port forwarding so that you can surf to your emulator: 
 <pre> 
 $ telnet localhost 5554 
 Android Console: type 'help' for a list of commands 
 OK 
 redir add tcp:8080:8080 
 </pre> 

 Point your browser to http://localhost:8080/ and enjoy your Wt application!