summary refs log tree commit diff stats
path: root/doc/backends.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/backends.md')
-rw-r--r--doc/backends.md406
1 files changed, 406 insertions, 0 deletions
diff --git a/doc/backends.md b/doc/backends.md
new file mode 100644
index 000000000..9f0c54835
--- /dev/null
+++ b/doc/backends.md
@@ -0,0 +1,406 @@
+================================
+   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:
+
+  ```
+  <html><body>
+  <script type="text/javascript">
+  function addTwoIntegers(a, b)
+  {
+    return a + b;
+  }
+  </script>
+  <script type="text/javascript" src="calculator.js"></script>
+  </body></html>
+  ```
+
+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 <stdio.h>
+
+  int fib(int a);
+  void NimMain();
+
+  int main(void)
+  {
+    NimMain();
+    for (int f = 0; f < 10; f++)
+      printf("Fib of %d is %d\n", f, fib(f));
+    return 0;
+  }
+  ```
+
+Now you can run the following Unix like commands to first generate C sources
+from the Nim code, then link them into a static binary along your main C
+program:
+
+  ```cmd
+  nim c --noMain --noLinking fib.nim
+  gcc -o m -I$HOME/.cache/nim/fib_d -Ipath/to/nim/lib $HOME/.cache/nim/fib_d/*.c maths.c
+  ```
+
+The first command runs the Nim compiler with three special options to avoid
+generating a `main()`:c: function in the generated files and to avoid linking the
+object files into a final binary. All the generated files are placed into the ``nimcache``
+directory. That's why the next command compiles the ``maths.c`` source plus
+all the ``.c`` files from ``nimcache``. In addition to this path, you also
+have to tell the C compiler where to find Nim's ``nimbase.h`` header file.
+
+Instead of depending on the generation of the individual ``.c`` files you can
+also ask the Nim compiler to generate a statically linked library:
+
+  ```cmd
+  nim c --app:staticLib fib.nim
+  gcc -o m -Inimcache -Ipath/to/nim/lib maths.c libfib.nim.a
+  ```
+
+The Nim compiler will handle linking the source files generated in the
+``nimcache`` directory into the ``libfib.nim.a`` static library, which you can
+then link into your C program. Note that these commands are generic and will
+vary for each system. For instance, on Linux systems you will likely need to
+use `-ldl`:option: too to link in required dlopen functionality.
+
+
+### Nim invocation example from JavaScript
+
+Create a ``mhost.html`` file with the following content:
+
+  ```
+  <html><body>
+  <script type="text/javascript" src="fib.js"></script>
+  <script type="text/javascript">
+  alert("Fib for 9 is " + fib(9));
+  </script>
+  </body></html>
+  ```
+
+Create a ``fib.nim`` file with the following content (or reuse the one
+from the previous section):
+
+  ```nim
+  proc fib(a: cint): cint {.exportc.} =
+    if a <= 2:
+      result = 1
+    else:
+      result = fib(a - 1) + fib(a - 2)
+  ```
+
+Compile the Nim code to JavaScript with `nim js -o:fib.js fib.nim`:cmd: and
+open ``mhost.html`` in a browser. If the browser supports javascript, you
+should see an alert box displaying the text ``Fib for 9 is 34``. As mentioned
+earlier, JavaScript doesn't require an initialization call to `NimMain` or
+a similar function and you can call the exported Nim proc directly.
+
+
+Nimcache naming logic
+---------------------
+
+The `nimcache`:idx: directory is generated during compilation and will hold
+either temporary or final files depending on your backend target. The default
+name for the directory depends on the used backend and on your OS but you can
+use the `--nimcache`:option: [compiler switch](
+nimc.html#compiler-usage-commandminusline-switches) to change it.
+
+
+Memory management
+=================
+
+In the previous sections, the `NimMain()` function reared its head. Since
+JavaScript already provides automatic memory management, you can freely pass
+objects between the two languages without problems. In C and derivate languages
+you need to be careful about what you do and how you share memory. The
+previous examples only dealt with simple scalar values, but passing a Nim
+string to C, or reading back a C string in Nim already requires you to be
+aware of who controls what to avoid crashing.
+
+
+Strings and C strings
+---------------------
+
+The manual mentions that [Nim strings are implicitly convertible to
+cstrings](manual.html#types-cstring-type) which makes interaction usually
+painless. Most C functions accepting a Nim string converted to a
+`cstring` will likely not need to keep this string around and by the time
+they return the string won't be needed anymore.
+
+A similar thing happens with C code invoking Nim code which returns a
+`cstring`. Consider the following proc:
+
+  ```nim
+  proc gimme(): cstring {.exportc.} =
+    result = "Hey there C code! " & $rand(100)
+  ```
+
+Since Nim's reference counting mechanism is not aware of the C code, once the
+`gimme` proc has finished it can reclaim the memory of the `cstring`.
+
+
+Custom data types
+-----------------
+
+Just like strings, custom data types that are to be shared between Nim and
+the backend will need careful consideration of who controls who. If you want
+to hand a Nim reference to C code, you will need to use [GC_ref](
+system.html#GC_ref,ref.T) to mark the reference as used, so it does not get
+freed. And for the C backend you will need to expose the [GC_unref](
+system.html#GC_unref,ref.T) proc to clean up this memory when it is not
+required anymore.
+
+Again, if you are wrapping a library which *mallocs* and *frees* data
+structures, you need to expose the appropriate *free* function to Nim so
+you can clean it up. And of course, once cleaned you should avoid accessing it
+from Nim (or C for that matter). Typically C data structures have their own
+`malloc_structure`:c: and `free_structure`:c: specific functions, so wrapping
+these for the Nim side should be enough.