- Published on
Actually Portable Nim
- Authors
- Name
- michael
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.
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.
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