Upgrading to the latest release of Nim

I have had some fun in the last few of days. I decided to upgrade to the latest version of Nim ... because I had gotten a couple of releases behind I think. It is not a hard thing to do, but was just something that I had not gotten round to.

Anyway, for some reason, I decided to rebuild everything, including the Aporia IDE whilst I was at it. That's where things went a bit wrong, and sadly I had already binned the previous version of Aporia. So I was at risk of not having my IDE for Nim.

Whenever I tried to use Nimble (Nim's package manager) to rebuild Aporia, I was getting errors about dependency conflicts with GTK. Eventually, I grabbed the Aporia repository and was able to hack the aporia.nimble file. If you're really interested, I found that removing #head from where it says it requires gtk2 did the trick. Finally, I was able to build the latest Aporia. Phew, panic over.

After having figured all that out, I was looking at the Nimble repository on GitHub and noticed this build failure:

So ... it looked like bad timing. Not being able to install Aporia was being worked on. This must be due to the Nim incarnation of dependency hell I guess. But I can now report that this problem has been fixed anyway. It seems that I had just chosen the wrong moment to do my rebuild. It happens.

After a little more digging and some discussion on GitHub, it appears that I had been using a bleeding-edge copy of the Nimble package manager. So it's understandable that things might break. When I retraced my steps, I realised that I had installed Nimble from a script included with the release of Nim I had been using. That script installs the bleeding edge version, which is probably the wrong thing to do. So I logged that as an issue on the Nim repository. But it seems like the next release of Nim is just round the corner anyway. I'll try to upgrade to that version more quickly this time!

So, for the time being all is well. I have the latest release of Nim installed and Aporia is back. I've also replaced Nimble on my machine with the latest tagged version (manually), so in the meantime I should have a more stable setup. And I kind of enjoyed all this stuff anyway, so no worries.

A little more about Nim

I am still tinkering with the Nim programming language, and quite enjoying it. I find the language to be well thought out, and it's very easy to build little libraries which have unit tests included in them. I like that idea.

But I have noticed that the binaries can be quite a lot bigger than my equivalent C programs, which I suppose is to be expected. So I have also been experimenting with the UPX packer which helps to keep the file size down ... this could be useful if you want to run your Nim programs on something tiny, like a router.

In the end, I did buy a copy of the Nim in Action book, available through Manning's early access program. I'd recommend this book to people who are learning Nim, I found it easy to follow and enjoyable to read.

Nim in Action book

Because Nim has not reached v1 yet, for the moment I'm only using it for experimentation and hobbyist type stuff. But when it actually hits v1, I think that I'd consider using it for real work too.

First steps into the world of Nim

I was recently doing a bit of reading up on the Rust programming language, but a stray comment somewhere about the Nim programming language sent me off on a bit of a tangent. The thing that really got me interested in Nim was that it compiles to C, and I noticed that this brings quite some options for portability. One of the reasons why I like programming in C is that you can run the code on all kinds of machines, from tiny embedded devices to supercomputers. But that does come at a cost, because it takes longer and you often have lots more typing to do because of all that boilerpate stuff.

But it looks like Nim would allow you to be quite productive, whilst the resulting executables should still be efficient and fast. To get some ideas, I went off to Rosetta Code and found the Nim code for a simple webserver which looks like this:

import asynchttpserver, asyncdispatch
 
proc cb(req: Request) {.async.} =
  await req.respond(Http200, "Hello, World!")
 
asyncCheck newAsyncHttpServer().serve(Port(8080), cb)
runForever()

Being able to create a webserver with just a few lines of code, and with the potential for the code to be portable and run on all kinds of devices seemed very tempting! By this point, I'd forgotten about Rust and wanted to explore Nim a bit further.

So whilst Nim has not reached v1.0 yet, it certainly looked very compelling. The compiler documentation made it look like cross-compilation was not that difficult, so I decided to try and cross-compile some code for a router running OpenWrt. Before going off and spendng a lot of time learning a new language, I wanted to see that I *really* can write portable code. I was very happy to see that in just a few minutes I had the example webserver code running on my TP-Link WR740N, as shown here:

To my amazement and joy, this really wasn't that hard. After installing Nim, I had to edit Nim/config/nim.cfg to point to my cross-compile toolchain, so I ended up with these lines:

mips.linux.gcc.exe =
 "/home/openwrt/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/
bin/mips-openwrt-linux-gcc"
mips.linux.gcc.linkerexe =
 "/home/openwrt/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/
bin/mips-openwrt-linux-gcc"

Then, after doing that I simply needed to pass the correct parameters to the Nim compiler, like this:

nim c --cpu:mips --os:linux webserver.nim

Which cross-compiled the example webserver ready for it to run on my TP-Link WR740N. That actually seems pretty awesome. I think that I need to learn more, perhaps I'll even go and buy the Nim in Action book. All this stuff worked perfectly without any trouble, which is pretty rare, so I am left feeling very impressed so far.