diff --git a/CoreFoundation/Base.subproj/CFInternal.h b/CoreFoundation/Base.subproj/CFInternal.h index f292ca63e8..7154c1a888 100644 --- a/CoreFoundation/Base.subproj/CFInternal.h +++ b/CoreFoundation/Base.subproj/CFInternal.h @@ -339,6 +339,16 @@ CF_PRIVATE Boolean __CFProcessIsRestricted(); #define STACK_BUFFER_DECL(T, N, C) T N[C] #endif +#ifdef __ANDROID__ +// Avoids crashes on Android +// https://bugs.swift.org/browse/SR-2587 +// https://bugs.swift.org/browse/SR-2588 +// Seemed to be a linker/relocation? problem. +// CFStrings using CONST_STRING_DECL() were not working +// Applies reference to _NSCFConstantString's isa here +// rather than using a linker option to create an alias. +#define __CFConstantStringClassReference _TMC10Foundation19_NSCFConstantString +#endif CF_EXPORT void * __CFConstantStringClassReferencePtr; #if defined(__CONSTANT_CFSTRINGS__) diff --git a/CoreFoundation/Base.subproj/CFPlatform.c b/CoreFoundation/Base.subproj/CFPlatform.c index d0b82a5244..a5c60bc7b4 100644 --- a/CoreFoundation/Base.subproj/CFPlatform.c +++ b/CoreFoundation/Base.subproj/CFPlatform.c @@ -157,7 +157,11 @@ const char *_CFProcessPath(void) { #if DEPLOYMENT_TARGET_LINUX #include +#if __has_include() #include +#else +#include +#endif Boolean _CFIsMainThread(void) { return syscall(SYS_gettid) == getpid(); diff --git a/CoreFoundation/Base.subproj/CFUtilities.c b/CoreFoundation/Base.subproj/CFUtilities.c index e16ab2bdb3..1b66990a56 100644 --- a/CoreFoundation/Base.subproj/CFUtilities.c +++ b/CoreFoundation/Base.subproj/CFUtilities.c @@ -25,6 +25,9 @@ #if DEPLOYMENT_TARGET_WINDOWS #include #endif +#ifdef __ANDROID__ +#include +#endif #include #include #include @@ -764,7 +767,45 @@ void CFLog(CFLogLevel lev, CFStringRef format, ...) { #if DEPLOYMENT_RUNTIME_SWIFT // Temporary as Swift cannot import varag C functions void CFLog1(CFLogLevel lev, CFStringRef message) { +#ifdef __ANDROID__ + android_LogPriority priority = ANDROID_LOG_UNKNOWN; + switch (lev) { + case kCFLogLevelEmergency: priority = ANDROID_LOG_FATAL; break; + case kCFLogLevelAlert: priority = ANDROID_LOG_ERROR; break; + case kCFLogLevelCritical: priority = ANDROID_LOG_ERROR; break; + case kCFLogLevelError: priority = ANDROID_LOG_ERROR; break; + case kCFLogLevelWarning: priority = ANDROID_LOG_WARN; break; + case kCFLogLevelNotice: priority = ANDROID_LOG_WARN; break; + case kCFLogLevelInfo: priority = ANDROID_LOG_INFO; break; + case kCFLogLevelDebug: priority = ANDROID_LOG_DEBUG; break; + } + + if (message == NULL) message = CFSTR("NULL"); + + char stack_buffer[1024] = { 0 }; + char *buffer = &stack_buffer[0]; + CFStringEncoding encoding = kCFStringEncodingUTF8; + CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(message), encoding) + 1; + + if (maxLength > sizeof(stack_buffer) / sizeof(stack_buffer[0])) { + buffer = calloc(sizeof(char), maxLength); + } + + if (maxLength == 1) { + // was crashing with zero length strings + // https://bugs.swift.org/browse/SR-2666 + strcpy(buffer, " "); // log empty string + } + else + CFStringGetCString(message, buffer, maxLength, encoding); + + const char *tag = "Swift"; // process name not available from NDK + __android_log_print(priority, tag, "%s", buffer); + + if (buffer != &stack_buffer[0]) free(buffer); +#else CFLog(lev, CFSTR("%@"), message); +#endif } #endif @@ -1265,7 +1306,7 @@ CFDictionaryRef __CFGetEnvironment() { extern char **environ; char **envp = environ; #elif DEPLOYMENT_TARGET_LINUX -#ifndef environ +#if !defined(environ) && !defined(__ANDROID__) #define environ __environ #endif char **envp = environ; diff --git a/CoreFoundation/Base.subproj/CoreFoundation_Prefix.h b/CoreFoundation/Base.subproj/CoreFoundation_Prefix.h index e930f52b99..08149a7599 100644 --- a/CoreFoundation/Base.subproj/CoreFoundation_Prefix.h +++ b/CoreFoundation/Base.subproj/CoreFoundation_Prefix.h @@ -178,6 +178,11 @@ typedef int boolean_t; #include +#ifdef __ANDROID__ +typedef unsigned long fd_mask; +#endif + +#ifndef __ANDROID__ CF_INLINE size_t strlcpy(char * dst, const char * src, size_t maxlen) { const size_t srclen = strlen(src); @@ -203,6 +208,7 @@ strlcat(char * dst, const char * src, size_t maxlen) { } return dstlen + srclen; } +#endif #define issetugid() 0 diff --git a/CoreFoundation/Base.subproj/SwiftRuntime/CoreFoundation.h b/CoreFoundation/Base.subproj/SwiftRuntime/CoreFoundation.h index 41eb6c16d7..d2776ae147 100644 --- a/CoreFoundation/Base.subproj/SwiftRuntime/CoreFoundation.h +++ b/CoreFoundation/Base.subproj/SwiftRuntime/CoreFoundation.h @@ -39,6 +39,10 @@ #include #include +#if __has_include() +#include // for NSHost.swift +#endif + #if defined(__STDC_VERSION__) && (199901L <= __STDC_VERSION__) #include diff --git a/CoreFoundation/NumberDate.subproj/CFTimeZone.c b/CoreFoundation/NumberDate.subproj/CFTimeZone.c index 451ab8da71..63b5ea80b3 100644 --- a/CoreFoundation/NumberDate.subproj/CFTimeZone.c +++ b/CoreFoundation/NumberDate.subproj/CFTimeZone.c @@ -32,7 +32,11 @@ #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD #include #include +#if __has_include() #include +#else +#include +#endif #endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED #include diff --git a/CoreFoundation/PlugIn.subproj/CFBundle_InfoPlist.c b/CoreFoundation/PlugIn.subproj/CFBundle_InfoPlist.c index 31a40a15c1..f9a053a369 100644 --- a/CoreFoundation/PlugIn.subproj/CFBundle_InfoPlist.c +++ b/CoreFoundation/PlugIn.subproj/CFBundle_InfoPlist.c @@ -25,7 +25,9 @@ #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_FREEBSD #include +#if __has_include() #include +#endif #include #endif diff --git a/CoreFoundation/PlugIn.subproj/CFBundle_Resources.c b/CoreFoundation/PlugIn.subproj/CFBundle_Resources.c index db73b4d5a5..620123c248 100644 --- a/CoreFoundation/PlugIn.subproj/CFBundle_Resources.c +++ b/CoreFoundation/PlugIn.subproj/CFBundle_Resources.c @@ -33,7 +33,9 @@ #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX #include +#if __has_include() #include +#endif #include #include #endif diff --git a/CoreFoundation/URL.subproj/CFURL.c b/CoreFoundation/URL.subproj/CFURL.c index 8fd1e31ba1..408714ec95 100644 --- a/CoreFoundation/URL.subproj/CFURL.c +++ b/CoreFoundation/URL.subproj/CFURL.c @@ -30,7 +30,11 @@ #include #include #include +#if __has_include() #include +#else +#include +#endif #include #endif diff --git a/Foundation/NSData.swift b/Foundation/NSData.swift index 2c44b61406..813b6ab864 100644 --- a/Foundation/NSData.swift +++ b/Foundation/NSData.swift @@ -423,7 +423,7 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding { repeat { #if os(OSX) || os(iOS) bytesWritten = Darwin.write(fd, buf.advanced(by: length - bytesRemaining), bytesRemaining) - #elseif os(Linux) + #elseif os(Linux) || os(Android) bytesWritten = Glibc.write(fd, buf.advanced(by: length - bytesRemaining), bytesRemaining) #endif } while (bytesWritten < 0 && errno == EINTR) @@ -444,7 +444,7 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding { // Preserve permissions. var info = stat() if lstat(path, &info) == 0 { - mode = info.st_mode + mode = mode_t(info.st_mode) } else if errno != ENOENT && errno != ENAMETOOLONG { throw _NSErrorWithErrno(errno, reading: false, path: path) } diff --git a/Foundation/NSFileHandle.swift b/Foundation/NSFileHandle.swift index 8e75b6c485..6339808664 100644 --- a/Foundation/NSFileHandle.swift +++ b/Foundation/NSFileHandle.swift @@ -71,11 +71,11 @@ open class FileHandle : NSObject, NSSecureCoding { } } } else { - let offset = lseek(_fd, 0, L_INCR) + let offset = lseek(_fd, 0, SEEK_CUR) if offset < 0 { fatalError("Unable to fetch current file offset") } - if statbuf.st_size > offset { + if off_t(statbuf.st_size) > offset { var remaining = size_t(statbuf.st_size - offset) remaining = min(remaining, size_t(length)) @@ -128,19 +128,19 @@ open class FileHandle : NSObject, NSSecureCoding { // TODO: Error handling. open var offsetInFile: UInt64 { - return UInt64(lseek(_fd, 0, L_INCR)) + return UInt64(lseek(_fd, 0, SEEK_CUR)) } open func seekToEndOfFile() -> UInt64 { - return UInt64(lseek(_fd, 0, L_XTND)) + return UInt64(lseek(_fd, 0, SEEK_END)) } open func seek(toFileOffset offset: UInt64) { - lseek(_fd, off_t(offset), L_SET) + lseek(_fd, off_t(offset), SEEK_SET) } open func truncateFile(atOffset offset: UInt64) { - if lseek(_fd, off_t(offset), L_SET) == 0 { + if lseek(_fd, off_t(offset), SEEK_SET) == 0 { ftruncate(_fd, off_t(offset)) } } diff --git a/Foundation/NSFileManager.swift b/Foundation/NSFileManager.swift index 171208890b..f496b105b7 100644 --- a/Foundation/NSFileManager.swift +++ b/Foundation/NSFileManager.swift @@ -13,6 +13,12 @@ import Glibc #endif +#if os(Android) // struct stat.st_mode is UInt32 +internal func &(left: UInt32, right: mode_t) -> mode_t { + return mode_t(left) & right +} +#endif + import CoreFoundation open class FileManager : NSObject { @@ -123,10 +129,10 @@ open class FileManager : NSObject { } #if os(OSX) || os(iOS) let modeT = number.uint16Value - #elseif os(Linux) + #elseif os(Linux) || os(Android) let modeT = number.uint32Value #endif - if chmod(path, modeT) != 0 { + if chmod(path, mode_t(modeT)) != 0 { fatalError("errno \(errno)") } } else { @@ -246,11 +252,11 @@ open class FileManager : NSObject { } #if os(OSX) || os(iOS) let tempEntryType = entryType - #elseif os(Linux) + #elseif os(Linux) || os(Android) let tempEntryType = Int(entryType) #endif - if tempEntryType == DT_DIR { + if tempEntryType == Int(DT_DIR) { let subPath: String = path + "/" + entryName let entries = try subpathsOfDirectory(atPath: subPath) @@ -279,6 +285,8 @@ open class FileManager : NSObject { #if os(OSX) || os(iOS) let ti = (TimeInterval(s.st_mtimespec.tv_sec) - kCFAbsoluteTimeIntervalSince1970) + (1.0e-9 * TimeInterval(s.st_mtimespec.tv_nsec)) +#elseif os(Android) + let ti = (TimeInterval(s.st_mtime) - kCFAbsoluteTimeIntervalSince1970) + (1.0e-9 * TimeInterval(s.st_mtime_nsec)) #else let ti = (TimeInterval(s.st_mtim.tv_sec) - kCFAbsoluteTimeIntervalSince1970) + (1.0e-9 * TimeInterval(s.st_mtim.tv_nsec)) #endif @@ -361,7 +369,7 @@ open class FileManager : NSObject { throw _NSErrorWithErrno(errno, reading: true, path: path) } - return self.string(withFileSystemRepresentation: buf, length: len) + return self.string(withFileSystemRepresentation: buf, length: Int(len)) } open func copyItem(atPath srcPath: String, toPath dstPath: String) throws { diff --git a/Foundation/NSLocale.swift b/Foundation/NSLocale.swift index b1230d5026..8c7628a929 100644 --- a/Foundation/NSLocale.swift +++ b/Foundation/NSLocale.swift @@ -18,7 +18,7 @@ open class NSLocale: NSObject, NSCopying, NSSecureCoding { private var _prefs: UnsafeMutableRawPointer? = nil #if os(OSX) || os(iOS) private var _lock = pthread_mutex_t() -#elseif os(Linux) +#elseif os(Linux) || os(Android) private var _lock = Int32(0) #endif private var _nullLocale = false diff --git a/Foundation/NSObjCRuntime.swift b/Foundation/NSObjCRuntime.swift index 9c5abf58f9..4a7f052712 100644 --- a/Foundation/NSObjCRuntime.swift +++ b/Foundation/NSObjCRuntime.swift @@ -196,6 +196,9 @@ internal func NSRequiresConcreteImplementation(_ fn: String = #function, file: S } internal func NSUnimplemented(_ fn: String = #function, file: StaticString = #file, line: UInt = #line) -> Never { + #if os(Android) + NSLog("\(fn) is not yet implemented. \(file):\(line)") + #endif fatalError("\(fn) is not yet implemented", file: file, line: line) } diff --git a/Foundation/NSOperation.swift b/Foundation/NSOperation.swift index 248f0255e7..a62b847830 100644 --- a/Foundation/NSOperation.swift +++ b/Foundation/NSOperation.swift @@ -9,7 +9,7 @@ #if DEPLOYMENT_ENABLE_LIBDISPATCH import Dispatch -#if os(Linux) +#if os(Linux) || os(Android) import CoreFoundation private func pthread_main_np() -> Int32 { return _CFIsMainThread() ? 1 : 0 diff --git a/Foundation/NSSwiftRuntime.swift b/Foundation/NSSwiftRuntime.swift index 1e8122c2dd..d7b368f66f 100644 --- a/Foundation/NSSwiftRuntime.swift +++ b/Foundation/NSSwiftRuntime.swift @@ -14,10 +14,16 @@ import CoreFoundation // This mimics the behavior of the swift sdk overlay on Darwin #if os(OSX) || os(iOS) @_exported import Darwin -#elseif os(Linux) +#elseif os(Linux) || os(Android) @_exported import Glibc #endif +#if os(Android) // shim required for bzero +@_transparent func bzero(_ ptr: UnsafeMutableRawPointer, _ size: size_t) { + memset(ptr, 0, size) +} +#endif + public typealias ObjCBool = Bool internal class __NSCFType : NSObject { diff --git a/Foundation/NSTask.swift b/Foundation/NSTask.swift index 5f4248d2d3..f4078b7f1c 100644 --- a/Foundation/NSTask.swift +++ b/Foundation/NSTask.swift @@ -7,6 +7,7 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // +#if !os(Android) // not available import CoreFoundation #if os(OSX) || os(iOS) @@ -455,3 +456,4 @@ private func posix(_ code: Int32) { default: fatalError("POSIX command failed with error: \(code)") } } +#endif diff --git a/Foundation/NSThread.swift b/Foundation/NSThread.swift index 2027af5d25..11f49654b0 100644 --- a/Foundation/NSThread.swift +++ b/Foundation/NSThread.swift @@ -133,7 +133,7 @@ open class Thread : NSObject { internal var _main: (Void) -> Void = {} #if os(OSX) || os(iOS) private var _thread: pthread_t? = nil -#elseif os(Linux) +#elseif os(Linux) || os(Android) private var _thread = pthread_t() #endif internal var _attr = pthread_attr_t() diff --git a/Foundation/NSURL.swift b/Foundation/NSURL.swift index 417ddb1e65..9a4dc8e346 100644 --- a/Foundation/NSURL.swift +++ b/Foundation/NSURL.swift @@ -496,7 +496,7 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying { open var password: String? { let absoluteURL = CFURLCopyAbsoluteURL(_cfObject) -#if os(Linux) +#if os(Linux) || os(Android) let passwordRange = CFURLGetByteRangeForComponent(absoluteURL, kCFURLComponentPassword, nil) #else let passwordRange = CFURLGetByteRangeForComponent(absoluteURL, .password, nil) diff --git a/Foundation/NSXMLNode.swift b/Foundation/NSXMLNode.swift index aaf63c56a0..28f5e80ece 100644 --- a/Foundation/NSXMLNode.swift +++ b/Foundation/NSXMLNode.swift @@ -83,7 +83,7 @@ open class XMLNode: NSObject, NSCopying { public static let nodePromoteSignificantWhitespace = Options(rawValue: 1 << 28) public static let nodePreserveEmptyElements = Options([.nodeExpandEmptyElement, .nodeCompactEmptyElement]) public static let nodePreserveQuotes = Options([.nodeUseSingleQuotes, .nodeUseDoubleQuotes]) - public static let nodePreserveAll = Options(rawValue: Options([.nodePreserveNamespaceOrder, .nodePreserveAttributeOrder, .nodePreserveEntities, .nodePreservePrefixes, .nodePreserveCDATA, .nodePreserveEmptyElements, .nodePreserveQuotes, .nodePreserveWhitespace, .nodePreserveDTD, .nodePreserveCharacterReferences]).rawValue | UInt(bitPattern: 0xFFF00000)) + public static let nodePreserveAll = Options(rawValue: 0xFFF00000).union([.nodePreserveNamespaceOrder, .nodePreserveAttributeOrder, .nodePreserveEntities, .nodePreservePrefixes, .nodePreserveCDATA, .nodePreserveEmptyElements, .nodePreserveQuotes, .nodePreserveWhitespace, .nodePreserveDTD, .nodePreserveCharacterReferences]) } open override func copy() -> Any { diff --git a/android/README.md b/android/README.md new file mode 100644 index 0000000000..ef274b1b07 --- /dev/null +++ b/android/README.md @@ -0,0 +1,51 @@ + +## Android Port of Foundation module + +This directory contains scripts used in the port of Foundation to +an Android toolchain. The short version of the story is that after +downloading the swift sources use the script "prepare.sh" in this +directory to install prebuilt binaries and headers for libxml, +libcurl and libdispatch then run the script "builder.sh". + +This build requires the path to a [r12 Android NDK](http://developer.android.com/ndk/downloads/index.html) in the +`ANDROID_NDK_HOME` environment variable and the path to the +android port of the "icu" libraries in `ANDROID_ICU_UC` +downloaded from [here](https://github.com/SwiftAndroid/libiconv-libicu-android/releases/download/android-ndk-r12/libiconv-libicu-armeabi-v7a-ubuntu-15.10-ndk-r12.tar.gz). +The port was tested against api 21 on a Android v5.1.1 LG K4 Phone (Lollipop) +and requires an Ubuntu 15 host with the Android NDK Gold linker from +`toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/arm-linux-androideabi/bin` installed as /usr/bin/ld.gold. + +The pre-built binaries were built from the following repos: + +[https://github.com/curl/curl](https://github.com/curl/curl) + +[https://github.com/android/platform_external_libxml2](https://github.com/android/platform_external_libxml2) + +[https://github.com/apple/swift-corelibs-libdispatch](https://github.com/apple/swift-corelibs-libdispatch) + +[https://github.com/mheily/libpwq](https://github.com/mheily/libpwq) + +[https://github.com/mheily/libkqueue](https://github.com/mheily/libkqueue) + +To build these the recipe was generally the same. autogen or configure +for Linux then alter their Makefiles to have CFLAGS = include: --target=armv7-none-linux-androideabi --sysroot=$(ANDROID_NDK_HOME)/platforms/android-21/arch-arm. + +There is a known issue when libdispatch background tasks exit +they will cause an exception as DetachCurrentThread has not +been called. To avoid this your app must include the line: + + DispatchGroup.threadCleanupCallback = JNI_DetachCurrentThread + +JNI_DetachCurrentThread is available in the package java_swift +available here: https://github.com/SwiftJava/java_swift + +Pre-built binaries of an Swift compiler with support for Android +including Foundation available here: + +http://johnholdsworth.com/android_toolchain.tgz + +### Other resources + +Check out the [SwiftAndroid](https://github.com/SwiftAndroid) and +[SwiftJava](https://github.com/SwiftJava) github projects for +starter Android applications and resources. diff --git a/android/builder.sh b/android/builder.sh new file mode 100755 index 0000000000..d00b8dad50 --- /dev/null +++ b/android/builder.sh @@ -0,0 +1,21 @@ +#!/bin/bash -x +# +# Build Android toolchain including Foundation +# + +cd "$(dirname $0)" && +#./prepare.sh && +./install.sh -u && + +pushd "../../swift" && +./utils/build-script \ + -R --skip-build-libdispatch --foundation \ + --android \ + --android-ndk "${ANDROID_NDK_HOME:?Please set ANDROID_NDK_HOME to path to an Android NDK downloaded from http://developer.android.com/ndk/downloads/index.html}" \ + --android-api-level 21 \ + --android-icu-uc "${ANDROID_ICU_UC:?Please set ANDROID_ICU_UC to path to Android ICU downloaded from https://github.com/SwiftAndroid/libiconv-libicu-android/releases/download/android-ndk-r12/libiconv-libicu-armeabi-v7a-ubuntu-15.10-ndk-r12.tar.gz}/armeabi-v7a" \ + --android-icu-uc-include "${ANDROID_ICU_UC}/armeabi-v7a/icu/source/common" \ + --android-icu-i18n "${ANDROID_ICU_UC}/armeabi-v7a" \ + --android-icu-i18n-include "${ANDROID_ICU_UC}/armeabi-v7a/icu/source/i18n" && + +popd && ./install.sh diff --git a/android/install.sh b/android/install.sh new file mode 100755 index 0000000000..c724695771 --- /dev/null +++ b/android/install.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Simple script to move Android Foundation into toolchain +# To build it again after this, use install.sh -u to reset +# + +cd "$(dirname $0)" + +SWIFT_ROOT="$(dirname $(dirname $(which swiftc)))" +BUILD_DIR="$(dirname $SWIFT_ROOT)" + +if [[ "$1" == "-u" ]]; then + rm -rf "${SWIFT_ROOT}/lib/swift/CoreFoundation" + exit +fi + +\cp -v "${BUILD_DIR}/foundation-linux-x86_64/Foundation/libFoundation.so" "${SWIFT_ROOT}/lib/swift/android" && + +\cp -v "${BUILD_DIR}/foundation-linux-x86_64/Foundation/Foundation.swift"* "${SWIFT_ROOT}/lib/swift/android/armv7" && + +rsync -arv "${BUILD_DIR}/foundation-linux-x86_64/Foundation/usr/lib/swift/CoreFoundation" "${SWIFT_ROOT}/lib/swift/" diff --git a/android/package.sh b/android/package.sh new file mode 100755 index 0000000000..4657c49ca1 --- /dev/null +++ b/android/package.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# +# Prepare binary package used to build Foundation for Android +# + +cd "$(dirname $0)" && +TAR_FILE="$(pwd)/android_dispatch" && + +cd "../../platform_external_libxml2/include" && +tar cf "$TAR_FILE.tar" libxml && + +cd "../../curl/include" && +tar rf "$TAR_FILE.tar" curl && + +cd "$(dirname $(dirname $(which swiftc)))/lib/swift" && + +tar rf "$TAR_FILE.tar" dispatch android/lib{xml2,curl,dispatch}.so android/armv7/Dispatch.swift* && + +gzip "$TAR_FILE.tar" && +\mv "$TAR_FILE.tar.gz" "$TAR_FILE.tgz" && + +tar tfvz "$TAR_FILE.tgz" diff --git a/android/prepare.sh b/android/prepare.sh new file mode 100755 index 0000000000..5e3ce2d7d2 --- /dev/null +++ b/android/prepare.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# +# Prepare swift sourcerelease to build Foundation for Android +# + +BUILD_DIR="build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift" + +cd "$(dirname $0)" && +TAR_FILE="$(pwd)/android_dispatch.tgz" && + +if [[ ! -f "${TAR_FILE}" ]]; then + echo "Fetching binaries and headers for libxml2, libcurl and libdispatch" + curl "https://raw.githubusercontent.com/SwiftJava/SwiftJava/master/android_dispatch.tgz" > "${TAR_FILE}" +fi + +cd "../.." && mkdir -p "${BUILD_DIR}" && +cd "${BUILD_DIR}" && tar xfvz "${TAR_FILE}" diff --git a/android/updater.sh b/android/updater.sh new file mode 100755 index 0000000000..1dcd2c7107 --- /dev/null +++ b/android/updater.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# +# Move freshly built dependencies for Foundation into +# build directory to be available for it's compilation. +# +# libxml2.so built from the android platform port: +# https://github.com/android/platform_external_libxml2 +# +# This is the most useful page found but it's not complete +# http://stackoverflow.com/questions/12052089/using-libxml-for-android +# Don't set CFLAGS or LDFLAGS and use ./autogen.sh instead of "configure" +# Remove HTMLparser.lo and HTMLtree.lo from the Makefile and make sure +# LIBXML_HTML_ENABLED and LIBXML_ICONV_ENABLED were not enabled in file +# "include/libxml/xmlversion.h". Add the following to CFLAGS in Makefile: +# -nostdlib --target=armv7-none-linux-androideabi +# --sysroot=$ANDROID_NDK/platforms/android-21/arch-arm +# +# libcurl.so is built similarly from https://github.com/curl/curl +# +# libdispatch.so is a difficult build soon to be automated by another PR. +# + +ANDROID_ICU_UC="${ANDROID_ICU_UC:-$HOME/libiconv-libicu-android}" + +cd "$(dirname $0)" && + +SWIFT_ROOT="$(dirname $(dirname $(which swiftc)))" && +BUILD_DIR="$(dirname $SWIFT_ROOT)" && + +\cp -v ../../platform_external_libxml2/libxml2.so ../../curl/libcurl.so ../../swift-corelibs-libdispatch/libdispatch.so "$ANDROID_ICU_UC"/armeabi-v7a/libicu*.so "${SWIFT_ROOT}/lib/swift/android" && + +\cp -v "${BUILD_DIR}/libdispatch-linux-x86_64/src/swift/Dispatch.swift"* "${SWIFT_ROOT}/lib/swift/android/armv7" && + +rsync -arv "../../swift-corelibs-libdispatch/dispatch" "${SWIFT_ROOT}/lib/swift/" && + +\cp -v "../../swift-corelibs-libdispatch/private/"*.h "${SWIFT_ROOT}/lib/swift/dispatch" && + +rpl -R -e libicu libscu "${SWIFT_ROOT}/lib/swift/android"/lib{icu,swift,Foundation,xml2}*.so && + +for i in "${SWIFT_ROOT}/lib/swift/android"/libicu*.so; do \mv -f $i ${i/libicu/libscu}; done diff --git a/build.py b/build.py index 876ee85cdf..0f22a9898a 100644 --- a/build.py +++ b/build.py @@ -75,7 +75,16 @@ '-I${SYSROOT}/usr/include/curl' ] -foundation.LDFLAGS += '-lpthread -ldl -lm -lswiftCore -lxml2 -lcurl ' +triple = Configuration.current.target.triple +if triple == "x86_64-linux-gnu" or triple == "armv7-none-linux-androideabi": + foundation.LDFLAGS += '-lcurl ' + +if triple == "armv7-none-linux-androideabi": + foundation.LDFLAGS += '-llog ' +else: + foundation.LDFLAGS += '-lpthread ' + +foundation.LDFLAGS += '-ldl -lm -lswiftCore -lxml2 ' # Configure use of Dispatch in CoreFoundation and Foundation if libdispatch is being built if "LIBDISPATCH_SOURCE_DIR" in Configuration.current.variables: diff --git a/lib/target.py b/lib/target.py index 5374c7669a..d9ff613c4d 100644 --- a/lib/target.py +++ b/lib/target.py @@ -380,7 +380,10 @@ def swift_triple(self): elif self.sdk == OSType.Linux: # FIXME: It would be nice to detect the host ABI here if (self.arch == ArchType.armv6) or (self.arch == ArchType.armv7): - triple += "-unknown-linux-gnueabihf" + if Configuration.current.target.triple == "armv7-none-linux-androideabi": + triple = Configuration.current.target.triple + else: + triple += "-unknown-linux-gnueabihf" else: triple += "-unknown-linux" elif self.sdk == OSType.FreeBSD: