mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 14:00:35 +00:00
Haiku support for Nim (#8542)
* posix_other: Haiku now has spawn.h This is added per https://dev.haiku-os.org/ticket/13446 * posix_other: Add Haiku specific Dirent members * cpuinfo: Add an implementation for Haiku * distros: Add basic Haiku support * encodings: update Haiku support * fenv, math: Haiku now provides libm * times: Add Haiku struct members * ansi_c, osalloc: Add Haiku constants * threads: Add Haiku support * testament: Haiku uses LIBRARY_PATH * nim.cfg: Update Haiku support libnetwork should only be linked if network functions are used * threads: Haiku does not support -pthread switch * tworkingdir: Haiku's env is in /bin * posix_other: add SIGKILLTHR for Haiku * sockets: link with libnetwork on Haiku * coro: correct ucontext.h location http://pubs.opengroup.org/onlinepubs/009696699/basedefs/ucontext.h.html * coro: ucontext backend is not available on Haiku Haiku doesn't provide the <ucontext.h> header, as it was removed from POSIX * coro: fix setjmp backend The compiler does not allow statements after a noreturn function * nativesockets: Haiku doesn't support AI_V4MAPPED * system: hostOS can contains "haiku" * os: add support for Haiku's packagefs packagefs is read-only, but there are writable holes to the underlying file system as well * os: update constant for Haiku
This commit is contained in:
@@ -82,19 +82,21 @@ path="$lib/pure"
|
||||
clang.cpp.options.linker = "-ldl"
|
||||
tcc.options.linker = "-ldl"
|
||||
@end
|
||||
@if bsd or haiku:
|
||||
@if bsd:
|
||||
# BSD got posix_spawn only recently, so we deactivate it for osproc:
|
||||
define:useFork
|
||||
# at least NetBSD has problems with thread local storage:
|
||||
tlsEmulation:on
|
||||
@end
|
||||
@if haiku:
|
||||
# -fopenmp
|
||||
gcc.options.linker = "-lroot -lnetwork"
|
||||
gcc.cpp.options.linker = "-lroot -lnetwork"
|
||||
clang.options.linker = "-lroot -lnetwork"
|
||||
clang.cpp.options.linker = "-lroot -lnetwork"
|
||||
tcc.options.linker = "-lroot -lnetwork"
|
||||
# Haiku currently have problems with TLS
|
||||
# https://dev.haiku-os.org/ticket/14342
|
||||
tlsEmulation:on
|
||||
gcc.options.linker = "-Wl,--as-needed -lnetwork"
|
||||
gcc.cpp.options.linker = "-Wl,--as-needed -lnetwork"
|
||||
clang.options.linker = "-Wl,--as-needed -lnetwork"
|
||||
clang.cpp.options.linker = "-Wl,--as-needed -lnetwork"
|
||||
tcc.options.linker = "-Wl,--as-needed -lnetwork"
|
||||
@end
|
||||
@end
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ include "system/inclrtl"
|
||||
|
||||
when hostOS == "solaris":
|
||||
{.passl: "-lsocket -lnsl".}
|
||||
elif hostOS == "haiku":
|
||||
{.passl: "-lnetwork".}
|
||||
|
||||
import os, parseutils
|
||||
from times import epochTime
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
{.deadCodeElim: on.} # dce option deprecated
|
||||
|
||||
const
|
||||
hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays
|
||||
hasSpawnH = true # should exist for every Posix system nowadays
|
||||
hasAioH = defined(linux)
|
||||
|
||||
when defined(linux) and not defined(android):
|
||||
@@ -43,6 +43,9 @@ type
|
||||
|
||||
Dirent* {.importc: "struct dirent",
|
||||
header: "<dirent.h>", final, pure.} = object ## dirent_t struct
|
||||
when defined(haiku):
|
||||
d_dev*: Dev ## Device (not POSIX)
|
||||
d_pdev*: Dev ## Parent device (only for queries) (not POSIX)
|
||||
d_ino*: Ino ## File serial number.
|
||||
when defined(dragonfly):
|
||||
# DragonflyBSD doesn't have `d_reclen` field.
|
||||
@@ -54,6 +57,9 @@ type
|
||||
## (not POSIX)
|
||||
when defined(linux) or defined(openbsd):
|
||||
d_off*: Off ## Not an offset. Value that ``telldir()`` would return.
|
||||
elif defined(haiku):
|
||||
d_pino*: Ino ## Parent inode (only for queries) (not POSIX)
|
||||
d_reclen*: cushort ## Length of this record. (not POSIX)
|
||||
|
||||
d_name*: array[0..255, char] ## Name of entry.
|
||||
|
||||
@@ -599,6 +605,10 @@ else:
|
||||
MSG_NOSIGNAL* {.importc, header: "<sys/socket.h>".}: cint
|
||||
## No SIGPIPE generated when an attempt to send is made on a stream-oriented socket that is no longer connected.
|
||||
|
||||
when defined(haiku):
|
||||
const
|
||||
SIGKILLTHR* = 21 ## BeOS specific: Kill just the thread, not team
|
||||
|
||||
when hasSpawnH:
|
||||
when defined(linux):
|
||||
# better be safe than sorry; Linux has this flag, macosx doesn't, don't
|
||||
|
||||
@@ -43,6 +43,14 @@ when defined(genode):
|
||||
proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {.
|
||||
importcpp: "@->cpu().affinity_space().total()".}
|
||||
|
||||
when defined(haiku):
|
||||
{.emit: "#include <OS.h>".}
|
||||
type
|
||||
SystemInfo {.importc: "system_info", bycopy.} = object
|
||||
cpuCount {.importc: "cpu_count".}: uint32
|
||||
|
||||
proc getSystemInfo(info: ptr SystemInfo): int32 {.importc: "get_system_info".}
|
||||
|
||||
proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
|
||||
## returns the numer of the processors/cores the machine has.
|
||||
## Returns 0 if it cannot be detected.
|
||||
@@ -86,6 +94,10 @@ proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
|
||||
result = sysconf(SC_NPROC_ONLN)
|
||||
elif defined(genode):
|
||||
result = runtimeEnv.affinitySpaceTotal().int
|
||||
elif defined(haiku):
|
||||
var sysinfo: SystemInfo
|
||||
if getSystemInfo(addr sysinfo) == 0:
|
||||
result = sysinfo.cpuCount.int
|
||||
else:
|
||||
result = sysconf(SC_NPROCESSORS_ONLN)
|
||||
if result <= 0: result = 0
|
||||
|
||||
@@ -43,6 +43,10 @@ when defined(windows):
|
||||
{.warning: "ucontext coroutine backend is not available on windows, defaulting to fibers.".}
|
||||
when defined(nimCoroutinesSetjmp):
|
||||
{.warning: "setjmp coroutine backend is not available on windows, defaulting to fibers.".}
|
||||
elif defined(haiku):
|
||||
const coroBackend = CORO_BACKEND_SETJMP
|
||||
when defined(nimCoroutinesUcontext):
|
||||
{.warning: "ucontext coroutine backend is not available on haiku, defaulting to setjmp".}
|
||||
elif defined(nimCoroutinesSetjmp) or defined(nimCoroutinesSetjmpBundled):
|
||||
const coroBackend = CORO_BACKEND_SETJMP
|
||||
else:
|
||||
@@ -55,21 +59,21 @@ when coroBackend == CORO_BACKEND_FIBERS:
|
||||
|
||||
elif coroBackend == CORO_BACKEND_UCONTEXT:
|
||||
type
|
||||
stack_t {.importc, header: "<sys/ucontext.h>".} = object
|
||||
stack_t {.importc, header: "<ucontext.h>".} = object
|
||||
ss_sp: pointer
|
||||
ss_flags: int
|
||||
ss_size: int
|
||||
|
||||
ucontext_t {.importc, header: "<sys/ucontext.h>".} = object
|
||||
ucontext_t {.importc, header: "<ucontext.h>".} = object
|
||||
uc_link: ptr ucontext_t
|
||||
uc_stack: stack_t
|
||||
|
||||
Context = ucontext_t
|
||||
|
||||
proc getcontext(context: var ucontext_t): int32 {.importc, header: "<sys/ucontext.h>".}
|
||||
proc setcontext(context: var ucontext_t): int32 {.importc, header: "<sys/ucontext.h>".}
|
||||
proc swapcontext(fromCtx, toCtx: var ucontext_t): int32 {.importc, header: "<sys/ucontext.h>".}
|
||||
proc makecontext(context: var ucontext_t, fn: pointer, argc: int32) {.importc, header: "<sys/ucontext.h>", varargs.}
|
||||
proc getcontext(context: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
|
||||
proc setcontext(context: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
|
||||
proc swapcontext(fromCtx, toCtx: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
|
||||
proc makecontext(context: var ucontext_t, fn: pointer, argc: int32) {.importc, header: "<ucontext.h>", varargs.}
|
||||
|
||||
elif coroBackend == CORO_BACKEND_SETJMP:
|
||||
proc coroExecWithStack*(fn: pointer, stack: pointer) {.noreturn, importc: "narch_$1", fastcall.}
|
||||
@@ -190,7 +194,7 @@ proc switchTo(current, to: CoroutinePtr) =
|
||||
elif to.state == CORO_CREATED:
|
||||
# Coroutine is started.
|
||||
coroExecWithStack(runCurrentTask, to.stack.bottom)
|
||||
doAssert false
|
||||
#doAssert false
|
||||
else:
|
||||
{.error: "Invalid coroutine backend set.".}
|
||||
# Execution was just resumed. Restore frame information and set active stack.
|
||||
|
||||
@@ -126,6 +126,8 @@ type
|
||||
OpenBSD
|
||||
DragonFlyBSD
|
||||
|
||||
Haiku
|
||||
|
||||
|
||||
const
|
||||
LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware,
|
||||
@@ -166,6 +168,8 @@ proc detectOsImpl(d: Distribution): bool =
|
||||
of Distribution.Solaris:
|
||||
let uname = toLowerAscii(uname())
|
||||
result = ("sun" in uname) or ("solaris" in uname)
|
||||
of Distribution.Haiku:
|
||||
result = defined(haiku)
|
||||
else:
|
||||
let dd = toLowerAscii($d)
|
||||
result = dd in toLowerAscii(uname()) or dd in toLowerAscii(release())
|
||||
@@ -224,6 +228,8 @@ proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) =
|
||||
result = ("pacman -S " & p, true)
|
||||
else:
|
||||
result = ("<your package manager here> install " & p, true)
|
||||
elif defined(haiku):
|
||||
result = ("pkgman install " & p, true)
|
||||
else:
|
||||
result = ("brew install " & p, false)
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ when defined(windows):
|
||||
|
||||
else:
|
||||
when defined(haiku):
|
||||
const iconvDll = "(libc.so.6|libiconv.so|libtextencoding.so)"
|
||||
const iconvDll = "libiconv.so"
|
||||
elif defined(macosx):
|
||||
const iconvDll = "libiconv.dylib"
|
||||
else:
|
||||
@@ -272,6 +272,8 @@ else:
|
||||
const EILSEQ = 86.cint
|
||||
elif defined(solaris):
|
||||
const EILSEQ = 88.cint
|
||||
elif defined(haiku):
|
||||
const EILSEQ = -2147454938.cint
|
||||
|
||||
var errno {.importc, header: "<errno.h>".}: cint
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
{.deadCodeElim: on.} # dce option deprecated
|
||||
|
||||
when defined(Posix) and not defined(haiku):
|
||||
when defined(Posix):
|
||||
{.passl: "-lm".}
|
||||
|
||||
var
|
||||
|
||||
@@ -49,7 +49,7 @@ proc fac*(n: int): int =
|
||||
|
||||
{.push checks:off, line_dir:off, stack_trace:off.}
|
||||
|
||||
when defined(Posix) and not defined(haiku):
|
||||
when defined(Posix):
|
||||
{.passl: "-lm".}
|
||||
|
||||
const
|
||||
|
||||
@@ -248,9 +248,10 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET,
|
||||
hints.ai_socktype = toInt(sockType)
|
||||
hints.ai_protocol = toInt(protocol)
|
||||
# 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, Haiku don't support AI_V4MAPPED but defines the macro.
|
||||
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092
|
||||
when not defined(freebsd) and not defined(openbsd) and not defined(netbsd) and not defined(android):
|
||||
# https://dev.haiku-os.org/ticket/14323
|
||||
when not defined(freebsd) and not defined(openbsd) and not defined(netbsd) and not defined(android) and not defined(haiku):
|
||||
if domain == AF_INET6:
|
||||
hints.ai_flags = AI_V4MAPPED
|
||||
var gaiResult = getaddrinfo(address, $port, addr(hints), result)
|
||||
|
||||
@@ -615,7 +615,10 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
|
||||
|
||||
when not declared(ENOENT) and not defined(Windows):
|
||||
when NoFakeVars:
|
||||
const ENOENT = cint(2) # 2 on most systems including Solaris
|
||||
when not defined(haiku):
|
||||
const ENOENT = cint(2) # 2 on most systems including Solaris
|
||||
else:
|
||||
const ENOENT = cint(-2147459069)
|
||||
else:
|
||||
var ENOENT {.importc, header: "<errno.h>".}: cint
|
||||
|
||||
@@ -972,6 +975,14 @@ proc rawCreateDir(dir: string): bool =
|
||||
result = false
|
||||
else:
|
||||
raiseOSError(osLastError(), dir)
|
||||
elif defined(haiku):
|
||||
let res = mkdir(dir, 0o777)
|
||||
if res == 0'i32:
|
||||
result = true
|
||||
elif errno == EEXIST or errno == EROFS:
|
||||
result = false
|
||||
else:
|
||||
raiseOSError(osLastError(), dir)
|
||||
elif defined(posix):
|
||||
let res = mkdir(dir, 0o777)
|
||||
if res == 0'i32:
|
||||
|
||||
@@ -892,7 +892,7 @@ else:
|
||||
weekday {.importc: "tm_wday".},
|
||||
yearday {.importc: "tm_yday".},
|
||||
isdst {.importc: "tm_isdst".}: cint
|
||||
when defined(linux) and defined(amd64):
|
||||
when defined(linux) and defined(amd64) or defined(haiku):
|
||||
gmtoff {.importc: "tm_gmtoff".}: clong
|
||||
zone {.importc: "tm_zone".}: cstring
|
||||
type
|
||||
|
||||
@@ -1365,7 +1365,7 @@ const
|
||||
hostOS* {.magic: "HostOS".}: string = ""
|
||||
## a string that describes the host operating system. Possible values:
|
||||
## "windows", "macosx", "linux", "netbsd", "freebsd", "openbsd", "solaris",
|
||||
## "aix", "standalone".
|
||||
## "aix", "haiku", "standalone".
|
||||
|
||||
hostCPU* {.magic: "HostCPU".}: string = ""
|
||||
## a string that describes the host CPU. Possible values:
|
||||
|
||||
@@ -59,6 +59,15 @@ elif defined(macosx) or defined(linux) or defined(freebsd) or
|
||||
SIGSEGV = cint(11)
|
||||
SIGTERM = cint(15)
|
||||
SIGPIPE = cint(13)
|
||||
elif defined(haiku):
|
||||
const
|
||||
SIGABRT = cint(6)
|
||||
SIGFPE = cint(8)
|
||||
SIGILL = cint(4)
|
||||
SIGINT = cint(2)
|
||||
SIGSEGV = cint(11)
|
||||
SIGTERM = cint(15)
|
||||
SIGPIPE = cint(7)
|
||||
else:
|
||||
when NoFakeVars:
|
||||
{.error: "SIGABRT not ported to your platform".}
|
||||
@@ -74,6 +83,8 @@ else:
|
||||
|
||||
when defined(macosx):
|
||||
const SIGBUS = cint(10)
|
||||
elif defined(haiku):
|
||||
const SIGBUS = cint(30)
|
||||
else:
|
||||
template SIGBUS: untyped = SIGSEGV
|
||||
|
||||
|
||||
@@ -207,6 +207,9 @@ elif defined(posix):
|
||||
# some arches like mips and alpha use different values
|
||||
const MAP_ANONYMOUS = 0x20
|
||||
const MAP_PRIVATE = 0x02 # Changes are private
|
||||
elif defined(haiku):
|
||||
const MAP_ANONYMOUS = 0x08
|
||||
const MAP_PRIVATE = 0x02
|
||||
else:
|
||||
var
|
||||
MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint
|
||||
|
||||
@@ -162,10 +162,12 @@ elif defined(genode):
|
||||
mainTls
|
||||
|
||||
else:
|
||||
when not defined(macosx):
|
||||
when not (defined(macosx) or defined(haiku)):
|
||||
{.passL: "-pthread".}
|
||||
|
||||
{.passC: "-pthread".}
|
||||
when not defined(haiku):
|
||||
{.passC: "-pthread".}
|
||||
|
||||
const
|
||||
schedh = "#define _GNU_SOURCE\n#include <sched.h>"
|
||||
pthreadh = "#define _GNU_SOURCE\n#include <pthread.h>"
|
||||
@@ -714,3 +716,13 @@ elif defined(solaris):
|
||||
if threadId == 0:
|
||||
threadId = int(thr_self())
|
||||
result = threadId
|
||||
|
||||
elif defined(haiku):
|
||||
type thr_id {.importc: "thread_id", header: "<OS.h>".} = distinct int32
|
||||
proc find_thread(name: cstring): thr_id {.importc, header: "<OS.h>".}
|
||||
|
||||
proc getThreadId*(): int =
|
||||
## get the ID of the currently running thread.
|
||||
if threadId == 0:
|
||||
threadId = int(find_thread(nil))
|
||||
result = threadId
|
||||
|
||||
@@ -28,9 +28,12 @@ if paramCount() == 0:
|
||||
# windows kill happens using TerminateProcess(h, 0), so we should get a
|
||||
# 0 here
|
||||
echo p.waitForExit() == 0
|
||||
elif defined(haiku):
|
||||
# on Haiku, the program main thread receive SIGKILLTHR
|
||||
echo p.waitForExit() == 128 + SIGKILLTHR
|
||||
else:
|
||||
# on posix (non-windows), kill sends SIGKILL
|
||||
echo p.waitForExit() == 128 + SIGKILL
|
||||
|
||||
else:
|
||||
sleep(5000) # should get killed before this
|
||||
sleep(5000) # should get killed before this
|
||||
|
||||
@@ -12,6 +12,8 @@ else:
|
||||
var process: Process
|
||||
when defined(android):
|
||||
process = startProcess("/system/bin/env", "/system/bin", ["true"])
|
||||
elif defined(haiku):
|
||||
process = startProcess("/bin/env", "/bin", ["true"])
|
||||
else:
|
||||
process = startProcess("/usr/bin/env", "/usr/bin", ["true"])
|
||||
let dir2 = getCurrentDir()
|
||||
|
||||
@@ -109,10 +109,14 @@ proc runBasicDLLTest(c, r: var TResults, cat: Category, options: string) =
|
||||
safeCopyFile("lib" / nimrtlDll, "tests/dll" / nimrtlDll)
|
||||
else:
|
||||
# posix relies on crappy LD_LIBRARY_PATH (ugh!):
|
||||
var libpath = getEnv"LD_LIBRARY_PATH".string
|
||||
const libpathenv = when defined(haiku):
|
||||
"LIBRARY_PATH"
|
||||
else:
|
||||
"LD_LIBRARY_PATH"
|
||||
var libpath = getEnv(libpathenv).string
|
||||
# Temporarily add the lib directory to LD_LIBRARY_PATH:
|
||||
putEnv("LD_LIBRARY_PATH", "tests/dll" & (if libpath.len > 0: ":" & libpath else: ""))
|
||||
defer: putEnv("LD_LIBRARY_PATH", libpath)
|
||||
putEnv(libpathenv, "tests/dll" & (if libpath.len > 0: ":" & libpath else: ""))
|
||||
defer: putEnv(libpathenv, libpath)
|
||||
var nimrtlDll = DynlibFormat % "nimrtl"
|
||||
safeCopyFile("lib" / nimrtlDll, "tests/dll" / nimrtlDll)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user