-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Port of Foundation to Android #622
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fc14279
80f82ae
bbd66a4
21457d1
6c904b9
9237e8d
0fdf620
4fa36dd
23ad327
83e5800
2e25c71
8e24456
a0457a5
604718e
9bc98b0
546cad2
60e6b73
6213cba
bc4cabb
5fe1c8c
6858ae8
e15e240
759eca6
ffe852b
a82e390
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,9 @@ | |
#if DEPLOYMENT_TARGET_WINDOWS | ||
#include <process.h> | ||
#endif | ||
#ifdef __ANDROID__ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @parkera should we perhaps instead of using macros defined by the compiler use a DEPLOYMENT_TARGET_ANDROID for these? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can change it back if you like. |
||
#include <android/log.h> | ||
#endif | ||
#include <math.h> | ||
#include <string.h> | ||
#include <stdio.h> | ||
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should check calloc() return value There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Too late now... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not too late - open up another PR. =) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright already, new PR #655 |
||
} | ||
|
||
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__) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this right? Do you really intend to leave environ undefined on Android? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe So in theory this additional There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. environ is already defined on Android. No need to redefine it to __environ. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this change can be reverted, yes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I’m saying it’s needed, honest! Full code is: #elif DEPLOYMENT_TARGET_LINUX There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused, if environ is already defined in Android, then the second half of your #if is never evaluated; if environ is undefined in Android, then what is envp on Android? Am I missing something? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. envrion is a C symbol on Android not a #define for the preprocessor so you can’t test for whether it exists with a #ifdef. It must be a #define on some other architectures. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it. |
||
#define environ __environ | ||
#endif | ||
char **envp = environ; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -178,6 +178,11 @@ typedef int boolean_t; | |
|
||
#include <pthread.h> | ||
|
||
#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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is fd_mask defined in an else clause with definitions of strlcpy/strlcat? Are the two related in some way that I am missing? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I’m just saving a line. I’ll separate them. |
||
|
||
#define issetugid() 0 | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,12 @@ | |
import Glibc | ||
#endif | ||
|
||
#if os(Android) // struct stat.st_mode is UInt32 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here too, does this also apply to Linux? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems to be an Android NDK specific thing |
||
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 { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did we add an NSLog here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fatalError() doesn’t print anything on Android (asserts do). Just giving people a pointer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't fatalError call __android_log_print on android? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should but this is a Foundation PR. I’ll take a look. Annoyingly, using __android_log_print requires a -llog when you link so it wouldn’t be a trivial change. Looks like a change to https://github.com/apple/swift/blob/master/stdlib/public/runtime/Errors.cpp#L204 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
fatalError("\(fn) is not yet implemented", file: file, line: line) | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
|
||
#if !os(Android) // not available | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still not happy about this. Is there a way, instead, to mark the class as unavailable on the Android platform? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you tell me the syntax to specify a NSTask unavailable for android please. I’ll make the class unavailable and #if !os(Android) out it’s methods or would they not try to compile if marked unavailable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Had a quick look at removing the #if !os(Android), got the following: Foundation/NSTask.swift:95:2: warning: unknown platform 'Android' for attribute 'available' There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does it take to add Android as a platform for the compiler to understand here? That may be a prereq to anyone doing anything meaningful on Android in the first place. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this means adding Android to the list of platforms that the Swift compiler knows about. Adding that (and maybe some other tweaks) should allow us to write There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It’s odd. The compiler knows about #if os(Android) giving an error if you mistype it but not @available(Android, unavailable). Can it be the list you mention as Linux is not on it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's a good point. I'm not 100% sure -- I just grepped around, found that spot, and thought it looked interesting. :) If adding Android to that list is indeed what @parkera had in mind, we could email the swift-dev mailing list to learn more about it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @parkera is having There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Jira https://bugs.swift.org/browse/SR-2670 has a response - currently not implemented. |
||
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the previous header does not exist what is to say the sys/syscall version exists? Perhaps that should be gated as well and #error'd on the else claiming that syscall.h is required
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
won’t it error anyway? It doesn’t fail silently or anything anti-social. This just improves the odds. I can gate it if you want.