Introduce first class support for Android (#5772)

This commit is contained in:
Fredrik Høisæther Rasch 2017-08-06 02:18:15 +02:00 • committed by Andreas Rumpf
commit c39e202976
15 changed files with 109 additions and 14 deletions

View file

@ -41,7 +41,10 @@ proc isDefined*(symbol: string): bool =
result = targetOS in {osLinux, osMorphos, osSkyos, osIrix, osPalmos, result = targetOS in {osLinux, osMorphos, osSkyos, osIrix, osPalmos,
osQnx, osAtari, osAix, osQnx, osAtari, osAix,
osHaiku, osVxWorks, osSolaris, osNetbsd, osHaiku, osVxWorks, osSolaris, osNetbsd,
osFreebsd, osOpenbsd, osDragonfly, osMacosx} osFreebsd, osOpenbsd, osDragonfly, osMacosx,
osAndroid}
of "linux":
result = targetOS in {osLinux, osAndroid}
of "bsd": of "bsd":
result = targetOS in {osNetbsd, osFreebsd, osOpenbsd, osDragonfly} result = targetOS in {osNetbsd, osFreebsd, osOpenbsd, osDragonfly}
of "emulatedthreadvars": of "emulatedthreadvars":

View file

@ -14,6 +14,7 @@ Platforms: """
openbsd: i386;amd64 openbsd: i386;amd64
dragonfly: i386;amd64 dragonfly: i386;amd64
haiku: i386;amd64 haiku: i386;amd64
android: i386;arm;arm64
""" """
Authors: "Andreas Rumpf" Authors: "Andreas Rumpf"

View file

@ -21,8 +21,8 @@ type
# conditionals to condsyms (end of module). # conditionals to condsyms (end of module).
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris, osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx, osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx,
osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osVxworks, osGenode osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osAndroid, osVxworks
osJS, osNimrodVM, osStandalone osGenode, osJS, osNimrodVM, osStandalone
type type
TInfoOSProp* = enum TInfoOSProp* = enum
@ -143,6 +143,10 @@ const
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/", objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".", scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}), props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
(name: "Android", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "VxWorks", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/", (name: "VxWorks", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\", objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\",
scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".", scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".",

View file

@ -90,6 +90,16 @@ path="$lib/pure"
@end @end
@end @end
@if android:
cc = clang
gcc.options.linker = "-landroid-glob"
gcc.cpp.options.linker = "-landroid-glob"
clang.options.linker = "-landroid-glob"
clang.cpp.options.linker = "-landroid-glob"
tcc.options.linker = "-landroid-glob"
define:"useShPath:/system/bin/sh"
@end
# Configuration for the Intel C/C++ compiler: # Configuration for the Intel C/C++ compiler:
@if windows: @if windows:
icl.options.speed = "/Ox /arch:SSE2" icl.options.speed = "/Ox /arch:SSE2"

View file

@ -278,6 +278,15 @@ Define Effect
what's in the Nim file with what's in the C header what's in the Nim file with what's in the C header
(requires a C compiler with _Static_assert support, like (requires a C compiler with _Static_assert support, like
any C11 compiler) any C11 compiler)
``tempDir`` This symbol takes a string as its value, like
``--define:tempDir:/some/temp/path`` to override the
temporary directory returned by ``os.getTempDir()``.
The value **should** end with a directory separator
character. (Relevant for the Android platform)
``useShPath`` This symbol takes a string as its value, like
``--define:useShPath:/opt/sh/bin/sh`` to override the
path for the ``sh`` binary, in cases where it is not
located in the default location ``/bin/sh``
================== ========================================================= ================== =========================================================

View file

@ -92,7 +92,7 @@ else:
# There used to be this name in posix.nim a long time ago, not sure why! # There used to be this name in posix.nim a long time ago, not sure why!
{.deprecated: [cSIG_HOLD: SIG_HOLD].} {.deprecated: [cSIG_HOLD: SIG_HOLD].}
when not defined(macosx): when not defined(macosx) and not defined(android):
proc st_atime*(s: Stat): Time {.inline.} = proc st_atime*(s: Stat): Time {.inline.} =
## Second-granularity time of last access ## Second-granularity time of last access
result = s.st_atim.tv_sec result = s.st_atim.tv_sec

View file

@ -215,7 +215,7 @@ type
## For a typed memory object, the length in bytes. ## For a typed memory object, the length in bytes.
## For other file types, the use of this field is ## For other file types, the use of this field is
## unspecified. ## unspecified.
when defined(macosx): when defined(macosx) or defined(android):
st_atime*: Time ## Time of last access. st_atime*: Time ## Time of last access.
st_mtime*: Time ## Time of last data modification. st_mtime*: Time ## Time of last data modification.
st_ctime*: Time ## Time of last status change. st_ctime*: Time ## Time of last status change.

View file

@ -233,7 +233,7 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET,
# OpenBSD doesn't support AI_V4MAPPED and doesn't define the macro AI_V4MAPPED. # OpenBSD doesn't support AI_V4MAPPED and doesn't define the macro AI_V4MAPPED.
# FreeBSD doesn't support AI_V4MAPPED but defines the macro. # FreeBSD doesn't support AI_V4MAPPED but defines the macro.
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092 # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092
when not defined(freebsd) and not defined(openbsd) and not defined(netbsd): when not defined(freebsd) and not defined(openbsd) and not defined(netbsd) and not defined(android):
if domain == AF_INET6: if domain == AF_INET6:
hints.ai_flags = AI_V4MAPPED hints.ai_flags = AI_V4MAPPED
var gaiResult = getaddrinfo(address, $port, addr(hints), result) var gaiResult = getaddrinfo(address, $port, addr(hints), result)

View file

@ -528,11 +528,26 @@ when declared(getEnv) or defined(nimscript):
elif getEnv("XDG_CONFIG_DIR"): return string(getEnv("XDG_CONFIG_DIR")) & "/" elif getEnv("XDG_CONFIG_DIR"): return string(getEnv("XDG_CONFIG_DIR")) & "/"
else: return string(getEnv("HOME")) & "/.config/" else: return string(getEnv("HOME")) & "/.config/"
when defined(android):
{.pragma: getTempDirEffects, tags: [ReadEnvEffect, ReadIOEffect, WriteDirEffect].}
elif defined(windows):
{.pragma: getTempDirEffects, tags: [ReadEnvEffect, ReadIOEffect].}
else:
{.pragma: getTempDirEffects, tags: [ReadIOEffect].}
proc getTempDir*(): string {.rtl, extern: "nos$1", proc getTempDir*(): string {.rtl, extern: "nos$1",
tags: [ReadEnvEffect, ReadIOEffect].} = getTempDirEffects.} =
## Returns the temporary directory of the current user for applications to ## Returns the temporary directory of the current user for applications to
## save temporary files in. ## save temporary files in.
when defined(windows): return string(getEnv("TEMP")) & "\\" when defined(tempDir):
const tempDir {.strdefine.}: string = nil
return tempDir
elif defined(windows): return string(getEnv("TEMP")) & "\\"
elif defined(android):
let tempDir = getHomeDir() / "nimtempfs"
try: createDir(tempDir)
except OSError: discard
return tempDir
else: return "/tmp/" else: return "/tmp/"
proc expandTilde*(path: string): string {. proc expandTilde*(path: string): string {.

View file

@ -762,7 +762,8 @@ elif not defined(useNimRtl):
var sysCommand: string var sysCommand: string
var sysArgsRaw: seq[string] var sysArgsRaw: seq[string]
if poEvalCommand in options: if poEvalCommand in options:
sysCommand = "/bin/sh" const useShPath {.strdefine.} = "/bin/sh"
sysCommand = useShPath
sysArgsRaw = @[sysCommand, "-c", command] sysArgsRaw = @[sysCommand, "-c", command]
assert args.len == 0, "`args` has to be empty when using poEvalCommand." assert args.len == 0, "`args` has to be empty when using poEvalCommand."
else: else:

View file

@ -35,7 +35,8 @@ type
OsPlatform* {.pure.} = enum ## the OS this program will run on. OsPlatform* {.pure.} = enum ## the OS this program will run on.
none, dos, windows, os2, linux, morphos, skyos, solaris, none, dos, windows, os2, linux, morphos, skyos, solaris,
irix, netbsd, freebsd, openbsd, aix, palmos, qnx, amiga, irix, netbsd, freebsd, openbsd, aix, palmos, qnx, amiga,
atari, netware, macos, macosx, haiku, js, nimVM, standalone atari, netware, macos, macosx, haiku, android, js, nimVM,
standalone
const const
targetOS* = when defined(windows): OsPlatform.windows targetOS* = when defined(windows): OsPlatform.windows
@ -58,6 +59,7 @@ const
elif defined(macosx): OsPlatform.macosx elif defined(macosx): OsPlatform.macosx
elif defined(macos): OsPlatform.macos elif defined(macos): OsPlatform.macos
elif defined(haiku): OsPlatform.haiku elif defined(haiku): OsPlatform.haiku
elif defined(android): OsPlatform.android
elif defined(js): OsPlatform.js elif defined(js): OsPlatform.js
elif defined(nimrodVM): OsPlatform.nimVM elif defined(nimrodVM): OsPlatform.nimVM
elif defined(standalone): OsPlatform.standalone elif defined(standalone): OsPlatform.standalone

View file

@ -9,7 +9,11 @@ when defined(windows):
discard discard
else: else:
let dir1 = getCurrentDir() let dir1 = getCurrentDir()
var process = startProcess("/usr/bin/env", "/usr/bin", ["true"]) var process: Process
when defined(android):
process = startProcess("/system/bin/env", "/system/bin", ["true"])
else:
process = startProcess("/usr/bin/env", "/usr/bin", ["true"])
let dir2 = getCurrentDir() let dir2 = getCurrentDir()
discard process.waitForExit() discard process.waitForExit()
process.close() process.close()

View file

@ -139,7 +139,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
" -d:release --gc:markAndSweep", cat, actionRun) " -d:release --gc:markAndSweep", cat, actionRun)
template test(filename: untyped) = template test(filename: untyped) =
testWithoutBoehm filename testWithoutBoehm filename
when not defined(windows): when not defined(windows) and not defined(android):
# AR: cannot find any boehm.dll on the net, right now, so disabled # AR: cannot find any boehm.dll on the net, right now, so disabled
# for windows: # for windows:
testSpec r, makeTest("tests/gc" / filename, options & testSpec r, makeTest("tests/gc" / filename, options &

View file

@ -1,4 +1,4 @@
#? stdtmpl(subsChar='?') | standard #? stdtmpl(subsChar='?') | standard
#proc generateBuildShellScript(c: ConfigData): string = #proc generateBuildShellScript(c: ConfigData): string =
# result = "#! /bin/sh\n# Generated from niminst\n" & # result = "#! /bin/sh\n# Generated from niminst\n" &
# "# Template is in tools/niminst/buildsh.tmpl\n" & # "# Template is in tools/niminst/buildsh.tmpl\n" &
@ -9,6 +9,18 @@ set -e
while : while :
do do
case "$1" in case "$1" in
--os)
optos=$2
shift 2
;;
--cpu)
optcpu=$2
shift 2
;;
--osname)
optosname=$2
shift 2
;;
--extraBuildArgs) --extraBuildArgs)
extraBuildArgs=" $2" extraBuildArgs=" $2"
shift 2 shift 2
@ -35,6 +47,7 @@ PS4=""
# add(result, "# platform detection\n") # add(result, "# platform detection\n")
ucpu=`uname -m` ucpu=`uname -m`
uos=`uname` uos=`uname`
uosname=`uname -o`
# add(result, "# bin dir detection\n") # add(result, "# bin dir detection\n")
binDir=?{firstBinPath(c).toUnix} binDir=?{firstBinPath(c).toUnix}
@ -46,9 +59,21 @@ if [ ! -d $binDir ]; then
mkdir $binDir mkdir $binDir
fi fi
# add(result, "# override OS, CPU and OS Name with command-line arguments\n")
if [ -n "$optos" ]; then
uos="$optos"
fi
if [ -n "$optcpu" ]; then
ucpu="$optcpu"
fi
if [ -n "$optcpu" ]; then
uosname="$optosname"
fi
# add(result, "# convert to lower case:\n") # add(result, "# convert to lower case:\n")
ucpu=`echo $ucpu | tr "[:upper:]" "[:lower:]"` ucpu=`echo $ucpu | tr "[:upper:]" "[:lower:]"`
uos=`echo $uos | tr "[:upper:]" "[:lower:]"` uos=`echo $uos | tr "[:upper:]" "[:lower:]"`
uosname=`echo $uosname | tr "[:upper:]" "[:lower:]"`
case $uos in case $uos in
*linux* ) *linux* )
@ -97,6 +122,11 @@ case $uos in
*mingw* ) *mingw* )
myos="windows" myos="windows"
;; ;;
*android* )
myos="android"
LINK_FLAGS="$LINK_FLAGS -ldl -lm -lrt"
LINK_FLAGS="$LINK_FLAGS -landroid-glob"
;;
*) *)
echo 2>&1 "Error: unknown operating system: $uos" echo 2>&1 "Error: unknown operating system: $uos"
exit 1 exit 1
@ -132,7 +162,7 @@ case $ucpu in
exit 1 exit 1
esac esac
;; ;;
*arm*|*armv6l* ) *arm*|*armv6l*|*armv71* )
mycpu="arm" ;; mycpu="arm" ;;
*aarch64* ) *aarch64* )
mycpu="arm64" ;; mycpu="arm64" ;;
@ -142,7 +172,17 @@ case $ucpu in
;; ;;
esac esac
case $uosname in
*android* )
LINK_FLAGS="$LINK_FLAGS -landroid-glob"
myosname="android"
myos="android"
;;
esac
# add(result, "# call the compiler:\n") # add(result, "# call the compiler:\n")
echo \# OS: $myos
echo \# CPU: $mycpu
case $myos in case $myos in
# for osA in 1..c.oses.len: # for osA in 1..c.oses.len:

View file

@ -17,6 +17,7 @@ endif
ucpu := $(shell sh -c 'uname -m | tr "[:upper:]" "[:lower:]"') ucpu := $(shell sh -c 'uname -m | tr "[:upper:]" "[:lower:]"')
uos := $(shell sh -c 'uname | tr "[:upper:]" "[:lower:]"') uos := $(shell sh -c 'uname | tr "[:upper:]" "[:lower:]"')
uosname := $(shell sh -c 'uname -o | tr "[:upper:]" "[:lower:]"')
ifeq ($(uos),linux) ifeq ($(uos),linux)
myos = linux myos = linux
@ -68,6 +69,11 @@ ifndef uos
$(error unknown operating system: $(uos)) $(error unknown operating system: $(uos))
endif endif
ifeq ($(uosname),android)
myos = android
LINK_FLAGS += -landroid-glob
endif
ifeq ($(ucpu),i386) ifeq ($(ucpu),i386)
mycpu = i386 mycpu = i386
endif endif