I'm new to Nim, and have been experimenting with running it on AVR chips. After googling a bit, I started with the example listed at https://disconnected.systems/blog/nim-on-adruino/
This works, and I ended up using these settings:
nim.cfg
.standalone.gcc.path = "/usr/local/bin"
avr.standalone.gcc.exe = "avr-gcc"
avr.standalone.gcc.linkerexe = "avr-gcc"
passC = "-Os"
passC = "-DF_CPU=16000000UL"
passC = "-mmcu=atmega328p"
passL = "-mmcu=atmega328p"
passC = "-flto"
passL = "-flto"
cpu = "avr"
define = "danger"
deadCodeElim = "on"
The compile command looks like this:
c --os:standalone \
--gc:arc \
--cpu:avr \
-d:useMalloc \
-d:danger \
--opt:size \
embedded.nim
I started to expand the example a bit by adding a few simple procs and objects. As soon as I did that, I get this error when compiling:
Error: system module needs: nimErrorFlag
Googling that I found this open bug: https://github.com/nim-lang/Nim/issues/16404
Being a newbie to Nim, I curious to see if I'm heading down a futile path. Thanks for the advice in advance!
We are seeing a bunch of regression when compiling for AVR or other microcontrollers, making it tricky to find a working combination of --gc / --os / noSignalHandler / useMalloc
https://github.com/nim-lang/Nim/issues?q=is%3Aopen+is%3Aissue+standalone+label%3Across-compilation
This works fine for me for nim-arduino [1], and allows most of the stdlib to be used as well:
--cpu:avr
--os:any
--gc:arc
--exceptions:goto
-d:noSignalHandler
-d:danger
-d:useMalloc
I am trying to do the same without success.
I created hello.nim:
echo "Hello, world!"
The panicoverride.nim file:
proc printf(frmt: cstring) {.varargs, importc, header: "<stdio.h>", cdecl.}
proc exit(code: int) {.importc, header: "<stdlib.h>", cdecl.}
{.push stack_trace: off, profiler:off.}
proc rawoutput(s: string) =
printf("%s\n", s)
proc panic(s: string) =
rawoutput(s)
exit(1)
{.pop.}
and nim.cfg:
avr.standalone.gcc.path = "/usr/bin"
avr.standalone.gcc.exe = "avr-gcc"
avr.standalone.gcc.linkerexe = "avr-gcc"
passC = "-Os"
passC = "-DF_CPU=16000000UL"
passC = "-mmcu=atmega328p"
passL = "-mmcu=atmega328p"
passC = "-flto"
passL = "-flto"
cpu = "avr"
define = "danger"
deadCodeElim = "on"
gc = "arc"
When I try to compile:
$ nim c --os:standalone hello
Hint: used config file '/home/jose/.choosenim/toolchains/nim-#devel/config/nim.cfg' [Conf]
Hint: used config file '/home/jose/.choosenim/toolchains/nim-#devel/config/config.nims' [Conf]
Hint: used config file '/home/jose/src/avr/nim/nim.cfg' [Conf]
....
Error: system module needs: raiseExceptionEx
I tried also with:
nim c --os:standalone --exceptions:quirky hello
(same issue)
What am I missing?
I am using ArchLinux:
$ nim --version
Nim Compiler Version 1.5.1 [Linux: amd64]
Compiled at 2021-03-31
Copyright (c) 2006-2021 by Andreas Rumpf
git hash: 7c09e0c75773a2df6469a2acd94f3090aef83255
active boot switches: -d:release
$ avr-gcc --version
avr-gcc (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Same result:
$ nim c --os:standalone --exceptions:quirky -d:noSignalHandler -d:danger hello
Hint: used config file '/home/jose/.choosenim/toolchains/nim-#devel/config/nim.cfg' [Conf]
Hint: used config file '/home/jose/.choosenim/toolchains/nim-#devel/config/config.nims' [Conf]
Hint: used config file '/home/jose/src/avr/nim/nim.cfg' [Conf]
....
Error: system module needs: raiseExceptionEx
This one puzzles me:
$ nim c --os:any --exceptions:goto -d:noSignalHandler -d:danger -d:useMalloc hello
Hint: used config file '/home/jose/.choosenim/toolchains/nim-#devel/config/nim.cfg' [Conf]
Hint: used config file '/home/jose/.choosenim/toolchains/nim-#devel/config/config.nims' [Conf]
Hint: used config file '/home/jose/src/avr/nim/nim.cfg' [Conf]
....
CC: stdlib_io.nim
CC: stdlib_system.nim
CC: hello.nim
gcc: error: unrecognized command-line option ‘-mmcu=atmega328p’
Error: execution of an external compiler program 'gcc -c -w -fmax-errors=3 -Os -DF_CPU=16000000UL -mmcu=atmega328p -flto -O3 -fno-strict-aliasing -fno-ident -I'/home/jose/.choosenim/toolchains/nim-#devel/lib' -I/home/jose/src/avr/nim -o /home/jose/.cache/nim/hello_r/stdlib_io.nim.c.o /home/jose/.cache/nim/hello_r/stdlib_io.nim.c' failed with exit code: 1
gcc: error: unrecognized command-line option ‘-mmcu=atmega328p’
gcc: error: unrecognized command-line option ‘-mmcu=atmega328p’
It looks like with -d:useMalloc, it is not using avr-gcc, but I don't know why.It's here, https://nim-lang.org/docs/nimc.html#nim-for-embedded-systems
Does it help that it's documented well? As we can see, it doesn't.
I assume you forgot to change these lines:
avr.standalone.gcc.path = "/usr/bin"
avr.standalone.gcc.exe = "avr-gcc"
avr.standalone.gcc.linkerexe = "avr-gcc"
in your nim.cfg file to:
avr.any.gcc.path = "/usr/bin"
avr.any.gcc.exe = "avr-gcc"
avr.any.gcc.linkerexe = "avr-gcc"
Is there any particular reason why those aren't the default for the avr target by the way?
After changing nim.cfg:
$ nim c --os:any --exceptions:quirky -d:noSignalHandler -d:danger -d:useMalloc hello
Hint: used config file '/home/jose/.choosenim/toolchains/nim-#devel/config/nim.cfg' [Conf]
Hint: used config file '/home/jose/.choosenim/toolchains/nim-#devel/config/config.nims' [Conf]
Hint: used config file '/home/jose/src/avr/nim/nim.cfg' [Conf]
Hint: used config file '/home/jose/src/avr/nim/borrame/nim.cfg' [Conf]
....
Hint: [Link]
/usr/bin/avr-ld: /tmp/hello.FkAjAx.ltrans0.ltrans.o: en la función `checkErr_systemZio_143.part.0':
<artificial>:(.text+0x9e6): referencia a `strerror' sin definir
collect2: error: ld returned 1 exit status
Error: execution of an external program failed: '/usr/bin/avr-gcc -o /home/jose/src/avr/nim/borrame/hello /home/jose/.cache/nim/hello_r/stdlib_io.nim.c.o /home/jose/.cache/nim/hello_r/stdlib_system.nim.c.o /home/jose/.cache/nim/hello_r/@mhello.nim.c.o -mmcu=atmega328p -flto -mmcu=atmega328p -flto '
Complains about 'strerror' not defined.
Hmm, not quite sure why that would be, works fine for me:
[peter /tmp/avrtest ] 17449 $ cat test.nim
echo "Hello world"
[peter /tmp/avrtest ] 17450 $ cat panicoverride.nim
proc printf(frmt: cstring) {.varargs, importc, header: "<stdio.h>", cdecl.}
proc exit(code: int) {.importc, header: "<stdlib.h>", cdecl.}
{.push stack_trace: off, profiler:off.}
proc rawoutput(s: string) =
printf("%s\n", s)
proc panic(s: string) =
rawoutput(s)
exit(1)
{.pop.}
[peter /tmp/avrtest ] 17451 $ cat nim.cfg
passC = "-Os"
passC = "-DF_CPU=16000000UL"
passC = "-mmcu=atmega328p"
passL = "-mmcu=atmega328p"
passC = "-flto"
passL = "-flto"
cpu = "avr"
gc = "arc"
define = "noSignalHandler"
define = "useMalloc"
deadCodeElim = "on"
exceptions = "quirky"
avr.any.gcc.path = "/usr/bin"
avr.any.gcc.exe = "avr-gcc"
avr.any.gcc.linkerexe = "avr-gcc"
[peter /tmp/avrtest ] 17452 $ nim c -d:danger --os:any test
Hint: used config file '/home/peter/Projects/Nim/config/nim.cfg' [Conf]
Hint: used config file '/home/peter/Projects/Nim/config/config.nims' [Conf]
Hint: used config file '/tmp/avrtest/nim.cfg' [Conf]
....
Hint: [Link]
Hint: 19091 lines; 0.104s; 16.656MiB peakmem; Dangerous Release build; proj: /tmp/avrtest/test; out: /tmp/avrtest/test [SuccessX]
[peter /tmp/avrtest ] 17453 $ file test
test: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, with debug_info, not stripped
[peter /tmp/avrtest ] 17454 $ avr-gcc --version
avr-gcc (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[peter /tmp/avrtest ] 17455 $ nim --version
Nim Compiler Version 1.4.2 [Linux: amd64]
Compiled at 2021-03-29
Copyright (c) 2006-2020 by Andreas Rumpf
git hash: 3fb5157ab1b666a5a5c34efde0f357a82d433d04
active boot switches: -d:release
That's it!
It works on stable but it doesn't on devel (at least for me).
Thanks all for your help.