diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..76a4725 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,364 @@ +name: Build + +on: + workflow_dispatch: + +concurrency: + group: build + cancel-in-progress: false + +permissions: + contents: read + +env: + VERSION: ${{ vars.MAJOR }}.${{ vars.MINOR }}.0.0 + + # Only these two repositories float. Each run resolves master once and then + # passes the exact SHA to BuildKit as a named Git context. + D3D11_REPO: https://github.com/qemus/virtio-d3d11.git + KMD_REPO: https://github.com/qemus/virtio-drivers-windows.git + + # Everything below is pinned. + BUILDER_IMAGE: buildpack-deps:sid@sha256:dfc7595de3e15149f7eefe40b41477d6dc90fd46bf901890fd97f9a32d2b2fa0 + DEBIAN_SNAPSHOT: "20260831T235959Z" + MINGW_GCC_PKG_VERSION: "16.2.0-1+29" + MINGW_HEADERS_PKG_VERSION: "14.0.0-1" + + MESA_ARCHIVE_URL: https://gitlab.freedesktop.org/anonymix007/mesa/-/archive/venus-win32/mesa-venus-win32.tar.gz + MESA_TREE_SHA256: 9070b043639cf230dbcedbe2614d649101c12e0a9c4ab2836c201b8ab652eab0 + + MAKECAT_REF: ee7aa4dd1d10ad5f254020ca0637df5abcc95618 + CLANG_CL_LINUX_REF: 84e723d170e7611c55fff30c44d24c5a04bd4cb7 + + EWDK_VERSION: "26100.6584" + EWDK_URL: https://software-static.download.prss.microsoft.com/dbazure/888969d5-f34g-4e03-ac9d-1f9786c66749/EWDK_ge_release_svc_prod1_26100_250904-1728.iso + EWDK_SHA256: 9f48251dd24ad31aac206d8256e95bda5f90a9783982c45a8aafeb9054562379 + WINSDKVER: "10.0.26100.0" + VCTOOLSVER: "14.44.35207" + + RUST_TOOLCHAIN: nightly-2026-08-31 + CBINDGEN_VERSION: "0.29.4" + +jobs: + build: + name: Build + runs-on: ubuntu-24.04 + timeout-minutes: 240 + + steps: + - name: Checkout + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + + - name: Validate version + shell: bash + run: | + set -euo pipefail + + # Fail clearly if MAJOR/MINOR repository variables were not set. + test -n "${{ vars.MAJOR }}" + test -n "${{ vars.MINOR }}" + + [[ "${{ vars.MAJOR }}" =~ ^[0-9]+$ ]] + [[ "${{ vars.MINOR }}" =~ ^[0-9]+$ ]] + + # Windows DriverVer is w.x.y.z: four numeric components, + # each strictly less than 65535. Our release scheme is + # MAJOR.MINOR.0.0. + [[ "${VERSION}" =~ ^[0-9]+\.[0-9]+\.0\.0$ ]] + + IFS='.' read -r v1 v2 v3 v4 <<< "${VERSION}" + for component in "${v1}" "${v2}" "${v3}" "${v4}"; do + [[ "${component}" =~ ^[0-9]+$ ]] + (( 10#${component} < 65535 )) + done + + test "${v1}" = "${{ vars.MAJOR }}" + test "${v2}" = "${{ vars.MINOR }}" + test "${v3}" = "0" + test "${v4}" = "0" + + echo "Building driver/release version ${VERSION}" + + - name: Free runner disk space + shell: bash + run: | + set -euxo pipefail + + df -h / + + sudo rm -rf /usr/local/lib/android + sudo rm -rf /usr/share/dotnet + sudo rm -rf /opt/ghc + sudo rm -rf /usr/local/.ghcup + sudo rm -rf /opt/hostedtoolcache + sudo docker system prune --all --force || true + sudo apt-get clean + + df -h / + + - name: Resolve master commits + id: refs + shell: bash + run: | + set -euo pipefail + + d3d11_sha="$( + git ls-remote "${D3D11_REPO}" refs/heads/master | awk '{print $1}' + )" + kmd_sha="$( + git ls-remote "${KMD_REPO}" refs/heads/master | awk '{print $1}' + )" + + [[ "${d3d11_sha}" =~ ^[0-9a-f]{40}$ ]] + [[ "${kmd_sha}" =~ ^[0-9a-f]{40}$ ]] + + # Resolve the DXVK gitlink from the exact D3D11 commit without + # checking out the working tree. + tmp="$(mktemp -d)" + trap 'rm -rf "${tmp}"' EXIT + + git -C "${tmp}" init --quiet + git -C "${tmp}" remote add origin "${D3D11_REPO}" + git -C "${tmp}" fetch --quiet --depth=1 origin "${d3d11_sha}" + + fetched_sha="$(git -C "${tmp}" rev-parse FETCH_HEAD)" + test "${fetched_sha}" = "${d3d11_sha}" + + dxvk_sha="$( + git -C "${tmp}" ls-tree "${d3d11_sha}" thirdparty/dxvk \ + | awk '{print $3}' + )" + [[ "${dxvk_sha}" =~ ^[0-9a-f]{40}$ ]] + + echo "D3D11 master: ${d3d11_sha}" + echo "DXVK gitlink: ${dxvk_sha}" + echo "KMD master: ${kmd_sha}" + + { + echo "d3d11_sha=${d3d11_sha}" + echo "dxvk_sha=${dxvk_sha}" + echo "kmd_sha=${kmd_sha}" + } >> "${GITHUB_OUTPUT}" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f + + - name: Prime reusable build cache + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 + with: + context: . + file: ./Dockerfile + target: cache-seed + push: false + pull: false + provenance: false + + # Only D3D11 is needed by the prerequisite target. KMD is deliberately + # excluded so KMD master changes cannot invalidate this checkpoint. + build-contexts: | + d3d11=${{ env.D3D11_REPO }}#${{ steps.refs.outputs.d3d11_sha }} + + build-args: | + BUILDER_IMAGE=${{ env.BUILDER_IMAGE }} + DEBIAN_SNAPSHOT=${{ env.DEBIAN_SNAPSHOT }} + MINGW_GCC_PKG_VERSION=${{ env.MINGW_GCC_PKG_VERSION }} + MINGW_HEADERS_PKG_VERSION=${{ env.MINGW_HEADERS_PKG_VERSION }} + + D3D11_SHA=${{ steps.refs.outputs.d3d11_sha }} + DXVK_SHA=${{ steps.refs.outputs.dxvk_sha }} + + MESA_ARCHIVE_URL=${{ env.MESA_ARCHIVE_URL }} + MESA_TREE_SHA256=${{ env.MESA_TREE_SHA256 }} + + MAKECAT_REF=${{ env.MAKECAT_REF }} + CLANG_CL_LINUX_REF=${{ env.CLANG_CL_LINUX_REF }} + + EWDK_VERSION=${{ env.EWDK_VERSION }} + EWDK_URL=${{ env.EWDK_URL }} + EWDK_SHA256=${{ env.EWDK_SHA256 }} + WINSDKVER=${{ env.WINSDKVER }} + VCTOOLSVER=${{ env.VCTOOLSVER }} + + RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} + CBINDGEN_VERSION=${{ env.CBINDGEN_VERSION }} + + # Run the expensive prerequisite graph to completion without exporting + # a filesystem/image, then publish every stage to the shared GHA cache. + outputs: type=cacheonly + cache-from: type=gha,scope=qemus-virtio-gpu-x64 + cache-to: type=gha,mode=max,scope=qemus-virtio-gpu-x64,ignore-error=false + + - name: Build package + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 + with: + context: . + file: ./Dockerfile + target: artifact + push: false + pull: false + provenance: false + + # The two current masters are resolved once above. Full 40-character + # commit fragments make each named context immutable for this run. + build-contexts: | + d3d11=${{ env.D3D11_REPO }}#${{ steps.refs.outputs.d3d11_sha }} + kmd=${{ env.KMD_REPO }}#${{ steps.refs.outputs.kmd_sha }} + + build-args: | + BUILDER_IMAGE=${{ env.BUILDER_IMAGE }} + DEBIAN_SNAPSHOT=${{ env.DEBIAN_SNAPSHOT }} + MINGW_GCC_PKG_VERSION=${{ env.MINGW_GCC_PKG_VERSION }} + MINGW_HEADERS_PKG_VERSION=${{ env.MINGW_HEADERS_PKG_VERSION }} + + VERSION_ARG=${{ env.VERSION }} + + D3D11_SHA=${{ steps.refs.outputs.d3d11_sha }} + DXVK_SHA=${{ steps.refs.outputs.dxvk_sha }} + KMD_SHA=${{ steps.refs.outputs.kmd_sha }} + + MESA_ARCHIVE_URL=${{ env.MESA_ARCHIVE_URL }} + MESA_TREE_SHA256=${{ env.MESA_TREE_SHA256 }} + + MAKECAT_REF=${{ env.MAKECAT_REF }} + CLANG_CL_LINUX_REF=${{ env.CLANG_CL_LINUX_REF }} + + EWDK_VERSION=${{ env.EWDK_VERSION }} + EWDK_URL=${{ env.EWDK_URL }} + EWDK_SHA256=${{ env.EWDK_SHA256 }} + WINSDKVER=${{ env.WINSDKVER }} + VCTOOLSVER=${{ env.VCTOOLSVER }} + + RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }} + CBINDGEN_VERSION=${{ env.CBINDGEN_VERSION }} + + outputs: type=local,dest=./out + + # qemus master changes invalidate only stages consuming their named + # contexts. Pinned Mesa/EWDK/toolchain stages remain reusable. + cache-from: type=gha,scope=qemus-virtio-gpu-x64 + cache-to: type=gha,mode=max,scope=qemus-virtio-gpu-x64,ignore-error=true + + - name: Verify exported package and version + shell: bash + run: | + set -euxo pipefail + + required=( + virtio_wddm_rs.inf + virtio_wddm_rs.cat + virtio_wddm_rs.sys + virtio_gpu_wddm_rs.pdb + dx11um_virtio.dll + dx11um_virtio.debug + vulkan_virtio.dll + vulkan_virtio.debug + virtio_icd.x86_64.json + virtio_test_signing.cer + BUILDINFO.txt + ) + + for file_name in "${required[@]}"; do + test -s "out/${file_name}" + done + + # The release version must literally equal the installed Windows + # DriverVer version, not merely resemble it. + driver_version="$( + sed -n 's/^DriverVer=[^,]*,[[:space:]]*//p' out/virtio_wddm_rs.inf + )" + test "${driver_version}" = "${VERSION}" + + grep -Fq "Driver / release version: ${VERSION}" out/BUILDINFO.txt + grep -Fq "${{ steps.refs.outputs.d3d11_sha }}" out/BUILDINFO.txt + grep -Fq "${{ steps.refs.outputs.dxvk_sha }}" out/BUILDINFO.txt + grep -Fq "${{ steps.refs.outputs.kmd_sha }}" out/BUILDINFO.txt + grep -Fq "${MESA_TREE_SHA256}" out/BUILDINFO.txt + grep -Fq "${BUILDER_IMAGE}" out/BUILDINFO.txt + grep -Fq "${DEBIAN_SNAPSHOT}" out/BUILDINFO.txt + grep -Fq "${MINGW_GCC_PKG_VERSION}" out/BUILDINFO.txt + grep -Fq "${MINGW_HEADERS_PKG_VERSION}" out/BUILDINFO.txt + + echo + echo "Driver version: ${driver_version}" + cat out/BUILDINFO.txt + echo + find out -maxdepth 1 -type f -printf '%f\n' | sort + + - name: Create release ZIP + shell: bash + run: | + set -euxo pipefail + + archive="virtio-gpu-${VERSION}.zip" + + python3 - "${archive}" <<'PY' + import sys + import zipfile + from pathlib import Path + + archive = Path(sys.argv[1]) + source = Path("out") + + with zipfile.ZipFile( + archive, + "w", + compression=zipfile.ZIP_DEFLATED, + compresslevel=9, + ) as zf: + for path in sorted(source.iterdir()): + if path.is_file(): + zf.write(path, path.name) + PY + + test -s "${archive}" + sha256sum "${archive}" + + - name: Upload Actions artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 + with: + name: virtio-gpu-${{ env.VERSION }} + path: | + out/ + virtio-gpu-${{ env.VERSION }}.zip + if-no-files-found: error + compression-level: 0 + retention-days: 30 + + - name: Create a release + uses: action-pack/github-release@d887b892618f95e19985108bfbc0c26833efa505 + with: + tag: "v${{ env.VERSION }}" + title: "v${{ env.VERSION }}" + token: ${{ secrets.REPO_ACCESS_TOKEN }} + + - name: Add package to release + env: + GH_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} + shell: bash + run: | + set -euxo pipefail + gh release upload \ + "v${VERSION}" \ + "virtio-gpu-${VERSION}.zip" + + - name: Increment version variable + uses: action-pack/increment@1458c307cedd62641619be2480c6263cf39864ac + with: + name: 'MINOR' + token: ${{ secrets.REPO_ACCESS_TOKEN }} + + - name: Send mail + uses: action-pack/send-mail@33d560748d5c56be2a180c578ba4cf92b22a4723 + with: + to: ${{ secrets.MAILTO }} + from: Github Actions <${{ secrets.MAILTO }}> + connection_url: ${{ secrets.MAIL_CONNECTION }} + subject: Build of ${{ github.event.repository.name }} v${{ env.VERSION }} completed + body: | + The build job of ${{ github.event.repository.name }} v${{ env.VERSION }} was completed successfully! + + Driver version: ${{ env.VERSION }} + D3D11: ${{ steps.refs.outputs.d3d11_sha }} + KMD: ${{ steps.refs.outputs.kmd_sha }} + + See https://github.com/${{ github.repository }}/actions for more information. diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml new file mode 100644 index 0000000..45f67a5 --- /dev/null +++ b/.github/workflows/review.yml @@ -0,0 +1,14 @@ +on: + pull_request: + +name: "Review" + +permissions: + contents: read + pull-requests: write + checks: write + +jobs: + review: + name: review + uses: action-pack/.github/.github/workflows/review.yml@master diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..05c9771 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,549 @@ +# syntax=docker/dockerfile:1.7@sha256:a57df69d0ea827fb7266491f2813635de6f17269be881f696fbfdf2d83dda33e + +ARG BUILDER_IMAGE=buildpack-deps:sid@sha256:dfc7595de3e15149f7eefe40b41477d6dc90fd46bf901890fd97f9a32d2b2fa0 +ARG DEBIAN_SNAPSHOT=20260831T235959Z +ARG MINGW_GCC_PKG_VERSION=16.2.0-1+29 +ARG MINGW_HEADERS_PKG_VERSION=14.0.0-1 + +FROM ${BUILDER_IMAGE} AS toolchain + +ARG DEBIAN_FRONTEND=noninteractive +ARG DEBIAN_SNAPSHOT +ARG MINGW_GCC_PKG_VERSION +ARG MINGW_HEADERS_PKG_VERSION +ARG RUST_TOOLCHAIN=nightly-2026-08-31 +ARG CBINDGEN_VERSION=0.29.4 + +ENV RUSTUP_HOME=/opt/rustup +ENV CARGO_HOME=/opt/cargo +ENV PATH=/opt/cargo/bin:/opt/mingw-posix/bin:${PATH} + +# buildpack-deps already contains the generic native source-build stack +# (gcc/g++/make, git, curl, file, common development libraries, etc.). +# Only install the project-specific tools and the Windows cross compiler. +# Use an immutable Debian archive snapshot so Sid cannot drift between runs. +RUN set -eux; \ + rm -f /etc/apt/sources.list.d/*.sources /etc/apt/sources.list; \ + printf 'deb [check-valid-until=no] https://snapshot.debian.org/archive/debian/%s/ sid main\n' \ + "${DEBIAN_SNAPSHOT}" > /etc/apt/sources.list; \ + apt-get -o Acquire::Retries=5 update; \ + apt-get install -y --no-install-recommends \ + aria2 \ + bison \ + clang \ + cmake \ + flex \ + gettext \ + glslang-tools \ + jq \ + libclang-dev \ + libexpat1-dev \ + libwine-dev \ + lld \ + llvm \ + gcc-mingw-w64-x86-64-posix="${MINGW_GCC_PKG_VERSION}" \ + g++-mingw-w64-x86-64-posix="${MINGW_GCC_PKG_VERSION}" \ + mingw-w64-x86-64-dev="${MINGW_HEADERS_PKG_VERSION}" \ + ninja-build \ + openssl \ + osslsigncode \ + p7zip-full \ + pkg-config \ + python3 \ + python3-dev \ + python3-venv; \ + test "$(dpkg-query -W -f='${Version}' gcc-mingw-w64-x86-64-posix)" = "${MINGW_GCC_PKG_VERSION}"; \ + test "$(dpkg-query -W -f='${Version}' g++-mingw-w64-x86-64-posix)" = "${MINGW_GCC_PKG_VERSION}"; \ + test "$(dpkg-query -W -f='${Version}' mingw-w64-x86-64-dev)" = "${MINGW_HEADERS_PKG_VERSION}"; \ + rm -rf /var/lib/apt/lists/* + +# Make the POSIX-threading MinGW compiler the unqualified x86_64-w64-mingw32 +# toolchain used by Mesa and virtio-d3d11. +RUN set -eux; \ + mkdir -p /opt/mingw-posix/bin; \ + ln -s "$(command -v x86_64-w64-mingw32-gcc-posix)" /opt/mingw-posix/bin/x86_64-w64-mingw32-gcc; \ + ln -s "$(command -v x86_64-w64-mingw32-g++-posix)" /opt/mingw-posix/bin/x86_64-w64-mingw32-g++; \ + for tool in ar gcc-ar ld objcopy ranlib strip windres; do \ + ln -s "$(command -v x86_64-w64-mingw32-${tool})" "/opt/mingw-posix/bin/x86_64-w64-mingw32-${tool}"; \ + done; \ + gcc_major="$(x86_64-w64-mingw32-gcc -dM -E -x c /dev/null | awk '$2 == "__GNUC__" { print $3 }')"; \ + test "${gcc_major}" = "16"; \ + printf '#include \nint main(void) { bool ok = true; return ok ? 0 : 1; }\n' > /tmp/c23-probe.c; \ + x86_64-w64-mingw32-gcc -c /tmp/c23-probe.c -o /tmp/c23-probe.o; \ + printf '#include \n_Maybenull_ int *p;\nint main(void) { return p != 0; }\n' > /tmp/sal-probe.c; \ + x86_64-w64-mingw32-gcc -c /tmp/sal-probe.c -o /tmp/sal-probe.o; \ + rm -f /tmp/c23-probe.c /tmp/c23-probe.o /tmp/sal-probe.c /tmp/sal-probe.o; \ + x86_64-w64-mingw32-gcc --version | head -1 + +# Pin the Rust compiler date and cbindgen version. rustup itself is only the +# bootstrap mechanism; the installed compiler/toolchain is the dated nightly. +RUN curl --proto '=https' --tlsv1.2 --fail --location \ + https://sh.rustup.rs -o /tmp/rustup.sh \ + && sh /tmp/rustup.sh -y --no-modify-path --profile minimal --default-toolchain none \ + && rm /tmp/rustup.sh \ + && rustup toolchain install "${RUST_TOOLCHAIN}" --profile minimal --component rust-src \ + && rustup default "${RUST_TOOLCHAIN}" \ + && rustup target add x86_64-pc-windows-msvc --toolchain "${RUST_TOOLCHAIN}" \ + && cargo install cbindgen --version "${CBINDGEN_VERSION}" --locked \ + && rustc --version \ + && cargo --version \ + && cbindgen --version + + +FROM toolchain AS ewdk + +ARG EWDK_VERSION=26100.6584 +ARG EWDK_URL +ARG EWDK_SHA256 +ARG VCTOOLSVER=14.44.35207 +ARG WINSDKVER=10.0.26100.0 +ARG CLANG_CL_LINUX_REF=84e723d170e7611c55fff30c44d24c5a04bd4cb7 + +# The 18.6 GB ISO only exists during this RUN. It is deleted before the layer +# is committed, so the cache stores the extracted toolchain subset, not the ISO. +RUN set -eux; \ + test -n "${EWDK_URL}"; \ + test -n "${EWDK_SHA256}"; \ + iso=/tmp/ewdk.iso; \ + aria2c \ + --continue=true \ + --max-connection-per-server=8 \ + --min-split-size=10M \ + --split=8 \ + --file-allocation=none \ + --dir=/tmp \ + --out=ewdk.iso \ + "${EWDK_URL}"; \ + echo "${EWDK_SHA256} ${iso}" | sha256sum --check -; \ + mkdir -p /opt/ewdk; \ + 7z x -y -r "${iso}" -o/opt/ewdk \ + "Program Files/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/${VCTOOLSVER}/include/*" \ + "Program Files/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/${VCTOOLSVER}/lib/x64/*" \ + "Program Files/Windows Kits/10/Include/${WINSDKVER}/*" \ + "Program Files/Windows Kits/10/Include/wdf/kmdf/1.27/*" \ + "Program Files/Windows Kits/10/Lib/${WINSDKVER}/km/x64/*" \ + "Program Files/Windows Kits/10/Lib/wdf/kmdf/x64/1.27/*"; \ + rm -f "${iso}"; \ + test -d "/opt/ewdk/Program Files/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/${VCTOOLSVER}/include"; \ + test -f "/opt/ewdk/Program Files/Windows Kits/10/Include/${WINSDKVER}/km/ntddk.h"; \ + test -f "/opt/ewdk/Program Files/Windows Kits/10/Include/wdf/kmdf/1.27/wdf.h"; \ + test -d "/opt/ewdk/Program Files/Windows Kits/10/Lib/${WINSDKVER}/km/x64"; \ + test -d "/opt/ewdk/Program Files/Windows Kits/10/Lib/wdf/kmdf/x64/1.27" + +# Pin clang-cl-linux by immutable commit and retain only the VFS generator. +RUN curl --fail --location --retry 5 \ + "https://raw.githubusercontent.com/tmp64/clang-cl-linux/${CLANG_CL_LINUX_REF}/generate_vfs.py" \ + -o /opt/ewdk/generate_vfs.py \ + && python3 /opt/ewdk/generate_vfs.py \ + --msvc "/opt/ewdk/Program Files/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC" \ + --sdk "/opt/ewdk/Program Files/Windows Kits/10" \ + --out /opt/ewdk/vfs-overlay.json \ + && test -s /opt/ewdk/vfs-overlay.json + + +FROM toolchain AS makecat-build + +ARG MAKECAT_REF=ee7aa4dd1d10ad5f254020ca0637df5abcc95618 + +RUN set -eux; \ + git init /src/makecat; \ + git -C /src/makecat remote add origin https://github.com/anonymix007/makecat.git; \ + git -C /src/makecat fetch --depth=1 origin "${MAKECAT_REF}"; \ + git -C /src/makecat checkout --detach FETCH_HEAD; \ + test "$(git -C /src/makecat rev-parse HEAD)" = "${MAKECAT_REF}" + +WORKDIR /src/makecat +RUN --mount=type=cache,target=/opt/cargo/registry \ + --mount=type=cache,target=/opt/cargo/git \ + cargo build --release --locked \ + && install -Dm755 target/release/makecat /out/makecat + + +FROM toolchain AS mesa-build + +ARG MESA_ARCHIVE_URL=https://gitlab.freedesktop.org/anonymix007/mesa/-/archive/venus-win32/mesa-venus-win32.tar.gz +ARG MESA_TREE_SHA256=9070b043639cf230dbcedbe2614d649101c12e0a9c4ab2836c201b8ab652eab0 +ARG WINSDKVER=10.0.26100.0 + +COPY --from=ewdk /opt/ewdk /opt/ewdk + +# Mesa is content-pinned. The URL may name the branch, but the normalized +# extracted tree must match MESA_TREE_SHA256 exactly or the production build +# stops. Changing the pin intentionally invalidates this layer. +RUN set -eux; \ + mkdir -p /src/mesa; \ + curl --fail --location --retry 5 "${MESA_ARCHIVE_URL}" -o /tmp/mesa.tar.gz; \ + tar -xzf /tmp/mesa.tar.gz -C /src/mesa --strip-components=1; \ + rm /tmp/mesa.tar.gz; \ + actual="$(cd /src/mesa && tar \ + --sort=name \ + --mtime='UTC 1970-01-01' \ + --owner=0 \ + --group=0 \ + --numeric-owner \ + -cf - . | sha256sum | awk '{print $1}')"; \ + echo "Mesa normalized tree: ${actual}"; \ + test "${actual}" = "${MESA_TREE_SHA256}" + +# Populate precisely the WDK headers listed by the pinned Mesa source tree. +RUN set -eux; \ + sdk="/opt/ewdk/Program Files/Windows Kits/10/Include/${WINSDKVER}"; \ + mkdir -p /src/mesa/include/winddk; \ + while IFS= read -r header; do \ + test -n "${header}" || continue; \ + source_header="$(find "${sdk}" -type f -iname "${header}" -print -quit)"; \ + if [ -z "${source_header}" ]; then \ + echo "Missing EWDK header for Mesa: ${header}" >&2; \ + exit 1; \ + fi; \ + cp "${source_header}" "/src/mesa/include/winddk/${header}"; \ + done < /src/mesa/include/winddk/.gitignore + +RUN cat > /tmp/mingw-x86_64.ini <<'EOF' +[binaries] +c = 'x86_64-w64-mingw32-gcc' +cpp = 'x86_64-w64-mingw32-g++' +ar = 'x86_64-w64-mingw32-ar' +strip = 'x86_64-w64-mingw32-strip' +windres = 'x86_64-w64-mingw32-windres' + +[host_machine] +system = 'windows' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' + +[properties] +needs_exe_wrapper = true +EOF + +RUN python3 -m venv /opt/mesa-venv \ + && /opt/mesa-venv/bin/pip install --no-cache-dir \ + "meson==1.7.2" \ + "jinja2==3.1.6" \ + "mako==1.3.10" \ + "packaging==25.0" \ + "ply==3.11" \ + "pyyaml==6.0.2" + +ENV PATH=/opt/mesa-venv/bin:/opt/cargo/bin:/opt/mingw-posix/bin:${PATH} + +RUN meson setup \ + /src/mesa/build-win64 \ + /src/mesa \ + --cross-file /tmp/mingw-x86_64.ini \ + --buildtype=release \ + --prefix=/ \ + -Dplatforms=windows \ + -Dvulkan-drivers=virtio \ + -Dgallium-drivers= \ + -Dopengl=false \ + -Degl=disabled \ + -Dglx=disabled \ + -Dgbm=disabled \ + -Dllvm=disabled \ + -Dxmlconfig=disabled \ + -Dbuild-tests=false \ + -Dvulkan-manifest-per-architecture=true \ + && meson compile -C /src/mesa/build-win64 -j "$(nproc)" \ + && DESTDIR=/tmp/mesa-stage meson install -C /src/mesa/build-win64 \ + && mesa_dll="$(find /tmp/mesa-stage -type f -name vulkan_virtio.dll -print -quit)" \ + && mesa_json="$(find /tmp/mesa-stage -type f -name virtio_icd.x86_64.json -print -quit)" \ + && test -n "${mesa_dll}" \ + && test -n "${mesa_json}" \ + && mkdir -p /out \ + && cp "${mesa_dll}" /out/vulkan_virtio.dll \ + && cp "${mesa_json}" /out/virtio_icd.x86_64.json \ + && cp /src/mesa/src/virtio/virtio-gpu/wddm_hw.h /out/mesa_wddm_hw.h \ + && grep -q 'vulkan_virtio.dll' /out/virtio_icd.x86_64.json \ + && file /out/vulkan_virtio.dll | grep -q 'PE32+' + + +FROM toolchain AS d3d11-build + +ARG D3D11_SHA +ARG DXVK_SHA +ARG WINSDKVER=10.0.26100.0 + +COPY --from=ewdk /opt/ewdk /opt/ewdk +COPY --from=d3d11 / /src/d3d11/ + +# The named Git context is recursively cloned by BuildKit, including the DXVK +# submodule. D3D11_SHA/DXVK_SHA are recorded and checked by the workflow. +RUN set -eux; \ + test -n "${D3D11_SHA}"; \ + test -n "${DXVK_SHA}"; \ + test -f /src/d3d11/thirdparty/dxvk/version.h.in; \ + test -f /src/d3d11/include/virtio_wddm_uapi.h + +# Fill in the ignored WDK headers from the pinned EWDK. +RUN set -eux; \ + sdk="/opt/ewdk/Program Files/Windows Kits/10/Include/${WINSDKVER}"; \ + mkdir -p /src/d3d11/include/winddk; \ + while IFS= read -r header; do \ + test -n "${header}" || continue; \ + source_header="$(find "${sdk}" -type f -iname "${header}" -print -quit)"; \ + if [ -z "${source_header}" ]; then \ + echo "Missing EWDK header for D3D11: ${header}" >&2; \ + exit 1; \ + fi; \ + cp "${source_header}" "/src/d3d11/include/winddk/${header}"; \ + done < /src/d3d11/include/winddk/.gitignore + +WORKDIR /src/d3d11 +RUN set -eux; \ + vulkan_import="$(find /usr/lib -type f -path '*/wine/x86_64-windows/libvulkan-1.a' -print -quit)"; \ + test -s "${vulkan_import}"; \ + test -d /usr/x86_64-w64-mingw32/lib; \ + install -m0644 "${vulkan_import}" /usr/x86_64-w64-mingw32/lib/libvulkan-1.dll.a; \ + printf '%s\n' \ + '__declspec(dllimport) void *vkGetInstanceProcAddr(void *, const char *);' \ + 'int main(void) { return vkGetInstanceProcAddr(0, 0) != 0; }' \ + > /tmp/vulkan-link-probe.c; \ + x86_64-w64-mingw32-gcc \ + /tmp/vulkan-link-probe.c \ + -o /tmp/vulkan-link-probe.exe \ + -lvulkan-1; \ + file /tmp/vulkan-link-probe.exe | grep -q 'PE32+'; \ + x86_64-w64-mingw32-objdump -p /tmp/vulkan-link-probe.exe \ + | grep -Eiq 'DLL Name: .*vulkan-1\.dll'; \ + rm -f /tmp/vulkan-link-probe.c /tmp/vulkan-link-probe.exe; \ + make -j"$(nproc)" DXVK_GIT_VERSION="${DXVK_SHA}"; \ + test -f build/dist/dx11um_virtio.dll; \ + test -f build/dist/dx11um_virtio.debug; \ + mkdir -p /out; \ + cp build/dist/dx11um_virtio.dll /out/; \ + cp build/dist/dx11um_virtio.debug /out/; \ + cp include/virtio_wddm_uapi.h /out/d3d11_virtio_wddm_uapi.h; \ + file /out/dx11um_virtio.dll | grep -q 'PE32+'; \ + if x86_64-w64-mingw32-objdump -p /out/dx11um_virtio.dll \ + | grep -Eiq 'DLL Name: (libgcc_s|libstdc\+\+|libwinpthread)'; then \ + echo "Unexpected MinGW runtime dependency in dx11um_virtio.dll" >&2; \ + exit 1; \ + fi + + +# Successful cache checkpoint for all expensive prerequisites. +# The CI workflow builds this target first with the cache-only exporter so +# these layers are published even if the later KMD/package stage fails. +FROM scratch AS cache-seed +COPY --from=ewdk /opt/ewdk/vfs-overlay.json /ewdk-vfs-overlay.json +COPY --from=makecat-build /out/makecat /makecat +COPY --from=mesa-build /out/vulkan_virtio.dll /vulkan_virtio.dll +COPY --from=d3d11-build /out/dx11um_virtio.dll /dx11um_virtio.dll + +FROM toolchain AS package + +ARG BUILDER_IMAGE +ARG DEBIAN_SNAPSHOT +ARG MINGW_GCC_PKG_VERSION +ARG MINGW_HEADERS_PKG_VERSION +ARG VERSION_ARG +ARG KMD_SHA +ARG D3D11_SHA +ARG DXVK_SHA +ARG MESA_TREE_SHA256 +ARG MAKECAT_REF +ARG CLANG_CL_LINUX_REF +ARG EWDK_VERSION +ARG VCTOOLSVER +ARG WINSDKVER +ARG RUST_TOOLCHAIN +ARG CBINDGEN_VERSION + +ENV VCTOOLSVER=${VCTOOLSVER} +ENV WINSDKVER=${WINSDKVER} +ENV RUSTUP_TOOLCHAIN=${RUST_TOOLCHAIN} +ENV RUSTUP_AUTO_INSTALL=0 +ENV AR_x86_64_pc_windows_msvc=llvm-lib + +COPY --from=ewdk /opt/ewdk /opt/ewdk +COPY --from=makecat-build /out/makecat /usr/local/bin/makecat +COPY --from=kmd / /src/kmd/ +COPY --from=mesa-build /out/ /opt/mesa-artifacts/ +COPY --from=d3d11-build /out/ /opt/d3d11-artifacts/ + +WORKDIR /src/kmd + +# Configure the EWDK exactly the way the Rust WDK helper expects it. +RUN cat > /src/kmd/ewdk.env < /src/kmd/cert.env <<'EOF' +#!/bin/bash +export CERT="/opt/test-cert/cert.pem" +export KEY="/opt/test-cert/key.pem" +EOF + +# Build/package the floating KMD master using the pinned environment and the +# two UMD artifacts. RUSTUP_TOOLCHAIN overrides the repository's floating +# rust-toolchain.toml (`channel = "nightly"`), while RUSTUP_AUTO_INSTALL=0 +# prevents rustup from silently downloading a different nightly. +RUN set -eux; \ + rustup show active-toolchain | grep -F "${RUST_TOOLCHAIN}"; \ + rustup target list --installed | grep -Fx 'x86_64-pc-windows-msvc'; \ + test "$(command -v "${AR_x86_64_pc_windows_msvc}")" = "/usr/bin/llvm-lib"; \ + llvm-lib /? >/tmp/llvm-lib-help.txt 2>&1 || true; \ + grep -qi 'LLVM Lib' /tmp/llvm-lib-help.txt; \ + rm -f /tmp/llvm-lib-help.txt; \ + sysroot="$(rustc --print sysroot)"; \ + test -f "${sysroot}/lib/rustlib/src/rust/library/Cargo.lock"; \ + rustc --version; \ + cargo --version + +RUN --mount=type=cache,target=/opt/cargo/registry \ + --mount=type=cache,target=/opt/cargo/git \ + ./dist.sh + +RUN set -eux; \ + dist=/src/kmd/target/dist; \ + cp /opt/test-cert/virtio_test_signing.cer "${dist}/"; \ + cat > "${dist}/BUILDINFO.txt" <&2; \ + exit 1; \ + fi; \ + done; \ + find "${dist}" -maxdepth 1 -type f -printf '%f\n' | sort + + +FROM scratch AS artifact +COPY --from=package /src/kmd/target/dist/ /