TensorFlow Lite
CMake
Static Library
Build Guide
Cross-Compilation

How to build TensorFlow Lite as a static library and link to it from a separate CMake project?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Building TensorFlow Lite as a static library is possible with CMake, but the important part is not just producing libtensorflow-lite.a. The harder part is linking it cleanly from another project without losing the include paths, compile definitions, and transitive libraries that TensorFlow Lite depends on.

The Safest Mental Model

Treat TensorFlow Lite as a CMake target, not just as a raw archive file. A static .a file by itself is often not enough, because TensorFlow Lite also depends on headers and other libraries built alongside it.

In practice, you have two workable approaches:

  1. include the TensorFlow Lite CMake project from your own CMake build
  2. build the static archive separately and create an imported target in your consumer project

The first option is usually more reliable.

Build TensorFlow Lite with CMake

Clone the TensorFlow repository and configure the TensorFlow Lite subproject with shared libraries disabled.

bash
1git clone https://github.com/tensorflow/tensorflow.git
2cmake -S tensorflow/tensorflow/lite -B build-tflite \
3  -DCMAKE_BUILD_TYPE=Release \
4  -DBUILD_SHARED_LIBS=OFF
5cmake --build build-tflite -j

That produces a static tensorflow-lite target and, on a typical Unix-like build, a libtensorflow-lite.a archive in the build output.

A minimal test program might look like this:

cpp
1#include <iostream>
2#include "tensorflow/lite/model.h"
3
4int main() {
5    auto model = tflite::FlatBufferModel::BuildFromFile("model.tflite");
6    if (!model) {
7        std::cerr << "failed to load model\n";
8        return 1;
9    }
10    std::cout << "model loaded\n";
11    return 0;
12}

This is enough to verify that the headers and core runtime link correctly.

Preferred Integration: add_subdirectory

The most robust way to consume TensorFlow Lite from a separate CMake project is to add its source tree as a subdirectory and link the target directly.

cmake
1cmake_minimum_required(VERSION 3.16)
2project(tflite_consumer CXX)
3
4set(CMAKE_CXX_STANDARD 17)
5set(BUILD_SHARED_LIBS OFF)
6
7add_subdirectory(/absolute/path/to/tensorflow/tensorflow/lite
8                 ${CMAKE_BINARY_DIR}/tflite-build
9                 EXCLUDE_FROM_ALL)
10
11add_executable(app main.cpp)
12target_link_libraries(app PRIVATE tensorflow-lite)

Why this is preferable:

  • TensorFlow Lite's include directories stay attached to the target
  • transitive dependencies remain encoded in CMake
  • you avoid hand-maintaining a fragile list of extra libraries

Even though the consumer is a separate project, you are still letting CMake understand the full dependency graph.

Linking a Prebuilt Static Archive

If you really need to build TensorFlow Lite separately and then link the result later, define an imported target in the consumer project.

cmake
1cmake_minimum_required(VERSION 3.16)
2project(tflite_consumer CXX)
3
4set(CMAKE_CXX_STANDARD 17)
5
6add_library(tflite STATIC IMPORTED)
7set_target_properties(tflite PROPERTIES
8    IMPORTED_LOCATION "/opt/tflite/lib/libtensorflow-lite.a"
9    INTERFACE_INCLUDE_DIRECTORIES "/opt/tflite/include"
10)
11
12find_package(Threads REQUIRED)
13
14add_executable(app main.cpp)
15target_link_libraries(app PRIVATE tflite Threads::Threads dl m)

This works only if /opt/tflite/include contains the TensorFlow Lite headers your program needs and the extra system libraries match the platform. In real builds, you may also need additional third-party dependency outputs that were built together with TensorFlow Lite.

That is why raw-archive linking tends to break more often than target-based integration.

Header Layout Matters

A common stumbling block is assuming that only one header directory is required. TensorFlow Lite pulls in headers from its own source tree and from generated or third-party dependency locations depending on how it was built.

If compilation fails with missing headers, the issue is usually not the static library itself. It is that the consumer project does not have the same include path view as the original build.

In other words, building the archive is only half the job. Exporting the correct build interface is the other half.

Cross-Compilation Considerations

If you are building for ARM or another non-host architecture, the producer and consumer builds must use compatible toolchains. A static library compiled for x86_64 cannot be linked into an ARM target just because the headers match.

For cross builds:

  • pass the same toolchain file to both builds
  • keep C++ standard and ABI settings aligned
  • verify whether optional delegates such as XNNPACK are enabled consistently

A mismatch here often shows up as linker errors that look unrelated to TensorFlow Lite until you inspect the object file architecture.

Common Pitfalls

The biggest mistake is treating libtensorflow-lite.a as self-contained. It is a binary artifact, not a full description of the build interface.

Another mistake is manually copying a few headers until the compiler stops complaining. That usually leaves the project in a brittle state that breaks on the next TensorFlow update.

Developers also mix toolchains between the TensorFlow Lite build and the consumer project, especially in embedded builds. Static linking does not forgive ABI mismatches.

Finally, if you only need the library in one application, prefer add_subdirectory over a manually imported archive. It is simpler and less error-prone.

Summary

  • Building TensorFlow Lite as a static library is straightforward; linking it correctly is the harder part.
  • The most reliable approach is to consume TensorFlow Lite as a CMake target with add_subdirectory.
  • A separately built libtensorflow-lite.a can work, but you must also provide matching headers and dependent libraries.
  • Keep toolchain, ABI, and optional feature settings aligned between producer and consumer builds.
  • Think in terms of build targets and interfaces, not just archive files.

Course illustration
Course illustration

All Rights Reserved.