================================ Nim Backend Integration ================================ :Author: Puppet Master :Version: |nimversion| .. default-role:: code .. include:: rstcommon.rst .. no syntax highlighting here by default: .. contents:: > "Heresy grows from idleness." -- Unknown. Introduction ============ The [Nim Compiler User Guide](nimc.html) documents the typical compiler invocation, using the `compile`:option: or `c`:option: command to transform a ``.nim`` file into one or more ``.c`` files which are then compiled with the platform's C compiler into a static binary. However, there are other commands to compile to C++, Objective-C, or JavaScript. This document tries to concentrate in a single place all the backend and interfacing options. The Nim compiler supports mainly two backend families: the C, C++ and Objective-C targets and the JavaScript target. [The C like targets]( #backends-the-c-like-targets) creates source files that can be compiled into a library or a final executable. [The JavaScript target]( #backends-the-javascript-target) can generate a ``.js`` file which you reference from an HTML file or create a [standalone Node.js program]( http://nodejs.org). On top of generating libraries or standalone applications, Nim offers bidirectional interfacing with the backend targets through generic and specific pragmas. Backends ======== The C like targets ------------------ The commands to compile to either C, C++ or Objective-C are: //compileToC, cc compile project with C code generator //compileToCpp, cpp compile project to C++ code //compileToOC, objc compile project to Objective C code The most significant difference between these commands is that if you look into the ``nimcache`` directory you will find ``.c``, ``.cpp`` or ``.m`` files, other than that all of them will produce a native binary for your project. This allows you to take the generated code and place it directly into a project using any of these languages. Here are some typical command- line invocations: ```cmd nim c hallo.nim nim cpp hallo.nim nim objc hallo.nim ``` The compiler commands select the target backend, but if needed you can [specify additional switches for cross-compilation]( nimc.html#crossminuscompilation) to select the target CPU, operative system or compiler/linker commands. The JavaScript target --------------------- Nim can also generate `JavaScript`:idx: code through the `js`:option: command. Nim targets JavaScript 1.5 which is supported by any widely used browser. Since JavaScript does not have a portable means to include another module, Nim just generates a long ``.js`` file. Features or modules that the JavaScript platform does not support are not available. This includes: * manual memory management (`alloc`, etc.) * casting and other unsafe operations (`cast` operator, `zeroMem`, etc.) * file management * OS-specific operations * threading, coroutines * some modules of the standard library * proper 64-bit integer arithmetic To compensate, the standard library has modules [catered to the JS backend]( lib.html#pure-libraries-modules-for-js-backend) and more support will come in the future (for instance, Node.js bindings to get OS info). To compile a Nim module into a ``.js`` file use the `js`:option: command; the default is a ``.js`` file that is supposed to be referenced in an ``.html`` file. However, you can also run the code with `nodejs`:idx: (http://nodejs.org): ```cmd nim js -d:nodejs -r examples/hallo.nim ``` If you experience errors saying that `globalThis` is not defined, be sure to run a recent version of Node.js (at least 12.0). Interfacing =========== Nim offers bidirectional interfacing with the target backend. This means that you can call backend code from Nim and Nim code can be called by the backend code. Usually the direction of which calls which depends on your software architecture (is Nim your main program or is Nim providing a component?). Nim code calling the backend ---------------------------- Nim code can interface with the backend through the [Foreign function interface](manual.html#foreign-function-interface) mainly through the [importc pragma](manual.html#foreign-function-interface-importc-pragma). The `importc` pragma is the *generic* way of making backend symbols available in Nim and is available in all the target backends (JavaScript too). The C++ or Objective-C backends have their respective [ImportCpp]( manual.html#implementation-specific-pragmas-importcpp-pragma) and [ImportObjC](manual.html#implementation-specific-pragmas-importobjc-pragma) pragmas to call methods from classes. Whenever you use any of these pragmas you need to integrate native code into your final binary. In the case of JavaScript this is no problem at all, the same HTML file which hosts the generated JavaScript will likely provide other JavaScript functions which you are importing with `importc`. However, for the C like targets you need to link external code either statically or dynamically. The preferred way of integrating native code is to use dynamic linking because it allows you to compile Nim programs without the need for having the related development libraries installed. This is done through the [dynlib pragma for import]( manual.html#foreign-function-interface-dynlib-pragma-for-import), though more specific control can be gained using the [dynlib module](dynlib.html). The [dynlibOverride](nimc.html#dynliboverride) command line switch allows to avoid dynamic linking if you need to statically link something instead. Nim wrappers designed to statically link source files can use the [compile pragma](manual.html#implementation-specific-pragmas-compile-pragma) if there are few sources or providing them along the Nim code is easier than using a system library. Libraries installed on the host system can be linked in with the [PassL pragma](manual.html#implementation-specific-pragmas-passl-pragma). To wrap native code, take a look at the [c2nim tool]( https://github.com/nim-lang/c2nim/blob/master/doc/c2nim.rst) which helps with the process of scanning and transforming header files into a Nim interface. ### C invocation example Create a ``logic.c`` file with the following content: ```c int addTwoIntegers(int a, int b) { return a + b; } ``` Create a ``calculator.nim`` file with the following content: ```nim {.compile: "logic.c".} proc addTwoIntegers(a, b: cint): cint {.importc.} when isMainModule: echo addTwoIntegers(3, 7) ``` With these two files in place, you can run `nim c -r calculator.nim`:cmd: and the Nim compiler will compile the ``logic.c`` file in addition to ``calculator.nim`` and link both into an executable, which outputs `10` when run. Another way to link the C file statically and get the same effect would be to remove the line with the `compile` pragma and run the following typical Unix commands: ```cmd gcc -c logic.c ar rvs mylib.a logic.o nim c --passL:mylib.a -r calculator.nim ``` Just like in this example we pass the path to the ``mylib.a`` library (and we could as well pass ``logic.o``) we could be passing switches to link any other static C library. ### JavaScript invocation example Create a ``host.html`` file with the following content: ```
``` Create a ``calculator.nim`` file with the following content (or reuse the one from the previous section): ```nim proc addTwoIntegers(a, b: int): int {.importc.} when isMainModule: echo addTwoIntegers(3, 7) ``` Compile the Nim code to JavaScript with `nim js -o:calculator.js calculator.nim`:cmd: and open ``host.html`` in a browser. If the browser supports javascript, you should see the value `10` in the browser's console. Use the [dom module](dom.html) for specific DOM querying and modification procs or take a look at [karax](https://github.com/pragmagic/karax) for how to develop browser-based applications. Backend code calling Nim ------------------------ Backend code can interface with Nim code exposed through the [exportc pragma](manual.html#foreign-function-interface-exportc-pragma). The `exportc` pragma is the *generic* way of making Nim symbols available to the backends. By default, the Nim compiler will mangle all the Nim symbols to avoid any name collision, so the most significant thing the `exportc` pragma does is maintain the Nim symbol name, or if specified, use an alternative symbol for the backend in case the symbol rules don't match. The JavaScript target doesn't have any further interfacing considerations since it also has garbage collection, but the C targets require you to initialize Nim's internals, which is done calling a `NimMain` function. Also, C code requires you to specify a forward declaration for functions or the compiler will assume certain types for the return value and parameters which will likely make your program crash at runtime. The name `NimMain` can be influenced via the `--nimMainPrefix:prefix` switch. Use `--nimMainPrefix:MyLib` and the function to call is named `MyLibNimMain`. When compiling to static or dynamic libraries, they don't call destructors of global variables as normal Nim programs would do. A C API `NimDestroyGlobals` is provided to call these global destructors. ### Nim invocation example from C Create a ``fib.nim`` file with the following content: ```nim proc fib(a: cint): cint {.exportc.} = if a <= 2: result = 1 else: result = fib(a - 1) + fib(a - 2) ``` Create a ``maths.c`` file with the following content: ```c #include