summary refs log blame commit diff stats
path: root/doc/backends.txt
blob: 9d57450dd078ee1c05507fd1a52beed6a3ae196c (plain) (tree)



















                                                                      




                                                                            
 





                                                                              
























                                                                          



                                                                             





































                                                                            





                                                                            



                                






































                                                                              












                                   
================================
   Nimrod Backend Integration
================================

:Author: Puppet Master
:Version: |nimrodversion|

.. contents::

  "If we all reacted the same way, we'd be predictable, and there's
  always more than one way to view a situation. What's true for the
  group is also true for the individual. It's simple: overspecialize,
  and you breed in weakness.  It's slow death." -- Major Motoko
  Kusanagi


Introduction
============

The `Nimrod Compiler User Guide <nimrodc.html>`_ documents the typical
compiler invocation, using the ``compile`` or ``c`` 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 Nimrod compiler supports mainly two backends: the C (and derivate) and the
JavaScript targets. The C target creates source files which can be compiled
into a library or a final executable. The JavaScript target generates a
``.js`` file which you call from an HTML file. On top of generating a library
or executable, Nimrod 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::

    $ nimrod c hallo.nim
    $ nimrod cpp hallo.nim
    $ nimrod objc hallo.nim

The compiler commands select the target backend, but if needed you can
`specify additional switches for cross compilation
<nimrodc.html#cross-compilation>`_ to select the target CPU, operative system
or compiler/linker commands.


The JavaScript target
---------------------

Nimrod can also generate `JavaScript`:idx: code through the ``js`` command.
However, the JavaScript code generator is experimental!

Nimrod targets JavaScript 1.5 which is supported by any widely used browser.
Since JavaScript does not have a portable means to include another module,
Nimrod 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
* most modules of the Standard library
* proper 64 bit integer arithmetic
* unsigned integer arithmetic

However, the modules `strutils <strutils.html>`_, `math <math.html>`_, and
`times <times.html>`_ are available! To access the DOM, use the `dom
<dom.html>`_ module that is only available for the JavaScript platform.

To compile a Nimrod module into a ``.js`` file use the ``js`` 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:, a `software
platform for easily building fast, scalable network applications
<http://nodejs.org>`_::

  nimrod js -d:nodejs -r examples/hallo.nim


Interfacing
===========

Nimrod offers bidirectional interfacing with the target backend. This means
that you can call backend code from Nimrod and Nimrod code can be called by
the backend code. Usually the direction of which calls which depends on your
software architecture (is Nimrod your main program or is Nimrod providing a
component?).


Nimrod code calling the backend
--------------------------------

Nimrod code can interface with the backend through the `Foreign function
interface <manual.html#foreign-function-interface>`_ mainly through the
`importc pragma <manual.html#importc-pragma>`_. The ``importc`` pragma is the
*generic* way of making backend code available in Nimrod and is available in
all the target backends (JavaScript too).  The C++ or Objective-C backends
have their respective `ImportCpp <nimrodc.html#importcpp-pragma>`_ and
`ImportObjC <nimrodc.html#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 Nimrod programs without
the need for having the related development libraries installed. This is done
through the `dynlib pragma for import
<manual.html#dynlib-pragma-for-import>`_, though more specific control can be
gained using the `dynlib module <dynlib.html>`_.

The `dynlibOverride <nimrodc.html#dynliboverride>`_ command line switch allows
to avoid dynamic linking if you need to statically link something instead.
Nimrod wrappers designed to statically link source files can use the `compile
pragma <nimrodc.html#compile-pragma>`_ if there are few sources or providing
them along the Nimrod code is easier than using a system library. Libraries
installed on the host system can be linked in with the `PassL pragma
<nimrodc.html#passl-pragma>`_.

To wrap native code, take a look at the `c2nim tool <c2nim.html>`_ which helps
with the process of scanning and transforming header files into a Nimrod
interface.

Example in C.

Example in JS.


Backend code calling Nimrod
---------------------------

mention NimMain

Memory management
=================

Garbage collection, life of objects
-----------------------------------

Thread coordination
-------------------
class="p">.Printf("Invalid command: %q\n", os.Args[1]) printUsage() os.Exit(1) } switch os.Args[2] { case "apod", "nasa": apodCmd.Parse(os.Args[3:]) if apodCmd.Parsed() { execAPOD() } case "bpod", "bing": bpodCmd.Parse(os.Args[3:]) if bpodCmd.Parsed() { execBPOD() } default: fmt.Printf("Invalid service: %q\n", os.Args[2]) printUsage() os.Exit(1) } } func printUsage() { fmt.Println("Usage: cetus <command> <service> [<flags>]\n") fmt.Println("Commands: ") fmt.Println(" set Set the latest image as background") fmt.Println(" fetch Fetch the latest image information") fmt.Println(" version Print version") fmt.Println("\nServices: ") fmt.Println(" apod NASA Astronomy Picture of the Day") fmt.Println(" bpod Bing Photo of the Day") } // Check whether user has set CETUS_CACHE_DIR, if not then use the // XDG_CACHE_HOME. If XDG_CACHE_HOME is not set then $HOME/.config // should be used, according to XDG Base Directory Specification func getCacheDir() string { cacheDir := os.Getenv("CETUS_CACHE_DIR") if len(cacheDir) == 0 { cacheDir = os.Getenv("XDG_CACHE_HOME") } if len(cacheDir) == 0 { cacheDir = fmt.Sprintf("%s/%s/%s", os.Getenv("HOME"), ".cache", "cetus") } return cacheDir } func chkErr(err error) { if err != nil { fmt.Println(err) os.Exit(1) } }