diff --git a/repos/base/mk/generic.mk b/repos/base/mk/generic.mk index f90b59fe8..88e3493a9 100644 --- a/repos/base/mk/generic.mk +++ b/repos/base/mk/generic.mk @@ -85,6 +85,41 @@ endif $(MSG_CONVERT)$@ $(VERBOSE)ar p $< $*.0.o > $@ +# +# Compiling Nim source code +# +ifneq ($(SRC_NIM),) + +ifeq ($(NIM_CPU),) +$(warning NIM_CPU not defined for any of the following SPECS: $(SPECS)) +else + +NIM_MAKEFILES := $(foreach X,$(SRC_NIM),$(X).mk) +NIM_ARGS = --compileOnly --os:genode --cpu:$(NIM_CPU) +NIM_ARGS += --verbosity:0 --hint[Processing]:off --nimcache:. +NIM_ARGS += $(NIM_OPT) + +# Generate the C++ sources and compilation info +# +# Unfortunately the existing sources must be purged +# because of comma problems in the JSON recipe +%.nim.mk: %.nim + $(MSG_BUILD)$(basename $@).cpp + $(VERBOSE) rm -f stdlib_*.cpp + $(VERBOSE)$(NIM) compileToCpp $(NIM_ARGS) $< + $(VERBOSE)$(JQ) --raw-output '"SRC_O_NIM +=" + (.link | join(" ")) +"\n" + (.compile | map((.[0] | sub("cpp$$";"o: ")) + .[0] + "\n\t"+(.[1] | sub("^g\\++";"$$(MSG_COMP)$$@\n\t$$(VERBOSE)$$(NIM_CC)"))) | join("\n"))' < $(basename $(basename $@)).json > $@ + +NIM_CC := $(CXX) $(CXX_DEF) $(CC_CXX_OPT) $(INCLUDES) -D__GENODE__ + +# Parse the generated makefiles +-include $(NIM_MAKEFILES) + +# Append the new objects +SRC_O += $(sort $(SRC_O_NIM)) + +endif +endif + # # Assembler files that must be preprocessed are fed to the C compiler. # diff --git a/repos/base/mk/global.mk b/repos/base/mk/global.mk index 246d90128..44c283b5b 100644 --- a/repos/base/mk/global.mk +++ b/repos/base/mk/global.mk @@ -50,6 +50,16 @@ STRIP = $(CUSTOM_STRIP) GNATMAKE = $(CUSTOM_GNATMAKE) HOST_CC = $(CUSTOM_HOST_CC) +# +# Nim toolchain +# +NIM ?= nim + +# +# JSON parsing utility +# +JQ ?= jq + # # Compiler and Linker options # diff --git a/repos/base/mk/spec/arm.mk b/repos/base/mk/spec/arm.mk index c2d42ead8..6b320482a 100644 --- a/repos/base/mk/spec/arm.mk +++ b/repos/base/mk/spec/arm.mk @@ -5,6 +5,8 @@ REP_INC_DIR += include/spec/arm SPECS += 32bit +NIM_CPU ?= arm + # # Prevent compiler message # "note: the mangling of 'va_list' has changed in GCC 4.4" diff --git a/repos/base/mk/spec/x86_32.mk b/repos/base/mk/spec/x86_32.mk index 631e04c66..21a9f1208 100644 --- a/repos/base/mk/spec/x86_32.mk +++ b/repos/base/mk/spec/x86_32.mk @@ -16,5 +16,7 @@ CC_MARCH ?= -march=i686 -m32 LD_MARCH ?= -melf_i386 AS_MARCH ?= -march=i686 --32 +NIM_CPU ?= i386 + include $(BASE_DIR)/mk/spec/32bit.mk include $(BASE_DIR)/mk/spec/x86.mk diff --git a/repos/base/mk/spec/x86_64.mk b/repos/base/mk/spec/x86_64.mk index 0c7c95fdd..1d131adf3 100644 --- a/repos/base/mk/spec/x86_64.mk +++ b/repos/base/mk/spec/x86_64.mk @@ -20,5 +20,7 @@ CC_MARCH ?= -m64 # LD_MARCH ?= -melf_x86_64 +NIM_CPU ?= amd64 + include $(BASE_DIR)/mk/spec/64bit.mk include $(BASE_DIR)/mk/spec/x86.mk diff --git a/repos/libports/lib/import/import-libc.mk b/repos/libports/lib/import/import-libc.mk index f579bc8ae..30ed33368 100644 --- a/repos/libports/lib/import/import-libc.mk +++ b/repos/libports/lib/import/import-libc.mk @@ -55,3 +55,8 @@ CC_OPT += -D__ISO_C_VISIBLE=1999 # or 'sincosf', which is a GNU extension, not provided by our libc. # CC_OPT += -fno-builtin-sin -fno-builtin-cos -fno-builtin-sinf -fno-builtin-cosf + +# +# Enable Nim POSIX support when linking with this library +# +NIM_OPT += -d:posix diff --git a/repos/libports/lib/import/import-nim-threads.mk b/repos/libports/lib/import/import-nim-threads.mk new file mode 100644 index 000000000..c42b778e5 --- /dev/null +++ b/repos/libports/lib/import/import-nim-threads.mk @@ -0,0 +1 @@ +NIM_OPT += --threads:on --tlsEmulation:on diff --git a/repos/libports/lib/mk/nim-threads.mk b/repos/libports/lib/mk/nim-threads.mk new file mode 100644 index 000000000..e69de29bb diff --git a/repos/libports/run/nim.run b/repos/libports/run/nim.run new file mode 100644 index 000000000..73d6b9e5f --- /dev/null +++ b/repos/libports/run/nim.run @@ -0,0 +1,62 @@ +set build_components { + core init + drivers/timer + drivers/rtc + test/nim +} + +build $build_components + +create_boot_directory + +set config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +set boot_modules { + core init ld.lib.so + libc.lib.so + rtc_drv + test-nim + timer +} + +build_boot_image $boot_modules + +append qemu_args "-nographic" + +run_genode_until {child "test-nim" exited with exit value 0} 30 diff --git a/repos/libports/run/nim_netty.run b/repos/libports/run/nim_netty.run new file mode 100644 index 000000000..f2a216b15 --- /dev/null +++ b/repos/libports/run/nim_netty.run @@ -0,0 +1,84 @@ +assert_spec linux + +set build_components { + core init + drivers/timer drivers/nic server/ram_fs server/vfs + test/nim_echo_server + lib/vfs/lxip +} + +source ${genode_dir}/repos/base/run/platform_drv.inc +append_platform_drv_build_components + +build $build_components + +create_boot_directory + +set config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +append_platform_drv_config + +append config { + +} + +install_config $config + +set boot_modules { + core init timer linux_nic_drv ram_fs vfs + ld.lib.so libc.lib.so libm.lib.so + libc_resolv.lib.so stdcxx.lib.so libc_pipe.lib.so + vfs_lxip.lib.so lxip.lib.so + test-nim_echo_server +} + +append_platform_drv_boot_modules + +build_boot_image $boot_modules + +run_genode_until forever + +# vi: set ft=tcl : diff --git a/repos/libports/src/test/nim/main.nim b/repos/libports/src/test/nim/main.nim new file mode 100644 index 000000000..8a15a299f --- /dev/null +++ b/repos/libports/src/test/nim/main.nim @@ -0,0 +1,112 @@ +import unittest +const + Text = "Hello world!" + +suite "echo": + echo Text + +suite "system": + echo "compile date: ", CompileDate, " - ", CompileTime + echo("endianness: ", + case cpuEndian: + of littleEndian: + "littleEndian" + of bigEndian: + "bigEndian" + ) + echo "hostCPU: ", hostCPU + echo "NimVersion: ", NimVersion + echo "nativeStackTraceSupported: ", $nativeStackTraceSupported + echo "getStackTrace:\n", getStackTrace() + echo "getFreeMem: ", getFreeMem() + echo "getTotalMem: ", getTotalMem() + echo "getOccupiedMem: ", getOccupiedMem() + + test "isMainModule": + assert isMainModule == true + test "hostOS == genode": + assert hostOS == "genode" + + test "alloc/dealloc": + let p = alloc 768 + assert(not p.isNil) + dealloc p + + test "exception handling": + type NovelError = object of SystemError + try: raise newException(NovelError, "test exception") + except NovelError: + discard + +import locks, threadpool +suite "threadpool": + + test "spawn": + var L: Lock + + proc threadProc(interval: tuple[a,b: int]) = + for i in interval.a..interval.b: + acquire L + echo i + release L + + initLock L + for i in 0..3: + spawn threadProc((i*10, i*10+4)) + sync() + deinitLock L + + test "threadvar": + var + L: Lock + x {.threadvar.}: int + y: int + + proc printVal(id: string) = + acquire L + echo( + id, + " x: ", repr(addr(x)), + " y: ", repr(addr(y)) + ) + inc x + inc y + release L + + initLock L + release L + printVal("main thread") + for i in 1..4: + spawn printVal("spawn "& $i) + sync() + deinitLock L + +suite "I/O": + const + TestFile = "/testfile" + Text = NimVersion & " - " & CompileDate & " - " & CompileTime + test "writeFile": + writeFile(TestFile, Text) + test "readFile": + assert readFile(TestFile) == Text + +suite "staticExec": + const rev = staticExec("git describe") + echo "compile time 'git describe': ", rev + +import times +suite "time": + + echo "epochTime() float value: ", epochTime() + echo "getTime() float value: ", toSeconds(getTime()) + echo "cpuTime() float value: ", cpuTime() + echo "An hour from now : ", getLocalTime(getTime()) + 1.hours + echo "An hour from (UTC) now: ", getGmTime(getTime()) + initInterval(0,0,0,1) + + test "getTime": + assert(getTime() != 0.Time) + +suite "garbage collector": + echo GC_getStatistics() + +echo "done" diff --git a/repos/libports/src/test/nim/target.mk b/repos/libports/src/test/nim/target.mk new file mode 100644 index 000000000..1aed479ef --- /dev/null +++ b/repos/libports/src/test/nim/target.mk @@ -0,0 +1,6 @@ +TARGET = test-nim +LIBS = nim-threads libc +SRC_NIM = main.nim + +# Enable extra system assertions +NIM_OPT += -d:useSysAssert diff --git a/repos/libports/src/test/nim_echo_server/main.nim b/repos/libports/src/test/nim_echo_server/main.nim new file mode 100644 index 000000000..cb8ca32c2 --- /dev/null +++ b/repos/libports/src/test/nim_echo_server/main.nim @@ -0,0 +1,27 @@ +import asyncnet, asyncdispatch + +const + CRLF* = "\c\L" + +proc processClient(address: string, client: AsyncSocket) {.async.} = + echo "accepted connection from ", address + while not client.isClosed(): + let line = await client.recvLine() + if line == "": + break + await client.send(line & CRLF) + echo address, " closed connection" + +proc serve() {.async.} = + let server = newAsyncSocket() + server.bindAddr(7.Port) + server.listen() + + echo "echo service listening on port 7" + + while true: + let res = await server.acceptAddr() + asyncCheck processClient(res[0], res[1]) + +asyncCheck serve() +runForever() diff --git a/repos/libports/src/test/nim_echo_server/target.mk b/repos/libports/src/test/nim_echo_server/target.mk new file mode 100644 index 000000000..99fd281e3 --- /dev/null +++ b/repos/libports/src/test/nim_echo_server/target.mk @@ -0,0 +1,6 @@ +TARGET = test-nim_echo_server +LIBS = libc libc_resolv +SRC_NIM = main.nim + +# Enable extra system assertions +NIM_OPT += -d:useSysAssert