Installing Wt on Android » History » Revision 2
« Previous |
Revision 2/4
(diff)
| Next »
Wim Dumon, 09/07/2010 04:36 PM
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 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. Compiling 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:
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 ;
In boost_1_44_0/tools/build/v2/user-config.jam, add the following lines (modify paths to your NDK installation directory as needed):
using gcc : arm : /home/wim/project/android/android-ndk-r4-crystax/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/arm-eabi-c++ :
-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
-D_ANDROID_
-Wa,--noexecstack
'official' android flags stop here¶
arm
-fvisibility=hidden
-fvisibility-inlines-hidden
-fdata-sections
-DBOOST_THREAD_LINUX
-DBOOST_HAS_PTHREADS
-D_arm_
-D_REENTRANT
-D_GLIBCXX__PTHREADS
-DBOOST_HAS_GETTIMEOFDAY
;
You'll need to patch boost. This is a diff of my patched boost against an original one:
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
#elif defined(sun)
# include
-#elif defined(GNUC_) && defined(arm)
+#elif defined(GNUC) && defined(arm) && !defined(thumb)
# include
#elif defined(GNUC) && (defined(hppa) || defined(hppa))
# include
#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 #elif defined(GNUC) && (defined(i386) || defined(x86_64)) # include @@ -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
-# if !defined(APPLE) && !defined(OpenBSD)
+# if !defined(APPLE) && !defined(OpenBSD) && !defined(ANDROID)
# include
# define BOOST_STATVFS statvfs
# define BOOST_STATVFS_F_FRSIZE vfs.f_frsize
# else
-#ifdef OpenBSD
-# include
-#endif
+# ifdef OpenBSD
+# include
+# elif defined(ANDROID)
+# include
+# endif
# include
# define BOOST_STATVFS statfs
# define BOOST_STATVFS_F_FRSIZE static_castboost::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
-# if !defined(APPLE) && !defined(OpenBSD)
+# if !defined(APPLE) && !defined(OpenBSD) && !defined(ANDROID)
# include
# define BOOST_STATVFS statvfs
# define BOOST_STATVFS_F_FRSIZE vfs.f_frsize
# else
# ifdef OpenBSD
# include
+# elif defined(ANDROID)
+# include
# endif
# include
# 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', ['multi'], ['-pthread'])
- #flags('gcc', 'OPTIONS', ['multi'], ['-pthread']) # there is no -lrt on BSD
- pass elif host_os_name == 'DragonFly':
- flags('gcc', 'OPTIONS', ['multi'], ['-pthread'])
- #flags('gcc', 'OPTIONS', ['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', ['multi'], ['-pthread'])
- flags('gcc', 'FINDLIBS-SA', [], ['rt'])
- #flags('gcc', 'OPTIONS', ['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
Now invoke bjam, and you should have a nice boost installation in the path that you specified in project-config.jam.
./bjam link=static threading=multi --layout=versioned install
h2. Preparing cmake
Create a toolchain file. Call it ~/toolchain-android.cmake
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)
Create a platform file. Put it in a file called cmake/Platform/Android.cmake
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
-DANDROID_
-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 " ${ANDROID_COMPILE_FLAGS} -o -c ")
SET(CMAKE_C_COMPILE_OBJECT " ${ANDROID_COMPILE_FLAGS} -o -c ")
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 " ${ANDROID_LINK_EXE_FLAGS} ${ANDROID_CRT_PRE} -o ${ANDROID_CRT_POST}")
SET(CMAKE_C_LINK_EXECUTABLE " ${ANDROID_LINK_EXE_FLAGS} ${ANDROID_CRT_PRE} -o ${ANDROID_CRT_POST}")
SET(ANDROID_LINK_SHARED_FLAGS
"-nostdlib -Wl,-soname, -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
" ${ANDROID_LINK_SHARED_FLAGS} -o ${ANDROID_LINK_SHARED_LIBS}"
)
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. Build Wt
Adjust paths as necessary. The CMAKE_MODULE_PATH is the directory where you put your Android platform file.
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
Android doesn't have libdl, so omit it while compiling the sqlite3 backend:
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
Now compile Wt:
make -j 8
cd examples
make -j 8 -k
Examples that use crypt will fail to build.
h2. Deploying and running Wt
Log in on your android device and make a temporary directory:
$ adb shell
mkdir /data/tmp¶
cd /data/tmp¶
Copy your executable (and all dependency files, such as the resources directory, if necessary) to the temporary directory:
$ adb shell push hello.wt /data/tmp/hello.wt
Run the executable:
$ adb shell
cd /data/tmp¶
chmod 755 hello.wt¶
./hello.wt --docroot=. --http-address=0.0.0.0 --http-port=8080¶
Set up port forwarding so that you can surf to your emulator:
$ telnet localhost 5554
Android Console: type 'help' for a list of commands
OK
redir add tcp:8080:8080
Point your browser to http://localhost:8080/ and enjoy your Wt application!
Updated by Wim Dumon over 14 years ago · 2 revisions