I'm trying to get some Nim bindings for this neat little game programming library called raylib. But well, I'm having some difficulties trying to do so.

After cleaning up raylib.h, I was able to use c2nim to auto-generate a .nim. I commented out a few things and added in the {.importc.} pragmas manually. You can see it thus far here.

If you want to help me out, you'll need to build your own copy of raylib, off of the develop branch, using the SHARED_RAYLIB=YES option at make. There are some extra instructions on their Wiki.

On Linux:

I can't seem to get the library to load at runtime. It compiles fine. But when I try to run the core_basic_window in examples, I keep on getting could not load: libraylib.so messages. I tried compiling with the extra information and it only said that it couldn't find the .so file. I tried placing the .so in /usr/local/lib, and the current working directory (with setting LD_LIBRARY_PATH). Still nothing. Does anyone see what's wrong here?

EDIT: It seems to be an issue with the .so that is generated by raylib. I'm trying to figure out a fix for it. If anyone would like to help: https://github.com/raysan5/raylib/issues/332

2nd EDIT: I got a simple Nim binding to work under linux using the .so`s, but it's been a little bit of a pain since I think I also might have found an issue with the `.so that GLFW makes for the platform. I'll document what I've done to make it work on post #5 of this thread.

On OS X:

It's in a partial working state. For now, the .dylib needs to be in the same folder as the .nim you want to compile, as well as for to run the executable. There's a bit of a problem though. It's failing to load some of the functions from the .dylib, thus making the application crash if I don't have that {.deadCodeElim: on.} pragma at the top of src/raylib.nim. For example, if I remove that pragma, it will compile, but at runtime it will say could not import: LoadMeshEx. The proc id in Nim looks fine to me. Anyone know what's going wrong?

For Windows:

I haven't tried yet. If someone else to try this out and see how they are going, I'd be very appreciative.

2017-07-19 21:47:18
Well you use dynlib: LIB_RAYLIB (which is fine) and add linker commands {.passL: "-L. -lraylib".} at the same time! That's wrong! Use one way or the other, preferably the dynlib solution.
2017-07-20 06:47:54
you can also add all c files of raylib manually with the compile pragma, like I did it in AntTweakBar https://github.com/krux02/nimAntTweakBar/blob/master/AntTweakBar.nim#L43
2017-07-20 16:54:49
I found out some more information about the issue on Linux. If you read the link to my edited post at the top it explains a little more. tl;dr the raylib.so Linux .so is broken. 2017-07-21 03:50:44
I've been able to get the Nim bindings to work on Linux using .so files!! There is still a bit of an odd quirk:
  1. GLFW 3.2.1 needs to be installed (with cmake -DBUILD_SHARED_LIBS=ON) from source (sudo make install). So those get put in /usr/local/lib
  2. raylib needs to be installed (with make SHARED_RAYLIB=YES) from source (sudo make install SHARED_RAYLIB=YES). Those get put in /usr/local/lib too.

So at this point, you can compile the core_basic_window.nim example I have in examples. But the problem is that if I try to run it, I get this:

[email protected]:examples$ ./core_basic_window
/usr/local/lib/libraylib.so: undefined symbol: glfwSetWindowIcon
could not load: libraylib.so

But when I did export LD_LIBRARY_PATH=/usr/local/lib. then it would run fine. What the hell is going on here? Isn't /usr/local/lib one of the default library search paths? That's where the .so files are put.

2017-07-22 03:21:21

Add it through /etc/ld.so.conf.d/ example here. Relevant thread in Archlinux forum.

You might want to file a bug to your linux distro.

2017-07-22 07:36:52
I use ubuntu (well, xubuntu... technically). I doubt it's a bug on their side. Someone else would have tripped over this way before I would have and fixed it too. 2017-07-22 22:14:02

I think I figured out why setting export LD_LIBRARY_PATH=/usr/local/lib was necessary to make it work. The dlopen() function is used under the hood for the dynlib macro on Linux. dlopen() will not search /usr/local/lib by default. It needs to be manually specified...

Is this something that maybe should be fixed in the Nim source to also search /usr/local/lib for .so files on unix systems?

2017-07-23 22:28:45

It is not Nim's problem.

From the dlopen doco, you definitely need to either use ldconfig or set LD_LIBRARY_PATH, because dlopen does not check /usr/local/lib by default:

       o   (ELF only) If the executable file for the calling program
           contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag,
           then the directories listed in the DT_RPATH tag are searched.
       o   If, at the time that the program was started, the environment
           variable LD_LIBRARY_PATH was defined to contain a colon-separated
           list of directories, then these are searched.  (As a security
           measure, this variable is ignored for set-user-ID and set-group-
           ID programs.)
       o   (ELF only) If the executable file for the calling program
           contains a DT_RUNPATH tag, then the directories listed in that
           tag are searched.
       o   The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is
           checked to see whether it contains an entry for filename.
       o   The directories /lib and /usr/lib are searched (in that order).

2017-07-23 23:50:53
I consider it something that Nim should be concerned about. It's already caused me a fair bit of grief trying to get the bindings working on Linux and I'm sure anyone else will run into the same issue down the road. Keep in mind it's not my .so that it was failing to find, but an .so that mine depended on, which was in a well known install location.
2017-07-24 02:24:26