Search code examples
rubyruby-native-extensions

issues building ruby native extension


I've created some code in c that I'd like to call from ruby. I've used this article as a guide, but I'm having problems getting it to run without linking issues.

To start, I have to directly copy the source files into my ext/NAME/ directory. They don't seem to be picked up if I git submodule them into that directory, meaning they'd be under some subdirectory like ext/NAME/CLIB_GIT_SUBMODULE_FILES/.

Next, it seems like I have to run my c projects makefile, otherwise I run into segfaults. If I run my makefile, object files (.o) are created in the ext/NAME directory, and now when I try to run rake (which runs my test cases under /test/ I see linking issues like:

linking shared-object NAME/NAME.so
gcc: error: SOMEFILE_ONE.o: No such file or directory
gcc: error: SOMEFILE_TWO.o: No such file or directory
gcc: error: SOMEFILE_THREE.o: No such file or directory
make: *** [ruby_fast_numerizer.so] Error 1
rake aborted!

Note that when I run the makefile under ext/NAME/ it creates SOMEFILE_ONE.o, etc.

I'm not sure what's going on at this point :( The guides all seem to be writing new c code in the ext/NAME directory, not wrapping an existing c library. I tried looking at other projects for guidance like nokogiri, but they're doing a whole lot more which makes it hard to sift through.

Any help is much appreciated!


Solution

  • Building an extension

    Normally, ext/NAME/extconf.rb uses mkmf (MakeMakefile) to write a new Makefile with all the configuration to build a Ruby extension from the provided sources. MakeMakefile has defaults for where to find source code, headers, and all the other pieces, but you can override them (using dir_config for example).

    The generated Makefile will have instructions to compile source files and link everything with the relevant Ruby libraries to produce a native Ruby extension.

    If you have an existing C library which has nothing to do with Ruby, it probably has its own Makefile and build process. Don't confuse Ruby's generated Makefile with your own!

    Loading a library

    For wrapping an existing C library, I would not build a native extension at all, but instead load the library with FFI. The two major FFI options are Fiddle (comes with Ruby, but tutorials are scarce) or the ffi gem (better documented, but requires a gem).

    Additional resources