Hello!

I've been wondering whether compilation of the open source libsynthesis
and SyncEvolution for Android is possible. There is of course the
official Synthesis SDK for Android, which is the better alternative for
those who need something which works right away *and* has the Java
bindings that are needed for GUI apps on Android.

For those who prefer compiling from source and/or want a working SyncML
client to play with, keep reading...

After some fiddling, I was able to compile both and run syncs with the
SyncEvolution file backend. Limitations:
      * no GUI, only the command line tool
      * no Java bindings (they are not part of the open source code
        base)
      * every exception aborts the program (does not happen during
        normal runs)

Setup:
      * install Android SDK and NDK
      * install NDK wrappers (http://umbel.mooo.com/)
      * ensure that the arm-linux-* binaries from the NDK wrappers are
        in the PATH
      * add a symbolic link from arm-linux-pkg-config to /bin/false in
        the PATH: this prevents calling the build machine's native
        pkg-config and thus detecting packages which don't exist on
        Android
      * download and compile libcurl, using --host=arm-linux as
        configure flag

Compilation of libsynthesis and SyncEvolution uses the normal autotools
scripts. The source of libsynthesis required some fixes to compile
cleanly on Android. These patches were pushed into the "android" branch
on git.moblin.org.

SyncEvolution changes for Android were also pushed into an "android"
branch. The biggest change is a patch which makes exception handling
optional, because that is not supported by the Android compiler and
runtime libraries.

One change in both repos is for static linking: as you will see below,
installing a single binary is fairly easy, so that's how I wanted to
compile syncevolution. The Synthesis engine expects to load plugins
dynamically. Our previous solution for static linking depended on
dlsym(RTLD_DEFAULT) and --export-dynamic. The latter didn't have any
effect on the resulting Android executable, therefore I had to find a
different solution. I went for specifying the addresses of all plugin
functions in the XML config which is generated at runtime.

Another complication was SyncEvolution's dependency on Boost header
files. They work without exceptions, but some of them use typeinfo(),
which is not supported either. As a crude solution (not done 100%
correctly for non-Android platforms and with unknown implications for
the code which depends on runtime type information) I patched the header
files (patch attached).

Copy and prepare some set of Boost header files (I
used /usr/include/boost from Debian's 1.34.1-14) like this:
      * mkdir <boost_path>/include
      * cp -a /usr/include/boost <boost_path>/include
      * cd <boost_path>/include/boost && patch -p1 <boost.patch

Finally, here's how I compiled SyncEvolution:
./configure --with-synthesis-src=<path>/libsynthesis \
            CFLAGS="-g -Wall -Werror -Wno-unknown-pragmas" \
            CXXFLAGS="-g -Wall -Werror -Wno-unknown-pragmas" \
            
LDFLAGS=-L<path>/ndk-wrappers/stlport/build/lib/obj/arm-linux-gcc/so/ \
            --disable-shared --enable-static --enable-libcurl \
            --disable-unit-tests --disable-integration-tests \
            --disable-ecal --disable-ebook \
            --with-boost=<boost_path> \
            --with-xmltok=builtin \
            --host=arm-linux 
  
I originally also used --disable-sqlite --disable-ical --disable-reqgex,
but with the arm-linux-pkg-config link that should no longer be
necessary.

Copy SyncEvolution into a running emulator (started via "android"
command earlier):
adb push syncevolution /data/local/bin/syncevolution && \
adb shell chmod 755 /data/local/bin/syncevolution

Configure SyncEvolution for contact sync with ScheduleWorld:
adb shell "cd /data && /data/local/bin/syncevolution --configure
           --source-property type=file:text/vcard:3.0
           --source-property 
evolutionsource=file:///data/syncevolution/addressbook
           --source-property sync=two-way
           --sync-property username=<username>
           --sync-property password=<password>
           scheduleworld addressbook"

The "cd" is important because there is no HOME env variable;
SyncEvolution then defaults to the current directory. Files created
above and during a sync end up in /data/.config/syncevolution
(config), /data/.cache (logs) and /data/syncvolution/addressbook (one
vcard file per contact).

Run the initial sync:
adb shell "cd /data && /data/local/bin/syncevolution 
           --run --sync-property sync=slow
           scheduleworld"

I was using the "slow-sync" branch, therefore a slow sync is only done
when expected by the user. All following runs:
adb shell "cd /data && /data/local/bin/syncevolution 
           scheduleworld"

This was just an experiment. I have not tried to get the automated
testing via "client-test" working, because that depends on CPPUnit and
thus another set of "no exception" patches.

Some of the resulting patches might be generally useful. Lukas, I
suggest that you pick whatever you find useful from the libsynthesis
repo. The static linking part would also be useful for Mac OS X, where
--export-dynamic is not a valid option to start with.

For SyncEvolution I'll probably let this settle a bit and then propose
patches for merging into master.

-- 
Best Regards, Patrick Ohly

The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.

diff --git a/config/stdlib/stlport.hpp b/config/stdlib/stlport.hpp
index 98fdd43..baa72e1 100644
--- a/config/stdlib/stlport.hpp
+++ b/config/stdlib/stlport.hpp
@@ -126,6 +126,10 @@
       && (defined(__STL_VENDOR_GLOBAL_CSTD) || defined (_STLP_VENDOR_GLOBAL_CSTD))
 #     define BOOST_NO_STDC_NAMESPACE
 #     define BOOST_NO_EXCEPTION_STD_NAMESPACE
+
+// necessary on Android so that BOOST_FUNCTION_STD_NS::type_info with
+// empty BOOST_FUNCTION_STD_NS works
+using std::type_info;
 #  endif
 #elif defined(__BORLANDC__) && __BORLANDC__ < 0x560
 // STLport doesn't import std::abs correctly:
@@ -157,7 +161,7 @@ namespace std{ using _STLP_VENDOR_CSTD::strcmp; using _STLP_VENDOR_CSTD::strcpy;
 // only if BOOST_NO_STDC_NAMESPACE is not defined (if it is then we do the import 
 // into std:: ourselves).
 //
-#if defined(_STLP_NO_NATIVE_WIDE_FUNCTIONS) && !defined(BOOST_NO_STDC_NAMESPACE)
+#if 1 || defined(_STLP_NO_NATIVE_WIDE_FUNCTIONS) && !defined(BOOST_NO_STDC_NAMESPACE)
 #  define BOOST_NO_CWCHAR
 #  define BOOST_NO_CWCTYPE
 #endif
diff --git a/detail/sp_counted_impl.hpp b/detail/sp_counted_impl.hpp
index 6963f59..ef575d2 100644
--- a/detail/sp_counted_impl.hpp
+++ b/detail/sp_counted_impl.hpp
@@ -36,6 +36,11 @@
 #endif
 
 #include <typeinfo>         // std::type_info in get_deleter
+#if defined(BOOST_HAVE_TYPEINFO)
+# define BOOST_TYPES_EQUAL(_x, _y) ((_x) == (_y))
+#else
+# define BOOST_TYPES_EQUAL(_x, _y) true
+#endif
 #include <cstddef>          // std::size_t
 
 namespace boost
@@ -147,7 +152,7 @@ public:
 
     virtual void * get_deleter( std::type_info const & ti )
     {
-        return ti == typeid(D)? &del: 0;
+        return BOOST_TYPES_EQUAL(ti, typeid(D))? &del: 0;
     }
 
 #if defined(BOOST_SP_USE_STD_ALLOCATOR)
@@ -217,7 +222,7 @@ public:
 
     virtual void * get_deleter( std::type_info const & ti )
     {
-        return ti == typeid( D )? &d_: 0;
+        return BOOST_TYPES_EQUAL(ti, typeid( D ))? &d_: 0;
     }
 };
 
diff --git a/function/function_base.hpp b/function/function_base.hpp
index aa7376a..b73c844 100644
--- a/function/function_base.hpp
+++ b/function/function_base.hpp
@@ -46,7 +46,9 @@
 
 // Borrowed from Boost.Python library: determines the cases where we
 // need to use std::type_info::name to compare instead of operator==.
-# if (defined(__GNUC__) && __GNUC__ >= 3) \
+# if !defined(BOOST_HAVE_TYPEINFO)
+#  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) true
+# elif (defined(__GNUC__) && __GNUC__ >= 3) \
  || defined(_AIX) \
  || (   defined(__sgi) && defined(__host_mips))
 #  include <cstring>
@@ -239,7 +241,11 @@ namespace boost {
             return;
 
           case get_functor_type_tag:
+#ifdef BOOST_HAVE_TYPEID
             out_buffer.const_obj_ptr = &typeid(F);
+#else
+            boost::throw_exception(std::runtime_error("no rtti"));
+#endif
             return;
           }
         }
@@ -279,8 +285,10 @@ namespace boost {
           else if (op == destroy_functor_tag)
             out_buffer.func_ptr = 0;
           else /* op == check_functor_type_tag */ {
+#ifdef BOOST_HAVE_TYPEID
             const BOOST_FUNCTION_STD_NS::type_info& check_type = 
               *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
+#endif
             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
               out_buffer.obj_ptr = &in_buffer.func_ptr;
             else
@@ -301,8 +309,10 @@ namespace boost {
             // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
             reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
           } else /* op == check_functor_type_tag */ {
+#ifdef BOOST_HAVE_TYPEINFO
             const BOOST_FUNCTION_STD_NS::type_info& check_type = 
               *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
+#endif
             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
               out_buffer.obj_ptr = &in_buffer.data;
             else
@@ -362,8 +372,10 @@ namespace boost {
 #  endif // BOOST_NO_STD_ALLOCATOR
             out_buffer.obj_ptr = 0;
           } else /* op == check_functor_type_tag */ {
+#ifdef BOOST_HAVE_TYPEID
             const BOOST_FUNCTION_STD_NS::type_info& check_type = 
               *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
+#endif
             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
               out_buffer.obj_ptr = in_buffer.obj_ptr;
             else
@@ -401,7 +413,11 @@ namespace boost {
           typedef typename get_function_tag<functor_type>::type tag_type;
           switch (op) {
           case get_functor_type_tag:
+#ifdef BOOST_HAVE_TYPEID
             out_buffer.const_obj_ptr = &typeid(functor_type);
+#else
+            boost::throw_exception(std::runtime_error("no rtti"));
+#endif
             return;
 
           default:
@@ -504,13 +520,21 @@ public:
       if this is empty. */
   const BOOST_FUNCTION_STD_NS::type_info& target_type() const
   {
-    if (!vtable) return typeid(void);
+    if (!vtable) {
+#ifdef BOOST_HAVE_TYPEID
+        return typeid(void);
+#else
+        boost::throw_exception(std::runtime_error("no rtti"));
+        return *(BOOST_FUNCTION_STD_NS::type_info *)0;
+#endif
+    }
 
     detail::function::function_buffer type;
     vtable->manager(functor, type, detail::function::get_functor_type_tag);
     return *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(type.const_obj_ptr);
   }
 
+#ifdef BOOST_HAVE_TYPEID
   template<typename Functor>
     Functor* target()
     {
@@ -522,7 +546,9 @@ public:
                       detail::function::check_functor_type_tag);
       return static_cast<Functor*>(type_result.obj_ptr);
     }
+#endif
 
+#ifdef BOOST_HAVE_TYPEID
   template<typename Functor>
 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
     const Functor* target( Functor * = 0 ) const
@@ -540,6 +566,7 @@ public:
       // can't do the static_cast that we should do.
       return (const Functor*)(type_result.obj_ptr);
     }
+#endif
 
   template<typename F>
     bool contains(const F& f) const
diff --git a/shared_ptr.hpp b/shared_ptr.hpp
index 9edc86f..838dbaf 100644
--- a/shared_ptr.hpp
+++ b/shared_ptr.hpp
@@ -523,6 +523,7 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::
 
 #endif // __GNUC__ < 3
 
+#ifdef BOOST_HAVE_TYPEINFO
 // get_deleter (experimental)
 
 #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
@@ -546,6 +547,7 @@ template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
 }
 
 #endif
+#endif // BOOST_HAVE_TYPEINFO
 
 } // namespace boost
 
diff --git a/throw_exception.hpp b/throw_exception.hpp
index bb79a37..b68ca89 100644
--- a/throw_exception.hpp
+++ b/throw_exception.hpp
@@ -25,6 +25,18 @@
 # include <exception>
 #endif
 
+#ifndef BOOST_HAVE_BADALLOC
+namespace std
+{
+    class bad_alloc : public exception {
+    public:
+        bad_alloc() throw() {}
+        virtual ~bad_alloc() throw() {}
+        virtual const char* what() const throw() { return "bad alloc"; }
+    };
+}
+#endif
+
 namespace boost
 {
 
_______________________________________________
os-libsynthesis mailing list
[email protected]
http://lists.synthesis.ch/mailman/listinfo/os-libsynthesis

Reply via email to