I've been thinking about how to use nim to write system libraries and create 
tightly integrated applications. There's a couple things that I think need to 
get done in nim and I'd like to request some comments.

I've also been slowly adding nim support to meson, and lots of this stuff comes 
out of a desire for good integration there, including with multi-language 
projects

**System libraries**

Since most Linux sysadmins are interested in security updates and thus in 
shared libraries or at least a central location for dependencies, it would be 
good if nim supported these things.

# Shared libraries and interfaces

For shared libraries we are almost there, but it's hard to create a shared 
library for a module that's written in nim and meant to be consumed by nim 
code. You can exportc everything but then you are limited to c features and 
(for example) no overloading. Exporting nim identifiers seems fine to me but 
there should be safeguards (maybe in the "header" files, which I'll get to 
later) so that you can't accidently use a shared library built with an ABI 
incompatible version of the compiler (or, for example, a different GC).

If we do want to be able to generate nim shared libraries (with the nim ABI of 
a particular compiler) then we need some way to generate nim files with the 
prototypes for things exported by those libraries. D has [interface 
files](https://dlang.org/dmd-linux.html#interface-files) which are generated by 
the compiler automatically to solve just this problem. It's probably possible 
to implement this as a nim program that uses the compiler module, and maybe 
even as a (probably term rewriting) macro.

# Finding libraries and interfaces

If we generate "system" libraries we then need a way to figure out include 
paths and link options. D uses pkg-config for this and simply uses Cflags for 
the dmd/ldc flags and Link for the linker options (including the flag to get 
dmd/ldc to pass options to the linker. Since nim compiles to C we _may_ want to 
separate nimflags and cflags, I think the best way to deal with this is to just 
include --passc and --passl in the pkgconfig file and then let tools extract 
those parameters if they need to compile the C code separately.

an example pc file could be:
    
    
    prefix=/usr
    exec_prefix=${prefix}
    includedir=${prefix}/include/nim
    libdir=${exec_prefix}/lib64
    
    Name: NimPackageExample
    Description: an example of a nim pc file
    Version: 1.0.0
    Cflags: --path:${includedir}/NimPackageExample
    Libs: -L${libdir} -lNimPackageExample
    

# Filesystem

I've been thinking about where to put files associated with system libraries on 
the filesystem. I'm not sure what the best locations are but D (on fedora) uses 
/usr/include/d/ for includes, /usr/lib64 for shared libraries, and 
/usr/lib64/pkg-config for the pc files. This seems good to me so I propose the 
following:

  * /usr/include/nim \-- directory for interface files and nim libraries, 
structure could be the same as .nimble/pkgs
  * /usr/lib64 \-- shared libraries go here
  * /usr/lib{64|32|}/pkgconfig \-- pkgconfig goes here, or wherever the distro 
usually puts pc files.



# Nimble

I don't think much is needed in terms of new nimble features, but nimscript 
modules could be provided to help with pc files and install directories. I know 
fedora already has someone working on rpm macros to help package nim programs 
and libraries.

**GNOME ideas**

While we already have StefanSalewski's gintro project for generating nim source 
from typelibs, it could be improved (and indeed I'm starting to work on 
improving it).

  * It would be great if there was an easy way to tell gintro what nim specific 
tweaks it needs to make, like gir-to-d's APILayout.txt files or rust-gir's toml 
config files. the cfg file syntax could be used for this (or maybe even 
nimscript).
  * we need to be able to give gintro flags for where to output files, and 
which libraries to introspect. (working on this now)
  * IMO gintro should be using gir XML instead of typelib files to generate 
bindings, this avoids needing to bootstrap the girepository library



Next it would be EXTREMELY cool to be able to create new introspectable 
libraries in nim. I actually think nim is a really good language for this 
because, somewhat like c, it makes the ABI of your code quite clear.

  * this could be again done using a program (perhaps nim-g-ir-scanner) that 
uses the compiler module and essentially implements a new codegen backend, or a 
new pass for gir files, it may also be possible to use nim's existing --header 
option to make a header that g-ir-scanner can understand (comments would need 
to be passed through). This lacks some flexibility since we then couldn't use 
nim features like custom pragmas, effect tracking, and so on, to influence 
generation.



This happens to create a pretty good story for integration into other 
languages, you could write a library in nim, and use it in a pretty natural way 
from: d, rust, python, perl, javascript, C++, (not C yet, strangely), vala, and 
probably others, all without writing much, if any, binding code. I think 
gobject introspection even works on windows.

Thanks for reading this somewhat long post, It's largely a wishlist but I want 
to hack on some of this stuff and start a discussion on how to make nim a 
killer language for people that are currently writing C because of it's binding 
friendliness and system integration on POSIX. (most new languages fail 
spectacularly here).

**Discuss!**

Reply via email to