From 4874be967c0286fafa398fa6f018126ecb2cc48d Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 16:58:09 +0900 Subject: [PATCH 01/23] Add config section for Nintendo Switch --- config/nim.cfg | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config/nim.cfg b/config/nim.cfg index e11826587e34..5342676de756 100644 --- a/config/nim.cfg +++ b/config/nim.cfg @@ -109,6 +109,14 @@ path="$lib/pure" @end @end +@if nintendoswitch: + cc = "switch_gcc" + switch_gcc.options.linker = "-specs=$DEVKITPRO/libnx/switch.specs -g -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -L$DEVKITPRO/portlibs/switch/lib -L$DEVKITPRO/libnx/lib -lnx $SWITCH_LIBS" + switch_gcc.cpp.options.linker = "-specs=$DEVKITPRO/libnx/switch.specs -g -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -L$DEVKITPRO/portlibs/switch/lib -L$DEVKITPRO/libnx/lib -lnx $SWITCH_LIBS" + switch_gcc.options.always = "-g -Wall -O2 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -I$DEVKITPRO/portlibs/switch/include -I$DEVKITPRO/libnx/include $SWITCH_INCLUDES -D__SWITCH__" + switch_gcc.cpp.options.always = "-g -Wall -O2 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -I$DEVKITPRO/portlibs/switch/include -I$DEVKITPRO/libnx/include $SWITCH_INCLUDES -D__SWITCH__ -fno-rtti -fno-exceptions -std=gnu++11" +@end + # Configuration for the Intel C/C++ compiler: @if windows: icl.options.speed = "/Ox /arch:SSE2" From c40ececccb4082bf1adb3647594720f186613d84 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 17:07:10 +0900 Subject: [PATCH 02/23] Add compiler configuration for Nintendo Switch and it's CPU --- compiler/extccomp.nim | 40 ++++++++++++++++++++++++++++++++++++++++ compiler/installer.ini | 1 + compiler/options.nim | 4 +++- compiler/platform.nim | 14 ++++++++++---- 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 615b8c1e1c75..5a890b790365 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -83,6 +83,31 @@ compiler gcc: props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm, hasAttribute}) +# GNU C and C++ Compiler +compiler aarch64NoneElfGCC: + result = ( + name: "switch_gcc", + objExt: "o", + optSpeed: " -O3 -ffast-math ", + optSize: " -Os -ffast-math ", + compilerExe: "aarch64-none-elf-gcc", + cppCompiler: "aarch64-none-elf-g++", + compileTmpl: "-MMD -MP -MF $dfile -c $options $include -o $objfile $file", + buildGui: " -mwindows", + buildDll: " -shared", + buildLib: "aarch64-none-elf-gcc-ar rcs $libfile $objfiles", + linkerExe: "aarch64-none-elf-gcc", + linkTmpl: "$buildgui $builddll -Wl,-Map,$mapfile -o $exefile $objfiles $options", + includeCmd: " -I", + linkDirCmd: " -L", + linkLibCmd: " -l$1", + debug: "", + pic: "-fPIE", + asmStmtFrmt: "asm($1);$n", + structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name + props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm, + hasAttribute}) + # LLVM Frontend for GCC/G++ compiler llvmGcc: result = gcc() # Uses settings from GCC @@ -316,6 +341,7 @@ compiler ucc: const CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [ gcc(), + aarch64NoneElfGCC(), llvmGcc(), clang(), lcc(), @@ -556,14 +582,20 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile): string = else: cfile.obj + # D files are required by nintendo switch libs for + # compilation. They are basically a list of all includes. + let dfile = objfile.replace(".o", ".d").quoteShell() + objfile = quoteShell(objfile) cf = quoteShell(cf) result = quoteShell(compilePattern % [ + "dfile", dfile, "file", cf, "objfile", objfile, "options", options, "include", includeCmd, "nim", getPrefixDir(conf), "nim", getPrefixDir(conf), "lib", conf.libpath]) add(result, ' ') addf(result, CC[c].compileTmpl, [ + "dfile", dfile, "file", cf, "objfile", objfile, "options", options, "include", includeCmd, "nim", quoteShell(getPrefixDir(conf)), @@ -659,16 +691,24 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string = if optCDebug in conf.globalOptions: writeDebugInfo(exefile.changeFileExt("ndb")) exefile = quoteShell(exefile) + + # Map files are required by Nintendo Switch compilation. They are a list + # of all function calls in the library and where they come from. + var mapfile = getNimcacheDir(conf) / splitFile(projectFile).name & ".map" + mapfile = quoteShell(mapfile) + let linkOptions = getLinkOptions(conf) & " " & getConfigVar(conf, conf.cCompiler, ".options.linker") var linkTmpl = getConfigVar(conf, conf.cCompiler, ".linkTmpl") if linkTmpl.len == 0: linkTmpl = CC[conf.cCompiler].linkTmpl result = quoteShell(result % ["builddll", builddll, + "mapfile", mapfile, "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, "exefile", exefile, "nim", getPrefixDir(conf), "lib", conf.libpath]) result.add ' ' addf(result, linkTmpl, ["builddll", builddll, + "mapfile", mapfile, "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, "exefile", exefile, "nim", quoteShell(getPrefixDir(conf)), diff --git a/compiler/installer.ini b/compiler/installer.ini index 2847e4e62de6..7ee98622995e 100644 --- a/compiler/installer.ini +++ b/compiler/installer.ini @@ -15,6 +15,7 @@ Platforms: """ dragonfly: i386;amd64 haiku: i386;amd64 android: i386;arm;arm64 + nintendoswitch: armv8a57 """ Authors: "Andreas Rumpf" diff --git a/compiler/options.nim b/compiler/options.nim index 1d6ddb09f7d2..aea55e94fdef 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -124,7 +124,7 @@ type disabledSf, writeOnlySf, readOnlySf, v2Sf TSystemCC* = enum - ccNone, ccGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, + ccNone, ccGcc, ccaarch64NoneElfGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, ccTcc, ccPcc, ccUcc, ccIcl, ccIcc CfileFlag* {.pure.} = enum @@ -356,6 +356,8 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool = of "mswindows", "win32": result = conf.target.targetOS == osWindows of "macintosh": result = conf.target.targetOS in {osMacos, osMacosx} of "sunos": result = conf.target.targetOS == osSolaris + of "nintendoswitch": + result = conf.target.targetOS == osNintendoSwitch of "littleendian": result = CPU[conf.target.targetCPU].endian == platform.littleEndian of "bigendian": result = CPU[conf.target.targetCPU].endian == platform.bigEndian of "cpu8": result = CPU[conf.target.targetCPU].bit == 8 diff --git a/compiler/platform.nim b/compiler/platform.nim index 0db16f26c867..14ce4e0f7b0d 100644 --- a/compiler/platform.nim +++ b/compiler/platform.nim @@ -22,7 +22,7 @@ type osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris, osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx, osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osAndroid, osVxworks - osGenode, osJS, osNimVM, osStandalone + osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch type TInfoOSProp* = enum @@ -168,7 +168,12 @@ const (name: "Standalone", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/", objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/", scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".", - props: {})] + props: {}), + (name: "NintendoSwitch", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/", + objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/", + scriptExt: ".sh", curDir: ".", exeExt: ".elf", extSep: ".", + props: {ospNeedsPIC, ospPosix}), + ] type TSystemCPU* = enum # Also add CPU for in initialization section and @@ -176,7 +181,7 @@ type cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64, cpuPowerpc64el, cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuMipsel, cpuArm, cpuArm64, cpuJS, cpuNimVM, cpuAVR, cpuMSP430, cpuSparc64, - cpuMips64, cpuMips64el, cpuRiscV64 + cpuMips64, cpuMips64el, cpuRiscV64, cpuArmv8A57 type TEndian* = enum @@ -208,7 +213,8 @@ const (name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64), (name: "mips64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64), (name: "mips64el", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64), - (name: "riscv64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64)] + (name: "riscv64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64), + (name: "armv8a57", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64)] type Target* = object From 8a0bff973fd24e2030efa759b864e1e52d786dac Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 17:11:22 +0900 Subject: [PATCH 03/23] Add specific lib code for Nintendo Switch --- lib/pure/os.nim | 7 ++++--- lib/pure/selectors.nim | 2 ++ lib/system/ansi_c.nim | 2 +- lib/system/dyncalls.nim | 18 ++++++++++++++++++ lib/system/platforms.nim | 7 +++++-- lib/system/sysio.nim | 4 ++-- lib/system/threads.nim | 8 ++++++++ 7 files changed, 40 insertions(+), 8 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 3bc87728bf0f..90c52657cffe 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -819,7 +819,8 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: y = dir / y var k = pcFile - when defined(linux) or defined(macosx) or defined(bsd) or defined(genode): + when defined(linux) or defined(macosx) or + defined(bsd) or defined(genode) or defined(nintendoswitch): if x.d_type != DT_UNKNOWN: if x.d_type == DT_DIR: k = pcDir if x.d_type == DT_LNK: @@ -1285,7 +1286,7 @@ elif defined(windows): elif not defined(createNimRtl) and not(defined(posix) and appType == "lib") and - not defined(genode): + not defined(genode) and not defined(nintendoswitch): # On Posix, there is no portable way to get the command line from a DLL. var cmdCount {.importc: "cmdCount".}: cint @@ -1439,7 +1440,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} = result = getApplAux("/proc/self/exe") elif defined(solaris): result = getApplAux("/proc/" & $getpid() & "/path/a.out") - elif defined(genode): + elif defined(genode) or defined(nintendoswitch): raiseOSError(OSErrorCode(-1), "POSIX command line not supported") elif defined(freebsd) or defined(dragonfly): result = getApplFreebsd() diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 640df8282a9b..935250e085c3 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -312,6 +312,8 @@ else: include ioselects/ioselectors_poll # need to replace it with event ports elif defined(genode): include ioselects/ioselectors_select # TODO: use the native VFS layer + elif defined(nintendoswitch): + include ioselects/ioselectors_select else: include ioselects/ioselectors_poll diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 0bac979e722c..52cb15e39b79 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -45,7 +45,7 @@ when defined(windows): SIGTERM = cint(15) elif defined(macosx) or defined(linux) or defined(freebsd) or defined(openbsd) or defined(netbsd) or defined(solaris) or - defined(dragonfly): + defined(dragonfly) or defined(nintendoswitch): const SIGABRT = cint(6) SIGFPE = cint(8) diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim index f1ff307da1bc..8fb69482902d 100644 --- a/lib/system/dyncalls.nim +++ b/lib/system/dyncalls.nim @@ -167,6 +167,24 @@ elif defined(genode): proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {. error: "nimGetProcAddr not implemented".} +elif defined(nintendoswitch): + proc nimUnloadLibrary(lib: LibHandle) = + stderr.rawWrite("nimUnLoadLibrary not implemented") + stderr.rawWrite("\n") + quit(1) + + proc nimLoadLibrary(path: string): LibHandle = + stderr.rawWrite("nimLoadLibrary not implemented") + stderr.rawWrite("\n") + quit(1) + + + proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr = + stderr.rawWrite("nimGetProAddr not implemented") + stderr.write(name) + stderr.rawWrite("\n") + quit(1) + else: {.error: "no implementation for dyncalls".} diff --git a/lib/system/platforms.nim b/lib/system/platforms.nim index b561cd3ba265..aab270312432 100644 --- a/lib/system/platforms.nim +++ b/lib/system/platforms.nim @@ -31,13 +31,14 @@ type vm, ## Some Virtual machine: Nim's VM or JavaScript avr, ## AVR based processor msp430, ## TI MSP430 microcontroller - riscv64 ## RISC-V 64-bit processor + riscv64, ## RISC-V 64-bit processor + armv8a57 ## Arm Cortex A57 64-bit processor for Nintendo Switch OsPlatform* {.pure.} = enum ## the OS this program will run on. none, dos, windows, os2, linux, morphos, skyos, solaris, irix, netbsd, freebsd, openbsd, aix, palmos, qnx, amiga, atari, netware, macos, macosx, haiku, android, js, nimVM, - standalone + standalone, nintendoswitch const targetOS* = when defined(windows): OsPlatform.windows @@ -64,6 +65,7 @@ const elif defined(js): OsPlatform.js elif defined(nimVM): OsPlatform.nimVM elif defined(standalone): OsPlatform.standalone + elif defined(nintendoswitch): OsPlatform.nintendoswitch else: OsPlatform.none ## the OS this program will run on. @@ -86,5 +88,6 @@ const elif defined(avr): CpuPlatform.avr elif defined(msp430): CpuPlatform.msp430 elif defined(riscv64): CpuPlatform.riscv64 + elif defined(armv8a57): CpuPlatform.armv8a57 else: CpuPlatform.none ## the CPU this program will run on. diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index 86b2902308f4..f3a576be094b 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -419,7 +419,7 @@ proc setStdIoUnbuffered() = when declared(stdout): proc echoBinSafe(args: openArray[string]) {.compilerProc.} = # flockfile deadlocks some versions of Android 5.x.x - when not defined(windows) and not defined(android): + when not defined(windows) and not defined(android) and not defined(nintendoswitch): proc flockfile(f: File) {.importc, noDecl.} proc funlockfile(f: File) {.importc, noDecl.} flockfile(stdout) @@ -428,7 +428,7 @@ when declared(stdout): const linefeed = "\n" # can be 1 or more chars discard c_fwrite(linefeed.cstring, linefeed.len, 1, stdout) discard c_fflush(stdout) - when not defined(windows) and not defined(android): + when not defined(windows) and not defined(android) and not defined(nintendoswitch): funlockfile(stdout) {.pop.} diff --git a/lib/system/threads.nim b/lib/system/threads.nim index c8ea03f92976..350fe5d0ccfb 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -185,6 +185,14 @@ else: abi: array[56 div sizeof(clong), clong] ThreadVarSlot {.importc: "pthread_key_t", header: "".} = distinct cuint + elif defined(nintendoswitch): + type + SysThread* {.importc: "pthread_t", + header: "" .} = distinct cuint + Pthread_attr {.importc: "pthread_attr_t", + header: "".} = object + ThreadVarSlot {.importc: "pthread_key_t", + header: "".} = distinct cuint else: type SysThread* {.importc: "pthread_t", header: "".} = object From c3490830e4e36d9e4201250c673428b866e75b06 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 17:12:07 +0900 Subject: [PATCH 04/23] Add GC support for Nintendo Switch --- lib/nintendoswitch/switch_memory.nim | 24 +++++++++++++++++++++++ lib/system/osalloc.nim | 29 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 lib/nintendoswitch/switch_memory.nim diff --git a/lib/nintendoswitch/switch_memory.nim b/lib/nintendoswitch/switch_memory.nim new file mode 100644 index 000000000000..fd0a215def5d --- /dev/null +++ b/lib/nintendoswitch/switch_memory.nim @@ -0,0 +1,24 @@ +const virtMemHeader = "" +const svcHeader = "" +const mallocHeader = "" + +type + Result* = uint32 + +proc memalign*(bytes: csize, size: csize): pointer {.importc: "memalign", + header: mallocHeader.} + +proc free*(address: pointer) {.importc: "free", + header: mallocHeader.} + +proc svcMapMemory*(dst_addr: pointer; src_addr: pointer; size: uint64): Result {. + importc: "svcMapMemory", header: svcHeader.} + +proc svcUnmapMemory*(dst_addr: pointer; src_addr: pointer; size: uint64): Result {. + importc: "svcUnmapMemory", header: svcHeader.} + +proc virtmemReserveMap*(size: csize): pointer {.importc: "virtmemReserveMap", + header: virtMemHeader.} + +proc virtmemFreeMap*(address: pointer; size: csize) {.importc: "virtmemFreeMap", + header: virtMemHeader.} diff --git a/lib/system/osalloc.nim b/lib/system/osalloc.nim index a63eadf8eccf..9b517cf49b70 100644 --- a/lib/system/osalloc.nim +++ b/lib/system/osalloc.nim @@ -80,6 +80,35 @@ when defined(emscripten): elif defined(genode): include genode/alloc # osAllocPages, osTryAllocPages, osDeallocPages +elif defined(nintendoswitch): + import nintendoswitch/switch_memory + + var + stack: pointer + + proc osAllocPages(size: int): pointer {.inline.} = + stack = memalign(0x1000, size) + result = virtmemReserveMap(size.csize) + let rc = svcMapMemory(result, stack, size.uint64) + if rc.uint32 != 0: + #discard svcUnmapMemory(result, stack, size.csize) + raiseOutOfMem() + + proc osTryAllocPages(size: int): pointer {.inline.} = + stack = memalign(0x1000, size) + result = virtmemReserveMap(size.csize) + let rc = svcMapMemory(result, stack, size.uint64) + if rc.uint32 != 0: + #discard svcUnmapMemory(result, stack, size.csize) + result = nil + + proc osDeallocPages(p: pointer, size: int) {.inline.} = + when reallyOsDealloc: + discard svcUnmapMemory(p, stack, size.uint64) + virtmemFreeMap(p, size.csize) + free(stack) + + elif defined(posix): const PROT_READ = 1 # page can be read From c8e0c5a5bb7e1fd5e1c96d015845b9509f602760 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 17:21:43 +0900 Subject: [PATCH 05/23] Update changelog for Nintendo Switch --- changelog.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/changelog.md b/changelog.md index 4067cb69394b..1a90d612db8a 100644 --- a/changelog.md +++ b/changelog.md @@ -170,4 +170,13 @@ - ``experimental`` is now a pragma / command line switch that can enable specific language extensions, it is not an all-or-nothing switch anymore. +- Nintendo Switch was added as a new platform target. Simply add --os:nintendoswitch + to your usual ``nim c`` or ``nim cpp`` command. DevkitPro setup must be the same as + what is the default with their new installer + [here for Mac/Linux](https://github.com/devkitPro/pacman/releases) or + [here for Windows](https://github.com/devkitPro/installer/releases). + Environment variables are ``DEVKITPRO`` for the devkitpro path, ``SWITCH_LIBS`` for any extra + libraries required by your application (``-lLIBNAME`` or ``-LLIBPATH``), and + ``SWITCH_INCLUDES`` for any extra include files (``-IINCLUDE_PATH``). + ### Bugfixes From e4dff3a4416a437cf564d584604f937ca1ca3155 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 17:33:16 +0900 Subject: [PATCH 06/23] Update changelog with more info about fixed paths --- changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.md b/changelog.md index 1a90d612db8a..a0f5f484aba0 100644 --- a/changelog.md +++ b/changelog.md @@ -178,5 +178,7 @@ Environment variables are ``DEVKITPRO`` for the devkitpro path, ``SWITCH_LIBS`` for any extra libraries required by your application (``-lLIBNAME`` or ``-LLIBPATH``), and ``SWITCH_INCLUDES`` for any extra include files (``-IINCLUDE_PATH``). + There are some directories expected to exist in a specific structure for now until I figure out a better way to specify them. They are: ``DEVKITPRO/portlibs/switch/lib``, ``DEVKITPRO/libnx/lib``, + ``DEVKITPRO/portlibs/switch/include``, and ``DEVKITPRO/libnx/include`` ### Bugfixes From 14ebe3e4cf12b3925b03e19691ec9f76a48c63b9 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 19:07:57 +0900 Subject: [PATCH 07/23] Cleaned up GC memory management a bit --- lib/system/osalloc.nim | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/system/osalloc.nim b/lib/system/osalloc.nim index 9b517cf49b70..048077b504aa 100644 --- a/lib/system/osalloc.nim +++ b/lib/system/osalloc.nim @@ -86,28 +86,36 @@ elif defined(nintendoswitch): var stack: pointer - proc osAllocPages(size: int): pointer {.inline.} = + proc alignSize(size: int): int = + (size + 0x00000FFF) and not 0x00000FFF + + proc freeMem(p: pointer, msize: int) = + let size = alignSize(msize) + discard svcUnmapMemory(p, stack, size.uint64) + virtmemFreeMap(p, size.csize) + free(stack) + + proc osAllocPages(msize: int): pointer {.inline.} = + let size = alignSize(msize) stack = memalign(0x1000, size) result = virtmemReserveMap(size.csize) let rc = svcMapMemory(result, stack, size.uint64) if rc.uint32 != 0: - #discard svcUnmapMemory(result, stack, size.csize) + freeMem(result, size) raiseOutOfMem() - proc osTryAllocPages(size: int): pointer {.inline.} = + proc osTryAllocPages(msize: int): pointer {.inline.} = + let size = alignSize(msize) stack = memalign(0x1000, size) result = virtmemReserveMap(size.csize) let rc = svcMapMemory(result, stack, size.uint64) if rc.uint32 != 0: - #discard svcUnmapMemory(result, stack, size.csize) + freeMem(result, size) result = nil proc osDeallocPages(p: pointer, size: int) {.inline.} = when reallyOsDealloc: - discard svcUnmapMemory(p, stack, size.uint64) - virtmemFreeMap(p, size.csize) - free(stack) - + freeMem(p, size) elif defined(posix): const From ed18079e8a5b3678d766e4ac994dafff750c862b Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 19:23:58 +0900 Subject: [PATCH 08/23] Relocate docs for Switch --- changelog.md | 12 ++---------- doc/nimc.rst | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/changelog.md b/changelog.md index a0f5f484aba0..a10b6218645d 100644 --- a/changelog.md +++ b/changelog.md @@ -170,15 +170,7 @@ - ``experimental`` is now a pragma / command line switch that can enable specific language extensions, it is not an all-or-nothing switch anymore. -- Nintendo Switch was added as a new platform target. Simply add --os:nintendoswitch - to your usual ``nim c`` or ``nim cpp`` command. DevkitPro setup must be the same as - what is the default with their new installer - [here for Mac/Linux](https://github.com/devkitPro/pacman/releases) or - [here for Windows](https://github.com/devkitPro/installer/releases). - Environment variables are ``DEVKITPRO`` for the devkitpro path, ``SWITCH_LIBS`` for any extra - libraries required by your application (``-lLIBNAME`` or ``-LLIBPATH``), and - ``SWITCH_INCLUDES`` for any extra include files (``-IINCLUDE_PATH``). - There are some directories expected to exist in a specific structure for now until I figure out a better way to specify them. They are: ``DEVKITPRO/portlibs/switch/lib``, ``DEVKITPRO/libnx/lib``, - ``DEVKITPRO/portlibs/switch/include``, and ``DEVKITPRO/libnx/include`` +- Nintendo Switch was added as a new platform target. See [the compiler user guide](https://nim-lang.org/docs/nimc.html) + for more info. ### Bugfixes diff --git a/doc/nimc.rst b/doc/nimc.rst index 29dbdea42900..e19d4ad2f41e 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -228,6 +228,29 @@ configuration file should contain something like:: arm.linux.gcc.exe = "arm-linux-gcc" arm.linux.gcc.linkerexe = "arm-linux-gcc" +Cross compilation for Nintendo Switch +===================================== + +Simply add --os:nintendoswitch +to your usual ``nim c`` or ``nim cpp`` command. DevkitPro setup must be the same as +what is the default with their new installer +[here for Mac/Linux](https://github.com/devkitPro/pacman/releases) or +[here for Windows](https://github.com/devkitPro/installer/releases). + +For example:: + + nim c --os:nintendoswitch switchhomebrew.nim + +This will generate a file called ``switchhomebrew.elf`` which can then be turned into +an nro file with the ``elf2nro`` tool in the DevkitPro release. Examples can be found at +[the nim-libnx github repo](https://github.com/jyapayne/nim-libnx.git). + +Environment variables are ``DEVKITPRO`` for the devkitpro path, ``SWITCH_LIBS`` for any extra +libraries required by your application (``-lLIBNAME`` or ``-LLIBPATH``), and +``SWITCH_INCLUDES`` for any extra include files (``-IINCLUDE_PATH``). + +There are some directories expected to exist in a specific structure for now until I figure out a better way to specify them. They are: ``DEVKITPRO/portlibs/switch/lib``, ``DEVKITPRO/libnx/lib``, +``DEVKITPRO/portlibs/switch/include``, and ``DEVKITPRO/libnx/include``. DLL generation ============== From 0cf2e68648f5c59e48fb2c68a70416941a77f9ee Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 19:35:14 +0900 Subject: [PATCH 09/23] Rename aarch64NoneElfGcc to nintendoSwitchGCC --- compiler/extccomp.nim | 4 ++-- compiler/options.nim | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 5a890b790365..51f4d38ae9a5 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -84,7 +84,7 @@ compiler gcc: hasAttribute}) # GNU C and C++ Compiler -compiler aarch64NoneElfGCC: +compiler nintendoSwitchGCC: result = ( name: "switch_gcc", objExt: "o", @@ -341,7 +341,7 @@ compiler ucc: const CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [ gcc(), - aarch64NoneElfGCC(), + nintendoSwitchGCC(), llvmGcc(), clang(), lcc(), diff --git a/compiler/options.nim b/compiler/options.nim index aea55e94fdef..1516a40706b0 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -124,7 +124,7 @@ type disabledSf, writeOnlySf, readOnlySf, v2Sf TSystemCC* = enum - ccNone, ccGcc, ccaarch64NoneElfGcc, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, + ccNone, ccGcc, ccNintendoSwitch, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, ccTcc, ccPcc, ccUcc, ccIcl, ccIcc CfileFlag* {.pure.} = enum From 1935c1695c299c17a81534e9e87714de38dd0e54 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 19:35:44 +0900 Subject: [PATCH 10/23] Remove armv8a57 --- compiler/platform.nim | 5 ++--- lib/system/platforms.nim | 4 +--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/platform.nim b/compiler/platform.nim index 14ce4e0f7b0d..7eb8978168c8 100644 --- a/compiler/platform.nim +++ b/compiler/platform.nim @@ -181,7 +181,7 @@ type cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64, cpuPowerpc64el, cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuMipsel, cpuArm, cpuArm64, cpuJS, cpuNimVM, cpuAVR, cpuMSP430, cpuSparc64, - cpuMips64, cpuMips64el, cpuRiscV64, cpuArmv8A57 + cpuMips64, cpuMips64el, cpuRiscV64 type TEndian* = enum @@ -213,8 +213,7 @@ const (name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64), (name: "mips64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64), (name: "mips64el", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64), - (name: "riscv64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64), - (name: "armv8a57", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64)] + (name: "riscv64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64)] type Target* = object diff --git a/lib/system/platforms.nim b/lib/system/platforms.nim index aab270312432..31d2cb01e183 100644 --- a/lib/system/platforms.nim +++ b/lib/system/platforms.nim @@ -31,8 +31,7 @@ type vm, ## Some Virtual machine: Nim's VM or JavaScript avr, ## AVR based processor msp430, ## TI MSP430 microcontroller - riscv64, ## RISC-V 64-bit processor - armv8a57 ## Arm Cortex A57 64-bit processor for Nintendo Switch + riscv64 ## RISC-V 64-bit processor OsPlatform* {.pure.} = enum ## the OS this program will run on. none, dos, windows, os2, linux, morphos, skyos, solaris, @@ -88,6 +87,5 @@ const elif defined(avr): CpuPlatform.avr elif defined(msp430): CpuPlatform.msp430 elif defined(riscv64): CpuPlatform.riscv64 - elif defined(armv8a57): CpuPlatform.armv8a57 else: CpuPlatform.none ## the CPU this program will run on. From f7ec3438f2b81e7d0b2f77d3509bfa66c9eec0d2 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 19:37:37 +0900 Subject: [PATCH 11/23] Fix installer.ini --- compiler/installer.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/installer.ini b/compiler/installer.ini index 7ee98622995e..79eb7178aa5b 100644 --- a/compiler/installer.ini +++ b/compiler/installer.ini @@ -15,7 +15,7 @@ Platforms: """ dragonfly: i386;amd64 haiku: i386;amd64 android: i386;arm;arm64 - nintendoswitch: armv8a57 + nintendoswitch: arm64 """ Authors: "Andreas Rumpf" From 3afe34468f82cc511577c02f675fba3452db9cf0 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 19 Jun 2018 19:38:05 +0900 Subject: [PATCH 12/23] Reuse code in linux and amd64 --- lib/system/threads.nim | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/system/threads.nim b/lib/system/threads.nim index 350fe5d0ccfb..df145628b971 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -176,7 +176,7 @@ else: else: type Time = int - when defined(linux) and defined(amd64): + when defined(linux) and defined(amd64) and defined(nintendoswitch): type SysThread* {.importc: "pthread_t", header: "" .} = distinct culong @@ -185,14 +185,6 @@ else: abi: array[56 div sizeof(clong), clong] ThreadVarSlot {.importc: "pthread_key_t", header: "".} = distinct cuint - elif defined(nintendoswitch): - type - SysThread* {.importc: "pthread_t", - header: "" .} = distinct cuint - Pthread_attr {.importc: "pthread_attr_t", - header: "".} = object - ThreadVarSlot {.importc: "pthread_key_t", - header: "".} = distinct cuint else: type SysThread* {.importc: "pthread_t", header: "".} = object From 9b300a5c9cc6ce209365e9eda1dce20687d06889 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Fri, 22 Jun 2018 10:44:28 +0900 Subject: [PATCH 13/23] Add posix defs for nintendo switch --- lib/posix/posix.nim | 68 ++-- lib/posix/posix_nintendoswitch.nim | 514 +++++++++++++++++++++++++++++ 2 files changed, 550 insertions(+), 32 deletions(-) create mode 100644 lib/posix/posix_nintendoswitch.nim diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index db5f575afb85..97b4124ec417 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -94,6 +94,8 @@ const StatHasNanoseconds* = defined(linux) or defined(freebsd) or when defined(linux) and defined(amd64): include posix_linux_amd64 +elif defined(nintendoswitch): + include posix_nintendoswitch else: include posix_other @@ -185,7 +187,7 @@ proc fnmatch*(a1, a2: cstring, a3: cint): cint {.importc, header: "". proc ftw*(a1: cstring, a2: proc (x1: cstring, x2: ptr Stat, x3: cint): cint {.noconv.}, a3: cint): cint {.importc, header: "".} -when not (defined(linux) and defined(amd64)): +when not (defined(linux) and defined(amd64)) and not defined(nintendoswitch): proc nftw*(a1: cstring, a2: proc (x1: cstring, x2: ptr Stat, x3: cint, x4: ptr FTW): cint {.noconv.}, @@ -226,25 +228,26 @@ proc setlocale*(a1: cint, a2: cstring): cstring {. proc strfmon*(a1: cstring, a2: int, a3: cstring): int {.varargs, importc, header: "".} -proc mq_close*(a1: Mqd): cint {.importc, header: "".} -proc mq_getattr*(a1: Mqd, a2: ptr MqAttr): cint {. - importc, header: "".} -proc mq_notify*(a1: Mqd, a2: ptr SigEvent): cint {. - importc, header: "".} -proc mq_open*(a1: cstring, a2: cint): Mqd {. - varargs, importc, header: "".} -proc mq_receive*(a1: Mqd, a2: cstring, a3: int, a4: var int): int {. - importc, header: "".} -proc mq_send*(a1: Mqd, a2: cstring, a3: int, a4: int): cint {. - importc, header: "".} -proc mq_setattr*(a1: Mqd, a2, a3: ptr MqAttr): cint {. - importc, header: "".} - -proc mq_timedreceive*(a1: Mqd, a2: cstring, a3: int, a4: int, - a5: ptr Timespec): int {.importc, header: "".} -proc mq_timedsend*(a1: Mqd, a2: cstring, a3: int, a4: int, - a5: ptr Timespec): cint {.importc, header: "".} -proc mq_unlink*(a1: cstring): cint {.importc, header: "".} +when not defined(nintendoswitch): + proc mq_close*(a1: Mqd): cint {.importc, header: "".} + proc mq_getattr*(a1: Mqd, a2: ptr MqAttr): cint {. + importc, header: "".} + proc mq_notify*(a1: Mqd, a2: ptr SigEvent): cint {. + importc, header: "".} + proc mq_open*(a1: cstring, a2: cint): Mqd {. + varargs, importc, header: "".} + proc mq_receive*(a1: Mqd, a2: cstring, a3: int, a4: var int): int {. + importc, header: "".} + proc mq_send*(a1: Mqd, a2: cstring, a3: int, a4: int): cint {. + importc, header: "".} + proc mq_setattr*(a1: Mqd, a2, a3: ptr MqAttr): cint {. + importc, header: "".} + + proc mq_timedreceive*(a1: Mqd, a2: cstring, a3: int, a4: int, + a5: ptr Timespec): int {.importc, header: "".} + proc mq_timedsend*(a1: Mqd, a2: cstring, a3: int, a4: int, + a5: ptr Timespec): cint {.importc, header: "".} + proc mq_unlink*(a1: cstring): cint {.importc, header: "".} proc getpwnam*(a1: cstring): ptr Passwd {.importc, header: "".} @@ -603,7 +606,7 @@ proc posix_madvise*(a1: pointer, a2: int, a3: cint): cint {. importc, header: "".} proc posix_mem_offset*(a1: pointer, a2: int, a3: var Off, a4: var int, a5: var cint): cint {.importc, header: "".} -when not (defined(linux) and defined(amd64)): +when not (defined(linux) and defined(amd64)) and not defined(nintendoswitch): proc posix_typed_mem_get_info*(a1: cint, a2: var Posix_typed_mem_info): cint {.importc, header: "".} proc posix_typed_mem_open*(a1: cstring, a2, a3: cint): cint {. @@ -713,12 +716,12 @@ proc sigwait*(a1: var Sigset, a2: var cint): cint {. proc sigwaitinfo*(a1: var Sigset, a2: var SigInfo): cint {. importc, header: "".} - -proc catclose*(a1: Nl_catd): cint {.importc, header: "".} -proc catgets*(a1: Nl_catd, a2, a3: cint, a4: cstring): cstring {. - importc, header: "".} -proc catopen*(a1: cstring, a2: cint): Nl_catd {. - importc, header: "".} +when not defined(nintendoswitch): + proc catclose*(a1: Nl_catd): cint {.importc, header: "".} + proc catgets*(a1: Nl_catd, a2, a3: cint, a4: cstring): cstring {. + importc, header: "".} + proc catopen*(a1: cstring, a2: cint): Nl_catd {. + importc, header: "".} proc sched_get_priority_max*(a1: cint): cint {.importc, header: "".} proc sched_get_priority_min*(a1: cint): cint {.importc, header: "".} @@ -800,11 +803,12 @@ when hasSpawnH: a4: var Tposix_spawnattr, a5, a6: cstringArray): cint {.importc, header: "".} -proc getcontext*(a1: var Ucontext): cint {.importc, header: "".} -proc makecontext*(a1: var Ucontext, a4: proc (){.noconv.}, a3: cint) {. - varargs, importc, header: "".} -proc setcontext*(a1: var Ucontext): cint {.importc, header: "".} -proc swapcontext*(a1, a2: var Ucontext): cint {.importc, header: "".} +when not defined(nintendoswitch): + proc getcontext*(a1: var Ucontext): cint {.importc, header: "".} + proc makecontext*(a1: var Ucontext, a4: proc (){.noconv.}, a3: cint) {. + varargs, importc, header: "".} + proc setcontext*(a1: var Ucontext): cint {.importc, header: "".} + proc swapcontext*(a1, a2: var Ucontext): cint {.importc, header: "".} proc readv*(a1: cint, a2: ptr IOVec, a3: cint): int {. importc, header: "".} diff --git a/lib/posix/posix_nintendoswitch.nim b/lib/posix/posix_nintendoswitch.nim new file mode 100644 index 000000000000..7b482a504f9c --- /dev/null +++ b/lib/posix/posix_nintendoswitch.nim @@ -0,0 +1,514 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2018 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# Types here should conform to the glibc ABI on linux / x86_64 +# When adding a type, the order and size of fields must match + +# To be included from posix.nim! + +{.deadCodeElim: on.} # dce option deprecated + +const + hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays + hasAioH = defined(linux) + +type + DIR* {.importc: "DIR", header: "", + incompleteStruct.} = object + ## A type representing a directory stream. + +const SIG_HOLD* = cast[SigHandler](2) + +type + SocketHandle* = distinct cint # The type used to represent socket descriptors + +type + Time* {.importc: "time_t", header: "".} = distinct clong + + Timespec* {.importc: "struct timespec", + header: "", final, pure.} = object ## struct timespec + tv_sec*: Time ## Seconds. + tv_nsec*: clong ## Nanoseconds. + + Dirent* {.importc: "struct dirent", + header: "", final, pure.} = object ## dirent_t struct + d_ino*: Ino + d_type*: int8 # cuchar really! + d_name*: array[256, cchar] + + Tflock* {.importc: "struct flock", final, pure, + header: "".} = object ## flock type + l_type*: cshort ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. + l_whence*: cshort ## Flag for starting offset. + l_start*: Off ## Relative offset in bytes. + l_len*: Off ## Size; if 0 then until EOF. + l_pid*: Pid ## Process ID of the process holding the lock; + ## returned with F_GETLK. + + # no struct FTW on linux + + Glob* {.importc: "glob_t", header: "", + final, pure.} = object ## glob_t + gl_pathc*: cint ## Count of paths matched by pattern. + gl_matchc*: cint ## Count of paths matching pattern + gl_offs*: cint ## Slots to reserve at the beginning of gl_pathv. + gl_flags*: cint + gl_pathv*: cstringArray ## Pointer to a list of matched pathnames. + gl_errfunc*: pointer + gl_closedir*: pointer + gl_readdir*: pointer + gl_opendir*: pointer + gl_lstat*: pointer + gl_stat*: pointer + + Group* {.importc: "struct group", header: "", + final, pure.} = object ## struct group + gr_name*: cstring ## The name of the group. + gr_passwd*: cstring + gr_gid*: Gid ## Numerical group ID. + gr_mem*: cstringArray ## Pointer to a null-terminated array of character + ## pointers to member names. + + Iconv* {.importc: "iconv_t", header: "".} = pointer + ## Identifies the conversion from one codeset to another. + + Lconv* {.importc: "struct lconv", header: "", final, + pure.} = object + decimal_point*: cstring + thousands_sep*: cstring + grouping*: cstring + int_curr_symbol*: cstring + currency_symbol*: cstring + mon_decimal_point*: cstring + mon_thousands_sep*: cstring + mon_grouping*: cstring + positive_sign*: cstring + negative_sign*: cstring + int_frac_digits*: char + frac_digits*: char + p_cs_precedes*: char + p_sep_by_space*: char + n_cs_precedes*: char + n_sep_by_space*: char + p_sign_posn*: char + n_sign_posn*: char + int_n_cs_precedes*: char + int_n_sep_by_space*: char + int_n_sign_posn*: char + int_p_cs_precedes*: char + int_p_sep_by_space*: char + int_p_sign_posn*: char + + Passwd* {.importc: "struct passwd", header: "", + final, pure.} = object ## struct passwd + pw_name*: cstring ## User's login name. + pw_passwd*: cstring + pw_uid*: Uid ## Numerical user ID. + pw_gid*: Gid ## Numerical group ID. + pw_comment*: cstring + pw_gecos*: cstring + pw_dir*: cstring ## Initial working directory. + pw_shell*: cstring ## Program to use as shell. + + Blkcnt* {.importc: "blkcnt_t", header: "".} = clong + ## used for file block counts + Blksize* {.importc: "blksize_t", header: "".} = clong + ## used for block sizes + Clock* {.importc: "clock_t", header: "".} = clong + ClockId* {.importc: "clockid_t", header: "".} = cint + Dev* {.importc: "dev_t", header: "".} = culong + Fsblkcnt* {.importc: "fsblkcnt_t", header: "".} = culong + Fsfilcnt* {.importc: "fsfilcnt_t", header: "".} = culong + Gid* {.importc: "gid_t", header: "".} = cuint + Id* {.importc: "id_t", header: "".} = cuint + Ino* {.importc: "ino_t", header: "".} = culong + Key* {.importc: "key_t", header: "".} = cint + Mode* {.importc: "mode_t", header: "".} = cint # cuint really! + Nlink* {.importc: "nlink_t", header: "".} = culong + Off* {.importc: "off_t", header: "".} = clong + Pid* {.importc: "pid_t", header: "".} = cint + Pthread_attr* {.importc: "pthread_attr_t", header: "", + pure, final.} = object + abi: array[56 div sizeof(clong), clong] + + Pthread_barrier* {.importc: "pthread_barrier_t", + header: "", pure, final.} = object + abi: array[32 div sizeof(clong), clong] + Pthread_barrierattr* {.importc: "pthread_barrierattr_t", + header: "", pure, final.} = object + abi: array[4 div sizeof(cint), cint] + + Pthread_cond* {.importc: "pthread_cond_t", header: "", + pure, final.} = object + abi: array[48 div sizeof(clonglong), clonglong] + Pthread_condattr* {.importc: "pthread_condattr_t", + header: "", pure, final.} = object + abi: array[4 div sizeof(cint), cint] + Pthread_key* {.importc: "pthread_key_t", header: "".} = cuint + Pthread_mutex* {.importc: "pthread_mutex_t", header: "", + pure, final.} = object + abi: array[48 div sizeof(clong), clong] + Pthread_mutexattr* {.importc: "pthread_mutexattr_t", + header: "", pure, final.} = object + abi: array[4 div sizeof(cint), cint] + Pthread_once* {.importc: "pthread_once_t", header: "".} = cint + Pthread_rwlock* {.importc: "pthread_rwlock_t", + header: "", pure, final.} = object + abi: array[56 div sizeof(clong), clong] + Pthread_rwlockattr* {.importc: "pthread_rwlockattr_t", + header: "".} = object + abi: array[8 div sizeof(clong), clong] + Pthread_spinlock* {.importc: "pthread_spinlock_t", + header: "".} = cint + Pthread* {.importc: "pthread_t", header: "".} = culong + Suseconds* {.importc: "suseconds_t", header: "".} = clong + #Ttime* {.importc: "time_t", header: "".} = int + Timer* {.importc: "timer_t", header: "".} = pointer + Uid* {.importc: "uid_t", header: "".} = cuint + Useconds* {.importc: "useconds_t", header: "".} = cuint + + Utsname* {.importc: "struct utsname", + header: "", + final, pure.} = object ## struct utsname + sysname*, ## Name of this implementation of the operating system. + nodename*, ## Name of this node within the communications + ## network to which this node is attached, if any. + release*, ## Current release level of this implementation. + version*, ## Current version level of this release. + machine*, ## Name of the hardware type on which the + ## system is running. + domainname*: array[65, char] + + Sem* {.importc: "sem_t", header: "", final, pure.} = object + abi: array[32 div sizeof(clong), clong] + + Stat* {.importc: "struct stat", + header: "", final, pure.} = object ## struct stat + st_dev*: Dev ## Device ID of device containing file. + st_ino*: Ino ## File serial number. + st_mode*: Mode ## Mode of file (see below). + st_nlink*: Nlink ## Number of hard links to the file. + st_uid*: Uid ## User ID of file. + st_gid*: Gid ## Group ID of file. + st_rdev*: Dev ## Device ID (if file is character or block special). + st_size*: Off ## For regular files, the file size in bytes. + ## For symbolic links, the length in bytes of the + ## pathname contained in the symbolic link. + ## For a shared 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 + ## unspecified. + when StatHasNanoseconds: + st_atim*: Timespec ## Time of last access. + pad1: clong + st_mtim*: Timespec ## Time of last data modification. + pad2: clong + st_ctim*: Timespec ## Time of last status change. + pad3: clong + else: + st_atime*: Time ## Time of last access. + pad1: clong + st_mtime*: Time ## Time of last data modification. + pad2: clong + st_ctime*: Time ## Time of last status change. + pad3: clong + st_blksize*: Blksize ## A file system-specific preferred I/O block size + ## for this object. In some file system types, this + ## may vary from file to file. + st_blocks*: Blkcnt ## Number of blocks allocated for this object. + reserved: array[2, clong] + + + + Statvfs* {.importc: "struct statvfs", header: "", + final, pure.} = object ## struct statvfs + f_bsize*: culong ## File system block size. + f_frsize*: culong ## Fundamental file system block size. + f_blocks*: Fsblkcnt ## Total number of blocks on file system + ## in units of f_frsize. + f_bfree*: Fsblkcnt ## Total number of free blocks. + f_bavail*: Fsblkcnt ## Number of free blocks available to + ## non-privileged process. + f_files*: Fsfilcnt ## Total number of file serial numbers. + f_ffree*: Fsfilcnt ## Total number of free file serial numbers. + f_favail*: Fsfilcnt ## Number of file serial numbers available to + ## non-privileged process. + f_fsid*: culong ## File system ID. + f_flag*: culong ## Bit mask of f_flag values. + f_namemax*: culong ## Maximum filename length. + + # No Posix_typed_mem_info + + Tm* {.importc: "struct tm", header: "", + final, pure.} = object ## struct tm + tm_sec*: cint ## Seconds [0,60]. + tm_min*: cint ## Minutes [0,59]. + tm_hour*: cint ## Hour [0,23]. + tm_mday*: cint ## Day of month [1,31]. + tm_mon*: cint ## Month of year [0,11]. + tm_year*: cint ## Years since 1900. + tm_wday*: cint ## Day of week [0,6] (Sunday =0). + tm_yday*: cint ## Day of year [0,365]. + tm_isdst*: cint ## Daylight Savings flag. + + Itimerspec* {.importc: "struct itimerspec", header: "", + final, pure.} = object ## struct itimerspec + it_interval*: Timespec ## Timer period. + it_value*: Timespec ## Timer expiration. + + Sig_atomic* {.importc: "sig_atomic_t", header: "".} = cint + ## Possibly volatile-qualified integer type of an object that can be + ## accessed as an atomic entity, even in the presence of asynchronous + ## interrupts. + Sigset* {.importc: "sigset_t", header: "", final.} = culong + + SigEvent* {.importc: "struct sigevent", + header: "", final, pure.} = object ## struct sigevent + sigev_notify*: cint ## Notification type. + sigev_signo*: cint ## Signal number. + sigev_value*: SigVal ## Signal value. + + SigVal* {.importc: "union sigval", + header: "", final, pure.} = object ## struct sigval + sival_int*: cint ## integer signal value + sival_ptr*: pointer ## pointer signal value; + + Sigaction* {.importc: "struct sigaction", + header: "", final, pure.} = object ## struct sigaction + sa_handler*: proc (x: cint) {.noconv.} ## Pointer to a signal-catching + ## function or one of the macros + ## SIG_IGN or SIG_DFL. + sa_mask*: Sigset ## Set of signals to be blocked during execution of + ## the signal handling function. + sa_flags*: cint ## Special flags. + + Stack* {.importc: "stack_t", + header: "", final, pure.} = object ## stack_t + ss_sp*: pointer ## Stack base or pointer. + ss_flags*: cint ## Flags. + ss_size*: csize ## Stack size. + + SigInfo* {.importc: "siginfo_t", + header: "", final, pure.} = object ## siginfo_t + si_signo*: cint ## Signal number. + si_code*: cint ## Signal code. + si_value*: SigVal ## Signal value. + + Nl_item* {.importc: "nl_item", header: "".} = cint + + Sched_param* {.importc: "struct sched_param", + header: "", + final, pure.} = object ## struct sched_param + sched_priority*: cint + + Timeval* {.importc: "struct timeval", header: "", + final, pure.} = object ## struct timeval + tv_sec*: Time ## Seconds. + tv_usec*: Suseconds ## Microseconds. + TFdSet* {.importc: "fd_set", header: "", + final, pure.} = object + abi: array[((64+(sizeof(clong) * 8)-1) div (sizeof(clong) * 8)), clong] + +proc si_pid*(info: SigInfo): Pid = + ## This might not be correct behavior. si_pid doesn't exist in Switch's + ## devkitpro headers + raise newException(OSError, "Nintendo switch cannot get si_pid!") + +type + Taiocb* {.importc: "struct aiocb", header: "", + final, pure.} = object ## struct aiocb + aio_fildes*: cint ## File descriptor. + aio_lio_opcode*: cint ## Operation to be performed. + aio_reqprio*: cint ## Request priority offset. + aio_buf*: pointer ## Location of buffer. + aio_nbytes*: csize ## Length of transfer. + aio_sigevent*: SigEvent ## Signal number and value. + next_prio: pointer + abs_prio: cint + policy: cint + error_Code: cint + return_value: clong + aio_offset*: Off ## File offset. + reserved: array[32, uint8] + +when hasSpawnH: + type + Tposix_spawnattr* {.importc: "posix_spawnattr_t", + header: "", final, pure.} = object + Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", + header: "", final, pure.} = object + +# from sys/un.h +const Sockaddr_un_path_length* = 108 + +type + Socklen* {.importc: "socklen_t", header: "".} = cuint + # cushort really + TSa_Family* {.importc: "sa_family_t", header: "".} = cshort + + SockAddr* {.importc: "struct sockaddr", header: "", + pure, final.} = object ## struct sockaddr + sa_len: cuchar + sa_family*: TSa_Family ## Address family. + sa_data*: array[14, char] ## Socket address (variable-length data). + + Sockaddr_storage* {.importc: "struct sockaddr_storage", + header: "", + pure, final.} = object ## struct sockaddr_storage + ss_len: cuchar + ss_family*: TSa_Family ## Address family. + ss_padding1: array[64 - sizeof(cuchar) - sizeof(cshort), char] + ss_align: clonglong + ss_padding2: array[ + 128 - sizeof(cuchar) - sizeof(cshort) - + (64 - sizeof(cuchar) - sizeof(cshort)) - 64, char] + + Tif_nameindex* {.importc: "struct if_nameindex", final, + pure, header: "".} = object ## struct if_nameindex + if_index*: cuint ## Numeric index of the interface. + if_name*: cstring ## Null-terminated name of the interface. + + + IOVec* {.importc: "struct iovec", pure, final, + header: "".} = object ## struct iovec + iov_base*: pointer ## Base address of a memory region for input or output. + iov_len*: csize ## The size of the memory pointed to by iov_base. + + Tmsghdr* {.importc: "struct msghdr", pure, final, + header: "".} = object ## struct msghdr + msg_name*: pointer ## Optional address. + msg_namelen*: Socklen ## Size of address. + msg_iov*: ptr IOVec ## Scatter/gather array. + msg_iovlen*: csize ## Members in msg_iov. + msg_control*: pointer ## Ancillary data; see below. + msg_controllen*: csize ## Ancillary data buffer len. + msg_flags*: cint ## Flags on received message. + + + Tcmsghdr* {.importc: "struct cmsghdr", pure, final, + header: "".} = object ## struct cmsghdr + cmsg_len*: csize ## Data byte count, including the cmsghdr. + cmsg_level*: cint ## Originating protocol. + cmsg_type*: cint ## Protocol-specific type. + + TLinger* {.importc: "struct linger", pure, final, + header: "".} = object ## struct linger + l_onoff*: cint ## Indicates whether linger option is enabled. + l_linger*: cint ## Linger time, in seconds. + # data follows... + + InPort* = uint16 + InAddrScalar* = uint32 + + InAddrT* {.importc: "in_addr_t", pure, final, + header: "".} = uint32 + + InAddr* {.importc: "struct in_addr", pure, final, + header: "".} = object ## struct in_addr + s_addr*: InAddrScalar + + Sockaddr_in* {.importc: "struct sockaddr_in", pure, final, + header: "".} = object ## struct sockaddr_in + sin_len*: cushort + sin_family*: TSa_Family ## AF_INET. + sin_port*: InPort ## Port number. + sin_addr*: InAddr ## IP address. + sin_zero: array[8, uint8] + + In6Addr* {.importc: "struct in6_addr", pure, final, + header: "".} = object ## struct in6_addr + s6_addr*: array[0..15, char] + + Sockaddr_in6* {.importc: "struct sockaddr_in6", pure, final, + header: "".} = object ## struct sockaddr_in6 + sin6_family*: TSa_Family ## AF_INET6. + sin6_port*: InPort ## Port number. + sin6_flowinfo*: uint32 ## IPv6 traffic class and flow information. + sin6_addr*: In6Addr ## IPv6 address. + sin6_scope_id*: uint32 ## Set of interfaces for a scope. + + Hostent* {.importc: "struct hostent", pure, final, + header: "".} = object ## struct hostent + h_name*: cstring ## Official name of the host. + h_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative host names, terminated by a + ## null pointer. + h_addrtype*: cint ## Address type. + h_length*: cint ## The length, in bytes, of the address. + h_addr_list*: cstringArray ## A pointer to an array of pointers to network + ## addresses (in network byte order) for the + ## host, terminated by a null pointer. + + Tnetent* {.importc: "struct netent", pure, final, + header: "".} = object ## struct netent + n_name*: cstring ## Official, fully-qualified (including the + ## domain) name of the host. + n_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative network names, terminated by a + ## null pointer. + n_addrtype*: cint ## The address type of the network. + n_net*: uint32 ## The network number, in host byte order. + + Protoent* {.importc: "struct protoent", pure, final, + header: "".} = object ## struct protoent + p_name*: cstring ## Official name of the protocol. + p_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative protocol names, terminated by + ## a null pointer. + p_proto*: cint ## The protocol number. + + Servent* {.importc: "struct servent", pure, final, + header: "".} = object ## struct servent + s_name*: cstring ## Official name of the service. + s_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative service names, terminated by + ## a null pointer. + s_port*: cint ## The port number at which the service + ## resides, in network byte order. + s_proto*: cstring ## The name of the protocol to use when + ## contacting the service. + + AddrInfo* {.importc: "struct addrinfo", pure, final, + header: "".} = object ## struct addrinfo + ai_flags*: cint ## Input flags. + ai_family*: cint ## Address family of socket. + ai_socktype*: cint ## Socket type. + ai_protocol*: cint ## Protocol of socket. + ai_addrlen*: Socklen ## Length of socket address. + ai_canonname*: cstring ## Canonical name of service location. + ai_addr*: ptr SockAddr ## Socket address of socket. + ai_next*: ptr AddrInfo ## Pointer to next in list. + + TPollfd* {.importc: "struct pollfd", pure, final, + header: "".} = object ## struct pollfd + fd*: cint ## The following descriptor being polled. + events*: cshort ## The input event flags (see below). + revents*: cshort ## The output event flags (see below). + + Tnfds* {.importc: "nfds_t", header: "".} = culong + +var + errno* {.importc, header: "".}: cint ## error variable + h_errno* {.importc, header: "".}: cint + daylight* {.importc: "_daylight", header: "".}: cint + timezone* {.importc: "_timezone", header: "".}: clong + +# Regenerate using detect.nim! +include posix_linux_amd64_consts + +const POSIX_SPAWN_USEVFORK* = cint(0x40) # needs _GNU_SOURCE! + +# +proc WEXITSTATUS*(s: cint): cint = (s and 0xff00) shr 8 +proc WTERMSIG*(s:cint): cint = s and 0x7f +proc WSTOPSIG*(s:cint): cint = WEXITSTATUS(s) +proc WIFEXITED*(s:cint) : bool = WTERMSIG(s) == 0 +proc WIFSIGNALED*(s:cint) : bool = (cast[int8]((s and 0x7f) + 1) shr 1) > 0 +proc WIFSTOPPED*(s:cint) : bool = (s and 0xff) == 0x7f +proc WIFCONTINUED*(s:cint) : bool = s == W_CONTINUED From d3cf79e3e7ebacbc50f4dde508b28d4f9d46e3fe Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Fri, 22 Jun 2018 10:47:37 +0900 Subject: [PATCH 14/23] Add more defined sections for nintendo switch --- lib/pure/dynlib.nim | 22 ++++++++++++++++++++++ lib/pure/os.nim | 31 +++++++++++++++++++------------ lib/pure/ospaths.nim | 2 +- lib/pure/times.nim | 4 ++-- lib/system/threads.nim | 2 +- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim index 5bd06f6fb323..d030ad532e94 100644 --- a/lib/pure/dynlib.nim +++ b/lib/pure/dynlib.nim @@ -137,6 +137,28 @@ when defined(posix): proc symAddr(lib: LibHandle, name: cstring): pointer = return dlsym(lib, name) +elif defined(nintendoswitch): + # + # ========================================================================= + # Nintendo switch DevkitPro sdk does not have these. Raise an error if called. + # ========================================================================= + # + + proc dlclose(lib: LibHandle) = + raise newException(OSError, "dlclose not implemented on Nintendo Switch!") + proc dlopen(path: cstring, mode: int): LibHandle = + raise newException(OSError, "dlopen not implemented on Nintendo Switch!") + proc dlsym(lib: LibHandle, name: cstring): pointer = + raise newException(OSError, "dlsym not implemented on Nintendo Switch!") + proc loadLib(path: string, global_symbols=false): LibHandle = + raise newException(OSError, "loadLib not implemented on Nintendo Switch!") + proc loadLib(): LibHandle = + raise newException(OSError, "loadLib not implemented on Nintendo Switch!") + proc unloadLib(lib: LibHandle) = + raise newException(OSError, "unloadLib not implemented on Nintendo Switch!") + proc symAddr(lib: LibHandle, name: cstring): pointer = + raise newException(OSError, "symAddr not implemented on Nintendo Switch!") + elif defined(windows) or defined(dos): # # ======================================================================= diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 90c52657cffe..e81f87e0a043 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -21,7 +21,7 @@ import when defined(windows): import winlean -elif defined(posix): +elif defined(posix) or defined(nintendoswitch): import posix proc toTime(ts: Timespec): times.Time {.inline.} = @@ -187,7 +187,7 @@ proc findExe*(exe: string, followSymlinks: bool = true; proc getLastModificationTime*(file: string): times.Time {.rtl, extern: "nos$1".} = ## Returns the `file`'s last modification time. - when defined(posix): + when defined(posix) or defined(nintendoswitch): var res: Stat if stat(file, res) < 0'i32: raiseOSError(osLastError()) result = res.st_mtim.toTime @@ -200,7 +200,7 @@ proc getLastModificationTime*(file: string): times.Time {.rtl, extern: "nos$1".} proc getLastAccessTime*(file: string): times.Time {.rtl, extern: "nos$1".} = ## Returns the `file`'s last read or write access time. - when defined(posix): + when defined(posix) or defined(nintendoswitch): var res: Stat if stat(file, res) < 0'i32: raiseOSError(osLastError()) result = res.st_atim.toTime @@ -217,7 +217,7 @@ proc getCreationTime*(file: string): times.Time {.rtl, extern: "nos$1".} = ## **Note:** Under POSIX OS's, the returned time may actually be the time at ## which the file's attribute's were last modified. See ## `here `_ for details. - when defined(posix): + when defined(posix) or defined(nintendoswitch): var res: Stat if stat(file, res) < 0'i32: raiseOSError(osLastError()) result = res.st_ctim.toTime @@ -231,7 +231,7 @@ proc getCreationTime*(file: string): times.Time {.rtl, extern: "nos$1".} = proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} = ## Returns true if the file `a` is newer than file `b`, i.e. if `a`'s ## modification time is later than `b`'s. - when defined(posix): + when defined(posix) or defined(nintendoswitch): # If we don't have access to nanosecond resolution, use '>=' when not StatHasNanoseconds: result = getLastModificationTime(a) >= getLastModificationTime(b) @@ -446,7 +446,7 @@ proc getFilePermissions*(filename: string): set[FilePermission] {. ## retrieves file permissions for `filename`. `OSError` is raised in case of ## an error. On Windows, only the ``readonly`` flag is checked, every other ## permission is available in any case. - when defined(posix): + when defined(posix) or defined(nintendoswitch): var a: Stat if stat(filename, a) < 0'i32: raiseOSError(osLastError()) result = {} @@ -478,7 +478,7 @@ proc setFilePermissions*(filename: string, permissions: set[FilePermission]) {. ## sets the file permissions for `filename`. `OSError` is raised in case of ## an error. On Windows, only the ``readonly`` flag is changed, depending on ## ``fpUserWrite``. - when defined(posix): + when defined(posix) or defined(nintendoswitch): var p = 0'i32 if fpUserRead in permissions: p = p or S_IRUSR if fpUserWrite in permissions: p = p or S_IWUSR @@ -645,7 +645,7 @@ proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", ## the process has finished. To execute a program without having a ## shell involved, use the `execProcess` proc of the `osproc` ## module. - when defined(posix): + when defined(posix) or defined(nintendoswitch): result = c_system(command) shr 8 else: result = c_system(command) @@ -739,7 +739,7 @@ type pcLinkToDir ## path refers to a symbolic link to a directory -when defined(posix): +when defined(posix) or defined(nintendoswitch): proc getSymlinkFileKind(path: string): PathComponent = # Helper function. var s: Stat @@ -911,7 +911,7 @@ proc rawCreateDir(dir: string): bool = result = false else: raiseOSError(osLastError()) - elif defined(posix): + elif defined(posix) or defined(nintendoswitch): let res = mkdir(dir, 0o777) if res == 0'i32: result = true @@ -1284,9 +1284,16 @@ elif defined(windows): if i < ownArgv.len and i >= 0: return TaintedString(ownArgv[i]) raise newException(IndexError, "invalid index") +elif defined(nintendoswitch): + proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} = + raise newException(OSError, "paramStr is not implemented on Nintendo Switch") + + proc paramCount*(): int {.tags: [ReadIOEffect].} = + raise newException(OSError, "paramCount is not implemented on Nintendo Switch") + elif not defined(createNimRtl) and not(defined(posix) and appType == "lib") and - not defined(genode) and not defined(nintendoswitch): + not defined(genode): # On Posix, there is no portable way to get the command line from a DLL. var cmdCount {.importc: "cmdCount".}: cint @@ -1649,7 +1656,7 @@ proc isHidden*(path: string): bool = proc setLastModificationTime*(file: string, t: times.Time) = ## Sets the `file`'s last modification time. `OSError` is raised in case of ## an error. - when defined(posix): + when defined(posix) or defined(nintendoswitch): let unixt = posix.Time(t.toUnix) let micro = convert(Nanoseconds, Microseconds, t.nanosecond) var timevals = [Timeval(tv_sec: unixt, tv_usec: micro), diff --git a/lib/pure/ospaths.nim b/lib/pure/ospaths.nim index c0d3ef51273a..905a659255bb 100644 --- a/lib/pure/ospaths.nim +++ b/lib/pure/ospaths.nim @@ -597,7 +597,7 @@ proc quoteShellPosix*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} else: return "'" & s.replace("'", "'\"'\"'") & "'" -when defined(windows) or defined(posix): +when defined(windows) or defined(posix) or defined(nintendoswitch): proc quoteShell*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} = ## Quote ``s``, so it can be safely passed to shell. when defined(windows): diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 7cecc31ab594..a5dc42c37075 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -61,7 +61,7 @@ when defined(JS): system.inc(a, b) {.pop.} -when defined(posix): +when defined(posix) or defined(nintendoswitch): import posix type CTime = posix.Time @@ -2031,7 +2031,7 @@ when not defined(JS): ## on the hardware/OS). ## ## ``getTime`` should generally be prefered over this proc. - when defined(posix): + when defined(posix) or defined(nintendoswitch): var a: Timeval gettimeofday(a) result = toBiggestFloat(a.tv_sec.int64) + toFloat(a.tv_usec)*0.00_0001 diff --git a/lib/system/threads.nim b/lib/system/threads.nim index df145628b971..3bfaa1dc20c7 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -176,7 +176,7 @@ else: else: type Time = int - when defined(linux) and defined(amd64) and defined(nintendoswitch): + when (defined(linux) or defined(nintendoswitch)) and defined(amd64): type SysThread* {.importc: "pthread_t", header: "" .} = distinct culong From de8eb3d838a9f3027b47217e412bde78f7de9641 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Fri, 22 Jun 2018 10:54:02 +0900 Subject: [PATCH 15/23] Remove old comment --- lib/posix/posix_nintendoswitch.nim | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/posix/posix_nintendoswitch.nim b/lib/posix/posix_nintendoswitch.nim index 7b482a504f9c..aa8b48a1972c 100644 --- a/lib/posix/posix_nintendoswitch.nim +++ b/lib/posix/posix_nintendoswitch.nim @@ -7,9 +7,6 @@ # distribution, for details about the copyright. # -# Types here should conform to the glibc ABI on linux / x86_64 -# When adding a type, the order and size of fields must match - # To be included from posix.nim! {.deadCodeElim: on.} # dce option deprecated From 06ba6534884433d7f97d065dce00b89ee18accd6 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Sat, 23 Jun 2018 09:34:58 +0900 Subject: [PATCH 16/23] Add what's not supported for Nintendo Switch docs --- doc/nimc.rst | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/doc/nimc.rst b/doc/nimc.rst index e19d4ad2f41e..fb4c792da9dc 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -249,8 +249,21 @@ Environment variables are ``DEVKITPRO`` for the devkitpro path, ``SWITCH_LIBS`` libraries required by your application (``-lLIBNAME`` or ``-LLIBPATH``), and ``SWITCH_INCLUDES`` for any extra include files (``-IINCLUDE_PATH``). -There are some directories expected to exist in a specific structure for now until I figure out a better way to specify them. They are: ``DEVKITPRO/portlibs/switch/lib``, ``DEVKITPRO/libnx/lib``, -``DEVKITPRO/portlibs/switch/include``, and ``DEVKITPRO/libnx/include``. +There are some directories expected to exist in a specific structure for now until I +figure out a better way to specify them. They are: ``DEVKITPRO/portlibs/switch/lib``, +``DEVKITPRO/libnx/lib``, ``DEVKITPRO/portlibs/switch/include``, and ``DEVKITPRO/libnx/include``. + +There are a few things that don't work because the DevkitPro libraries don't support them. +They are: + + 1. Waiting for a subprocess to finish. A subprocess can be started, but right + now it can't be waited on, which sort of makes subprocesses a bit hard to use + 2. Dynamic calls. DevkitPro libraries have no dlopen/dlclose functions. + 3. Command line parameters. It doesn't make sense to have these for a console + anyways, so no big deal here. + 4. mqueue. Sadly there are no mqueue headers. + 5. ucontext. No headers for these either. No coroutines for now :( + 6. nl_types. No headers for this. DLL generation ============== From cd42369dce68a97d3c720c6c5ee0c5330977ae66 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Sat, 23 Jun 2018 16:03:07 +0900 Subject: [PATCH 17/23] Make nintendoswitch == posix --- compiler/options.nim | 2 +- lib/pure/os.nim | 22 +++++++++++----------- lib/pure/times.nim | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/options.nim b/compiler/options.nim index 1516a40706b0..2aa515e35b5d 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -345,7 +345,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool = osQnx, osAtari, osAix, osHaiku, osVxWorks, osSolaris, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osMacosx, - osAndroid} + osAndroid, osNintendoSwitch} of "linux": result = conf.target.targetOS in {osLinux, osAndroid} of "bsd": diff --git a/lib/pure/os.nim b/lib/pure/os.nim index e81f87e0a043..5997451769ba 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -21,7 +21,7 @@ import when defined(windows): import winlean -elif defined(posix) or defined(nintendoswitch): +elif defined(posix): import posix proc toTime(ts: Timespec): times.Time {.inline.} = @@ -187,7 +187,7 @@ proc findExe*(exe: string, followSymlinks: bool = true; proc getLastModificationTime*(file: string): times.Time {.rtl, extern: "nos$1".} = ## Returns the `file`'s last modification time. - when defined(posix) or defined(nintendoswitch): + when defined(posix): var res: Stat if stat(file, res) < 0'i32: raiseOSError(osLastError()) result = res.st_mtim.toTime @@ -200,7 +200,7 @@ proc getLastModificationTime*(file: string): times.Time {.rtl, extern: "nos$1".} proc getLastAccessTime*(file: string): times.Time {.rtl, extern: "nos$1".} = ## Returns the `file`'s last read or write access time. - when defined(posix) or defined(nintendoswitch): + when defined(posix): var res: Stat if stat(file, res) < 0'i32: raiseOSError(osLastError()) result = res.st_atim.toTime @@ -217,7 +217,7 @@ proc getCreationTime*(file: string): times.Time {.rtl, extern: "nos$1".} = ## **Note:** Under POSIX OS's, the returned time may actually be the time at ## which the file's attribute's were last modified. See ## `here `_ for details. - when defined(posix) or defined(nintendoswitch): + when defined(posix): var res: Stat if stat(file, res) < 0'i32: raiseOSError(osLastError()) result = res.st_ctim.toTime @@ -231,7 +231,7 @@ proc getCreationTime*(file: string): times.Time {.rtl, extern: "nos$1".} = proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} = ## Returns true if the file `a` is newer than file `b`, i.e. if `a`'s ## modification time is later than `b`'s. - when defined(posix) or defined(nintendoswitch): + when defined(posix): # If we don't have access to nanosecond resolution, use '>=' when not StatHasNanoseconds: result = getLastModificationTime(a) >= getLastModificationTime(b) @@ -446,7 +446,7 @@ proc getFilePermissions*(filename: string): set[FilePermission] {. ## retrieves file permissions for `filename`. `OSError` is raised in case of ## an error. On Windows, only the ``readonly`` flag is checked, every other ## permission is available in any case. - when defined(posix) or defined(nintendoswitch): + when defined(posix): var a: Stat if stat(filename, a) < 0'i32: raiseOSError(osLastError()) result = {} @@ -478,7 +478,7 @@ proc setFilePermissions*(filename: string, permissions: set[FilePermission]) {. ## sets the file permissions for `filename`. `OSError` is raised in case of ## an error. On Windows, only the ``readonly`` flag is changed, depending on ## ``fpUserWrite``. - when defined(posix) or defined(nintendoswitch): + when defined(posix): var p = 0'i32 if fpUserRead in permissions: p = p or S_IRUSR if fpUserWrite in permissions: p = p or S_IWUSR @@ -645,7 +645,7 @@ proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", ## the process has finished. To execute a program without having a ## shell involved, use the `execProcess` proc of the `osproc` ## module. - when defined(posix) or defined(nintendoswitch): + when defined(posix): result = c_system(command) shr 8 else: result = c_system(command) @@ -739,7 +739,7 @@ type pcLinkToDir ## path refers to a symbolic link to a directory -when defined(posix) or defined(nintendoswitch): +when defined(posix): proc getSymlinkFileKind(path: string): PathComponent = # Helper function. var s: Stat @@ -911,7 +911,7 @@ proc rawCreateDir(dir: string): bool = result = false else: raiseOSError(osLastError()) - elif defined(posix) or defined(nintendoswitch): + elif defined(posix): let res = mkdir(dir, 0o777) if res == 0'i32: result = true @@ -1656,7 +1656,7 @@ proc isHidden*(path: string): bool = proc setLastModificationTime*(file: string, t: times.Time) = ## Sets the `file`'s last modification time. `OSError` is raised in case of ## an error. - when defined(posix) or defined(nintendoswitch): + when defined(posix): let unixt = posix.Time(t.toUnix) let micro = convert(Nanoseconds, Microseconds, t.nanosecond) var timevals = [Timeval(tv_sec: unixt, tv_usec: micro), diff --git a/lib/pure/times.nim b/lib/pure/times.nim index a5dc42c37075..7cecc31ab594 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -61,7 +61,7 @@ when defined(JS): system.inc(a, b) {.pop.} -when defined(posix) or defined(nintendoswitch): +when defined(posix): import posix type CTime = posix.Time @@ -2031,7 +2031,7 @@ when not defined(JS): ## on the hardware/OS). ## ## ``getTime`` should generally be prefered over this proc. - when defined(posix) or defined(nintendoswitch): + when defined(posix): var a: Timeval gettimeofday(a) result = toBiggestFloat(a.tv_sec.int64) + toFloat(a.tv_usec)*0.00_0001 From 3561f83e33c574e55451fa7bc7e9089ae648b93f Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 26 Jun 2018 11:12:19 +0900 Subject: [PATCH 18/23] Remove DEVKITPRO references from nim.cfg --- config/nim.cfg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/nim.cfg b/config/nim.cfg index 5342676de756..626f4494a1e5 100644 --- a/config/nim.cfg +++ b/config/nim.cfg @@ -111,10 +111,10 @@ path="$lib/pure" @if nintendoswitch: cc = "switch_gcc" - switch_gcc.options.linker = "-specs=$DEVKITPRO/libnx/switch.specs -g -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -L$DEVKITPRO/portlibs/switch/lib -L$DEVKITPRO/libnx/lib -lnx $SWITCH_LIBS" - switch_gcc.cpp.options.linker = "-specs=$DEVKITPRO/libnx/switch.specs -g -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -L$DEVKITPRO/portlibs/switch/lib -L$DEVKITPRO/libnx/lib -lnx $SWITCH_LIBS" - switch_gcc.options.always = "-g -Wall -O2 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -I$DEVKITPRO/portlibs/switch/include -I$DEVKITPRO/libnx/include $SWITCH_INCLUDES -D__SWITCH__" - switch_gcc.cpp.options.always = "-g -Wall -O2 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -I$DEVKITPRO/portlibs/switch/include -I$DEVKITPRO/libnx/include $SWITCH_INCLUDES -D__SWITCH__ -fno-rtti -fno-exceptions -std=gnu++11" + switch_gcc.options.linker = "-g -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE $SWITCH_LIBS" + switch_gcc.cpp.options.linker = "-g -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE $SWITCH_LIBS" + switch_gcc.options.always = "-g -Wall -O2 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE $SWITCH_INCLUDES -D__SWITCH__" + switch_gcc.cpp.options.always = "-g -Wall -O2 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE $SWITCH_INCLUDES -D__SWITCH__ -fno-rtti -fno-exceptions -std=gnu++11" @end # Configuration for the Intel C/C++ compiler: From 25ae23a84bcdae745270299d049063f416cf0eb3 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 27 Jun 2018 10:02:37 +0900 Subject: [PATCH 19/23] Make PR extccomp changes --- compiler/extccomp.nim | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 51f4d38ae9a5..1aa659fff022 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -584,7 +584,7 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile): string = # D files are required by nintendo switch libs for # compilation. They are basically a list of all includes. - let dfile = objfile.replace(".o", ".d").quoteShell() + let dfile = objfile.changeFileExt(".d").quoteShell() objfile = quoteShell(objfile) cf = quoteShell(cf) @@ -694,8 +694,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string = # Map files are required by Nintendo Switch compilation. They are a list # of all function calls in the library and where they come from. - var mapfile = getNimcacheDir(conf) / splitFile(projectFile).name & ".map" - mapfile = quoteShell(mapfile) + let mapfile = quoteShell(getNimcacheDir(conf) / splitFile(projectFile).name & ".map") let linkOptions = getLinkOptions(conf) & " " & getConfigVar(conf, conf.cCompiler, ".options.linker") From b525bccc8878b3a66ea05f5fa692d6588637175b Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 27 Jun 2018 10:02:58 +0900 Subject: [PATCH 20/23] Remove Result type alias --- lib/nintendoswitch/switch_memory.nim | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/nintendoswitch/switch_memory.nim b/lib/nintendoswitch/switch_memory.nim index fd0a215def5d..09b34c5d01d3 100644 --- a/lib/nintendoswitch/switch_memory.nim +++ b/lib/nintendoswitch/switch_memory.nim @@ -2,19 +2,16 @@ const virtMemHeader = "" const svcHeader = "" const mallocHeader = "" -type - Result* = uint32 - proc memalign*(bytes: csize, size: csize): pointer {.importc: "memalign", header: mallocHeader.} proc free*(address: pointer) {.importc: "free", header: mallocHeader.} -proc svcMapMemory*(dst_addr: pointer; src_addr: pointer; size: uint64): Result {. +proc svcMapMemory*(dst_addr: pointer; src_addr: pointer; size: uint64): uint32 {. importc: "svcMapMemory", header: svcHeader.} -proc svcUnmapMemory*(dst_addr: pointer; src_addr: pointer; size: uint64): Result {. +proc svcUnmapMemory*(dst_addr: pointer; src_addr: pointer; size: uint64): uint32 {. importc: "svcUnmapMemory", header: svcHeader.} proc virtmemReserveMap*(size: csize): pointer {.importc: "virtmemReserveMap", From 66c0ed945ca7caa0a5bb8eb8c3792b13d80f070c Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 27 Jun 2018 10:04:21 +0900 Subject: [PATCH 21/23] Add separate switch consts file --- lib/posix/posix_nintendoswitch.nim | 22 +- lib/posix/posix_nintendoswitch_consts.nim | 586 ++++++++++++++++++++++ 2 files changed, 593 insertions(+), 15 deletions(-) create mode 100644 lib/posix/posix_nintendoswitch_consts.nim diff --git a/lib/posix/posix_nintendoswitch.nim b/lib/posix/posix_nintendoswitch.nim index aa8b48a1972c..7e5d6282b422 100644 --- a/lib/posix/posix_nintendoswitch.nim +++ b/lib/posix/posix_nintendoswitch.nim @@ -1,7 +1,7 @@ # # # Nim's Runtime Library -# (c) Copyright 2018 Andreas Rumpf +# (c) Copyright 2018 Joey Yakimowich-Payne # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -9,16 +9,9 @@ # To be included from posix.nim! -{.deadCodeElim: on.} # dce option deprecated - -const - hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays - hasAioH = defined(linux) - type DIR* {.importc: "DIR", header: "", incompleteStruct.} = object - ## A type representing a directory stream. const SIG_HOLD* = cast[SigHandler](2) @@ -334,12 +327,11 @@ type aio_offset*: Off ## File offset. reserved: array[32, uint8] -when hasSpawnH: - type - Tposix_spawnattr* {.importc: "posix_spawnattr_t", - header: "", final, pure.} = object - Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", - header: "", final, pure.} = object +type + Tposix_spawnattr* {.importc: "posix_spawnattr_t", + header: "", final, pure.} = object + Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", + header: "", final, pure.} = object # from sys/un.h const Sockaddr_un_path_length* = 108 @@ -497,7 +489,7 @@ var timezone* {.importc: "_timezone", header: "".}: clong # Regenerate using detect.nim! -include posix_linux_amd64_consts +include posix_nintendoswitch_consts const POSIX_SPAWN_USEVFORK* = cint(0x40) # needs _GNU_SOURCE! diff --git a/lib/posix/posix_nintendoswitch_consts.nim b/lib/posix/posix_nintendoswitch_consts.nim new file mode 100644 index 000000000000..33470d22bb70 --- /dev/null +++ b/lib/posix/posix_nintendoswitch_consts.nim @@ -0,0 +1,586 @@ +# Generated by detect.nim + + +# + +# + +# +const E2BIG* = cint(7) +const EACCES* = cint(13) +const EADDRINUSE* = cint(112) +const EADDRNOTAVAIL* = cint(125) +const EAFNOSUPPORT* = cint(106) +const EAGAIN* = cint(11) +const EALREADY* = cint(120) +const EBADF* = cint(9) +const EBADMSG* = cint(77) +const EBUSY* = cint(16) +const ECANCELED* = cint(140) +const ECHILD* = cint(10) +const ECONNABORTED* = cint(113) +const ECONNREFUSED* = cint(111) +const ECONNRESET* = cint(104) +const EDEADLK* = cint(45) +const EDESTADDRREQ* = cint(121) +const EDOM* = cint(33) +const EDQUOT* = cint(132) +const EEXIST* = cint(17) +const EFAULT* = cint(14) +const EFBIG* = cint(27) +const EHOSTUNREACH* = cint(118) +const EIDRM* = cint(36) +const EILSEQ* = cint(138) +const EINPROGRESS* = cint(119) +const EINTR* = cint(4) +const EINVAL* = cint(22) +const EIO* = cint(5) +const EISCONN* = cint(127) +const EISDIR* = cint(21) +const ELOOP* = cint(92) +const EMFILE* = cint(24) +const EMLINK* = cint(31) +const EMSGSIZE* = cint(122) +const EMULTIHOP* = cint(74) +const ENAMETOOLONG* = cint(91) +const ENETDOWN* = cint(115) +const ENETRESET* = cint(126) +const ENETUNREACH* = cint(114) +const ENFILE* = cint(23) +const ENOBUFS* = cint(105) +const ENODATA* = cint(61) +const ENODEV* = cint(19) +const ENOENT* = cint(2) +const ENOEXEC* = cint(8) +const ENOLCK* = cint(46) +const ENOLINK* = cint(67) +const ENOMEM* = cint(12) +const ENOMSG* = cint(35) +const ENOPROTOOPT* = cint(109) +const ENOSPC* = cint(28) +const ENOSR* = cint(63) +const ENOSTR* = cint(60) +const ENOSYS* = cint(88) +const ENOTCONN* = cint(128) +const ENOTDIR* = cint(20) +const ENOTEMPTY* = cint(90) +const ENOTSOCK* = cint(108) +const ENOTSUP* = cint(134) +const ENOTTY* = cint(25) +const ENXIO* = cint(6) +const EOPNOTSUPP* = cint(95) +const EOVERFLOW* = cint(139) +const EPERM* = cint(1) +const EPIPE* = cint(32) +const EPROTO* = cint(71) +const EPROTONOSUPPORT* = cint(123) +const EPROTOTYPE* = cint(107) +const ERANGE* = cint(34) +const EROFS* = cint(30) +const ESPIPE* = cint(29) +const ESRCH* = cint(3) +const ESTALE* = cint(133) +const ETIME* = cint(62) +const ETIMEDOUT* = cint(116) +const ETXTBSY* = cint(26) +const EWOULDBLOCK* = cint(11) +const EXDEV* = cint(18) + +# +const F_DUPFD* = cint(0) +const F_GETFD* = cint(1) +const F_SETFD* = cint(2) +const F_GETFL* = cint(3) +const F_SETFL* = cint(4) +const F_GETLK* = cint(7) +const F_SETLK* = cint(8) +const F_SETLKW* = cint(9) +const F_GETOWN* = cint(5) +const F_SETOWN* = cint(6) +const FD_CLOEXEC* = cint(1) +const F_RDLCK* = cint(1) +const F_UNLCK* = cint(3) +const F_WRLCK* = cint(2) +const O_CREAT* = cint(512) +const O_EXCL* = cint(2048) +const O_NOCTTY* = cint(32768) +const O_TRUNC* = cint(1024) +const O_APPEND* = cint(8) +const O_NONBLOCK* = cint(16384) +const O_SYNC* = cint(8192) +const O_ACCMODE* = cint(3) +const O_RDONLY* = cint(0) +const O_RDWR* = cint(2) +const O_WRONLY* = cint(1) + +# + +# + +# +const FNM_NOMATCH* = cint(1) +const FNM_PATHNAME* = cint(2) +const FNM_PERIOD* = cint(4) +const FNM_NOESCAPE* = cint(1) + +# + +# +const GLOB_APPEND* = cint(1) +const GLOB_DOOFFS* = cint(2) +const GLOB_ERR* = cint(4) +const GLOB_MARK* = cint(8) +const GLOB_NOCHECK* = cint(16) +const GLOB_NOSORT* = cint(32) +const GLOB_NOSPACE* = cint(-1) + +# +const CODESET* = cint(0) +const D_T_FMT* = cint(1) +const D_FMT* = cint(2) +const T_FMT* = cint(3) +const T_FMT_AMPM* = cint(4) +const AM_STR* = cint(5) +const PM_STR* = cint(6) +const DAY_1* = cint(7) +const DAY_2* = cint(8) +const DAY_3* = cint(9) +const DAY_4* = cint(10) +const DAY_5* = cint(11) +const DAY_6* = cint(12) +const DAY_7* = cint(13) +const ABDAY_1* = cint(14) +const ABDAY_2* = cint(15) +const ABDAY_3* = cint(16) +const ABDAY_4* = cint(17) +const ABDAY_5* = cint(18) +const ABDAY_6* = cint(19) +const ABDAY_7* = cint(20) +const MON_1* = cint(21) +const MON_2* = cint(22) +const MON_3* = cint(23) +const MON_4* = cint(24) +const MON_5* = cint(25) +const MON_6* = cint(26) +const MON_7* = cint(27) +const MON_8* = cint(28) +const MON_9* = cint(29) +const MON_10* = cint(30) +const MON_11* = cint(31) +const MON_12* = cint(32) +const ABMON_1* = cint(33) +const ABMON_2* = cint(34) +const ABMON_3* = cint(35) +const ABMON_4* = cint(36) +const ABMON_5* = cint(37) +const ABMON_6* = cint(38) +const ABMON_7* = cint(39) +const ABMON_8* = cint(40) +const ABMON_9* = cint(41) +const ABMON_10* = cint(42) +const ABMON_11* = cint(43) +const ABMON_12* = cint(44) +const ERA* = cint(45) +const ERA_D_FMT* = cint(46) +const ERA_D_T_FMT* = cint(47) +const ERA_T_FMT* = cint(48) +const ALT_DIGITS* = cint(49) +const RADIXCHAR* = cint(50) +const THOUSEP* = cint(51) +const YESEXPR* = cint(52) +const NOEXPR* = cint(53) +const CRNCYSTR* = cint(56) + +# +const LC_ALL* = cint(0) +const LC_COLLATE* = cint(1) +const LC_CTYPE* = cint(2) +const LC_MESSAGES* = cint(6) +const LC_MONETARY* = cint(3) +const LC_NUMERIC* = cint(4) +const LC_TIME* = cint(5) + +# +const IPPORT_RESERVED* = cint(1024) +const HOST_NOT_FOUND* = cint(1) +const NO_DATA* = cint(4) +const NO_RECOVERY* = cint(3) +const TRY_AGAIN* = cint(2) +const AI_PASSIVE* = cint(1) +const AI_CANONNAME* = cint(2) +const AI_NUMERICHOST* = cint(4) +const AI_NUMERICSERV* = cint(8) +const AI_V4MAPPED* = cint(2048) +const AI_ALL* = cint(256) +const AI_ADDRCONFIG* = cint(1024) +const NI_NOFQDN* = cint(1) +const NI_NUMERICHOST* = cint(2) +const NI_NAMEREQD* = cint(4) +const NI_NUMERICSERV* = cint(8) +const NI_NUMERICSCOPE* = cint(32) +const NI_DGRAM* = cint(16) +const EAI_AGAIN* = cint(2) +const EAI_BADFLAGS* = cint(3) +const EAI_FAIL* = cint(4) +const EAI_FAMILY* = cint(5) +const EAI_MEMORY* = cint(6) +const EAI_NONAME* = cint(8) +const EAI_SERVICE* = cint(9) +const EAI_SOCKTYPE* = cint(10) +const EAI_SYSTEM* = cint(11) +const EAI_OVERFLOW* = cint(14) + +# +const IF_NAMESIZE* = cint(16) + +# +const IPPROTO_IP* = cint(0) +const IPPROTO_IPV6* = cint(41) +const IPPROTO_ICMP* = cint(1) +const IPPROTO_RAW* = cint(255) +const IPPROTO_TCP* = cint(6) +const IPPROTO_UDP* = cint(17) +const INADDR_ANY* = InAddrScalar(0) +const INADDR_LOOPBACK* = InAddrScalar(2130706433) +const INADDR_BROADCAST* = InAddrScalar(-1) +const INET_ADDRSTRLEN* = cint(16) +const INET6_ADDRSTRLEN* = cint(46) +const IPV6_JOIN_GROUP* = cint(12) +const IPV6_LEAVE_GROUP* = cint(13) +const IPV6_MULTICAST_HOPS* = cint(10) +const IPV6_MULTICAST_IF* = cint(9) +const IPV6_MULTICAST_LOOP* = cint(11) +const IPV6_UNICAST_HOPS* = cint(4) +const IPV6_V6ONLY* = cint(27) + +# +const TCP_NODELAY* = cint(1) + +# + +# +const POLLIN* = cshort(1) +const POLLRDNORM* = cshort(64) +const POLLRDBAND* = cshort(128) +const POLLPRI* = cshort(2) +const POLLOUT* = cshort(4) +const POLLWRNORM* = cshort(4) +const POLLWRBAND* = cshort(256) +const POLLERR* = cshort(8) +const POLLHUP* = cshort(16) +const POLLNVAL* = cshort(32) + +# +const PTHREAD_CREATE_DETACHED* = cint(0) +const PTHREAD_CREATE_JOINABLE* = cint(1) +const PTHREAD_EXPLICIT_SCHED* = cint(2) +const PTHREAD_INHERIT_SCHED* = cint(1) +const PTHREAD_SCOPE_PROCESS* = cint(0) +const PTHREAD_SCOPE_SYSTEM* = cint(1) + +# +const SCHED_FIFO* = cint(1) +const SCHED_RR* = cint(2) +const SCHED_OTHER* = cint(0) + +# + +# +const SIGEV_NONE* = cint(1) +const SIGEV_SIGNAL* = cint(2) +const SIGEV_THREAD* = cint(3) +const SIGABRT* = cint(6) +const SIGALRM* = cint(14) +const SIGBUS* = cint(10) +const SIGCHLD* = cint(20) +const SIGCONT* = cint(19) +const SIGFPE* = cint(8) +const SIGHUP* = cint(1) +const SIGILL* = cint(4) +const SIGINT* = cint(2) +const SIGKILL* = cint(9) +const SIGPIPE* = cint(13) +const SIGQUIT* = cint(3) +const SIGSEGV* = cint(11) +const SIGSTOP* = cint(17) +const SIGTERM* = cint(15) +const SIGTSTP* = cint(18) +const SIGTTIN* = cint(21) +const SIGTTOU* = cint(22) +const SIGUSR1* = cint(30) +const SIGUSR2* = cint(31) +const SIGPOLL* = cint(23) +const SIGPROF* = cint(27) +const SIGSYS* = cint(12) +const SIGTRAP* = cint(5) +const SIGURG* = cint(16) +const SIGVTALRM* = cint(26) +const SIGXCPU* = cint(24) +const SIGXFSZ* = cint(25) +const SA_NOCLDSTOP* = cint(1) +const SIG_BLOCK* = cint(1) +const SIG_UNBLOCK* = cint(2) +const SIG_SETMASK* = cint(0) +const SS_ONSTACK* = cint(1) +const SS_DISABLE* = cint(2) +const MINSIGSTKSZ* = cint(2048) +const SIGSTKSZ* = cint(8192) +const SIG_DFL* = cast[Sighandler](0) +const SIG_ERR* = cast[Sighandler](-1) +const SIG_IGN* = cast[Sighandler](1) + +# + +# + +# + +# +const FD_SETSIZE* = cint(64) + +# +const MSG_CTRUNC* = cint(32) +const MSG_DONTROUTE* = cint(4) +const MSG_EOR* = cint(8) +const MSG_OOB* = cint(1) +const SCM_RIGHTS* = cint(1) +const SO_ACCEPTCONN* = cint(2) +const SO_BROADCAST* = cint(32) +const SO_DEBUG* = cint(1) +const SO_DONTROUTE* = cint(16) +const SO_ERROR* = cint(4103) +const SO_KEEPALIVE* = cint(8) +const SO_LINGER* = cint(128) +const SO_OOBINLINE* = cint(256) +const SO_RCVBUF* = cint(4098) +const SO_RCVLOWAT* = cint(4100) +const SO_RCVTIMEO* = cint(4102) +const SO_REUSEADDR* = cint(4) +const SO_SNDBUF* = cint(4097) +const SO_SNDLOWAT* = cint(4099) +const SO_SNDTIMEO* = cint(4101) +const SO_TYPE* = cint(4104) +const SOCK_DGRAM* = cint(2) +const SOCK_RAW* = cint(3) +const SOCK_SEQPACKET* = cint(5) +const SOCK_STREAM* = cint(1) +const SOL_SOCKET* = cint(65535) +const SOMAXCONN* = cint(128) +const SO_REUSEPORT* = cint(512) +const MSG_NOSIGNAL* = cint(131072) +const MSG_PEEK* = cint(2) +const MSG_TRUNC* = cint(16) +const MSG_WAITALL* = cint(64) +const AF_INET* = TSa_Family(2) +const AF_INET6* = TSa_Family(28) +const AF_UNIX* = TSa_Family(1) +const AF_UNSPEC* = TSa_Family(0) +const SHUT_RD* = cint(0) +const SHUT_RDWR* = cint(2) +const SHUT_WR* = cint(1) + +# +const S_IFBLK* = cint(24576) +const S_IFCHR* = cint(8192) +const S_IFDIR* = cint(16384) +const S_IFIFO* = cint(4096) +const S_IFLNK* = cint(40960) +const S_IFMT* = cint(61440) +const S_IFREG* = cint(32768) +const S_IFSOCK* = cint(49152) +const S_IRGRP* = cint(32) +const S_IROTH* = cint(4) +const S_IRUSR* = cint(256) +const S_IRWXG* = cint(56) +const S_IRWXO* = cint(7) +const S_IRWXU* = cint(448) +const S_ISGID* = cint(1024) +const S_ISUID* = cint(2048) +const S_ISVTX* = cint(512) +const S_IWGRP* = cint(16) +const S_IWOTH* = cint(2) +const S_IWUSR* = cint(128) +const S_IXGRP* = cint(8) +const S_IXOTH* = cint(1) +const S_IXUSR* = cint(64) + +# +const ST_RDONLY* = cint(1) +const ST_NOSUID* = cint(2) + +# +const WNOHANG* = cint(1) +const WUNTRACED* = cint(2) + +# +const POSIX_SPAWN_RESETIDS* = cint(1) +const POSIX_SPAWN_SETPGROUP* = cint(2) +const POSIX_SPAWN_SETSCHEDPARAM* = cint(4) +const POSIX_SPAWN_SETSCHEDULER* = cint(8) +const POSIX_SPAWN_SETSIGDEF* = cint(16) +const POSIX_SPAWN_SETSIGMASK* = cint(32) + +# +const IOFBF* = cint(0) +const IONBF* = cint(2) + +# +const CLOCKS_PER_SEC* = clong(100) +const CLOCK_REALTIME* = cint(1) +const TIMER_ABSTIME* = cint(4) +const CLOCK_MONOTONIC* = cint(4) + +# +const F_OK* = cint(0) +const R_OK* = cint(4) +const W_OK* = cint(2) +const X_OK* = cint(1) +const F_LOCK* = cint(1) +const F_TEST* = cint(3) +const F_TLOCK* = cint(2) +const F_ULOCK* = cint(0) +const PC_2_SYMLINKS* = cint(13) +const PC_ALLOC_SIZE_MIN* = cint(15) +const PC_ASYNC_IO* = cint(9) +const PC_CHOWN_RESTRICTED* = cint(6) +const PC_FILESIZEBITS* = cint(12) +const PC_LINK_MAX* = cint(0) +const PC_MAX_CANON* = cint(1) +const PC_MAX_INPUT* = cint(2) +const PC_NAME_MAX* = cint(3) +const PC_NO_TRUNC* = cint(7) +const PC_PATH_MAX* = cint(4) +const PC_PIPE_BUF* = cint(5) +const PC_PRIO_IO* = cint(10) +const PC_REC_INCR_XFER_SIZE* = cint(16) +const PC_REC_MIN_XFER_SIZE* = cint(18) +const PC_REC_XFER_ALIGN* = cint(19) +const PC_SYMLINK_MAX* = cint(14) +const PC_SYNC_IO* = cint(11) +const PC_VDISABLE* = cint(8) +const SC_2_C_BIND* = cint(108) +const SC_2_C_DEV* = cint(109) +const SC_2_CHAR_TERM* = cint(107) +const SC_2_FORT_DEV* = cint(110) +const SC_2_FORT_RUN* = cint(111) +const SC_2_LOCALEDEF* = cint(112) +const SC_2_PBS* = cint(113) +const SC_2_PBS_ACCOUNTING* = cint(114) +const SC_2_PBS_CHECKPOINT* = cint(115) +const SC_2_PBS_LOCATE* = cint(116) +const SC_2_PBS_MESSAGE* = cint(117) +const SC_2_PBS_TRACK* = cint(118) +const SC_2_SW_DEV* = cint(119) +const SC_2_UPE* = cint(120) +const SC_2_VERSION* = cint(121) +const SC_ADVISORY_INFO* = cint(54) +const SC_AIO_LISTIO_MAX* = cint(34) +const SC_AIO_MAX* = cint(35) +const SC_AIO_PRIO_DELTA_MAX* = cint(36) +const SC_ARG_MAX* = cint(0) +const SC_ASYNCHRONOUS_IO* = cint(21) +const SC_ATEXIT_MAX* = cint(55) +const SC_BARRIERS* = cint(56) +const SC_BC_BASE_MAX* = cint(57) +const SC_BC_DIM_MAX* = cint(58) +const SC_BC_SCALE_MAX* = cint(59) +const SC_BC_STRING_MAX* = cint(60) +const SC_CHILD_MAX* = cint(1) +const SC_CLK_TCK* = cint(2) +const SC_CLOCK_SELECTION* = cint(61) +const SC_COLL_WEIGHTS_MAX* = cint(62) +const SC_CPUTIME* = cint(63) +const SC_DELAYTIMER_MAX* = cint(37) +const SC_EXPR_NEST_MAX* = cint(64) +const SC_FSYNC* = cint(22) +const SC_GETGR_R_SIZE_MAX* = cint(50) +const SC_GETPW_R_SIZE_MAX* = cint(51) +const SC_HOST_NAME_MAX* = cint(65) +const SC_IOV_MAX* = cint(66) +const SC_IPV6* = cint(67) +const SC_JOB_CONTROL* = cint(5) +const SC_LINE_MAX* = cint(68) +const SC_LOGIN_NAME_MAX* = cint(52) +const SC_MAPPED_FILES* = cint(23) +const SC_MEMLOCK* = cint(24) +const SC_MEMLOCK_RANGE* = cint(25) +const SC_MEMORY_PROTECTION* = cint(26) +const SC_MESSAGE_PASSING* = cint(27) +const SC_MONOTONIC_CLOCK* = cint(69) +const SC_MQ_OPEN_MAX* = cint(13) +const SC_MQ_PRIO_MAX* = cint(14) +const SC_NGROUPS_MAX* = cint(3) +const SC_OPEN_MAX* = cint(4) +const SC_PAGE_SIZE* = cint(8) +const SC_PRIORITIZED_IO* = cint(28) +const SC_PRIORITY_SCHEDULING* = cint(101) +const SC_RAW_SOCKETS* = cint(70) +const SC_RE_DUP_MAX* = cint(73) +const SC_READER_WRITER_LOCKS* = cint(71) +const SC_REALTIME_SIGNALS* = cint(29) +const SC_REGEXP* = cint(72) +const SC_RTSIG_MAX* = cint(15) +const SC_SAVED_IDS* = cint(6) +const SC_SEM_NSEMS_MAX* = cint(16) +const SC_SEM_VALUE_MAX* = cint(17) +const SC_SEMAPHORES* = cint(30) +const SC_SHARED_MEMORY_OBJECTS* = cint(31) +const SC_SHELL* = cint(74) +const SC_SIGQUEUE_MAX* = cint(18) +const SC_SPAWN* = cint(75) +const SC_SPIN_LOCKS* = cint(76) +const SC_SPORADIC_SERVER* = cint(77) +const SC_SS_REPL_MAX* = cint(78) +const SC_STREAM_MAX* = cint(100) +const SC_SYMLOOP_MAX* = cint(79) +const SC_SYNCHRONIZED_IO* = cint(32) +const SC_THREAD_ATTR_STACKADDR* = cint(43) +const SC_THREAD_ATTR_STACKSIZE* = cint(44) +const SC_THREAD_CPUTIME* = cint(80) +const SC_THREAD_DESTRUCTOR_ITERATIONS* = cint(53) +const SC_THREAD_KEYS_MAX* = cint(38) +const SC_THREAD_PRIO_INHERIT* = cint(46) +const SC_THREAD_PRIO_PROTECT* = cint(47) +const SC_THREAD_PRIORITY_SCHEDULING* = cint(45) +const SC_THREAD_PROCESS_SHARED* = cint(48) +const SC_THREAD_SAFE_FUNCTIONS* = cint(49) +const SC_THREAD_SPORADIC_SERVER* = cint(81) +const SC_THREAD_STACK_MIN* = cint(39) +const SC_THREAD_THREADS_MAX* = cint(40) +const SC_THREADS* = cint(42) +const SC_TIMEOUTS* = cint(82) +const SC_TIMER_MAX* = cint(19) +const SC_TIMERS* = cint(33) +const SC_TRACE* = cint(83) +const SC_TRACE_EVENT_FILTER* = cint(84) +const SC_TRACE_EVENT_NAME_MAX* = cint(85) +const SC_TRACE_INHERIT* = cint(86) +const SC_TRACE_LOG* = cint(87) +const SC_TRACE_NAME_MAX* = cint(88) +const SC_TRACE_SYS_MAX* = cint(89) +const SC_TRACE_USER_EVENT_MAX* = cint(90) +const SC_TTY_NAME_MAX* = cint(41) +const SC_TYPED_MEMORY_OBJECTS* = cint(91) +const SC_TZNAME_MAX* = cint(20) +const SC_V6_ILP32_OFF32* = cint(92) +const SC_V6_ILP32_OFFBIG* = cint(93) +const SC_V6_LP64_OFF64* = cint(94) +const SC_V6_LPBIG_OFFBIG* = cint(95) +const SC_VERSION* = cint(7) +const SC_XBS5_ILP32_OFF32* = cint(92) +const SC_XBS5_ILP32_OFFBIG* = cint(93) +const SC_XBS5_LP64_OFF64* = cint(94) +const SC_XBS5_LPBIG_OFFBIG* = cint(95) +const SC_XOPEN_CRYPT* = cint(96) +const SC_XOPEN_ENH_I18N* = cint(97) +const SC_XOPEN_LEGACY* = cint(98) +const SC_XOPEN_REALTIME* = cint(99) +const SC_XOPEN_REALTIME_THREADS* = cint(102) +const SC_XOPEN_SHM* = cint(103) +const SC_XOPEN_STREAMS* = cint(104) +const SC_XOPEN_UNIX* = cint(105) +const SC_XOPEN_VERSION* = cint(106) +const SC_NPROCESSORS_ONLN* = cint(10) +const SEEK_SET* = cint(0) +const SEEK_CUR* = cint(1) +const SEEK_END* = cint(2) From bec2c9673008ac575b7b6607effef9874e7da4fc Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 27 Jun 2018 10:30:59 +0900 Subject: [PATCH 22/23] Update docs for nintendo switch --- doc/nimc.rst | 52 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/doc/nimc.rst b/doc/nimc.rst index fb4c792da9dc..a3adcc143d44 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -232,38 +232,48 @@ Cross compilation for Nintendo Switch ===================================== Simply add --os:nintendoswitch -to your usual ``nim c`` or ``nim cpp`` command. DevkitPro setup must be the same as -what is the default with their new installer -[here for Mac/Linux](https://github.com/devkitPro/pacman/releases) or -[here for Windows](https://github.com/devkitPro/installer/releases). +to your usual ``nim c`` or ``nim cpp`` command and set the ``SWITCH_LIBS`` +and ``SWITCH_INCLUDES`` environment variables to something like: -For example:: +.. code-block:: console + export SWITCH_INCLUDES="-I$DEVKITPRO/libnx/include" + export SWITCH_LIBS="-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx" + +or setup a nim.cfg file like so: + +.. code-block:: Nim + #nim.cfg + --passC="-I$DEVKITPRO/libnx/include" + --passL="-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx" + +The DevkitPro setup must be the same as the default with their new installer +`here for Mac/Linux `_ or +`here for Windows `_. + +For example, with the above mentioned config:: nim c --os:nintendoswitch switchhomebrew.nim This will generate a file called ``switchhomebrew.elf`` which can then be turned into an nro file with the ``elf2nro`` tool in the DevkitPro release. Examples can be found at -[the nim-libnx github repo](https://github.com/jyapayne/nim-libnx.git). - -Environment variables are ``DEVKITPRO`` for the devkitpro path, ``SWITCH_LIBS`` for any extra -libraries required by your application (``-lLIBNAME`` or ``-LLIBPATH``), and -``SWITCH_INCLUDES`` for any extra include files (``-IINCLUDE_PATH``). +`the nim-libnx github repo `_ or you can use +`the switch builder tool `_. -There are some directories expected to exist in a specific structure for now until I -figure out a better way to specify them. They are: ``DEVKITPRO/portlibs/switch/lib``, -``DEVKITPRO/libnx/lib``, ``DEVKITPRO/portlibs/switch/include``, and ``DEVKITPRO/libnx/include``. +Environment variables are: + - ``SWITCH_LIBS`` for any extra libraries required by your application (``-lLIBNAME`` or ``-LLIBPATH``) + - ``SWITCH_INCLUDES`` for any extra include files (``-IINCLUDE_PATH``) There are a few things that don't work because the DevkitPro libraries don't support them. They are: - 1. Waiting for a subprocess to finish. A subprocess can be started, but right - now it can't be waited on, which sort of makes subprocesses a bit hard to use - 2. Dynamic calls. DevkitPro libraries have no dlopen/dlclose functions. - 3. Command line parameters. It doesn't make sense to have these for a console - anyways, so no big deal here. - 4. mqueue. Sadly there are no mqueue headers. - 5. ucontext. No headers for these either. No coroutines for now :( - 6. nl_types. No headers for this. +1. Waiting for a subprocess to finish. A subprocess can be started, but right + now it can't be waited on, which sort of makes subprocesses a bit hard to use +2. Dynamic calls. DevkitPro libraries have no dlopen/dlclose functions. +3. Command line parameters. It doesn't make sense to have these for a console + anyways, so no big deal here. +4. mqueue. Sadly there are no mqueue headers. +5. ucontext. No headers for these either. No coroutines for now :( +6. nl_types. No headers for this. DLL generation ============== From b233ce0f2328971663269a90e8b7cabd67326ee7 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Wed, 27 Jun 2018 18:36:13 +0900 Subject: [PATCH 23/23] Fix travis errors with undefined consts and add correct wait.h procs --- lib/posix/posix_nintendoswitch.nim | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/posix/posix_nintendoswitch.nim b/lib/posix/posix_nintendoswitch.nim index 7e5d6282b422..892ea33701d1 100644 --- a/lib/posix/posix_nintendoswitch.nim +++ b/lib/posix/posix_nintendoswitch.nim @@ -9,6 +9,10 @@ # To be included from posix.nim! +const + hasSpawnH = true + hasAioH = false + type DIR* {.importc: "DIR", header: "", incompleteStruct.} = object @@ -494,10 +498,9 @@ include posix_nintendoswitch_consts const POSIX_SPAWN_USEVFORK* = cint(0x40) # needs _GNU_SOURCE! # -proc WEXITSTATUS*(s: cint): cint = (s and 0xff00) shr 8 +proc WEXITSTATUS*(s: cint): cint = (s shr 8) and 0xff +proc WIFEXITED*(s:cint) : bool = (s and 0xff) == 0 proc WTERMSIG*(s:cint): cint = s and 0x7f proc WSTOPSIG*(s:cint): cint = WEXITSTATUS(s) -proc WIFEXITED*(s:cint) : bool = WTERMSIG(s) == 0 -proc WIFSIGNALED*(s:cint) : bool = (cast[int8]((s and 0x7f) + 1) shr 1) > 0 +proc WIFSIGNALED*(s:cint) : bool = ((s and 0x7f) > 0) and ((s and 0x7f) < 0x7f) proc WIFSTOPPED*(s:cint) : bool = (s and 0xff) == 0x7f -proc WIFCONTINUED*(s:cint) : bool = s == W_CONTINUED