# syntax=docker/dockerfile:1.7
#
# py-alpha-lib 构建环境
# ----------------------------------------------------------------------------
# 一切都烤进镜像：工具链 + cargo 依赖 + MSVC CRT/SDK。
# CI 不挂任何 volume，跑起来就是镜像内自带的状态，没有 docker-in-docker
# 的挂卷路径解析坑。
#
# 镜像内置：
#   - Python 3.11
#   - Rust stable + 三个 target (linux-gnu / linux-musl / windows-msvc)
#   - sccache（编译缓存）
#   - cargo-xwin + 预下载好的 MSVC CRT/SDK（写入 /opt/xwin/xwin/DONE）
#   - maturin[zig] + twine
#   - llvm / clang / lld（提供 llvm-dlltool / llvm-lib / lld-link / clang-cl）
#   - Node.js 20（Gitea Actions / act 跑 actions/checkout 必需）
#
# 合规提示：
#   镜像里包含 Microsoft VC++ Build Tools 和 Windows SDK 文件，许可证见
#       https://go.microsoft.com/fwlink/?LinkId=2086102
#   按 EULA 这些文件不得再分发到第三方。**只能推到对内可信的 registry**
#   （内网 Gitea / Harbor），不要推到 Docker Hub 等公网仓库。
# ----------------------------------------------------------------------------

FROM python:3.11-slim-bookworm

LABEL org.opencontainers.image.title="py-alpha-lib builder" \
      org.opencontainers.image.description="Pre-baked toolchain for building py-alpha-lib wheels (manylinux/musllinux/win_amd64) + sdist"

ENV DEBIAN_FRONTEND=noninteractive \
    LANG=C.UTF-8 \
    LC_ALL=C.UTF-8 \
    PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

ENV RUSTUP_HOME=/usr/local/rustup \
    CARGO_HOME=/usr/local/cargo \
    PATH=/usr/local/cargo/bin:$PATH \
    CARGO_INCREMENTAL=0 \
    RUSTC_WRAPPER=sccache \
    SCCACHE_DIR=/opt/sccache \
    SCCACHE_CACHE_SIZE=2G \
    XWIN_CACHE_DIR=/opt/xwin \
    XWIN_ACCEPT_LICENSE=1 \
    RUSTFLAGS="-C target-feature=+sse4.2 -C target-feature=+avx2 -C target-feature=+pclmulqdq"

# ---- 系统依赖 + LLVM 工具链（cargo-xwin 需要 llvm-dlltool / lld-link 等） ----
RUN apt-get update \
 && apt-get install -y --no-install-recommends \
        build-essential \
        ca-certificates \
        curl \
        git \
        gnupg \
        pkg-config \
        xz-utils \
        llvm \
        clang \
        lld \
 && rm -rf /var/lib/apt/lists/*

# ---- Node.js（actions/checkout@v4 等 JS action 必需） ----
ARG NODE_MAJOR=20
RUN set -eux; \
    curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash -; \
    apt-get install -y --no-install-recommends nodejs; \
    rm -rf /var/lib/apt/lists/*; \
    node --version; \
    npm --version

# ---- Rust stable + 三个 target ----
ARG RUST_TOOLCHAIN=stable
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
      | sh -s -- -y --default-toolchain "${RUST_TOOLCHAIN}" --profile minimal --no-modify-path \
 && rustup target add x86_64-unknown-linux-gnu \
 && rustup target add x86_64-unknown-linux-musl \
 && rustup target add x86_64-pc-windows-msvc \
 && rustc --version

# ---- sccache（mozilla 官方静态二进制） ----
ARG SCCACHE_VERSION=v0.10.0
RUN set -eux; \
    curl -fL -o /tmp/sccache.tgz \
        "https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/sccache-${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz"; \
    tar -xzf /tmp/sccache.tgz -C /tmp; \
    install -m 0755 \
        "/tmp/sccache-${SCCACHE_VERSION}-x86_64-unknown-linux-musl/sccache" \
        /usr/local/cargo/bin/sccache; \
    rm -rf /tmp/sccache*; \
    sccache --version

# ---- maturin (含 zig) + twine ----
RUN python -m pip install --no-cache-dir --upgrade pip \
 && python -m pip install --no-cache-dir \
        "maturin[zig]>=1.10,<2.0" \
        twine \
 && maturin --version \
 && twine --version

# ---- cargo-xwin（windows-msvc 交叉编译驱动） ----
RUN cargo install --locked cargo-xwin --root /usr/local/cargo \
 && ls -l /usr/local/cargo/bin/cargo-xwin

# ---- 预下载并解包 MSVC CRT + Windows SDK 到 /opt/xwin/xwin/ ----
# cargo-xwin 命中缓存的关键文件是 $XWIN_CACHE_DIR/xwin/DONE。
# 直接把它写到镜像里 /opt/xwin，CI 不挂卷直接命中。
#
# 重要：cargo-xwin 命中缓存要求“请求架构 ⊆ DONE 中已下载架构”。
# 这里只 splat x86_64，所以 CI 调用 cargo-xwin 时也必须强制
# XWIN_ARCH=x86_64（默认是 [x86_64, aarch64]），否则会重新下载。
# 这条 ENV 不在镜像里，而是在 publish.yml 的 job env 中设置，
# 这样以后想换架构组合时只改一处即可，不需要重 build 镜像。
RUN set -eux; \
    mkdir -p /opt/xwin; \
    cargo xwin cache xwin --xwin-arch x86_64; \
    test -f /opt/xwin/xwin/DONE; \
    du -sh /opt/xwin; \
    ls /opt/xwin/xwin

WORKDIR /work
CMD ["bash"]
