TensorFlow
Travis-CI
shared library
continuous integration
build process

How to build a shared library for TensorFlow on Travis-CI

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Building a shared library that links against TensorFlow on Travis CI is mostly a C++ build-and-dependency problem, not a special Travis-only feature. The important parts are choosing a consistent Python and TensorFlow version, obtaining the correct compiler and linker flags from TensorFlow, and making the CI environment match what you expect locally. Travis is less common today than some newer CI platforms, but the mechanics are still straightforward.

Decide What You Are Building Against

There are two common cases:

  • a shared library that links against TensorFlow headers and libraries exposed through the Python package
  • a custom TensorFlow op or plugin built from C++

For many lightweight cases, installing TensorFlow in Python and using tf.sysconfig to obtain compile and link flags is the easiest route.

A minimal source file might look like this:

cpp
1#include <iostream>
2#include <tensorflow/core/public/version.h>
3
4extern "C" void print_tf_version() {
5    std::cout << "TensorFlow version: " << TF_VERSION_STRING << std::endl;
6}

This is enough to verify that your build can see TensorFlow headers and produce a shared object.

Use tf.sysconfig for Flags

TensorFlow's Python package can tell you which compiler and linker flags are required.

bash
1python - <<'PY'
2import tensorflow as tf
3print(tf.sysconfig.get_compile_flags())
4print(tf.sysconfig.get_link_flags())
5PY

That is much safer than hardcoding include and library paths manually, because TensorFlow packaging details vary by version and platform.

A local build command can then look like:

bash
g++ -std=c++17 -shared -fPIC example.cpp -o libexample.so \
  $(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_compile_flags()))') \
  $(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_link_flags()))')

Travis CI Configuration

A minimal .travis.yml for this style of build might be:

yaml
1language: python
2python:
3  - "3.10"
4
5install:
6  - pip install --upgrade pip
7  - pip install tensorflow
8
9script:
10  - python -c "import tensorflow as tf; print(tf.__version__)"
11  - g++ -std=c++17 -shared -fPIC example.cpp -o libexample.so $(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_compile_flags()))') $(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_link_flags()))')
12  - test -f libexample.so

This does three things:

  • installs TensorFlow
  • confirms the package imports
  • compiles the shared library using TensorFlow's own reported flags

Keep the Build Environment Predictable

TensorFlow and C++ toolchains can be sensitive to version drift. A build that works locally may fail in CI because of:

  • different Python versions
  • incompatible TensorFlow wheels
  • older system compilers
  • missing system libraries

That is why pinning versions helps.

yaml
install:
  - pip install tensorflow==2.16.1

Use a version that you know matches the rest of your project and platform expectations.

Artifact Handling

If the library build is an intermediate verification step, checking that libexample.so exists may be enough. If the built artifact needs to be downloaded later, configure Travis to upload it as a build artifact or publish it in a release workflow.

The important point is that CI should do more than "compile without crashing." It should verify that the resulting library is actually present and, ideally, loadable by a small test.

A Basic Runtime Check

A simple post-build smoke test can catch linker issues early.

python
1import ctypes
2
3lib = ctypes.CDLL("./libexample.so")
4lib.print_tf_version()

If compilation succeeds but loading fails, you may have runtime library-path or symbol issues even though the compiler stage passed.

Common Pitfalls

The most common mistake is hardcoding include or linker paths instead of using tf.sysconfig. TensorFlow packaging details change enough that hardcoded paths become brittle quickly.

Another mistake is letting the CI environment drift from local development, especially in Python version, TensorFlow version, or compiler version.

Developers also often stop at a successful compile without testing whether the shared library can actually be loaded.

Finally, be aware that Travis itself is not the hard part here. The real issues are TensorFlow binary compatibility and reliable dependency pinning.

Summary

  • Install TensorFlow in CI and use tf.sysconfig for compile and link flags.
  • Keep Python, TensorFlow, and compiler versions consistent with local development.
  • Build the shared library with -shared and -fPIC as appropriate.
  • Add at least a smoke test that confirms the artifact exists and can be loaded.
  • Treat TensorFlow version compatibility as part of the build design, not as an afterthought.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.