Where should shared libraries be placed in a Crystal shard, especially for shards that include C bindings?

Question: Where should shared libraries be placed in a Crystal shard, especially for shards that include C bindings?

Shared libraries should be stored in the default directories of the operating system. However, in the Ruby, it is common to include shared libraries in a Gem. For example, when writing a C extension library, running the rake compile command generates the shared library in the lib directory. Some Fat gems also include third-party shared libraries and use a Rakefile to download the latest binaries into the vendor directory, or download the source code and compile the shared libraries.

Of course, it is preferable to use the OS package manager to install libraries in the designated locations and manage them with pkg-config. However, not all libraries can be managed this way. For example, you have a custom shared library that you want to use only for the shard.

While there is no absolute right answer, how would you handle this issue in Crystal?

1 Like

src/ext/ is where I tend to put them

1 Like

I’m going to say “depends”. I usually make a folder called rsrc in the root project directory that contains anything that isn’t crystal source code, like images, audio, etc. Naturally for web projects I put stuff like images in public/. I usually put mine in rsrc/native and include subdirectories for windows and linux, however I am also a big fan of compile it for them with an install.sh script or whatever. That’s the method I use for raylib-cr. If I do it that way I can just call make install in raylib and not have to worry about much else as it should install where it needs to.

Another way would to just include the shared libraries in the folder and reference them in your Link annotation directly. This might be the “cleaner” way because then you can ensure that the proper version of your shared library is used and included with your project but may cause issues if people need to compile special versions of their shared library. Case in point, I can compile raylib without audio support in miniaudio, and raylib-cr supports that as long as you make install a version of raylib without the audio stuff.

It really depends on how much you want to hold the user’s hand. In the case of raylib I feel that it is overall better to make it super super easy to install and use, rather than make users fiddle with what version of raylib and what feature set raylib provides. raylib is also meant to be used directly, so another point of it needing to be “easy”, since I do not wrap raylib and I don’t really expect to because there is no feature that wrapping can provide that would be better than just using the functions directly.

If you throw users to the wolves I would say either prepare for no one to ever use your c binding/library or to be flooded with issues due to users installing (pick one) the latest version/and old version/wrong branch/wrong release/etc,etc. I also dislike this because when things do go wrong because of any of these issues, it becomes a nightmare to track down.

TLDR OPTIONS:

  1. Make a folder and put the shared libraries in there and reference them relative. I like rsrc/native but whatever works.
  2. Compile the libraries on the fly and make install to put them in the right place. Basically make an install.sh
  3. Throw user the the wolves and make them do it themselves and watch them suffer.
1 Like