Skip to content

Repository files navigation

docker-image

🚜 robotFarm

One command builds the C++ libraries your robotics project needs.

robotFarm is a CMake super build. You pick the libraries. It downloads their sources, builds them in dependency order, and installs everything into one prefix. Use it when the apt versions are too old, when you need CUDA builds, or when every machine on a team should carry the same stack.

🐧 Linux only. Needs C, C++, Fortran, and CUDA (13 or newer) compilers. Tested on Ubuntu 22.04, 24.04, and 26.04. MIT license.

  • No lock-in: your project stays a plain find_package client. Nothing robotFarm-specific enters your CMake:

    # Configure your project with -DCMAKE_PREFIX_PATH=/opt/robotFarm and use the libraries as usual.
    find_package(OpenCV REQUIRED)
    target_link_libraries(myApp PRIVATE opencv_core opencv_imgproc)
  • Hands-off: inter-library build order resolves automatically, and the system packages each library needs are computed for you.

  • Auditable: each library's version and feature flags live in one reviewable recipe under externalProjects/.

πŸ“š Supported libraries

Abseil Boost Cap'n Proto Google Eigen FlatBuffers
Abseil Boost Cap'n Proto Ceres Solver Eigen FlatBuffers
Google Google Google nlohmann/json Oat++ OGRE
Google Gflags Google Glog Google Test Nlohmann Json Oat++ * OGRE
OpenCV Google Python 3 spdlog SuiteSparse VTK
OpenCV Protocol Buffers Python 3 Spdlog SuiteSparse † VTK

* oatpp also bundles oatpp-websocket.

† SuiteSparse bundles AMD, CAMD, CCOLAMD, CHOLMOD, COLAMD, SPQR, and SuiteSparse_config.

Exact versions and feature flags are pinned per recipe in externalProjects/. One licensing-sensitive gate to know about: OpenCV's contrib modules and CUDA features build only with -DROBOT_FARM_OPENCV_WITH_NON_FREE_CONTRIB:BOOL=ON, which is off by default and off in the release tarballs.

⚑ Quick Start

Three ways in, ordered by effort. Building everything from source takes tens of minutes; the first two options skip that.

πŸ“¦ Option 1: prebuilt release tarballs

A release is cut by tagging, and each release attaches one install archive per Ubuntu version and CMake preset (gnu-shared, gnu-static, clang-shared, clang-static; pick shared unless you know you need static). Download yours from the releases page and extract it under /opt:

tar --zstd -C /opt -xf robotFarm-<os>-<preset>-sha-<commit>.tar.zst

The archive ships a systemDependencies.txt at its root. It lists the system packages the libraries need at runtime. Install them:

sudo apt update && sudo apt install -y --no-install-recommends \
  $(cat /opt/robotFarm/systemDependencies.txt)

🐳 Option 2: prebuilt base images

CI publishes a build-environment image per Ubuntu version. Compilers, every build dependency, and a recent cmake are preinstalled; robotFarm itself is not:

  • ghcr.io/ajakhotia/robotfarm/ubuntu-22-04/base:latest
  • ghcr.io/ajakhotia/robotfarm/ubuntu-24-04/base:latest
  • ghcr.io/ajakhotia/robotfarm/ubuntu-26-04/base:latest

Replace latest with a sha-<commit> tag to pin a version. The recipe is docker/ubuntu.dockerfile.

Build robotFarm inside a container and keep the install tree on the host:

git clone https://github.com/ajakhotia/robotFarm.git /tmp/robotFarm-src
git -C /tmp/robotFarm-src submodule update --init
mkdir -p /tmp/robotFarm-install

docker run --rm                                                                                 \
  --volume /tmp/robotFarm-src:/src:ro                                                           \
  --volume /tmp/robotFarm-install:/opt/robotFarm                                                \
  ghcr.io/ajakhotia/robotfarm/ubuntu-24-04/base:latest                                          \
  bash -c '
    set -euo pipefail
    cmake -G Ninja -S /src -B /tmp/build                                                        \
        -DCMAKE_BUILD_TYPE=Release                                                              \
        -DCMAKE_INSTALL_PREFIX=/opt/robotFarm
    cmake --build /tmp/build
  '

Replace /tmp/robotFarm-install with any writable host path. Before using the install tree, install the runtime packages on the host:

sudo apt update && sudo apt install -y --no-install-recommends \
  $(cat /tmp/robotFarm-install/systemDependencies.txt)

For CI, bake a derived image once: FROM the base image, then either run the same build in a RUN layer or extract a release tarball into it. Jobs then start with the stack already in place.

πŸ§‘β€πŸ’» Option 3: quickBuild.sh

quickBuild.sh builds robotFarm directly on your machine. It clones the source, registers the apt sources, installs the dependencies, builds, installs, and cleans up after itself. Good for a build-once machine setup.

Warning

The commands below use sudo.

curl -fsSL                                                                                          \
  https://raw.githubusercontent.com/ajakhotia/robotFarm/refs/heads/main/tools/quickBuild.sh |       \
  sudo bash

Version, toolchain, install prefix, and build list are overridable:

curl -fsSL                                                                                          \
  https://raw.githubusercontent.com/ajakhotia/robotFarm/refs/heads/main/tools/quickBuild.sh |       \
  sudo bash -s --                                                                                   \
    --version v2.3.1                                                                                \
    --toolchain linux-clang-22                                                                      \
    --prefix /tmp/robotFarm                                                                         \
    --build-list "GlogExternalProject;GoogleTestExternalProject;FlatBuffersExternalProject"

nioc is a real consumer; its README shows this in use.

🐒 Manual build

The full manual path. Tested on Ubuntu 22.04, 24.04, and 26.04; docker/ubuntu.dockerfile is the working reference.

To pick a compiler, linkage, or a subset of libraries, read Build Customization first.

πŸ“‚ Clone

Pick three writable paths. The commands below refer to them through environment variables:

Variable Purpose Example
SOURCE_TREE Where robotFarm is cloned. Temporary is fine. /tmp/robotFarm
BUILD_TREE Where CMake builds. Temporary is fine. /tmp/robotFarm-build
INSTALL_TREE Where the libraries install. Keep this one. ${HOME}/opt/robotFarm

An install path that needs root (/opt, /usr) needs sudo on the Build step; prefer a path your user can write.

export SOURCE_TREE=/tmp/robotFarm
export BUILD_TREE=/tmp/robotFarm-build
export INSTALL_TREE=${HOME}/opt/robotFarm

git clone https://github.com/ajakhotia/robotFarm.git ${SOURCE_TREE}
git -C ${SOURCE_TREE} submodule update --init
cd ${SOURCE_TREE}

πŸ”§ Install tools

Mandatory: jq, a recent cmake (3.27 or newer, provided by the kitware apt source), and the basic build tools:

sudo apt update &&                                                                            \
sudo apt install -y --no-install-recommends                                                   \
  ca-certificates curl gnupg jq software-properties-common                                &&  \
sudo bash external/infraCommons/tools/apt/addAptSources.sh -y kitware                     &&  \
sudo apt update                                                                           &&  \
sudo apt install -y --no-install-recommends                                                   \
  $(sh external/infraCommons/tools/extractDependencies.sh Basics systemDependencies.json)

Compilers: robotFarm needs C, C++, CUDA, and Fortran compilers. The C, C++, and Fortran compilers must be reachable through their unversioned names (gcc, clang, gfortran); CUDA's nvcc is handed to CMake by path in the Configure step. Install them any way you like. One option is to register the gnu, llvm, and nvidia apt sources and install the Compilers group:

sudo bash external/infraCommons/tools/apt/addAptSources.sh -y gnu llvm nvidia    &&  \
sudo apt update                                                                  &&  \
sudo apt install -y --no-install-recommends                                          \
  $(sh external/infraCommons/tools/extractDependencies.sh Compilers systemDependencies.json)

The minimum supported CUDA Toolkit is 13. The packages above install versioned names only (gcc-15, clang-22, and so on), so register them as the defaults for the unversioned names:

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-15 100          \
  --slave /usr/bin/g++ g++ /usr/bin/g++-15                                       \
  --slave /usr/bin/gfortran gfortran /usr/bin/gfortran-15                    &&  \
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-22 100    \
  --slave /usr/bin/clang++ clang++ /usr/bin/clang++-22                           \
  --slave /usr/bin/flang flang /usr/bin/flang-22

The CUDA toolkit installs under /usr/local/cuda, outside the default search paths. No PATH change is needed: the Configure step hands nvcc's location to CMake as a cache entry, and every cache entry handed to the top-level configure forwards into each library's own configure.

Warning

Do not symlink nvcc into /usr/bin, by hand or through update-alternatives. nvcc locates its toolkit through the literal path it is invoked as, without resolving symlinks, and CMake prefers an nvcc that sits next to the C++ compiler over the ones on PATH. Such a symlink therefore breaks CUDA toolkit detection even when /usr/local/cuda/bin is on PATH.

docker/ubuntu.dockerfile performs the same registration when baking the base images.

πŸ§‘β€πŸ’» Compile

Three steps, one command each.

Configure step

Creates the build tree and sets the install location. The default compilers on PATH, the ones registered in Install tools, do the compiling. The CMAKE_CUDA_COMPILER entry points at nvcc through the alternatives-managed /usr/local/cuda symlink, so a CUDA upgrade needs no edit:

cmake -G Ninja -S ${SOURCE_TREE} -B ${BUILD_TREE}       \
    -DCMAKE_BUILD_TYPE=Release                          \
    -DBUILD_SHARED_LIBS=ON                              \
    -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc      \
    -DCMAKE_CUDA_ARCHITECTURES=all-major                \
    -DCMAKE_INSTALL_PREFIX=${INSTALL_TREE}

BUILD_SHARED_LIBS=ON selects shared libraries, the recommended and best-tested mode; robotFarm defaults to static archives when the flag is omitted.

all-major compiles device code for every major GPU architecture the CUDA toolkit supports, so the install tree runs on any of them. To shorten the build for a single known machine, replace it with that GPU's architecture (nvidia-smi --query-gpu=compute_cap --format=csv,noheader, dot removed, e.g. 120), or with native to let CMake detect the GPU present at build time.

To pin a compiler family or version explicitly instead, add -DCMAKE_TOOLCHAIN_FILE=<path-to-toolchain-file> from Pre-packaged toolchain files.

System dependencies step

The configure writes the required system packages to ${BUILD_TREE}/systemDependencies.txt. Install them:

sudo apt install -y --no-install-recommends $(cat ${BUILD_TREE}/systemDependencies.txt)

Build step

Builds and installs every library into ${INSTALL_TREE}; no separate cmake --install is needed:

cmake --build ${BUILD_TREE}

πŸŽ›οΈ Build Customization

CMake presets

CMakePresets.json covers the compiler-family and linkage combinations CI builds: clang-shared, clang-static, gnu-shared, and gnu-static. They use the unversioned system compilers at /usr/bin/gcc and /usr/bin/clang, through the linux-gnu.cmake and linux-clang.cmake toolchain files. If one matches your environment, it replaces the Configure step:

cmake --preset gnu-shared -S ${SOURCE_TREE} -B ${BUILD_TREE} \
    -DCMAKE_INSTALL_PREFIX=${INSTALL_TREE}

If none matches, ignore them, or copy one into a gitignored CMakeUserPresets.json and edit it there.

Pre-packaged toolchain files

A toolchain file pins the compiler family and version explicitly, overriding the defaults registered in Install tools. Ready-to-use files ship in the infraCommons submodule at ${SOURCE_TREE}/external/infraCommons/cmake/toolchains/:

Every file probes for CUDA and wires it in when present. The versioned files pin absolute compiler paths (/usr/bin/gcc-15 and so on), and the configure fails if a pinned compiler is not installed. Pass your pick as -DCMAKE_TOOLCHAIN_FILE in the Configure step.

Selecting a subset of libraries

By default robotFarm builds every supported library. To build a subset, name the projects:

cmake -G Ninja -S ${SOURCE_TREE} -B ${BUILD_TREE}                                  \
    -DCMAKE_BUILD_TYPE=Release                                                     \
    -DBUILD_SHARED_LIBS=ON                                                         \
    -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc                                 \
    -DCMAKE_CUDA_ARCHITECTURES=all-major                                           \
    -DCMAKE_INSTALL_PREFIX=${INSTALL_TREE}                                         \
    -DROBOT_FARM_REQUESTED_BUILD_LIST="Eigen3ExternalProject;OpenCVExternalProject"

Dependencies of the requested projects build automatically. The allowed values are:

  • AbseilExternalProject
  • BoostExternalProject
  • CapnprotoExternalProject
  • CeresSolverExternalProject
  • Eigen3ExternalProject
  • FlatBuffersExternalProject
  • GFlagsExternalProject
  • GlogExternalProject
  • GoogleTestExternalProject
  • NlohmannJsonExternalProject
  • OatppExternalProject
  • OatppWebSocketExternalProject
  • OgreExternalProject
  • OpenCVExternalProject
  • ProtobufExternalProject
  • Python3ExternalProject
  • SpdLogExternalProject
  • SuiteSparseExternalProject
  • VTKExternalProject

Declaring your project's robotFarm system packages

A consumer project owns the complete list of system packages it needs, including the packages required to build its robotFarm subset; nothing is read from robotFarm's generated files when a consumer builds its images. To derive a RobotFarmDependencies group for your project's systemDependencies.json:

  1. Expand your requested build list to its transitive closure. Each recipe in externalProjects/ include()s the recipes it depends on, so follow those includes; for example, Eigen3ExternalProject pulls in SuiteSparseExternalProject.
  2. Union the groups named after each project in the closure from robotFarm's own systemDependencies.json. A project without a group needs no system packages and contributes nothing.

The systemDependencies.txt that a configure emits is the same computation performed for the configured build list, so it makes a convenient cross-check for a hand-derived group.

πŸ§‘β€πŸ’» Developer notes

Python 3

robotFarm uses the system Python 3 by default. To build Python 3 from source instead, pass -DROBOT_FARM_SKIP_Python3ExternalProject:BOOL=OFF in the Configure step.

OpenCV

  • Contrib modules and CUDA features are gated behind -DROBOT_FARM_OPENCV_WITH_NON_FREE_CONTRIB:BOOL=ON (off by default): the CUDA features depend on cudev from contrib, and contrib carries non-free licensing that you must comply with.
  • CUDA codecs are absent from CUDA 10.0 and later, so the build turns off cudacodec.
  • The full flag set is in externalProjects/OpenCVExternalProject.cmake; read it before assuming a feature is on.

πŸ“œ License

MIT.

About

A configurable super-build setup to compile commonly used AI and robotics libraries from source.

Topics

Resources

Stars

3 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages