Published on

Actually Portable Nim

Authors
  • avatar
    Name
    michael
    Twitter

Nim

Nim is a niche but powerful language that combines a comfortable Pythonic syntax with native performance and a tiny footprint. This combination makes Nim an attractive choice for malware dev but, unfortunately, is yet to find more widespread adoption and lacks any serious corporate backing relative to its peers.

asyncdispatch.nim
import std/[asyncdispatch, httpclient]

proc asyncProc(): Future[string] {.async.} =
  var client = newAsyncHttpClient()
  return await client.getContent("http://example.com")

echo waitFor asyncProc()

Reference implementation of an async HTTP GET from Nim's standard library

Portable Executable

A Portable Executable (PE) is Microsoft's binary image format that is used by the Windows OS loader to manage programs. The main POSIX equivalent is an ELF (Executable and Linkable Format) file.

These binaries are products of their respective platform's toolchains and are not cross-platform despite many clever hacks being devised to work around this (WINE, MinGW, etc.).

αcτµαlly pδrταblε εxεcµταblε

One of the most technically impressive achievements in this space is Justine Tunney's platform agnostic C / C++ / FORTRAN tooling project Cosmopolitan Libc which you can read about here.

Who could have predicted that cross-platform native builds would be this easy? As it turns out, they're surprisingly cheap too. Even with all the magic numbers, win32 utf-8 polyfills, and bios bootloader code, exes still end up being roughly 100x smaller than Go Hello World

Since its release in 2020, fans of the project have carried the Actually Portable torch far and wide: from Actually Portable Python to Actually Portable Rust and now we can finally add Actually Portable Nim to that repertoire.

Actually Portable Nim

Leveraging Nim's excellent compiler and existing C toolchains it was a pretty painless process to stand on the shoulders of giants and apply the same magic pioneered by Cosmopolitan Libc to create Actually Portable Nim which you can find on GitHub here.

Makefile
build:
	nim c -d:release --passC:"-Iinclude -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone -include include/cosmopolitan.h" \
--passL:"-static -nostdlib -nostdinc -Wl,-T,cosmo/ape.lds cosmo/crt.o cosmo/ape.o cosmo/cosmopolitan.a" \
-o:portablenim.ape src/main.nim && objcopy -S -O binary portablenim.ape portablenim.com

The highlights: we swap out the standard library -nostdlib for cosmopolitan.a Libc, generate some stub headers to appease the compiler in include/, apply the usual flags like -static and -fno-PIE and out comes our 100kb Hello World executable that runs on six operating systems (Linux, Windows, MacOS, FreeBSD, NetBSD, OpenBSD).

You could likely get it even smaller with flags like -d:danger and --opt:size.

24-10-2023 edit: special thanks to @PhilippMDoerner for identifying a broken link to APE