|
| 1 | +# Dockerfile to build the FlagTree wheel, then assemble a Debian package. |
| 2 | +# |
| 3 | +# Two-stage: |
| 4 | +# 1. wheel-builder: heavy stage with CMake/Ninja/LLVM that compiles the |
| 5 | +# flagtree wheel from source. Produces /wheels/flagtree-*.whl. |
| 6 | +# 2. deb-assembler: light stage that runs dpkg-buildpackage to wrap the |
| 7 | +# pre-built wheel into a .deb. The deb stage does NOT recompile. |
| 8 | +# |
| 9 | +# Build: |
| 10 | +# docker build -f packaging/debian/build-helpers/Dockerfile.deb \ |
| 11 | +# --target deb-output \ |
| 12 | +# -t flagtree-deb-nvidia . |
| 13 | +# |
| 14 | +# COPY-narrowing: the wheel-builder COPYs only the paths the build |
| 15 | +# needs (python/, third_party/, include/, lib/, cmake/, bin/, |
| 16 | +# CMakeLists.txt, *.toml, LICENSE, README*). It deliberately does NOT |
| 17 | +# copy packaging/, docs/, .github/, dockerfiles/, etc. — that way edits |
| 18 | +# to debian/control or rpm/specs/ don't invalidate the 36-min wheel |
| 19 | +# build cache. The deb-assembler stage gets packaging/debian via its |
| 20 | +# own narrow COPY. |
| 21 | +# |
| 22 | +# FLAGTREE_BACKEND notes: FlagTree's "default" backend IS nvidia (no |
| 23 | +# nvidia.py module exists in setup_tools/utils/). Setting |
| 24 | +# FLAGTREE_BACKEND=nvidia would make setup_helper.py try to import a |
| 25 | +# missing module and silently produce an empty stub. We unset the env |
| 26 | +# var explicitly in the wheel-build RUN. |
| 27 | + |
| 28 | +ARG DEB_BASE_IMAGE=ubuntu:24.04 |
| 29 | + |
| 30 | +# ---------- Stage 1: build the wheel ---------- |
| 31 | +FROM ${DEB_BASE_IMAGE} AS wheel-builder |
| 32 | +SHELL ["/bin/bash", "-o", "pipefail", "-c"] |
| 33 | + |
| 34 | +ENV DEBIAN_FRONTEND=noninteractive |
| 35 | +ENV VIRTUAL_ENV=/opt/flagtree-build-venv |
| 36 | +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" |
| 37 | +ENV PIP_ROOT_USER_ACTION=ignore |
| 38 | + |
| 39 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 40 | + python3 python3-pip python3-dev python3-venv \ |
| 41 | + build-essential cmake ninja-build git \ |
| 42 | + zlib1g zlib1g-dev libxml2 libxml2-dev \ |
| 43 | + wget curl ca-certificates \ |
| 44 | + && apt-get clean && rm -rf /var/lib/apt/lists/* |
| 45 | + |
| 46 | +# Ubuntu 24.04 marks /usr Python as externally managed (PEP 668). Keep all |
| 47 | +# wheel-builder pip installs inside a venv instead of mutating system Python. |
| 48 | +RUN python3 -m venv "${VIRTUAL_ENV}" && \ |
| 49 | + python -m pip install --no-cache-dir --upgrade pip setuptools wheel build |
| 50 | + |
| 51 | +WORKDIR /src |
| 52 | +# Dependency layer first so source edits don't invalidate it. |
| 53 | +COPY python/requirements.txt /src/python/requirements.txt |
| 54 | +RUN python -m pip install --no-cache-dir -r python/requirements.txt |
| 55 | + |
| 56 | +# Narrow COPY: only the paths the wheel build needs, so packaging-only |
| 57 | +# edits (specs, debian/, helpers) do NOT invalidate the ~50 min wheel |
| 58 | +# layer. setup.py / pyproject.toml / MANIFEST.in live at the repo root |
| 59 | +# since the post-#607 restructure. |
| 60 | +COPY python /src/python |
| 61 | +COPY third_party /src/third_party |
| 62 | +COPY include /src/include |
| 63 | +COPY lib /src/lib |
| 64 | +COPY cmake /src/cmake |
| 65 | +COPY bin /src/bin |
| 66 | +COPY test /src/test |
| 67 | +COPY unittest /src/unittest |
| 68 | +COPY CMakeLists.txt pyproject.toml setup.py MANIFEST.in LICENSE README.md /src/ |
| 69 | + |
| 70 | +# Build wheel with MAX_JOBS capped to reduce peak RAM. Spike timing on a |
| 71 | +# 4-core builder: ~36 min wall. |
| 72 | +# FLAGTREE_DEFAULT_BACKENDS=nvidia,amd matches the historical package |
| 73 | +# contents and keeps the tileir backend (GCC >= 13 + cuda-tile |
| 74 | +# submodule) out of the distro build. |
| 75 | +RUN unset FLAGTREE_BACKEND && \ |
| 76 | + FLAGTREE_DEFAULT_BACKENDS=nvidia,amd \ |
| 77 | + MAX_JOBS=4 python -m pip wheel . --no-build-isolation --no-deps -w /wheels -v && \ |
| 78 | + ls -lh /wheels/ && \ |
| 79 | + test -n "$(ls /wheels/flagtree-*.whl 2>/dev/null)" |
| 80 | + |
| 81 | +# ---------- Stage 2: assemble the .deb ---------- |
| 82 | +FROM ${DEB_BASE_IMAGE} AS deb-assembler |
| 83 | +SHELL ["/bin/bash", "-o", "pipefail", "-c"] |
| 84 | + |
| 85 | +ENV DEBIAN_FRONTEND=noninteractive |
| 86 | +ENV PIP_ROOT_USER_ACTION=ignore |
| 87 | + |
| 88 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 89 | + build-essential \ |
| 90 | + debhelper dh-python python3-all python3-pip python3-setuptools \ |
| 91 | + python3-wheel devscripts fakeroot lintian \ |
| 92 | + && apt-get clean && rm -rf /var/lib/apt/lists/* |
| 93 | + |
| 94 | +WORKDIR /build |
| 95 | +COPY packaging/debian /build/debian |
| 96 | +COPY --from=wheel-builder /wheels /build/dist |
| 97 | + |
| 98 | +# debian/source/format = "3.0 (native)" -> no orig.tar.gz needed. |
| 99 | +ENV WHEEL_DIR=/build/dist |
| 100 | + |
| 101 | +RUN dpkg-buildpackage -us -uc -b && \ |
| 102 | + ls -lh /python3-flagtree-*.deb |
| 103 | + |
| 104 | +# Run lintian against the produced .deb — surface packaging warnings |
| 105 | +# (unused-license-paragraph, no-manual-page, missing-build-dependency, etc.) |
| 106 | +# in the build log without failing the build. |
| 107 | +RUN lintian --info --display-info /python3-flagtree-*.deb || true |
| 108 | + |
| 109 | +# ---------- Stage 3: just the .deb output ---------- |
| 110 | +FROM scratch AS deb-output |
| 111 | +COPY --from=deb-assembler /python3-flagtree-*.deb /output/ |
| 112 | +COPY --from=deb-assembler /flagtree_*.changes /output/ |
0 commit comments