Last active
November 7, 2015 20:48
-
-
Save joakim-noah/5d399fdcd5e484d6aaa2 to your computer and use it in GitHub Desktop.
Android support for phobos
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/osmodel.mak b/osmodel.mak | |
index f56716a..79cc523 100644 | |
--- a/osmodel.mak | |
+++ b/osmodel.mak | |
@@ -49,4 +49,4 @@ ifeq (,$(MODEL)) | |
endif | |
endif | |
-MODEL_FLAG:=-m$(MODEL) | |
+MODEL_FLAG:=-m$(MODEL)android | |
diff --git a/posix.mak b/posix.mak | |
index 5e25eb7..3721e1f 100644 | |
--- a/posix.mak | |
+++ b/posix.mak | |
@@ -86,13 +86,16 @@ else | |
ifeq ($(OS),win32) | |
CC = dmc | |
else | |
- CC = cc | |
+ CC = $(NDK)/toolchains/llvm-3.6/prebuilt/linux-x86/bin/clang | |
endif | |
RUN = | |
endif | |
-# Set CFLAGS | |
-CFLAGS=$(MODEL_FLAG) -fPIC -DHAVE_UNISTD_H | |
+# Set CFLAGS and LDFLAGS | |
+LINKC=$(NDK)/toolchains/x86-4.9/prebuilt/linux-x86/bin/i686-linux-android-gcc | |
+CFLAGS=$(MODEL_FLAG) -fPIC -DHAVE_UNISTD_H -gcc-toolchain $(NDK)/toolchains/x86-4.8/prebuilt/linux-x86 -target i686-none-linux-android -ffunction-sections -funwind-tables -fstack-protector-strong -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -no-canonical-prefixes -O2 -g -DNDEBUG -fomit-frame-pointer -fstrict-aliasing -I$(NDK)/sources/android/native_app_glue -Ijni -DANDROID -Wa,--noexecstack -Wformat -Werror=format-security -I$(NDK)/platforms/android-9/arch-x86/usr/include | |
+# LDFLAGS=-Wl,-z,nocopyreloc --sysroot=$(NDK)/platforms/android-9/arch-x86 -lgcc -gcc-toolchain $(NDK)/toolchains/x86-4.8/prebuilt/linux-x86 -target i686-none-linux-android -no-canonical-prefixes -fuse-ld=bfd -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--export-dynamic -lc -lm | |
+LDFLAGS=-Wl,-z,nocopyreloc --sysroot=$(NDK)/platforms/android-9/arch-x86 -lgcc -no-canonical-prefixes -fuse-ld=bfd -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--export-dynamic -lc -lm | |
ifeq ($(BUILD),debug) | |
CFLAGS += -g | |
else | |
@@ -244,7 +247,7 @@ OBJS = $(addsuffix $(DOTOBJ),$(addprefix $(ROOT)/,$(C_MODULES))) | |
MAKEFILE = $(firstword $(MAKEFILE_LIST)) | |
# build with shared library support (defaults to true on supported platforms) | |
-SHARED=$(if $(findstring $(OS),linux freebsd),1,) | |
+SHARED=$(if $(findstring $(OS),freebsd),1,) | |
################################################################################ | |
# Rules begin here | |
@@ -331,7 +334,8 @@ ifneq (1,$(SHARED)) | |
$(UT_D_OBJS): $(DRUNTIME) | |
$(ROOT)/unittest/test_runner: $(DRUNTIME_PATH)/src/test_runner.d $(UT_D_OBJS) $(OBJS) $(DRUNTIME) | |
- $(DMD) $(DFLAGS) -unittest -of$@ $(DRUNTIME_PATH)/src/test_runner.d $(UT_D_OBJS) $(OBJS) $(DRUNTIME) $(LINKDL) -defaultlib= -debuglib= | |
+ $(DMD) $(DFLAGS) -unittest -c -oftest_runner.o $(DRUNTIME_PATH)/src/test_runner.d | |
+ $(LINKC) $(LDFLAGS) test_runner.o $(UT_D_OBJS) $(OBJS) $(DRUNTIME) -o ./test_runner | |
else | |
diff --git a/std/datetime.d b/std/datetime.d | |
index 937272a..03e649d 100644 | |
--- a/std/datetime.d | |
+++ b/std/datetime.d | |
@@ -28179,7 +28179,15 @@ public: | |
} | |
- version(Posix) | |
+ version(Android) | |
+ { | |
+ // One of two directories where the single file and possibly index | |
+ // containing timezone data may be, though I've only found them in | |
+ // this directory. | |
+ //import std.process; | |
+ enum defaultTZDatabaseDir = "/system/usr/share/zoneinfo/"; | |
+ } | |
+ else version(Posix) | |
{ | |
/++ | |
The default directory where the TZ Database files are. It's empty | |
@@ -28234,13 +28242,21 @@ public: | |
enforce(tzDatabaseDir.exists(), new DateTimeException(format("Directory %s does not exist.", tzDatabaseDir))); | |
enforce(tzDatabaseDir.isDir, new DateTimeException(format("%s is not a directory.", tzDatabaseDir))); | |
+ version(Android){ | |
+ auto tzOffset = name in tzdataIndex(tzDatabaseDir); | |
+ enforce(tzOffset, new DateTimeException(format("%s is not a zone.", name))); | |
+ string tzFilename = separate_index ? "zoneinfo.dat" : "tzdata"; | |
+ const file = asNormalizedPath(chainPath(tzDatabaseDir, tzFilename)).to!string; | |
+ } | |
+ else | |
const file = asNormalizedPath(chainPath(tzDatabaseDir, name)).to!string; | |
enforce(file.exists(), new DateTimeException(format("File %s does not exist.", file))); | |
enforce(file.isFile, new DateTimeException(format("%s is not a file.", file))); | |
auto tzFile = File(file); | |
- immutable gmtZone = file.representation().canFind("GMT"); | |
+ version(Android) tzFile.seek(*tzOffset); | |
+ immutable gmtZone = name.representation().canFind("GMT"); | |
try | |
{ | |
@@ -28424,8 +28440,11 @@ public: | |
auto posixEnvStr = tzFile.readln().strip(); | |
+ version(Android){} else | |
+ { | |
_enforceValidTZFile(tzFile.readln().strip().empty); | |
_enforceValidTZFile(tzFile.eof); | |
+ } | |
auto transitionTypes = new TransitionType*[](tempTTInfos.length); | |
@@ -28574,6 +28593,10 @@ public: | |
auto timezones = appender!(string[])(); | |
+ version(Android) { | |
+ import std.algorithm : each; | |
+ tzdataIndex(tzDatabaseDir).keys.each!(a => {if(a.startsWith(subName)) timezones.put(a);}); | |
+ } else { | |
foreach(DirEntry dentry; dirEntries(tzDatabaseDir, SpanMode.depth)) | |
{ | |
if(dentry.isFile) | |
@@ -28590,6 +28613,7 @@ public: | |
timezones.put(tzName); | |
} | |
} | |
+ } | |
sort(timezones.data); | |
@@ -28617,7 +28641,7 @@ public: | |
foreach(tzName; tzNames) | |
assertNotThrown!DateTimeException(testPTZSuccess(tzName)); | |
- foreach(DirEntry dentry; dirEntries(defaultTZDatabaseDir, SpanMode.depth)) | |
+ version(Android) {} else foreach(DirEntry dentry; dirEntries(defaultTZDatabaseDir, SpanMode.depth)) | |
{ | |
if(dentry.isFile) | |
{ | |
@@ -28846,6 +28870,60 @@ private: | |
_hasDST = hasDST; | |
} | |
+ version(Android) | |
+ { | |
+ static bool separate_index; | |
+ | |
+ static uint[string] tzdataIndex(string tzDir) | |
+ { | |
+ import std.format : format; | |
+ import std.path : asNormalizedPath, chainPath; | |
+ import std.conv : to; | |
+ | |
+ static uint[string] _tzIndex; | |
+ static _extractIndex = true; | |
+ | |
+ if(_extractIndex) | |
+ { | |
+ const combinedFile = asNormalizedPath(chainPath(tzDir, "tzdata")).to!string; | |
+ const indexFile = asNormalizedPath(chainPath(tzDir, "zoneinfo.idx")).to!string; | |
+ File tzFile; | |
+ uint indexEntries, dataOffset; | |
+ if(combinedFile.exists() && combinedFile.isFile) | |
+ { | |
+ tzFile = File(combinedFile); | |
+ _enforceValidTZFile(readVal!(char[])(tzFile, 6) == "tzdata"); | |
+ auto tzDataVersion = readVal!(char[])(tzFile, 6); | |
+ _enforceValidTZFile(tzDataVersion[5] == '\0'); | |
+ auto index_off = readVal!uint(tzFile); | |
+ dataOffset = readVal!uint(tzFile); | |
+ readVal!uint(tzFile); | |
+ indexEntries = (dataOffset - index_off)/52; | |
+ separate_index = false; | |
+ } | |
+ else if(indexFile.exists() && indexFile.isFile) | |
+ { | |
+ tzFile = File(indexFile); | |
+ indexEntries = cast(uint)(tzFile.size/52); | |
+ separate_index = true; | |
+ } | |
+ else | |
+ throw new DateTimeException(format("Files %s and %s do not exist.", combinedFile, indexFile)); | |
+ | |
+ foreach(i; 0 .. indexEntries) { | |
+ import std.conv: to; | |
+ auto tzName = to!string(readVal!(char[])(tzFile, 40).ptr); | |
+ auto tzOffset = readVal!uint(tzFile); | |
+ auto name_length = readVal!uint(tzFile); | |
+ readVal!uint(tzFile); | |
+ _tzIndex[tzName] = dataOffset + tzOffset; | |
+ } | |
+ _extractIndex = false; | |
+ } | |
+ return _tzIndex; | |
+ } | |
+ } | |
+ | |
/// List of times when the utc offset changes. | |
immutable Transition[] _transitions; | |
@@ -29340,6 +29418,9 @@ else version(Posix) | |
import core.sys.posix.stdlib : setenv; | |
import core.sys.posix.time : tzset; | |
+ version(Android) | |
+ auto value = asNormalizedPath(tzDatabaseName); | |
+ else | |
auto value = asNormalizedPath(chainPath(PosixTimeZone.defaultTZDatabaseDir, tzDatabaseName)); | |
setenv("TZ", value.tempCString(), 1); | |
tzset(); | |
diff --git a/std/experimental/allocator/building_blocks/stats_collector.d b/std/experimental/allocator/building_blocks/stats_collector.d | |
index 253bcc4..ca3df45 100644 | |
--- a/std/experimental/allocator/building_blocks/stats_collector.d | |
+++ b/std/experimental/allocator/building_blocks/stats_collector.d | |
@@ -667,7 +667,7 @@ unittest | |
import std.stdio : File; | |
import std.range : walkLength; | |
version(Posix) | |
- auto f = "/tmp/dlang.std.experimental.allocator.stats_collector.txt"; | |
+ auto f = "dlang.std.experimental.allocator.stats_collector.txt"; | |
version(Windows) | |
{ | |
import std.process: environment; | |
diff --git a/std/experimental/allocator/mallocator.d b/std/experimental/allocator/mallocator.d | |
index 89dcffa..cf4f99c 100644 | |
--- a/std/experimental/allocator/mallocator.d | |
+++ b/std/experimental/allocator/mallocator.d | |
@@ -1,6 +1,7 @@ | |
module std.experimental.allocator.mallocator; | |
import std.experimental.allocator.common; | |
+extern(C) void* memalign(size_t, size_t); | |
/** | |
The C heap allocator. | |
*/ | |
@@ -215,11 +216,15 @@ struct AlignedMallocator | |
import core.stdc.errno : ENOMEM; | |
assert(a.isGoodDynamicAlignment, to!string(a)); | |
void* result; | |
+ version(Android) | |
+ result = memalign(a, bytes); | |
+ else { | |
auto code = posix_memalign(&result, a, bytes); | |
if (code == ENOMEM) return null; | |
import std.exception : enforce; | |
import std.conv : text; | |
enforce(code == 0, text("Invalid alignment requested: ", a)); | |
+ } | |
return result[0 .. bytes]; | |
} | |
else version(Windows) @trusted | |
diff --git a/std/file.d b/std/file.d | |
index 5bbec58..4a547ba 100644 | |
--- a/std/file.d | |
+++ b/std/file.d | |
@@ -3147,7 +3147,7 @@ private void copyImpl(const(char)[] f, const(char)[] t, const(FSChar)* fromz, co | |
size -= toxfer; | |
} | |
if (preserve) | |
- cenforce(fchmod(fdw, statbuf.st_mode) == 0, f, fromz); | |
+ cenforce(fchmod(fdw, cast(mode_t)statbuf.st_mode) == 0, f, fromz); | |
} | |
cenforce(core.sys.posix.unistd.close(fdw) != -1, f, fromz); | |
diff --git a/std/format.d b/std/format.d | |
index 0711817..ac3603e 100644 | |
--- a/std/format.d | |
+++ b/std/format.d | |
@@ -1768,7 +1768,7 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) | |
fs.width, | |
// negative precision is same as no precision specified | |
fs.precision == fs.UNSPECIFIED ? -1 : fs.precision, | |
- tval); | |
+ cast(double)tval); | |
}(); | |
enforceFmt(n >= 0, | |
@@ -5526,7 +5526,7 @@ void doFormat()(scope void delegate(dchar) putc, TypeInfo[] arguments, va_list a | |
} | |
else | |
n = snprintf(fbuf.ptr, sl, format.ptr, field_width, | |
- precision, v); | |
+ precision, cast(double) v); | |
//printf("format = '%s', n = %d\n", cast(char*)format, n); | |
if (n >= 0 && n < sl) | |
{ sl = n; | |
diff --git a/std/math.d b/std/math.d | |
index 67605b6..85368c2 100644 | |
--- a/std/math.d | |
+++ b/std/math.d | |
@@ -197,7 +197,7 @@ version(unittest) | |
version(CRuntime_Microsoft) | |
alias real_t = double; | |
else | |
- alias real_t = real; | |
+ alias real_t = double; | |
ix = sprintf(bufx.ptr, "%.*Lg", ndigits, cast(real_t) x); | |
iy = sprintf(bufy.ptr, "%.*Lg", ndigits, cast(real_t) y); | |
assert(ix < bufx.length && ix > 0); | |
@@ -4172,7 +4172,7 @@ real round(real x) @trusted nothrow @nogc | |
return x; | |
} | |
else | |
- return core.stdc.math.roundl(x); | |
+ return core.stdc.math.round(x); | |
} | |
/********************************************** | |
@@ -4184,7 +4184,7 @@ real round(real x) @trusted nothrow @nogc | |
long lround(real x) @trusted nothrow @nogc | |
{ | |
version (Posix) | |
- return core.stdc.math.llroundl(x); | |
+ return core.stdc.math.llround(x); | |
else | |
assert (0, "lround not implemented"); | |
} | |
@@ -4244,7 +4244,7 @@ real trunc(real x) @trusted nothrow @nogc | |
} | |
} | |
else | |
- return core.stdc.math.truncl(x); | |
+ return core.stdc.math.trunc(x); | |
} | |
/**************************************************** | |
diff --git a/std/process.d b/std/process.d | |
index ac26437..1629555 100644 | |
--- a/std/process.d | |
+++ b/std/process.d | |
@@ -975,7 +975,7 @@ Pid spawnShell(in char[] command, | |
else version (Posix) | |
{ | |
const(char)[][3] args; | |
- args[0] = "/bin/sh"; | |
+ args[0] = userShell; //"/bin/sh"; | |
args[1] = shellSwitch; | |
args[2] = command; | |
} | |
@@ -1472,7 +1472,7 @@ unittest // tryWait() and kill() | |
TestScript prog = "while true; do sleep 1; done"; | |
} | |
auto pid = spawnProcess(prog.path); | |
- Thread.sleep(dur!"seconds"(1)); | |
+ //Thread.sleep(dur!"seconds"(1)); | |
kill(pid); | |
version (Windows) assert (wait(pid) == 1); | |
else version (Posix) assert (wait(pid) == -SIGTERM); | |
diff --git a/std/socket.d b/std/socket.d | |
index 63c65d3..5f7b135 100644 | |
--- a/std/socket.d | |
+++ b/std/socket.d | |
@@ -94,6 +94,8 @@ else version(Posix) | |
private import core.sys.posix.arpa.inet; | |
private import core.sys.posix.netinet.tcp; | |
private import core.sys.posix.netinet.in_; | |
+ version(Android) enum INADDR_LOOPBACK = 0x7f000001; //shut up std.net.curl, | |
+ //whose tests aren't run anyway | |
private import core.sys.posix.sys.time; | |
private import core.sys.posix.sys.select; | |
private import core.sys.posix.sys.socket; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment