Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building and linking shared Tensorflow library on OSX El Capitan to call from Ruby via Swig

I'm trying to help build a Ruby wrapper around Tensorflow using Swig. Currently, I'm stuck at making a shared build, .so, and exposing its C/C++ headers to Ruby. So the question is: How do I build a libtensorflow.so shared build including the full Tensorflow library so it's available as a shared library on OSX El Capitan (note: /usr/lib/ is read-only on El Capitan)?

Background

In this ruby-tensorflow project, I need to package a Tensorflow .bundle file, but whenever I irb -Ilib -rtensorflow or try to run the specs rspec, I get and errors that the basic numeric types are not defined, but they are clearly defined here.

I'm guessing this happens because my .so-file was not created properly or something is not linked as it should. C++/Swig/Bazel are not my strong sides, I'd like to focus on learning Tensorflow and building a good wrapper in Ruby, but I'm pretty stuck at this point getting to that fun part!

What I've done:

  1. git clone --recurse-submodules https://github.com/tensorflow/tensorflow
  2. cd tensorflow
  3. bazel build //tensorflow:libtensorflow.so (wait 10-15min on my machine)
  4. Copied the generated libtensorflow.so (166.6 MB) to the /ext-folder
  5. Run the ruby extconf.rb, make, and make install described in the project
  6. Run rspec

In desperation, I've also gone through the official installation from source several times, but I don't know if that, the last sudo pip install /tmp/tensorflow_pkg/tensorflow-0.9.0-py2-none-any.whl-step even creates a shared build or just exposes a Python interface.

The guy, Arafat, who made the original repository and made the instructions that I've followed, says his libtensorflow.so is 4.5 GB on his Linux machine – so over 20X the size of the shared build on my OSX machine. UPDATE1: he says his libtensorflow.so-build is 302.2 MB, 4.5GB was the size of the entire tensorflow folder.

Any help or alternative approaches are very appreciated!

like image 336
ChrHansen Avatar asked Jul 06 '16 07:07

ChrHansen


2 Answers

After more digging around, discovering otool (thanks Kristina) and better understanding what a .so-file is, the solution didn't require much change in my setup:

Shared Build

# Clone source files
git clone --recurse-submodules https://github.com/tensorflow/tensorflow
cd tensorflow
# Build library
bazel build //tensorflow:libtensorflow.so
# Copy the newly shared build/library to /usr/local/lib
sudo cp bazel-bin/tensorflow/libtensorflow.so /usr/local/lib

Calling from Ruby using Swig

Follow the steps here, https://github.com/chrhansen/ruby-tensorflow#install-ruby-tensorflow, to run Swig, create a Makefile and make

When you run make you should see a line saying:

$ make
$ linking shared-object libtensorflow.bundle

If your shared build is not accessible you'll see something like:

$ ld: library not found for -ltensorflow

Simple tutorial

For those starting on this adventure, using C/C++ libraries in Ruby, this post was a good tutorial for me: http://engineering.gusto.com/simple-ruby-c-extensions-with-swig/

like image 191
ChrHansen Avatar answered Oct 20 '22 14:10

ChrHansen


I don't think you actually want a .so, I think you want a .dylib (see What are the differences between .so and .dylib on osx?). You're forcing Bazel to build a .so by specifying libtensorflow.so as the target, build this instead:

bazel build //tensorflow

(//tensorflow is shorthand for //tensorflow:tensorflow, which is "build the tensorflow target." Specifying an exact file you want forces Bazel to build that file, if possible.)

Once you have a .dylib, you can check its contents with otool:

 otool -L bazel-bin/tensorflow/libtensorflow.dylib

Not sure if this will solve all your problems, but worth a try.

like image 38
kristina Avatar answered Oct 20 '22 14:10

kristina