Building and Linking Tensorflow in your C++ Project

30/03/2018

Currently building Tensorflow into a C++ project requires several steps and a modest amount of debugging. In this post I'm going to document how I've managed to build tensorflow in my own C++ projects, and update these instructions as and when I find better ways of doing this.

Overview

The steps are roughly as follows:
  1. Download the Tensorflow source and dependencies
  2. Build the Tensorflow static library
  3. Build the static nsync library (required by Tensorflow)
  4. Set the include paths for headers and the static libraries
These instructions have only been tested on macOS but should also work for Linux. Unfortunately I can't comment on how this will work on Windows.

If at any point you make a mistake with the build or need to reset your local repo, the following commands will forcefully remove any changes in your tensorflow directory:
    git reset --hard origin/r1.7 (or another later release tag)
    git checkout -f r1.7

1. Download the Tensorflow source and dependencies

Firstly, if you haven't already you'll need to download the source code for Tensorflow. Go to the directory you want to clone the source into, then run:
    git clone https://github.com/tensorflow/tensorflow
    git checkout r1.7 (or another later release tag)
The contrib/makefile directory in Tensorflow provides many components that you'll need to build the static library, and provides a makefile and script to download dependencies.

I'd recommend having a look at the makefile in this part of the project as it has some useful information.

Now we need to download some dependencies. From the top directory in the Tensorflow project, run the following command:
tensorflow/contrib/makefile/download_dependencies.sh

2. Build the Tensorflow static library

From the top directory in the Tensorflow project, run the following command:
tensorflow/contrib/makefile/build_all_linux.sh
This will provide a static library in:
tensorflow/tensorflow/contrib/makefile/gen/lib/

3. Build the static nsync library

Nsync is required by projects that link against Tensorflow, so we now need to build it. Go to tensorflow/contrib/makefile/downloads/nsync/builds/<platform> and run make. This will build libnsync.a which you can link your project against.

4. Set the include paths for headers and the static libraries

When building your projects there are some includes paths required for nsync, protobuf, eigen, and Tensorflow itself. Either set these in your IDE or makefile:
    -I/tensorflow/
    -I/tensorflow/tensorflow/contrib/makefile/gen/proto/
    -I/tensorflow/tensorflow/contrib/makefile/gen/protobuf/include/
    -I/tensorflow/tensorflow/contrib/makefile/downloads/eigen/
    -I/tensorflow/tensorflow/contrib/makefile/downloads/eigen/unsupported/Eigen/
    -I/tensorflow/tensorflow/contrib/makefile/downloads/nsync/public/
And the libraries to link against:
    -L/tensorflow/tensorflow/contrib/makefile/gen/lib/
    -ltensorflow-core
    -L/tensorflow/tensorflow/contrib/makefile/gen/protobuf/lib
    -lprotobuf
    -lprotoc
    -L/tensorflow/tensorflow/contrib/makefile/downloads/nsync/builds/
    -lnsync
Important: You'll also need to add one of the following linker flags depending on your platform:
    macOS: -all_load
    Linux: -Wl,--allow-multiple-definition -Wl,--whole-archive
This will prevent the runtime error `Not found: No session factory registered for the given session options`, which is caused by the linker removing symbols that are actually needed