Merge pull request #162 from gonzalolarralde/android-support

Android support
diff --git a/Makefile.am b/Makefile.am
index cdc642f..63c8b17 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,6 +12,10 @@
   MAYBE_KQUEUES = libkqueue
 endif
 
+if BUILD_TESTS
+  MAYBE_TESTS = tests
+endif
+
 SUBDIRS=						\
 	dispatch					\
 	$(MAYBE_PTHREAD_WORKQUEUES)	\
@@ -20,7 +24,7 @@
 	os							\
 	private						\
 	src							\
-	tests
+	$(MAYBE_TESTS)
 
 EXTRA_DIST=					\
 	README.md				\
diff --git a/configure.ac b/configure.ac
index b923c66..98e1142 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,6 +11,10 @@
 ac_clean_files=a.out.dSYM
 AM_MAINTAINER_MODE
 
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
 #
 # Command line argument to specify build variant (default to release).
 # Impacts default value of CFLAGS et al. so must come before AC_PROG_CC
@@ -57,6 +61,53 @@
 AC_PROG_OBJCXX([clang++ g++ c++])
 
 #
+# Android cross-compilation support
+#
+AC_ARG_WITH([android-ndk],
+  [AS_HELP_STRING([--with-android-ndk],
+    [Android NDK location])], [
+  android_ndk=${withval}
+])
+AC_ARG_WITH([android-ndk-gcc-version],
+  [AS_HELP_STRING([--with-android-ndk-gcc-version],
+    [Android NDK GCC version [defaults=4.9]])],
+  [android_ndk_gcc_version=${withval}], [android_ndk_gcc_version=4.9])
+AC_ARG_WITH([android-api-level],
+  [AS_HELP_STRING([--with-android-api-level],
+    [Android API level to link with])], [
+  android_api_level=${withval}
+])
+AC_ARG_ENABLE([android],
+  [AS_HELP_STRING([--enable-android],
+    [Compile for Android])], [
+  android=true
+
+  # Override values until there's real support for multiple Android platforms
+  host=armv7-none-linux-androideabi
+  host_alias=arm-linux-androideabi
+  host_cpu=armv7
+  host_os=linux-androideabi
+  host_vendor=unknown
+  arch=arm
+
+  sysroot=${android_ndk}/platforms/android-${android_api_level}/arch-${arch}
+  toolchain=${android_ndk}/toolchains/${host_alias}-${android_ndk_gcc_version}/prebuilt/linux-${build_cpu}
+
+  CFLAGS="$CFLAGS -target ${host_alias} --sysroot=${sysroot} -B${toolchain}/${host_alias}/bin"
+  CXXFLAGS="$CXXFLAGS -target ${host_alias} --sysroot=${sysroot} -B${toolchain}/${host_alias}/bin"
+  SWIFTC_FLAGS="-target ${host} -sdk ${sysroot} -L${toolchain}/lib/gcc/${host_alias}/${android_ndk_gcc_version}.x"
+  LIBS="$LIBS -L${toolchain}/lib/gcc/${host_alias}/${android_ndk_gcc_version}.x"
+  LDFLAGS="$LDFLAGS -Wc,'-target','${host_alias}','-B${toolchain}/${host_alias}/bin'"
+
+  # FIXME: empty CFLAGS and CXXFLAGS are assumed for this to work.
+  # FIXME: there should be a more elegant way to do this
+  ac_configure_args=`echo $ac_configure_args | sed -e "s/ 'CFLAGS='//" -e "s/ 'CXXFLAGS='//"`
+  # CFLAGS, CXXFLAGS and LIBS needs to be passed to libkqueue and libpwq
+  ac_configure_args="$ac_configure_args --enable-bionic-libc 'CFLAGS=$CFLAGS' 'CXXFLAGS=$CXXFLAGS' 'LIBS=$LIBS'"
+], [android=false])
+AM_CONDITIONAL(ANDROID, $android)
+
+#
 # On Mac OS X, some required header files come from other source packages;
 # allow specifying where those are.
 #
@@ -134,8 +185,6 @@
     [Define to use non-portable pthread TSD optimizations for Mac OS X)])]
 )
 
-AC_CANONICAL_TARGET
-
 #
 # Enable building Swift overlay support into libdispatch
 #
@@ -164,6 +213,7 @@
 )
 AM_CONDITIONAL(HAVE_SWIFT, $have_swift)
 AC_SUBST([SWIFTC])
+AC_SUBST([SWIFTC_FLAGS])
 AC_SUBST([SWIFT_LIBDIR])
 
 #
@@ -474,6 +524,13 @@
 )
 
 #
+# Add option to avoid building tests
+#
+AC_ARG_ENABLE([build-tests],
+  [AS_HELP_STRING([--disable-build-tests], [Disable tests compilation])])
+AM_CONDITIONAL(BUILD_TESTS, [test "x$enable_build_tests" != "xno"])
+
+#
 # Generate Makefiles.
 #
 AC_CONFIG_FILES([Makefile dispatch/Makefile man/Makefile os/Makefile private/Makefile src/Makefile tests/Makefile])
diff --git a/src/Makefile.am b/src/Makefile.am
index eaabce4..967d5a0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,6 +41,7 @@
 	trace.h					\
 	voucher_internal.h		\
 	firehose/firehose_internal.h \
+	shims/android_stubs.h	\
 	shims/atomic.h			\
 	shims/atomic_sfb.h		\
 	shims/getprogname.h		\
@@ -148,7 +149,7 @@
 SWIFT_ABS_SRC_FILES = $(SWIFT_SRC_FILES:%=$(abs_srcdir)/%)
 SWIFT_OBJ_FILES = $(abs_builddir)/swift/swift_overlay.o
 
-SWIFTC_FLAGS = -Xcc -fmodule-map-file=$(abs_top_srcdir)/dispatch/module.modulemap -I$(abs_top_srcdir) -Xcc -fblocks
+SWIFTC_FLAGS+= -Xcc -fmodule-map-file=$(abs_top_srcdir)/dispatch/module.modulemap -I$(abs_top_srcdir) -Xcc -fblocks
 if DISPATCH_ENABLE_OPTIMIZATION
 SWIFTC_FLAGS+=-O
 endif
@@ -180,4 +181,3 @@
 nodist_libdispatch_la_SOURCES=$(BUILT_SOURCES)
 CLEANFILES=$(BUILT_SOURCES) $(SWIFT_GEN_FILES)
 DISTCLEANFILES=pthread_machdep.h pthread System mach objc
-
diff --git a/src/internal.h b/src/internal.h
index 4408d96..8934b2c 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -155,6 +155,7 @@
 #endif
 
 /* private.h must be included last to avoid picking up installed headers. */
+#include <pthread.h>
 #include "os/object_private.h"
 #include "queue_private.h"
 #include "source_private.h"
@@ -245,7 +246,11 @@
 #include <sys/event.h>
 #include <sys/mount.h>
 #include <sys/queue.h>
+#ifdef __ANDROID__
+#include <linux/sysctl.h>
+#else
 #include <sys/sysctl.h>
+#endif /* __ANDROID__ */
 #include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/mman.h>
diff --git a/src/queue.c b/src/queue.c
index 0c058be..86018fd 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -976,6 +976,7 @@
 #include <unistd.h>
 #include <sys/syscall.h>
 
+#ifndef __ANDROID__
 #ifdef SYS_gettid
 DISPATCH_ALWAYS_INLINE
 static inline pid_t
@@ -985,7 +986,8 @@
 }
 #else
 #error "SYS_gettid unavailable on this system"
-#endif
+#endif /* SYS_gettid */
+#endif /* ! __ANDROID__ */
 
 #define _tsd_call_cleanup(k, f)  do { \
 		if ((f) && tsd->k) ((void(*)(void*))(f))(tsd->k); \
diff --git a/src/shims.h b/src/shims.h
index db28822..30d8929 100644
--- a/src/shims.h
+++ b/src/shims.h
@@ -97,6 +97,10 @@
 #include "shims/linux_stubs.h"
 #endif
 
+#ifdef __ANDROID__
+#include "shims/android_stubs.h"
+#endif
+
 typedef uint32_t dispatch_priority_t;
 #define DISPATCH_SATURATED_OVERRIDE ((dispatch_priority_t)UINT32_MAX)
 
diff --git a/src/shims/android_stubs.h b/src/shims/android_stubs.h
new file mode 100644
index 0000000..934552d
--- /dev/null
+++ b/src/shims/android_stubs.h
@@ -0,0 +1,34 @@
+/*
+ * This source file is part of the Swift.org open source project
+ *
+ * Copyright (c) 2015 Apple Inc. and the Swift project authors
+ *
+ * Licensed under Apache License v2.0 with Runtime Library Exception
+ *
+ * See http://swift.org/LICENSE.txt for license information
+ * See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+ *
+ */
+
+// forward declarations for functions we are stubbing out
+// in the intial android port.
+
+#ifndef __DISPATCH__ANDROID__STUBS__INTERNAL
+#define __DISPATCH__ANDROID__STUBS__INTERNAL
+
+/*
+ * Missing sys/queue.h macro stubs
+ */
+
+#ifndef TAILQ_FOREACH_SAFE
+#	define TAILQ_FOREACH_SAFE(var, head, field, tvar)                      \
+    	    for ((var) = TAILQ_FIRST((head));                              \
+        	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);           \
+            	(var) = (tvar))
+#endif /* TAILQ_FOREACH_SAFE */
+
+#ifndef TRASHIT
+#	define TRASHIT(x)      do {(x) = (void *)-1;} while (0)
+#endif /* TRASHIT */
+
+#endif /* __DISPATCH__ANDROID__STUBS__INTERNAL */
\ No newline at end of file
diff --git a/src/shims/getprogname.h b/src/shims/getprogname.h
index 74aba13..0aafaef 100644
--- a/src/shims/getprogname.h
+++ b/src/shims/getprogname.h
@@ -23,11 +23,18 @@
 #define __DISPATCH_SHIMS_GETPROGNAME__
 
 #if !HAVE_GETPROGNAME
+
+#ifdef __ANDROID__
+extern const char *__progname;
+#endif /* __ANDROID */)
+
 static inline char *
 getprogname(void)
 {
 # if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
 	return program_invocation_short_name;
+# elif defined(__ANDROID__)
+	return __progname;
 # else
 #   error getprogname(3) is not available on this platform
 # endif
diff --git a/src/shims/linux_stubs.c b/src/shims/linux_stubs.c
index 07ee8bc..4923eb0 100644
--- a/src/shims/linux_stubs.c
+++ b/src/shims/linux_stubs.c
@@ -17,7 +17,11 @@
  */
 
 #include <stdint.h>
+#ifdef __ANDROID__
+#include <sys/syscall.h>
+#else
 #include <syscall.h>
+#endif /* __ANDROID__ */
 
 #if __has_include(<config/config_ac.h>)
 #include <config/config_ac.h>
diff --git a/src/shims/linux_stubs.h b/src/shims/linux_stubs.h
index 0c12e82..8bdf3ff 100644
--- a/src/shims/linux_stubs.h
+++ b/src/shims/linux_stubs.h
@@ -71,7 +71,9 @@
 #endif
 
 // SIZE_T_MAX should not be hardcoded like this here.
-#define SIZE_T_MAX (0x7fffffff)
+#ifndef SIZE_T_MAX
+#define SIZE_T_MAX (~(size_t)0)
+#endif
 
 // Define to 0 the NOTE_ values that are not present on Linux.
 // Revisit this...would it be better to ifdef out the uses instead??
diff --git a/src/shims/lock.c b/src/shims/lock.c
index 2fab691..983fe47 100644
--- a/src/shims/lock.c
+++ b/src/shims/lock.c
@@ -117,7 +117,11 @@
 #pragma mark - futex wrappers
 #if HAVE_FUTEX
 #include <sys/time.h>
+#ifdef __ANDROID__
+#include <sys/syscall.h>
+#else
 #include <syscall.h>
+#endif /* __ANDROID__ */
 
 DISPATCH_ALWAYS_INLINE
 static inline int
diff --git a/src/source.c b/src/source.c
index afb811c..7537f32 100644
--- a/src/source.c
+++ b/src/source.c
@@ -2034,8 +2034,10 @@
 };
 #define DISPATCH_KEVENT_TIMEOUT_COUNT \
 		((sizeof(_dispatch_kevent_timeout) / sizeof(_dispatch_kevent_timeout[0])))
-static_assert(DISPATCH_KEVENT_TIMEOUT_COUNT == DISPATCH_TIMER_INDEX_COUNT - 1,
+#if __has_feature(c_static_assert)
+_Static_assert(DISPATCH_KEVENT_TIMEOUT_COUNT == DISPATCH_TIMER_INDEX_COUNT - 1,
 		"should have a kevent for everything but disarm (ddt assumes this)");
+#endif
 
 #define DISPATCH_KEVENT_COALESCING_WINDOW_INIT(qos, ms) \
 		[DISPATCH_TIMER_QOS_##qos] = 2ull * (ms) * NSEC_PER_MSEC
diff --git a/src/swift/Source.swift b/src/swift/Source.swift
index 9dab8f0..801ae71 100644
--- a/src/swift/Source.swift
+++ b/src/swift/Source.swift
@@ -112,7 +112,7 @@
 	}
 #endif
 
-#if !os(Linux)
+#if !os(Linux) && !os(Android)
 	public struct ProcessEvent : OptionSet, RawRepresentable {
 		public let rawValue: UInt
 		public init(rawValue: UInt) { self.rawValue = rawValue }
@@ -170,7 +170,7 @@
 	}
 #endif
 
-#if !os(Linux)
+#if !os(Linux) && !os(Android)
 	public class func makeProcessSource(identifier: pid_t, eventMask: ProcessEvent, queue: DispatchQueue? = nil) -> DispatchSourceProcess {
 		let source = dispatch_source_create(_swift_dispatch_source_type_proc(), UInt(identifier), eventMask.rawValue, queue?.__wrapped)
 		return DispatchSource(source: source) as DispatchSourceProcess
@@ -202,7 +202,7 @@
 		return DispatchSource(source: source) as DispatchSourceUserDataOr
 	}
 
-#if !os(Linux)
+#if !os(Linux) && !os(Android)
 	public class func makeFileSystemObjectSource(fileDescriptor: Int32, eventMask: FileSystemEvent, queue: DispatchQueue? = nil) -> DispatchSourceFileSystemObject {
 		let source = dispatch_source_create(_swift_dispatch_source_type_vnode(), UInt(fileDescriptor), eventMask.rawValue, queue?.__wrapped)
 		return DispatchSource(source: source) as DispatchSourceFileSystemObject
@@ -255,7 +255,7 @@
 }
 #endif
 
-#if !os(Linux)
+#if !os(Linux) && !os(Android)
 public extension DispatchSourceProcess {
 	public var handle: pid_t {
 		return pid_t(dispatch_source_get_handle(self as! DispatchSource))
@@ -299,7 +299,7 @@
 	}
 }
 
-#if !os(Linux)
+#if !os(Linux) && !os(Android)
 public extension DispatchSourceFileSystemObject {
 	public var handle: Int32 {
 		return Int32(dispatch_source_get_handle((self as! DispatchSource).__wrapped))
@@ -368,7 +368,7 @@
 internal func _swift_dispatch_source_type_memorypressure() -> dispatch_source_type_t
 #endif
 
-#if !os(Linux)
+#if !os(Linux) && !os(Android)
 @_silgen_name("_swift_dispatch_source_type_PROC")
 internal func _swift_dispatch_source_type_proc() -> dispatch_source_type_t
 #endif
@@ -382,7 +382,7 @@
 @_silgen_name("_swift_dispatch_source_type_TIMER")
 internal func _swift_dispatch_source_type_timer() -> dispatch_source_type_t
 
-#if !os(Linux)
+#if !os(Linux) && !os(Android)
 @_silgen_name("_swift_dispatch_source_type_VNODE")
 internal func _swift_dispatch_source_type_vnode() -> dispatch_source_type_t
 #endif
diff --git a/src/swift/Wrapper.swift b/src/swift/Wrapper.swift
index deb3c6d..34ccc1b 100644
--- a/src/swift/Wrapper.swift
+++ b/src/swift/Wrapper.swift
@@ -180,7 +180,7 @@
 }
 #endif
 
-#if !os(Linux)
+#if !os(Linux) && !os(Android)
 extension DispatchSource : DispatchSourceProcess,
 	DispatchSourceFileSystemObject {
 }
@@ -268,7 +268,7 @@
 }
 #endif
 
-#if !os(Linux)
+#if !os(Linux) && !os(Android)
 public protocol DispatchSourceProcess : DispatchSourceProtocol {
 	var handle: pid_t { get }
 
@@ -298,7 +298,7 @@
 	func scheduleRepeating(wallDeadline: DispatchWallTime, interval: Double, leeway: DispatchTimeInterval)
 }
 
-#if !os(Linux)
+#if !os(Linux) && !os(Android)
 public protocol DispatchSourceFileSystemObject : DispatchSourceProtocol {
 	var handle: Int32 { get }
 
diff --git a/tests/Foundation/bench.mm b/tests/Foundation/bench.mm
index 613dbb4..c516366 100644
--- a/tests/Foundation/bench.mm
+++ b/tests/Foundation/bench.mm
@@ -20,7 +20,11 @@
 
 #include <Foundation/Foundation.h>
 #include <libkern/OSAtomic.h>
+#ifdef __ANDROID__
+#include <linux/sysctl.h>
+#else
 #include <sys/sysctl.h>
+#endif /* __ANDROID__ */
 #include <mach/mach.h>
 #include <mach/mach_time.h>
 #include <stdio.h>
diff --git a/tests/dispatch_apply.c b/tests/dispatch_apply.c
index ff71fad..85bdf80 100644
--- a/tests/dispatch_apply.c
+++ b/tests/dispatch_apply.c
@@ -27,7 +27,11 @@
 #include <libkern/OSAtomic.h>
 #endif
 #include <sys/types.h>
+#ifdef __ANDROID__
+#include <linux/sysctl.h>
+#else
 #include <sys/sysctl.h>
+#endif /* __ANDROID__ */
 
 #include <bsdtests.h>
 #include "dispatch_test.h"
diff --git a/tests/dispatch_concur.c b/tests/dispatch_concur.c
index ffd42c0..ac62292 100644
--- a/tests/dispatch_concur.c
+++ b/tests/dispatch_concur.c
@@ -24,7 +24,11 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
+#ifdef __ANDROID__
+#include <linux/sysctl.h>
+#else
 #include <sys/sysctl.h>
+#endif /* __ANDROID__ */
 
 #include <bsdtests.h>
 #include "dispatch_test.h"
diff --git a/tests/dispatch_priority.c b/tests/dispatch_priority.c
index 590414e..3cbb7d9 100644
--- a/tests/dispatch_priority.c
+++ b/tests/dispatch_priority.c
@@ -28,7 +28,11 @@
 #include <TargetConditionals.h>
 #endif
 #include <sys/types.h>
+#ifdef __ANDROID__
+#include <linux/sysctl.h>
+#else
 #include <sys/sysctl.h>
+#endif /* __ANDROID__ */
 
 #include <bsdtests.h>
 #include "dispatch_test.h"
diff --git a/tests/dispatch_readsync.c b/tests/dispatch_readsync.c
index aaec909..207e60f 100644
--- a/tests/dispatch_readsync.c
+++ b/tests/dispatch_readsync.c
@@ -22,7 +22,11 @@
 #include <dispatch/private.h>
 #include <stdlib.h>
 #include <unistd.h>
+#ifdef __ANDROID__
+#include <linux/sysctl.h>
+#else
 #include <sys/sysctl.h>
+#endif /* __ANDROID__ */
 #include <assert.h>
 
 #include <bsdtests.h>
diff --git a/tests/dispatch_vm.c b/tests/dispatch_vm.c
index f246acf..6877411 100644
--- a/tests/dispatch_vm.c
+++ b/tests/dispatch_vm.c
@@ -26,7 +26,11 @@
 #include <libkern/OSAtomic.h>
 #endif
 #include <assert.h>
+#ifdef __ANDROID__
+#include <linux/sysctl.h>
+#else
 #include <sys/sysctl.h>
+#endif /* __ANDROID__ */
 #include <stdarg.h>
 #include <time.h>