So I'm working on wrapper for a library (stb_image) that is contained in a single header file. Right now if I want to get things to compile and work, I have to tell the nim compiler where that header file is located. For example, if my project structure is like this:

 - main.nim
 - header_lib.h
 - header_lib.nim

And I'm compiling from that src/ directory, I have to do this: nim c main.nim --cincludes:. I'd really like to drop that --includes part, so whoever uses this wrapper only has to do the import statement.

Is there a way that I can do this without copy and pasting the source of the header into the .nim wrapper file?

2016-12-17 01:28:32
I think you could rename your header file to c and then inside header_lib.nim add:
{.compile: "header_lib.c".} There are also ways to pass arguments to the compiler from code
2016-12-17 09:20:20
Headers can be included via {.emit: """#include "../some_header.h"""".}, or when using symbols from it: proc f: int {.importc: "some_c_func", header: "../some_header.h".}. The path with "../" is for the case when the header is in the folder with Nim code and "nimcache" folder too.
2016-12-17 14:10:52
I went with yglukhov's solution (since it seemed to be the simplest to use), but It's really what I wanted to avoid doing. 2016-12-17 22:32:59
Sorry for this late response but usually your nim file doesn't have to depend on a C header file at all. importc the identifiers and either use .dynlib or some {.link: "lib.a".} command to link against the library.
2016-12-22 14:59:06

Resurrecting this thread as I stumbled upon the exact same issue.

The library from def_pri_pub (stb_image) and the library I'm wrapping (ttmath) are header-only so we can't link to a library.

I've noticed that {.importc: "someProc", header: "path/to/header".} is either absolute or relative to the nimcache directory.

I think header: should either:

  • copy the header to nimcache if a dynlib pragma is not passed too to ease header-only library wrapping.
  • or be relative to the source file
2018-02-08 21:48:54
Actually header pragma will be converted to #include "header", so C compiler is looking it in current directory and directories specified in -I argument. So you can easily {.passC:"-I/some/directory/you/want".} and it will start looking for your headers not only in 'nimcache' directory. This must work for GCC and MSVC compilers.
2018-02-08 22:53:50

It doesn't work for headers distributed through nimble.

For some users the path will be {.header:"/home/cheatfate/.nimble/pkgs/foopkg-0.1.0/headers/fooheaders.h".} and others will have {.header:"/Users/mratsim/.nimble/pkgs/foopkg-0.2.0/headers/fooheaders.h".} ` There is probably a way through staticRead and then staticExec to copy the headers but I don't see an obvious non-hacky way.

2018-02-09 08:30:09

This workaround worked for me, but it is still hacky. Assuming the header file is in the same directory than the nim file:

from os import splitPath
{.passC:"-I" & currentSourcePath().splitPath.head .}

Not tested, but the following could work.

const myHeader = currentSourcePath().splitPath.head & "/myHeader.h"


proc foo() {.importc, header: myHeader.}

2018-02-09 09:36:41