mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-30 18:02:05 +00:00
884 lines
29 KiB
Plaintext
884 lines
29 KiB
Plaintext
===================================
|
|
Nim Compiler User Guide
|
|
===================================
|
|
|
|
:Author: Andreas Rumpf
|
|
:Version: |nimversion|
|
|
|
|
.. contents::
|
|
|
|
"Look at you, hacker. A pathetic creature of meat and bone, panting and
|
|
sweating as you run through my corridors. How can you challenge a perfect,
|
|
immortal machine?"
|
|
|
|
|
|
Introduction
|
|
============
|
|
|
|
This document describes the usage of the *Nim compiler*
|
|
on the different supported platforms. It is not a definition of the Nim
|
|
programming language (therefore is the `manual <manual.html>`_).
|
|
|
|
Nim is free software; it is licensed under the
|
|
`MIT License <http://www.opensource.org/licenses/mit-license.php>`_.
|
|
|
|
|
|
Compiler Usage
|
|
==============
|
|
|
|
Command line switches
|
|
---------------------
|
|
Basic command line switches are:
|
|
|
|
Usage:
|
|
|
|
.. include:: basicopt.txt
|
|
|
|
----
|
|
|
|
Advanced command line switches are:
|
|
|
|
.. include:: advopt.txt
|
|
|
|
|
|
|
|
List of warnings
|
|
----------------
|
|
|
|
Each warning can be activated individually with ``--warning[NAME]:on|off`` or
|
|
in a ``push`` pragma.
|
|
|
|
========================== ============================================
|
|
Name Description
|
|
========================== ============================================
|
|
CannotOpenFile Some file not essential for the compiler's
|
|
working could not be opened.
|
|
OctalEscape The code contains an unsupported octal
|
|
sequence.
|
|
Deprecated The code uses a deprecated symbol.
|
|
ConfigDeprecated The project makes use of a deprecated config
|
|
file.
|
|
SmallLshouldNotBeUsed The letter 'l' should not be used as an
|
|
identifier.
|
|
EachIdentIsTuple The code contains a confusing ``var``
|
|
declaration.
|
|
ShadowIdent A local variable shadows another local
|
|
variable of an outer scope.
|
|
User Some user defined warning.
|
|
========================== ============================================
|
|
|
|
|
|
Verbosity levels
|
|
----------------
|
|
|
|
===== ============================================
|
|
Level Description
|
|
===== ============================================
|
|
0 Minimal output level for the compiler.
|
|
1 Displays compilation of all the compiled files, including those imported
|
|
by other modules or through the `compile pragma<#compile-pragma>`_.
|
|
This is the default level.
|
|
2 Displays compilation statistics, enumerates the dynamic
|
|
libraries that will be loaded by the final binary and dumps to
|
|
standard output the result of applying `a filter to the source code
|
|
<filters.html>`_ if any filter was used during compilation.
|
|
3 In addition to the previous levels dumps a debug stack trace
|
|
for compiler developers.
|
|
===== ============================================
|
|
|
|
|
|
Compile time symbols
|
|
--------------------
|
|
|
|
Through the ``-d:x`` or ``--define:x`` switch you can define compile time
|
|
symbols for conditional compilation. The defined switches can be checked in
|
|
source code with the `when statement <manual.html#when-statement>`_ and
|
|
`defined proc <system.html#defined>`_. The typical use of this switch is to
|
|
enable builds in release mode (``-d:release``) where certain safety checks are
|
|
omitted for better performance. Another common use is the ``-d:ssl`` switch to
|
|
activate `SSL sockets <sockets.html>`_.
|
|
|
|
|
|
Configuration files
|
|
-------------------
|
|
|
|
**Note:** The *project file name* is the name of the ``.nim`` file that is
|
|
passed as a command line argument to the compiler.
|
|
|
|
|
|
The ``nim`` executable processes configuration files in the following
|
|
directories (in this order; later files overwrite previous settings):
|
|
|
|
1) ``$nim/config/nim.cfg``, ``/etc/nim.cfg`` (UNIX) or ``%NIMROD%/config/nim.cfg`` (Windows). This file can be skipped with the ``--skipCfg`` command line option.
|
|
2) ``/home/$user/.config/nim.cfg`` (UNIX) or ``%APPDATA%/nim.cfg`` (Windows). This file can be skipped with the ``--skipUserCfg`` command line option.
|
|
3) ``$parentDir/nim.cfg`` where ``$parentDir`` stands for any parent directory of the project file's path. These files can be skipped with the ``--skipParentCfg`` command line option.
|
|
4) ``$projectDir/nim.cfg`` where ``$projectDir`` stands for the project file's path. This file can be skipped with the ``--skipProjCfg`` command line option.
|
|
5) A project can also have a project specific configuration file named ``$project.nim.cfg`` that resides in the same directory as ``$project.nim``. This file can be skipped with the ``--skipProjCfg`` command line option.
|
|
|
|
|
|
Command line settings have priority over configuration file settings.
|
|
|
|
The default build of a project is a `debug build`:idx:. To compile a
|
|
`release build`:idx: define the ``release`` symbol::
|
|
|
|
nim c -d:release myproject.nim
|
|
|
|
|
|
Search path handling
|
|
--------------------
|
|
|
|
Nim has the concept of a global search path (PATH) that is queried to
|
|
determine where to find imported modules or include files. If multiple files are
|
|
found an ambiguity error is produced.
|
|
|
|
``nim dump`` shows the contents of the PATH.
|
|
|
|
However before the PATH is used the current directory is checked for the
|
|
file's existence. So if PATH contains ``$lib`` and ``$lib/bar`` and the
|
|
directory structure looks like this::
|
|
|
|
$lib/x.nim
|
|
$lib/bar/x.nim
|
|
foo/x.nim
|
|
foo/main.nim
|
|
other.nim
|
|
|
|
And ``main`` imports ``x``, ``foo/x`` is imported. If ``other`` imports ``x``
|
|
then both ``$lib/x.nim`` and ``$lib/bar/x.nim`` match and so the compiler
|
|
should reject it. Currently however this check is not implemented and instead
|
|
the first matching file is used.
|
|
|
|
|
|
Generated C code directory
|
|
--------------------------
|
|
The generated files that Nim produces all go into a subdirectory called
|
|
``nimcache`` in your project directory. This makes it easy to delete all
|
|
generated files. Files generated in this directory follow a naming logic which
|
|
you can read about in the `Nim Backend Integration document
|
|
<backends.html#nimcache-naming-logic>`_.
|
|
|
|
However, the generated C code is not platform independent. C code generated for
|
|
Linux does not compile on Windows, for instance. The comment on top of the
|
|
C file lists the OS, CPU and CC the file has been compiled for.
|
|
|
|
|
|
Compilation cache
|
|
=================
|
|
|
|
**Warning**: The compilation cache is still highly experimental!
|
|
|
|
The ``nimcache`` directory may also contain so called `rod`:idx:
|
|
or `symbol files`:idx:. These files are pre-compiled modules that are used by
|
|
the compiler to perform `incremental compilation`:idx:. This means that only
|
|
modules that have changed since the last compilation (or the modules depending
|
|
on them etc.) are re-compiled. However, per default no symbol files are
|
|
generated; use the ``--symbolFiles:on`` command line switch to activate them.
|
|
|
|
Unfortunately due to technical reasons the ``--symbolFiles:on`` needs
|
|
to *aggregate* some generated C code. This means that the resulting executable
|
|
might contain some cruft even when dead code elimination is turned on. So
|
|
the final release build should be done with ``--symbolFiles:off``.
|
|
|
|
Due to the aggregation of C code it is also recommended that each project
|
|
resides in its own directory so that the generated ``nimcache`` directory
|
|
is not shared between different projects.
|
|
|
|
|
|
Cross compilation
|
|
=================
|
|
|
|
To cross compile, use for example::
|
|
|
|
nim c --cpu:i386 --os:linux --compile_only --gen_script myproject.nim
|
|
|
|
Then move the C code and the compile script ``compile_myproject.sh`` to your
|
|
Linux i386 machine and run the script.
|
|
|
|
Another way is to make Nim invoke a cross compiler toolchain::
|
|
|
|
nim c --cpu:arm --os:linux myproject.nim
|
|
|
|
For cross compilation, the compiler invokes a C compiler named
|
|
like ``$cpu.$os.$cc`` (for example arm.linux.gcc) and the configuration
|
|
system is used to provide meaningful defaults. For example for ``ARM`` your
|
|
configuration file should contain something like::
|
|
|
|
arm.linux.gcc.path = "/usr/bin"
|
|
arm.linux.gcc.exe = "arm-linux-gcc"
|
|
arm.linux.gcc.linkerexe = "arm-linux-gcc"
|
|
|
|
|
|
DLL generation
|
|
==============
|
|
|
|
Nim supports the generation of DLLs. However, there must be only one
|
|
instance of the GC per process/address space. This instance is contained in
|
|
``nimrtl.dll``. This means that every generated Nim DLL depends
|
|
on ``nimrtl.dll``. To generate the "nimrtl.dll" file, use the command::
|
|
|
|
nim c -d:release lib/nimrtl.nim
|
|
|
|
To link against ``nimrtl.dll`` use the command::
|
|
|
|
nim c -d:useNimRtl myprog.nim
|
|
|
|
**Note**: Currently the creation of ``nimrtl.dll`` with thread support has
|
|
never been tested and is unlikely to work!
|
|
|
|
|
|
Additional compilation switches
|
|
===============================
|
|
|
|
The standard library supports a growing number of ``useX`` conditional defines
|
|
affecting how some features are implemented. This section tries to give a
|
|
complete list.
|
|
|
|
================== =========================================================
|
|
Define Effect
|
|
================== =========================================================
|
|
``release`` Turns off runtime checks and turns on the optimizer.
|
|
``useWinAnsi`` Modules like ``os`` and ``osproc`` use the Ansi versions
|
|
of the Windows API. The default build uses the Unicode
|
|
version.
|
|
``useFork`` Makes ``osproc`` use ``fork`` instead of ``posix_spawn``.
|
|
``useNimRtl`` Compile and link against ``nimrtl.dll``.
|
|
``useMalloc`` Makes Nim use C's `malloc`:idx: instead of Nim's
|
|
own memory manager. This only works with ``gc:none``.
|
|
``useRealtimeGC`` Enables support of Nim's GC for *soft* realtime
|
|
systems. See the documentation of the `gc <gc.html>`_
|
|
for further information.
|
|
``nodejs`` The JS target is actually ``node.js``.
|
|
``ssl`` Enables OpenSSL support for the sockets module.
|
|
``memProfiler`` Enables memory profiling for the native GC.
|
|
``uClibc`` Use uClibc instead of libc. (Relevant for Unix-like OSes)
|
|
================== =========================================================
|
|
|
|
|
|
|
|
Additional Features
|
|
===================
|
|
|
|
This section describes Nim's additional features that are not listed in the
|
|
Nim manual. Some of the features here only make sense for the C code
|
|
generator and are subject to change.
|
|
|
|
|
|
NoDecl pragma
|
|
-------------
|
|
The ``noDecl`` pragma can be applied to almost any symbol (variable, proc,
|
|
type, etc.) and is sometimes useful for interoperability with C:
|
|
It tells Nim that it should not generate a declaration for the symbol in
|
|
the C code. For example:
|
|
|
|
.. code-block:: Nim
|
|
var
|
|
EACCES {.importc, noDecl.}: cint # pretend EACCES was a variable, as
|
|
# Nim does not know its value
|
|
|
|
However, the ``header`` pragma is often the better alternative.
|
|
|
|
**Note**: This will not work for the LLVM backend.
|
|
|
|
|
|
Header pragma
|
|
-------------
|
|
The ``header`` pragma is very similar to the ``noDecl`` pragma: It can be
|
|
applied to almost any symbol and specifies that it should not be declared
|
|
and instead the generated code should contain an ``#include``:
|
|
|
|
.. code-block:: Nim
|
|
type
|
|
PFile {.importc: "FILE*", header: "<stdio.h>".} = distinct pointer
|
|
# import C's FILE* type; Nim will treat it as a new pointer type
|
|
|
|
The ``header`` pragma always expects a string constant. The string contant
|
|
contains the header file: As usual for C, a system header file is enclosed
|
|
in angle brackets: ``<>``. If no angle brackets are given, Nim
|
|
encloses the header file in ``""`` in the generated C code.
|
|
|
|
**Note**: This will not work for the LLVM backend.
|
|
|
|
|
|
IncompleteStruct pragma
|
|
-----------------------
|
|
The ``incompleteStruct`` pragma tells the compiler to not use the
|
|
underlying C ``struct`` in a ``sizeof`` expression:
|
|
|
|
.. code-block:: Nim
|
|
type
|
|
DIR* {.importc: "DIR", header: "<dirent.h>",
|
|
final, pure, incompleteStruct.} = object
|
|
|
|
|
|
Compile pragma
|
|
--------------
|
|
The ``compile`` pragma can be used to compile and link a C/C++ source file
|
|
with the project:
|
|
|
|
.. code-block:: Nim
|
|
{.compile: "myfile.cpp".}
|
|
|
|
**Note**: Nim computes a CRC checksum and only recompiles the file if it
|
|
has changed. You can use the ``-f`` command line option to force recompilation
|
|
of the file.
|
|
|
|
|
|
Link pragma
|
|
-----------
|
|
The ``link`` pragma can be used to link an additional file with the project:
|
|
|
|
.. code-block:: Nim
|
|
{.link: "myfile.o".}
|
|
|
|
|
|
PassC pragma
|
|
------------
|
|
The ``passC`` pragma can be used to pass additional parameters to the C
|
|
compiler like you would using the commandline switch ``--passC``:
|
|
|
|
.. code-block:: Nim
|
|
{.passC: "-Wall -Werror".}
|
|
|
|
Note that you can use ``gorge`` from the `system module <system.html>`_ to
|
|
embed parameters from an external command at compile time:
|
|
|
|
.. code-block:: Nim
|
|
{.passC: gorge("pkg-config --cflags sdl").}
|
|
|
|
PassL pragma
|
|
------------
|
|
The ``passL`` pragma can be used to pass additional parameters to the linker
|
|
like you would using the commandline switch ``--passL``:
|
|
|
|
.. code-block:: Nim
|
|
{.passL: "-lSDLmain -lSDL".}
|
|
|
|
Note that you can use ``gorge`` from the `system module <system.html>`_ to
|
|
embed parameters from an external command at compile time:
|
|
|
|
.. code-block:: Nim
|
|
{.passL: gorge("pkg-config --libs sdl").}
|
|
|
|
|
|
Emit pragma
|
|
-----------
|
|
The ``emit`` pragma can be used to directly affect the output of the
|
|
compiler's code generator. So it makes your code unportable to other code
|
|
generators/backends. Its usage is highly discouraged! However, it can be
|
|
extremely useful for interfacing with `C++`:idx: or `Objective C`:idx: code.
|
|
|
|
Example:
|
|
|
|
.. code-block:: Nim
|
|
{.emit: """
|
|
static int cvariable = 420;
|
|
""".}
|
|
|
|
{.push stackTrace:off.}
|
|
proc embedsC() =
|
|
var nimVar = 89
|
|
# use backticks to access Nim symbols within an emit section:
|
|
{.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimVar`);""".}
|
|
{.pop.}
|
|
|
|
embedsC()
|
|
|
|
As can be seen from the example, to Nim symbols can be referred via backticks.
|
|
Use two backticks to produce a single verbatim backtick.
|
|
|
|
|
|
ImportCpp pragma
|
|
----------------
|
|
|
|
**Note**: `c2nim <c2nim.html>`_ can parse a large subset of C++ and knows
|
|
about the ``importcpp`` pragma pattern language. It is not necessary
|
|
to know all the details described here.
|
|
|
|
|
|
Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the
|
|
``importcpp`` pragma can be used to import `C++`:idx: methods or C++ symbols
|
|
in general. The generated code then uses the C++ method calling
|
|
syntax: ``obj->method(arg)``. In combination with the ``header`` and ``emit``
|
|
pragmas this allows *sloppy* interfacing with libraries written in C++:
|
|
|
|
.. code-block:: Nim
|
|
# Horrible example of how to interface with a C++ engine ... ;-)
|
|
|
|
{.link: "/usr/lib/libIrrlicht.so".}
|
|
|
|
{.emit: """
|
|
using namespace irr;
|
|
using namespace core;
|
|
using namespace scene;
|
|
using namespace video;
|
|
using namespace io;
|
|
using namespace gui;
|
|
""".}
|
|
|
|
const
|
|
irr = "<irrlicht/irrlicht.h>"
|
|
|
|
type
|
|
IrrlichtDeviceObj {.final, header: irr,
|
|
importcpp: "IrrlichtDevice".} = object
|
|
IrrlichtDevice = ptr IrrlichtDeviceObj
|
|
|
|
proc createDevice(): IrrlichtDevice {.
|
|
header: irr, importcpp: "createDevice(@)".}
|
|
proc run(device: IrrlichtDevice): bool {.
|
|
header: irr, importcpp: "#.run(@)".}
|
|
|
|
The compiler needs to be told to generate C++ (command ``cpp``) for
|
|
this to work. The conditional symbol ``cpp`` is defined when the compiler
|
|
emits C++ code.
|
|
|
|
|
|
Namespaces
|
|
~~~~~~~~~~
|
|
|
|
The *sloppy interfacing* example uses ``.emit`` to produce ``using namespace``
|
|
declarations. It is usually much better to instead refer to the imported name
|
|
via the ``namespace::identifier`` notation:
|
|
|
|
.. code-block:: nim
|
|
type
|
|
IrrlichtDeviceObj {.final, header: irr,
|
|
importcpp: "irr::IrrlichtDevice".} = object
|
|
|
|
|
|
Importcpp for enums
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
When ``importcpp`` is applied to an enum type the numerical enum values are
|
|
annotated with the C++ enum type, like in this example: ``((TheCppEnum)(3))``.
|
|
(This turned out to be the simplest way to implement it.)
|
|
|
|
|
|
Importcpp for procs
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
Note that the ``importcpp`` variant for procs uses a somewhat cryptic pattern
|
|
language for maximum flexibility:
|
|
|
|
- A hash ``#`` symbol is replaced by the first or next argument.
|
|
- A dot following the hash ``#.`` indicates that the call should use C++'s dot
|
|
or arrow notation.
|
|
- An at symbol ``@`` is replaced by the remaining arguments, separated by
|
|
commas.
|
|
|
|
For example:
|
|
|
|
.. code-block:: nim
|
|
proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "#.CppMethod(@)".}
|
|
var x: ptr CppObj
|
|
cppMethod(x[], 1, 2, 3)
|
|
|
|
Produces:
|
|
|
|
.. code-block:: C
|
|
x->CppMethod(1, 2, 3)
|
|
|
|
As a special rule to keep backwards compatibility with older versions of the
|
|
``importcpp`` pragma, if there is no special pattern
|
|
character (any of ``# ' @``) at all, C++'s
|
|
dot or arrow notation is assumed, so the above example can also be written as:
|
|
|
|
.. code-block:: nim
|
|
proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "CppMethod".}
|
|
|
|
Note that the pattern language naturally also covers C++'s operator overloading
|
|
capabilities:
|
|
|
|
.. code-block:: nim
|
|
proc vectorAddition(a, b: Vec3): Vec3 {.importcpp: "# + #".}
|
|
proc dictLookup(a: Dict, k: Key): Value {.importcpp: "#[#]".}
|
|
|
|
|
|
- An apostrophe ``'`` followed by an integer ``i`` in the range 0..9
|
|
is replaced by the i'th parameter *type*. The 0th position is the result
|
|
type. This can be used to pass types to C++ function templates. Between
|
|
the ``'`` and the digit an asterisk can be used to get to the base type
|
|
of the type. (So it "takes away a star" from the type; ``T*`` becomes ``T``.)
|
|
Two stars can be used to get to the element type of the element type etc.
|
|
|
|
For example:
|
|
|
|
.. code-block:: nim
|
|
|
|
type Input {.importcpp: "System::Input".} = object
|
|
proc getSubsystem*[T](): ptr T {.importcpp: "SystemManager::getSubsystem<'*0>()".}
|
|
|
|
let x: ptr Input = getSubsystem[Input]()
|
|
|
|
Produces:
|
|
|
|
.. code-block:: C
|
|
x = SystemManager::getSubsystem<System::Input>()
|
|
|
|
|
|
- ``#@`` is a special case to support a ``cnew`` operation. It is required so
|
|
that the call expression is inlined directly, without going through a
|
|
temporary location. This is only required to circumvent a limitation of the
|
|
current code generator.
|
|
|
|
For example C++'s ``new`` operator can be "imported" like this:
|
|
|
|
.. code-block:: nim
|
|
proc cnew*[T](x: T): ptr T {.importcpp: "(new '*0#@)", nodecl.}
|
|
|
|
# constructor of 'Foo':
|
|
proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)".}
|
|
|
|
let x = cnew constructFoo(3, 4)
|
|
|
|
Produces:
|
|
|
|
.. code-block:: C
|
|
x = new Foo(3, 4)
|
|
|
|
However, depending on the use case ``new Foo`` can also be wrapped like this
|
|
instead:
|
|
|
|
.. code-block:: nim
|
|
proc newFoo(a, b: cint): ptr Foo {.importcpp: "new Foo(@)".}
|
|
|
|
let x = newFoo(3, 4)
|
|
|
|
|
|
Wrapping constructors
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Sometimes a C++ class has a private copy constructor and so code like
|
|
``Class c = Class(1,2);`` must not be generated but instead ``Class c(1,2);``.
|
|
For this purpose the Nim proc that wraps a C++ constructor needs to be
|
|
annotated with the `constructor`:idx: pragma. This pragma also helps to generate
|
|
faster C++ code since construction then doesn't invoke the copy constructor:
|
|
|
|
.. code-block:: nim
|
|
# a better constructor of 'Foo':
|
|
proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)", constructor.}
|
|
|
|
|
|
Wrapping destructors
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Since Nim generates C++ directly, any destructor is called implicitly by the
|
|
C++ compiler at the scope exits. This means that often one can get away with
|
|
not wrapping the destructor at all! However when it needs to be invoked
|
|
explicitly, it needs to be wrapped. But the pattern language already provides
|
|
everything that is required for that:
|
|
|
|
.. code-block:: nim
|
|
proc destroyFoo(this: var Foo) {.importcpp: "#.~Foo()".}
|
|
|
|
|
|
Importcpp for objects
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Generic ``importcpp``'ed objects are mapped to C++ templates. This means that
|
|
you can import C++'s templates rather easily without the need for a pattern
|
|
language for object types:
|
|
|
|
.. code-block:: nim
|
|
type
|
|
StdMap {.importcpp: "std::map", header: "<map>".} [K, V] = object
|
|
proc `[]=`[K, V](this: var StdMap[K, V]; key: K; val: V) {.
|
|
importcpp: "#[#] = #", header: "<map>".}
|
|
|
|
var x: StdMap[cint, cdouble]
|
|
x[6] = 91.4
|
|
|
|
|
|
Produces:
|
|
|
|
.. code-block:: C
|
|
std::map<int, double> x;
|
|
x[6] = 91.4;
|
|
|
|
|
|
ImportObjC pragma
|
|
-----------------
|
|
Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the
|
|
``importobjc`` pragma can be used to import `Objective C`:idx: methods. The
|
|
generated code then uses the Objective C method calling syntax: ``[obj method
|
|
param1: arg]``. In addition with the ``header`` and ``emit`` pragmas this
|
|
allows *sloppy* interfacing with libraries written in Objective C:
|
|
|
|
.. code-block:: Nim
|
|
# horrible example of how to interface with GNUStep ...
|
|
|
|
{.passL: "-lobjc".}
|
|
{.emit: """
|
|
#include <objc/Object.h>
|
|
@interface Greeter:Object
|
|
{
|
|
}
|
|
|
|
- (void)greet:(long)x y:(long)dummy;
|
|
@end
|
|
|
|
#include <stdio.h>
|
|
@implementation Greeter
|
|
|
|
- (void)greet:(long)x y:(long)dummy
|
|
{
|
|
printf("Hello, World!\n");
|
|
}
|
|
@end
|
|
|
|
#include <stdlib.h>
|
|
""".}
|
|
|
|
type
|
|
Id {.importc: "id", header: "<objc/Object.h>", final.} = distinct int
|
|
|
|
proc newGreeter: Id {.importobjc: "Greeter new", nodecl.}
|
|
proc greet(self: Id, x, y: int) {.importobjc: "greet", nodecl.}
|
|
proc free(self: Id) {.importobjc: "free", nodecl.}
|
|
|
|
var g = newGreeter()
|
|
g.greet(12, 34)
|
|
g.free()
|
|
|
|
The compiler needs to be told to generate Objective C (command ``objc``) for
|
|
this to work. The conditional symbol ``objc`` is defined when the compiler
|
|
emits Objective C code.
|
|
|
|
|
|
CodegenDecl pragma
|
|
------------------
|
|
|
|
The ``codegenDecl`` pragma can be used to directly influence Nim's code
|
|
generator. It receives a format string that determines how the variable or
|
|
proc is declared in the generated code:
|
|
|
|
.. code-block:: nim
|
|
var
|
|
a {.codegenDecl: "$# progmem $#".}: int
|
|
|
|
proc myinterrupt() {.codegenDecl: "__interrupt $# $#$#".} =
|
|
echo "realistic interrupt handler"
|
|
|
|
|
|
InjectStmt pragma
|
|
-----------------
|
|
|
|
The ``injectStmt`` pragma can be used to inject a statement before every
|
|
other statement in the current module. It is only supposed to be used for
|
|
debugging:
|
|
|
|
.. code-block:: nim
|
|
{.injectStmt: gcInvariants().}
|
|
|
|
# ... complex code here that produces crashes ...
|
|
|
|
|
|
LineDir option
|
|
--------------
|
|
The ``lineDir`` option can be turned on or off. If turned on the
|
|
generated C code contains ``#line`` directives. This may be helpful for
|
|
debugging with GDB.
|
|
|
|
|
|
StackTrace option
|
|
-----------------
|
|
If the ``stackTrace`` option is turned on, the generated C contains code to
|
|
ensure that proper stack traces are given if the program crashes or an
|
|
uncaught exception is raised.
|
|
|
|
|
|
LineTrace option
|
|
----------------
|
|
The ``lineTrace`` option implies the ``stackTrace`` option. If turned on,
|
|
the generated C contains code to ensure that proper stack traces with line
|
|
number information are given if the program crashes or an uncaught exception
|
|
is raised.
|
|
|
|
Debugger option
|
|
---------------
|
|
The ``debugger`` option enables or disables the *Embedded Nim Debugger*.
|
|
See the documentation of endb_ for further information.
|
|
|
|
|
|
Breakpoint pragma
|
|
-----------------
|
|
The *breakpoint* pragma was specially added for the sake of debugging with
|
|
ENDB. See the documentation of `endb <endb.html>`_ for further information.
|
|
|
|
|
|
Volatile pragma
|
|
---------------
|
|
The ``volatile`` pragma is for variables only. It declares the variable as
|
|
``volatile``, whatever that means in C/C++ (its semantics are not well defined
|
|
in C/C++).
|
|
|
|
**Note**: This pragma will not exist for the LLVM backend.
|
|
|
|
|
|
DynlibOverride
|
|
==============
|
|
|
|
By default Nim's ``dynlib`` pragma causes the compiler to generate
|
|
``GetProcAddress`` (or their Unix counterparts)
|
|
calls to bind to a DLL. With the ``dynlibOverride`` command line switch this
|
|
can be prevented and then via ``--passL`` the static library can be linked
|
|
against. For instance, to link statically against Lua this command might work
|
|
on Linux::
|
|
|
|
nim c --dynlibOverride:lua --passL:liblua.lib program.nim
|
|
|
|
|
|
Backend language options
|
|
========================
|
|
|
|
The typical compiler usage involves 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. More details
|
|
can be read in the `Nim Backend Integration document <backends.html>`_.
|
|
|
|
|
|
Nim documentation tools
|
|
=======================
|
|
|
|
Nim provides the `doc`:idx: and `doc2`:idx: commands to generate HTML
|
|
documentation from ``.nim`` source files. Only exported symbols will appear in
|
|
the output. For more details `see the docgen documentation <docgen.html>`_.
|
|
|
|
Nim idetools integration
|
|
========================
|
|
|
|
Nim provides language integration with external IDEs through the
|
|
idetools command. See the documentation of `idetools <idetools.html>`_
|
|
for further information.
|
|
|
|
|
|
Nim interactive mode
|
|
====================
|
|
|
|
The Nim compiler supports an interactive mode. This is also known as
|
|
a `REPL`:idx: (*read eval print loop*). If Nim has been built with the
|
|
``-d:useGnuReadline`` switch, it uses the GNU readline library for terminal
|
|
input management. To start Nim in interactive mode use the command
|
|
``nim i``. To quit use the ``quit()`` command. To determine whether an input
|
|
line is an incomplete statement to be continued these rules are used:
|
|
|
|
1. The line ends with ``[-+*/\\<>!\?\|%&$@~,;:=#^]\s*$`` (operator symbol followed by optional whitespace).
|
|
2. The line starts with a space (indentation).
|
|
3. The line is within a triple quoted string literal. However, the detection
|
|
does not work if the line contains more than one ``"""``.
|
|
|
|
|
|
Nim for embedded systems
|
|
========================
|
|
|
|
The standard library can be avoided to a point where C code generation
|
|
for 16bit micro controllers is feasible. Use the `standalone`:idx: target
|
|
(``--os:standalone``) for a bare bones standard library that lacks any
|
|
OS features.
|
|
|
|
To make the compiler output code for a 16bit target use the ``--cpu:avr``
|
|
target.
|
|
|
|
For example, to generate code for an `AVR`:idx: processor use this command::
|
|
|
|
nim c --cpu:avr --os:standalone --deadCodeElim:on --genScript x.nim
|
|
|
|
For the ``standalone`` target one needs to provide
|
|
a file ``panicoverride.nim``.
|
|
See ``tests/manyloc/standalone/panicoverride.nim`` for an example
|
|
implementation.
|
|
|
|
|
|
Nim for realtime systems
|
|
========================
|
|
|
|
See the documentation of Nim's soft realtime `GC <gc.html>`_ for further
|
|
information.
|
|
|
|
|
|
Debugging with Nim
|
|
==================
|
|
|
|
Nim comes with its own *Embedded Nim Debugger*. See
|
|
the documentation of endb_ for further information.
|
|
|
|
|
|
Optimizing for Nim
|
|
==================
|
|
|
|
Nim has no separate optimizer, but the C code that is produced is very
|
|
efficient. Most C compilers have excellent optimizers, so usually it is
|
|
not needed to optimize one's code. Nim has been designed to encourage
|
|
efficient code: The most readable code in Nim is often the most efficient
|
|
too.
|
|
|
|
However, sometimes one has to optimize. Do it in the following order:
|
|
|
|
1. switch off the embedded debugger (it is **slow**!)
|
|
2. turn on the optimizer and turn off runtime checks
|
|
3. profile your code to find where the bottlenecks are
|
|
4. try to find a better algorithm
|
|
5. do low-level optimizations
|
|
|
|
This section can only help you with the last item.
|
|
|
|
|
|
Optimizing string handling
|
|
--------------------------
|
|
|
|
String assignments are sometimes expensive in Nim: They are required to
|
|
copy the whole string. However, the compiler is often smart enough to not copy
|
|
strings. Due to the argument passing semantics, strings are never copied when
|
|
passed to subroutines. The compiler does not copy strings that are a result from
|
|
a procedure call, because the callee returns a new string anyway.
|
|
Thus it is efficient to do:
|
|
|
|
.. code-block:: Nim
|
|
var s = procA() # assignment will not copy the string; procA allocates a new
|
|
# string already
|
|
|
|
However it is not efficient to do:
|
|
|
|
.. code-block:: Nim
|
|
var s = varA # assignment has to copy the whole string into a new buffer!
|
|
|
|
For ``let`` symbols a copy is not always necessary:
|
|
|
|
.. code-block:: Nim
|
|
let s = varA # may only copy a pointer if it safe to do so
|
|
|
|
|
|
If you know what you're doing, you can also mark single string (or sequence)
|
|
objects as `shallow`:idx:\:
|
|
|
|
.. code-block:: Nim
|
|
var s = "abc"
|
|
shallow(s) # mark 's' as shallow string
|
|
var x = s # now might not copy the string!
|
|
|
|
Usage of ``shallow`` is always safe once you know the string won't be modified
|
|
anymore, similar to Ruby's `freeze`:idx:.
|
|
|
|
|
|
The compiler optimizes string case statements: A hashing scheme is used for them
|
|
if several different string constants are used. So code like this is reasonably
|
|
efficient:
|
|
|
|
.. code-block:: Nim
|
|
case normalize(k.key)
|
|
of "name": c.name = v
|
|
of "displayname": c.displayName = v
|
|
of "version": c.version = v
|
|
of "os": c.oses = split(v, {';'})
|
|
of "cpu": c.cpus = split(v, {';'})
|
|
of "authors": c.authors = split(v, {';'})
|
|
of "description": c.description = v
|
|
of "app":
|
|
case normalize(v)
|
|
of "console": c.app = appConsole
|
|
of "gui": c.app = appGUI
|
|
else: quit(errorStr(p, "expected: console or gui"))
|
|
of "license": c.license = UnixToNativePath(k.value)
|
|
else: quit(errorStr(p, "unknown variable: " & k.key))
|