From e64041e07a498a9d59ff99221dbc37ff914c7455 Mon Sep 17 00:00:00 2001 From: Duncan Betts Date: Wed, 26 Aug 2026 16:18:04 +0100 Subject: [PATCH 1/3] wip: cache cxx cuda --- Dockerfile | 17 ++++++++++++++--- README.md | 13 +++++++++++++ compose.yaml | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 compose.yaml diff --git a/Dockerfile b/Dockerfile index bc3dc5db9a..5175db4dc6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,11 @@ # syntax=docker/dockerfile:1 -FROM nvidia/cuda:13.1.2-devel-ubuntu24.04 AS build +FROM nvidia/cuda:13.1.2-devel-ubuntu24.04 AS build-env ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update \ && apt-get install --yes --no-install-recommends \ + ccache \ cmake \ libavcodec-dev \ libavformat-dev \ @@ -13,17 +14,27 @@ RUN apt-get update \ libswscale-dev \ ninja-build \ pkg-config \ + python3 \ && rm -rf /var/lib/apt/lists/* WORKDIR /src + +FROM build-env AS build + COPY . . -RUN cmake -S . -B /build -G Ninja \ +RUN --mount=type=cache,target=/ccache \ + export CCACHE_DIR=/ccache CCACHE_MAXSIZE=20G; \ + cmake -S . -B /build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache \ -DNINFER_BUILD_APPS=ON \ -DBUILD_TESTING=OFF \ -DNINFER_BUILD_BENCHMARKS=OFF \ - && cmake --build /build --parallel --target ninfer ninfer-serve + && cmake --build /build --parallel --target ninfer ninfer-serve \ + && ccache --show-stats FROM nvidia/cuda:13.1.2-runtime-ubuntu24.04 diff --git a/README.md b/README.md index b0a28379a9..ff4fbe3129 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,19 @@ docker run --rm \ --max-new 256 ``` +## Iterative Podman builds + +For iterative source builds with [Podman Compose](https://docs.podman.io/en/latest/markdown/podman-compose.1.html), +run: + +```bash +podman compose run --rm build +``` + +The build service keeps the CMake/Ninja build tree and [ccache](https://ccache.dev/manual/latest.html) +in named local volumes. It prints cumulative ccache statistics after each build; an unchanged tree +reports `ninja: no work to do` and adds no compiler-cache calls. + ## Download a model Use the Hugging Face CLI to download one of the registered artifacts: diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000000..d85e1edd3e --- /dev/null +++ b/compose.yaml @@ -0,0 +1,33 @@ +services: + build: + build: + context: . + target: build-env + working_dir: /src + environment: + CCACHE_DIR: /ccache + CCACHE_MAXSIZE: 20G + volumes: + - .:/src:ro + - ninfer-build:/build + - ninfer-ccache:/ccache + command: + - sh + - -lc + - >- + cmake -S /src -B /build -G Ninja + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_C_COMPILER_LAUNCHER=ccache + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache + -DNINFER_BUILD_APPS=ON + -DBUILD_TESTING=ON + -DNINFER_BUILD_BENCHMARKS=OFF + && cmake --build /build --parallel --target ninfer ninfer-serve + && ccache --show-stats + +volumes: + ninfer-build: + name: ninfer-build + ninfer-ccache: + name: ninfer-ccache From 03df31d55c9ea8e64c433c1f185d33561c6df024 Mon Sep 17 00:00:00 2001 From: Duncan Betts Date: Thu, 27 Aug 2026 00:12:40 +0100 Subject: [PATCH 2/3] fix(build): isolate Compose build volume and relabel source --- compose.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compose.yaml b/compose.yaml index d85e1edd3e..6a8dd755c0 100644 --- a/compose.yaml +++ b/compose.yaml @@ -8,7 +8,7 @@ services: CCACHE_DIR: /ccache CCACHE_MAXSIZE: 20G volumes: - - .:/src:ro + - .:/src:ro,Z - ninfer-build:/build - ninfer-ccache:/ccache command: @@ -28,6 +28,5 @@ services: volumes: ninfer-build: - name: ninfer-build ninfer-ccache: name: ninfer-ccache From ec1efc4b20c227eb860749233c4d4671c4443bee Mon Sep 17 00:00:00 2001 From: Duncan Betts Date: Sat, 12 Sep 2026 03:17:57 +0100 Subject: [PATCH 3/3] build: retain incremental compilation without compose --- Dockerfile | 27 +++++++++++++++---------- README.md | 57 ++++++++++++++++++++++++++++++++++++++++------------ compose.yaml | 32 ----------------------------- 3 files changed, 60 insertions(+), 56 deletions(-) delete mode 100644 compose.yaml diff --git a/Dockerfile b/Dockerfile index 5175db4dc6..10d0f4fc2a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -FROM nvidia/cuda:13.1.2-devel-ubuntu24.04 AS build-env +FROM nvidia/cuda:13.1.2-devel-ubuntu24.04 AS build ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update \ @@ -14,18 +14,21 @@ RUN apt-get update \ libswscale-dev \ ninja-build \ pkg-config \ - python3 \ + rsync \ && rm -rf /var/lib/apt/lists/* WORKDIR /src - -FROM build-env AS build - COPY . . -RUN --mount=type=cache,target=/ccache \ - export CCACHE_DIR=/ccache CCACHE_MAXSIZE=20G; \ - cmake -S . -B /build -G Ninja \ +# Keep source mtimes stable only when contents match; restored/older checkouts must +# still rebuild changed inputs. Package versions isolate toolchain/dependency changes. +# Lock the mutable Ninja tree and copy deliverables out of the transient cache mount. +RUN --mount=type=cache,id=ninfer-build,target=/build,sharing=locked \ + --mount=type=cache,target=/ccache \ + export CCACHE_DIR=/ccache CCACHE_MAXSIZE=20G \ + && build_dir="/build/$(dpkg-query -W | sha256sum | cut -d ' ' -f 1)" \ + && rsync --recursive --links --checksum --delete /src/ /build/src/ \ + && cmake -S /build/src -B "$build_dir" -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ @@ -33,7 +36,9 @@ RUN --mount=type=cache,target=/ccache \ -DNINFER_BUILD_APPS=ON \ -DBUILD_TESTING=OFF \ -DNINFER_BUILD_BENCHMARKS=OFF \ - && cmake --build /build --parallel --target ninfer ninfer-serve \ + && cmake --build "$build_dir" --parallel --target ninfer ninfer-serve \ + && mkdir -p /out \ + && cp "$build_dir/apps/ninfer" "$build_dir/apps/ninfer-serve" /out/ \ && ccache --show-stats FROM nvidia/cuda:13.1.2-runtime-ubuntu24.04 @@ -49,8 +54,8 @@ RUN apt-get update \ libswscale7 \ && rm -rf /var/lib/apt/lists/* -COPY --from=build /build/apps/ninfer /usr/local/bin/ninfer -COPY --from=build /build/apps/ninfer-serve /usr/local/bin/ninfer-serve +COPY --from=build /out/ninfer /usr/local/bin/ninfer +COPY --from=build /out/ninfer-serve /usr/local/bin/ninfer-serve WORKDIR /workspace EXPOSE 8080 diff --git a/README.md b/README.md index ff4fbe3129..e8eda604cc 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,37 @@ build/apps/ninfer-serve Tests, benchmarks, and maintainer tools are excluded from the default build. +### Optional compiler cache + +For repeated source builds, install [ccache](https://ccache.dev/) and configure CMake's +[compiler launchers](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_LAUNCHER.html): + +```bash +cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache +cmake --build build -j +ccache --show-stats +``` + +These commands run directly on the host; no container tooling is required. Keep the `build/` +directory for incremental builds: Ninja skips unchanged targets, while ccache can reuse C, C++, +and CUDA compiler outputs when compilation is needed again. ccache uses its normal per-user +cache; `CCACHE_DIR` and `CCACHE_MAXSIZE` can override its location and size limit. Statistics are +cumulative, and an unchanged Ninja build adds no compiler-cache calls. + +The ordinary build above does not require ccache. To disable it in a build directory previously +configured with these launchers, clear the cached CMake settings: + +```bash +cmake -S . -B build \ + -DCMAKE_C_COMPILER_LAUNCHER= \ + -DCMAKE_CXX_COMPILER_LAUNCHER= \ + -DCMAKE_CUDA_COMPILER_LAUNCHER= +cmake --build build -j +``` + ## Docker Build the runtime image on a 64-bit Linux host with an RTX 5090, a CUDA 13.1-compatible NVIDIA @@ -163,6 +194,19 @@ driver, Docker, and the docker build --tag ninfer:local . ``` +The Dockerfile enables the same compiler launchers automatically and uses +[build cache mounts](https://docs.docker.com/build/cache/optimize/#use-cache-mounts) for both the +CMake/Ninja build tree and ccache (limited to 20 GiB). Use Docker BuildKit or another builder that +supports `RUN --mount=type=cache`. After source edits, Ninja rebuilds only affected targets; ccache +can reuse compiler outputs when compilation is needed again. The build prints cumulative ccache +statistics, which do not count work skipped by Ninja. + +Source synchronization compares contents and removes deleted files, so restored files with older +timestamps still rebuild correctly. The mutable build-tree cache is locked during each build and +uses separate build directories for different installed toolchain/library versions. Missing or +evicted caches cause a normal rebuild. Finished binaries are copied out of the cache into the image; +ccache and the synchronization tool are only installed in the build stage. + Download a model into `models/` as described below, then run the HTTP server: ```bash @@ -187,19 +231,6 @@ docker run --rm \ --max-new 256 ``` -## Iterative Podman builds - -For iterative source builds with [Podman Compose](https://docs.podman.io/en/latest/markdown/podman-compose.1.html), -run: - -```bash -podman compose run --rm build -``` - -The build service keeps the CMake/Ninja build tree and [ccache](https://ccache.dev/manual/latest.html) -in named local volumes. It prints cumulative ccache statistics after each build; an unchanged tree -reports `ninja: no work to do` and adds no compiler-cache calls. - ## Download a model Use the Hugging Face CLI to download one of the registered artifacts: diff --git a/compose.yaml b/compose.yaml deleted file mode 100644 index 6a8dd755c0..0000000000 --- a/compose.yaml +++ /dev/null @@ -1,32 +0,0 @@ -services: - build: - build: - context: . - target: build-env - working_dir: /src - environment: - CCACHE_DIR: /ccache - CCACHE_MAXSIZE: 20G - volumes: - - .:/src:ro,Z - - ninfer-build:/build - - ninfer-ccache:/ccache - command: - - sh - - -lc - - >- - cmake -S /src -B /build -G Ninja - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_C_COMPILER_LAUNCHER=ccache - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache - -DNINFER_BUILD_APPS=ON - -DBUILD_TESTING=ON - -DNINFER_BUILD_BENCHMARKS=OFF - && cmake --build /build --parallel --target ninfer ninfer-serve - && ccache --show-stats - -volumes: - ninfer-build: - ninfer-ccache: - name: ninfer-ccache