Installation
Nimony must be built from source. You need to have Nim version 2.0 or later. For example:
nim --version Nim Compiler Version 2.3.1
Clone Nimony from github:
git clone https://github.com/nim-lang/nimony.git cd nimony
To build it run this command:
nim c -r src/hastur/hastur build all
Nifler, the tool that reads .nim source, is built with Nim's own compiler/parser.nim rather than with whatever parser the installed compiler happens to have — Nimony's stdlib uses syntax (concept of) that no release knows. That file is not part of this repository: the first build checks it out at the commit src/nifler/nimparser/upstream.commit pins, from a Nim git checkout on your machine if it has that commit and otherwise with one HTTPS request. Later builds reuse the copy on disk. Working offline with no local Nim checkout, the build says so and falls back to the installed compiler's parser, which is fine if you are on devel.
Usage
nimony c <program.nim>
For example:
import std / syncio echo "Hello from Nimony!"
Configuration
--compat switch
With the --compat switch Nimony completely supports Nim's nim.cfg and NimScript configuration mode. However, as it is a messy legacy system its usage for new projects is discouraged. Instead the "args configuration system" should be used. It has been designed with tooling in mind.
Args configuration system
There are different files that manage different aspects of the configuration:
- nimony.args is a text file that contains command line arguments that are processed as if they were passed on the command line.
- nimony.paths is a text file where every line is an entry to the search --path. This is so important for tooling that it became a separate file.
- $cc.args is a text file that contains command line arguments that are passed to the used C compiler. $cc here stands for a general C compiler key. This key is extracted from the --cc command line option.
- $linker.args is a text file that contains command line arguments that are passed to the used linker. $linker here stands for a general linker key. This key is extracted from the --linker command line option. If --linker is not used the C compiler command is used for linking.
.args files are processed before the real command line arguments are processed so that they can be overridden. An .args file can contain newlines as whitespace. Lines starting with # are comments. The POSIX command line parsing rules are used: Whitespace enclosed within single or double quotes is kept as is and the quotes are removed.
These files are searched for in the directory of the <program>.nim file and if not found in its parent directories. Only the first file found is used. The idea here is that nobody (neither humans nor tools) needs to perform a "merge" operation of different configuration files.
The --cc command line option
The --cc switch supports a general command prefix that can be as simple as gcc or as complex as /usr/bin/arm-linux-gnueabihf-gcc -Wall.
From the command prefix a "key" is extracted automatically. This key is then used to construct an .args file that can be used to configure the toolchain further. Examples:
- /usr/bin/gcc → gcc.args
- /usr/bin/arm-linux-gnueabihf-gcc → arm-linux-gnueabihf-gcc.args
- /usr/bin/x86_64-w64-mingw32-gcc.exe -Wall → x86_64-w64-mingw32-gcc.args
- /usr/local/bin/clang → clang.args
This way there is no hardcoded list of C compilers. In fact, C++ or an LLVM based backend is naturally supported too.
Runtime: -d:useLibc and friends
By default Nimony's standard library does not depend on libc: memory comes from Nimony's own allocator (a region allocator over mmap) and I/O goes straight to the operating system. With the C backend libc is still linked, and the standard library falls back to it where a libc-free implementation is impossible or only approximate. Three defines opt back into libc:
| Define | C backend (nimony c) | Native backend (nimony n) |
|---|---|---|
| -d:useLibc | mimalloc as the allocator, libc for I/O | Linux: link libc (see below); elsewhere ignored |
| -d:useMimalloc | mimalloc as the allocator | ignored |
| -d:useLibcIo | libc for I/O | ignored |
The native backend normally links no libc at all. On Linux it writes a static, freestanding executable, which cannot bind a foreign symbol. On Linux, nimony n -d:useLibc builds a program linked with libc instead:
- nifasm writes a relocatable object and the system linker finishes the program (--linker picks it; the default is clang), so foreign objects from {.compile.} and {.link.} can be linked in. A program that uses either pragma requires -d:useLibc on Linux, and says so when it is missing.
- Every importc proc calls libc, where the freestanding build turns a known one (write, exit, …) into a raw system call.
- Threads are pthreads, and thread-locals live in libc's static TLS block.
- main is called by the C runtime and returns to it, so C stdio buffers are flushed at exit.
The allocator and the I/O layer stay Nimony's own, as on the C backend's default configuration. The executable is a regular dynamically linked, non-PIE program. On macOS the native backend always links against libSystem and on Windows it binds through import tables, so the switch changes nothing there.
The --linker command line option
If the --linker command line option is not used, the C compiler's executable will also be used for linking. The used .args file is then $cc.linker.args.
If the --linker command line option is used, the specified executable will be used for linking. As for the --cc option, the used .args file will then be $linkerName.linker.args. For example --linker:gold.exe will look for a configuration file gold.linker.args.