Skip to content

build: add Guix reproducible release flow for Linux, MacOS, Windows#5149

Draft
eval-exec wants to merge 10 commits intonervosnetwork:developfrom
eval-exec:ckb.guix
Draft

build: add Guix reproducible release flow for Linux, MacOS, Windows#5149
eval-exec wants to merge 10 commits intonervosnetwork:developfrom
eval-exec:ckb.guix

Conversation

@eval-exec
Copy link
Copy Markdown
Collaborator

@eval-exec eval-exec commented Mar 19, 2026

What problem does this PR solve?

Problem Summary:

CKB does not have a Bitcoin-style Guix release flow for producing bit-for-bit reproducible Linux release tarballs from a pinned build environment.

What is changed and how it works?

What's Changed:

  • add contrib/guix/guix-build, manifest.scm, and libexec/build.sh to build in a pinned guix time-machine shell --container --pure environment
  • pin the Guix revision with contrib/guix/channels.scm
  • materialize Cargo crate sources from Cargo.lock via Guix cargo-inputs-from-lockfile
  • tighten contrib/guix/guix.scm path remapping for package reproducibility

Support:

  • x86_64-unknown-linux-gnu
  • aarch64-unknown-linux-gnu
  • x86_64-pc-windows-gnu
  • x86_64-pc-windows-msvc
  • aarch64-apple-darwin
  • x86_64-apple-darwin

Related changes

Check List

Tests

  • Manual test (commands below)

Commands:

  • FORCE_DIRTY_WORKTREE=1 ./contrib/guix/guix-build
  • ./contrib/guix/guix-build v0.205.0
  • repeated builds produced the same tarball hash: 3c7d003ca216fbb31173e0da5d965f472243ef4f8b6e1288d37e6053eb566d2d

Copilot AI review requested due to automatic review settings March 19, 2026 06:32
@eval-exec eval-exec requested a review from a team as a code owner March 19, 2026 06:32
@eval-exec eval-exec requested review from doitian and removed request for a team March 19, 2026 06:32
@eval-exec eval-exec marked this pull request as draft March 19, 2026 06:33
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a Guix-based “pinned environment” release builder intended to produce reproducible Linux release tarballs (Bitcoin Core–style), alongside a Guix package recipe for ckb.

Changes:

  • Add contrib/guix/guix-build + supporting scripts to vendor Rust crates and build a deterministic x86_64-unknown-linux-gnu release tarball in a guix time-machine shell --container --pure environment.
  • Pin the Guix channel revision (contrib/guix/channels.scm) and define the build toolchain manifest (contrib/guix/manifest.scm).
  • Add a Guix package recipe (contrib/guix/guix.scm) and generated Rust crate inputs (contrib/guix/rust-crates.scm), plus documentation and .gitignore updates.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
contrib/guix/guix-build New top-level entrypoint orchestrating source archive creation + containerized build.
contrib/guix/libexec/vendor-rust-sources.sh Vendors Cargo dependencies into a deterministic local directory and writes .cargo/config.toml.
contrib/guix/libexec/build.sh Container build script producing the staged install tree + deterministic tarball and SHA256SUMS.
contrib/guix/manifest.scm Declares pinned build tools (Rust, GCC toolchain, patchelf, etc.) for the container environment.
contrib/guix/channels.scm Pins the Guix channel commit used by guix time-machine.
contrib/guix/guix.scm Adds a Guix package definition for building ckb as a Guix package.
contrib/guix/rust-crates.scm Generated crate source definitions + lookup-cargo-inputs list used by guix.scm.
contrib/guix/README.md Documents the new release builder flow and Guix package recipe usage.
.gitignore Ignores guix-build-* output directories.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread contrib/guix/guix-build
Comment thread contrib/guix/libexec/vendor-rust-sources.sh
Comment thread contrib/guix/channels.scm
Comment thread contrib/guix/libexec/build.sh Outdated
Comment thread contrib/guix/libexec/build.sh Outdated
@eval-exec eval-exec force-pushed the ckb.guix branch 4 times, most recently from 02a3b1d to 8e9ff40 Compare March 23, 2026 06:53
@eval-exec eval-exec changed the title build: add Guix reproducible release flow build: add Guix reproducible release flow for Linux, MacOS, Windows Mar 26, 2026
@eval-exec eval-exec changed the title build: add Guix reproducible release flow for Linux, MacOS, Windows build: add Guix reproducible release flow for Linux, MacOS, Windows Mar 26, 2026
@eval-exec
Copy link
Copy Markdown
Collaborator Author

eval-exec commented Mar 26, 2026

Invite @doitian @chenyukang @driftluo @quake @Officeyutong @zhangsoledad to test guix reproducible build on x86_64 Linux platform(x86_64-unknown-linux-gnu):

If you have guix machine, execute: ./contrib/guix/guix-build v0.205.0

If you have no guix machine, execute: ./contrib/guix/guix-docker-build v0.205.0

It may cost 1 hour to finish. Then check the sha256sum is equal to:

❯ cat guix-build-0.205.0/output/x86_64-unknown-linux-gnu/SHA256SUMS
3c7d003ca216fbb31173e0da5d965f472243ef4f8b6e1288d37e6053eb566d2d  ckb_0.205.0_x86_64-unknown-linux-gnu.tar.gz
❯ cat guix-build-0.205.0/output/aarch64-apple-darwin/SHA256SUMS
7efa63c5b25b28e19c7cbfb143d45da2d10b05af8f427ac7e12097c40e20a937  ./ckb_0.205.0_aarch64-apple-darwin.tar.gz
❯ cat guix-build-0.205.0/output/x86_64-pc-windows-gnu/SHA256SUMS
39901c3e5f27559f6d30150c8dfbe2604cbef893981f5e5c1834df8652c6a1f8  ./ckb_0.205.0_x86_64-pc-windows-gnu.zip
❯ cat guix-build-0.205.0/output/aarch64-unknown-linux-gnu/SHA256SUMS
37b1b69faa879ab0f00188c51ab156df0f011912550708a5e400677c30443633  ./ckb_0.205.0_aarch64-unknown-linux-gnu.tar.gz
❯ cat guix-build-0.205.0/output/x86_64-pc-windows-msvc/SHA256SUMS
e31f5af8e04efde939f09d66cc3b1a77534f1cf575f5f9afc36894bdbbdd6226  ./ckb_0.205.0_x86_64-pc-windows-msvc.zip

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a pinned Guix time-machine/container-based build flow to produce reproducible CKB release artifacts (Linux tarball, Windows zip), including toolchain patching and post-build binary validation for Linux.

Changes:

  • Added contrib/guix/guix-build + libexec/build.sh pipeline to generate a vendored source archive and build it in a pure Guix container.
  • Added a pinned Guix manifest (manifest.scm + channels.scm) with an older-glibc cross toolchain, plus patches to improve toolchain reproducibility.
  • Added Linux ELF ABI/dependency validation (symbol-check.py) and a Docker-based convenience runner (guix-docker-build + Dockerfile).

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
contrib/guix/symbol-check.py New Linux ELF ABI/dependency checker (glibc symbol cap, interpreter, rpath/runpath, allowed libs).
contrib/guix/patches/rocksdb-cross-compile-platform.patch Patch intended for cross-compiling rocksdb-sys platform detection.
contrib/guix/patches/glibc-fixed-store-remap.patch Adds -ffile-prefix-map to glibc build flags to reduce Guix store path leakage.
contrib/guix/patches/gcc-ssa-generation.patch GCC patch to make SSA generation deterministic across architectures.
contrib/guix/patches/gcc-fixed-store-remap.patch Adds -ffile-prefix-map to GCC libgcc/libunwind build flags for reproducible debug paths.
contrib/guix/patches/ckb-disable-jemalloc-on-windows.patch Patch intended to disable jemalloc/memory tracker on all Windows targets.
contrib/guix/manifest.scm Pinned build manifest including cross toolchains and cross-compiled OpenSSL/sysroot selection.
contrib/guix/libexec/vendor-rust-sources.sh Vendors crates from Cargo.lock via Guix and writes .cargo/config.toml for offline builds.
contrib/guix/libexec/rust-linker.sh Linker wrapper to route host vs target link steps and enforce deterministic/linker flags.
contrib/guix/libexec/build.sh Main in-container build script: toolchain env setup, source patching, build, packaging, and Linux validation.
contrib/guix/guix.scm Guix package recipe for building ckb as a Guix package (separate from release-tarball flow).
contrib/guix/guix-docker-build Docker wrapper that runs guix-daemon and executes the Guix build inside a container.
contrib/guix/guix-build Top-level driver to create source archive + run per-host builds in a pure Guix container.
contrib/guix/channels.scm Pins the Guix revision for time-machine builds.
contrib/guix/README.md Documents the Guix release builder entry points and usage.
contrib/guix/Dockerfile Alpine-based builder image that installs Guix and runs guix-daemon.
.gitignore Ignores guix-build-* output directories.
Comments suppressed due to low confidence (1)

contrib/guix/patches/rocksdb-cross-compile-platform.patch:29

  • This patch file is not referenced by manifest.scm or applied by libexec/build.sh (which currently performs an inline sed replacement instead). Either wire this patch into the build flow (so it’s the single source of truth and fails cleanly on mismatch) or remove it to avoid future confusion about what is actually being applied.
Fix ckb-librocksdb-sys cross-compilation platform detection.

When cross-compiling from Linux to Windows, cfg!(target_os = "windows")
evaluates on the BUILD host (Linux), not the TARGET.  This causes
build_detect_platform (a Linux script) to run and set POSIX/Linux defines,
while the TARGET-based check also adds Windows defines -- resulting in
conflicting platform flags like -DROCKSDB_PLATFORM_POSIX and -DOS_WIN.

Fix: check the Cargo TARGET env var instead of cfg!() for platform
detection in build.rs, which correctly reflects the cross-compilation
target.

--- a/build.rs
+++ b/build.rs
@@ -6,8 +6,11 @@ use std::path::PathBuf;
 use std::process::Command;

 fn get_flags_from_detect_platform_script() -> Option<Vec<String>> {
-    if !cfg!(target_os = "windows") {
-        let mut cmd = Command::new("bash");
+    // Use the Cargo TARGET env var (not cfg!()) to detect the target platform.
+    // cfg!(target_os) reflects the BUILD host, which is wrong when cross-compiling.
+    let target = env::var("TARGET").unwrap_or_default();
+    if !target.contains("windows") {
+        let mut cmd = std::process::Command::new("bash");

         // if ROCKSDB_USE_IO_URING is not set, treat as enable
         // we use pkg_config probe library, more friendly for rust.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread contrib/guix/README.md
Comment thread contrib/guix/libexec/build.sh Outdated
Comment thread contrib/guix/libexec/build.sh Outdated
Comment thread contrib/guix/patches/ckb-disable-jemalloc-on-windows.patch
Comment thread contrib/guix/channels.scm
Comment thread contrib/guix/symbol-check.py
Comment thread contrib/guix/manifest.scm
Comment thread contrib/guix/README.md
Add pinned Guix packaging and a Bitcoin-style shell-based release builder under contrib/guix, using cargo-inputs-from-lockfile for Rust crate sources.
Major changes to the Guix reproducible build system:

manifest.scm:
- Add glibc-2.31 cross-toolchain (x86_64-linux-gnu-toolchain) using
  cross-gcc, cross-libc, and cross-kernel-headers from Guix
- Cross-compile OpenSSL 3.0.8 against glibc-2.31 as a Guix package
  (openssl-glibc-2.31), avoiding the bootstrap issues of
  package-with-c-toolchain by using our existing cross-toolchain
- Use standard gcc-toolchain-14 for native build tools and rust-1.92
  for the Rust compiler

build.sh:
- Add cross-compilation environment setup (CC, CXX, AR, RANLIB, etc.)
  using the cross-toolchain from the Guix profile
- Create CC/CXX wrappers that inject -Wl,-rpath for the cross-glibc
  so autoconf test programs (e.g., jemalloc) can execute in the
  container, with -static-libgcc to avoid native libgcc_s mismatch
- Set GUIX_LD_WRAPPER_DISABLE_RPATH only in rust-linker.sh for the
  final target link, not globally, so intermediate binaries get rpath
- Route host (build-script) linking through CKB_RUST_HOST_LIBRARY_PATH
  to avoid cross-glibc contamination in the Guix profile
- Use patchelf --remove-rpath alongside --set-interpreter
- Reference symbol-check.py from /ckb mount, not source tree

rust-linker.sh (new):
- Cargo linker wrapper that distinguishes host vs target linking
- Target links: cross-gcc with --dynamic-linker, -static-libstdc++,
  -static-libgcc, and GUIX_LD_WRAPPER_DISABLE_RPATH=yes
- Host links: native gcc with LIBRARY_PATH set to native glibc
- Path detection uses /target/<triple>/ to avoid false matches

guix-build:
- Support explicit git ref: ./contrib/guix/guix-build v0.205.0
- Archives the exact commit, not the worktree
- Add --help, usage text, and build progress message
- Keep HEAD mode with dirty-worktree check as default

symbol-check.py:
- Allow non-GLIBC version namespaces (GLIBCXX, GCC, CXXABI, OPENSSL)
- Fix LIEF interpreter check with fallback for single-entry arch maps
Add Dockerfile and guix-docker-build script for running reproducible
Guix builds inside Docker containers, following fanquake's approach
used by Bitcoin Core:

- guix-daemon runs as the container's main process (PID 1)
- Builds are executed via `docker exec`, not in the same shell
- Docker volumes cache /gnu/store across builds for performance
- Alpine-based image with Guix 1.5.0 binary and 32 build users

Usage:
  ./contrib/guix/guix-docker-build v0.205.0

Verified bit-for-bit identical output between host and Docker:
  3c7d003ca216fbb31173e0da5d965f472243ef4f8b6e1288d37e6053eb566d2d

Also fix tar extraction in build.sh with --no-same-owner to avoid
"Cannot change ownership" errors inside nested Guix containers.
Add reference comments linking to the original Bitcoin Core files
that this Guix build system is derived from. Each file now credits
its Bitcoin Core counterpart with a direct GitHub URL.

Files annotated:
- guix-build → bitcoin/contrib/guix/guix-build
- build.sh → bitcoin/contrib/guix/libexec/build.sh
- manifest.scm → bitcoin/contrib/guix/manifest.scm
- symbol-check.py → bitcoin/contrib/guix/symbol-check.py
- Dockerfile → fanquake/core-review/guix
- guix-docker-build → fanquake/core-review/guix
- rust-linker.sh → no Bitcoin equivalent (Rust-specific)
- gcc/glibc patches → bitcoin/contrib/guix/patches
Add MinGW-w64 cross-toolchain support for building CKB Windows binaries
reproducibly from Linux, following Bitcoin Core's approach.

manifest.scm:
- Add mingw-w64-base-gcc with POSIX thread support
- Add make-mingw-pthreads-cross-toolchain (MinGW-w64 + winpthreads)
- Add openssl-mingw-w64 (OpenSSL cross-compiled for Windows, static)
- Make package list HOST-dependent: Linux gets patchelf + glibc OpenSSL,
  Windows gets zip + MinGW OpenSSL

guix-build:
- Map Rust triples to GNU triples (MANIFEST_HOST) for the manifest
- Pass RUST_TARGET alongside HOST into the container
- Allow x86_64-pc-windows-gnu in SUPPORTED_HOSTS

build.sh:
- Add x86_64-w64-mingw32 case for cross-toolchain paths (winpthreads
  instead of glibc, no kernel headers)
- Windows CC wrapper: plain cross-gcc (no rpath injection)
- Windows OpenSSL: static linking (OPENSSL_STATIC=1)
- Windows packaging: deterministic .zip (not .tar.gz)
- Skip patchelf and ELF symbol checks for PE binaries

rust-linker.sh:
- Add *windows* case: -Wl,--no-insert-timestamp for deterministic PE
  headers, no --dynamic-linker

Usage:
  HOSTS=x86_64-pc-windows-gnu ./contrib/guix/guix-build v0.205.0
  HOSTS="x86_64-unknown-linux-gnu x86_64-pc-windows-gnu" ./contrib/guix/guix-build v0.205.0

Reference: https://github.com/bitcoin/bitcoin/blob/master/contrib/guix/manifest.scm
Add macOS Apple Silicon cross-compilation support, following Bitcoin
Core's approach for the toolchain while building Rust's library/std
from source (a world first — no existing project does this).

manifest.scm:
- Add clang-toolchain-19, lld-19, make-lld-wrapper for darwin targets

guix-build:
- Add aarch64-apple-darwin to SUPPORTED_HOSTS
- Add SDK_PATH check and sharing into the Guix container
- Reference Bitcoin's SDK extraction docs

build.sh:
- Build Rust library/std from source using x.py with Guix's
  bootstrapped rustc + Apple SDK (no pre-built binaries)
- Clang CC/CXX wrappers with -isysroot, -nostdlibinc, -fuse-ld=lld
- LLVM tools (llvm-ar, llvm-ranlib, llvm-strip, llvm-nm)
- ZERO_AR_DATE=1 for deterministic archives
- Vendor OpenSSL (no system OpenSSL in Apple SDK)

rust-linker.sh:
- Darwin case: -fuse-ld=lld, -Wl,-no_adhoc_codesign,
  -Wl,--threads=1 (deterministic LC_UUID),
  -Wl,-platform_version,macos,14.0,14.0

Usage:
  SDK_PATH=/path/to/SDKs HOSTS=aarch64-apple-darwin \
    ./contrib/guix/guix-build v0.205.0

Requires macOS SDK extracted from Xcode (not redistributable).
See: https://github.com/bitcoin/bitcoin/blob/master/contrib/macdeploy/README.md

Reference: https://github.com/bitcoin/bitcoin/blob/master/contrib/guix/manifest.scm
Three fixes surfaced during host-vs-docker reproducibility verification:

* guix-build: add --preserve='^HOST$' so the HOST env var is actually
  kept through `guix shell --pure`.  The comment in manifest.scm already
  referenced this flag, but it was never present, so manifest evaluation
  sometimes picked up a stale profile for the wrong target.

* rust-linker.sh: add -Wl,-s on the Windows link to strip the COFF
  symbol table.  Rustc embeds DLL import-lib symbols whose names
  contain its random temp directory (e.g.
  _head__tmp_rustc9s2NHV_kernel32_dll_imports_lib), which made each
  build differ.

* ckb-disable-jemalloc-on-windows.patch: regenerate via `git diff` so
  the hunk headers carry correct line counts and context lines are
  space-prefixed.  The hand-written version was rejected as malformed
  by the Guix-bundled `patch`.

Verified reproducible across two Docker runs and one host run:
  39901c3e5f27559f6d30150c8dfbe2604cbef893981f5e5c1834df8652c6a1f8
Adds a new supported target triple, cross-compiled from x86_64 Linux
using Guix's old-glibc toolchain machinery (same approach as the
existing x86_64-linux-gnu build):

* manifest.scm: aarch64-linux-gnu-toolchain built via
  make-ckb-cross-toolchain (glibc 2.31); openssl-aarch64-glibc-2.31
  cross-compiled against that toolchain; the host-dependent branch
  now selects x86_64 or aarch64 packages based on the target, and
  aarch64 pulls in a Rust sysroot via make-rust-sysroot/implementation
  (rustc only ships libstd for the build host).

* guix-build: aarch64-unknown-linux-gnu added to SUPPORTED_HOSTS and
  mapped to the aarch64-linux-gnu GNU triple.

* libexec/build.sh: new HOST case with
  DYNAMIC_LINKER=/lib/ld-linux-aarch64.so.1 and the right
  TARGET_ENV_SUFFIX.  Because cross-arch cross-compile differs from
  the existing same-arch glibc-downgrade, build scripts (build.rs,
  proc-macros) get CC_x86_64_unknown_linux_gnu/HOST_CC pointed at
  native gcc, and AARCH64_UNKNOWN_LINUX_GNU_OPENSSL_{INCLUDE,LIB}_DIR
  is set directly so openssl-sys doesn't try to use the host
  pkg-config for a differing target arch.  Hardcoded x86_64
  interpreter in the patchelf call replaced with ${DYNAMIC_LINKER}.

* symbol-check.py: recognise AARCH64 for the glibc 2.31 cap, the
  expected interpreter, and the ld-linux-aarch64.so.1 allow-list
  entry.

Verified reproducible:
  x86_64-unknown-linux-gnu: 3c7d003ca216fbb31173e0da5d965f472243ef4f8b6e1288d37e6053eb566d2d
  aarch64-unknown-linux-gnu: 37b1b69faa879ab0f00188c51ab156df0f011912550708a5e400677c30443633
x86_64 hash is identical with and without this commit applied.
Adds a fourth reproducibility target: the MSVC ABI Windows build that
CKB's CI currently produces via a Visual Studio runner.  Cross-compiled
from Linux using clang-cl + lld-link and an xwin-extracted Microsoft SDK
(user-provided at depends/SDKs/msvc-vs17-sdk10.0.22621, same pattern as
the Apple SDK for darwin).

What changes:

* manifest.scm — a (string-suffix? "-pc-windows-msvc" target) cond
  branch that pulls in clang-toolchain-20, lld-20, rust-src-pkg, and
  zip.  rust-src-pkg was inlined in the darwin branch; it's now a
  top-level definition shared between darwin and windows-msvc because
  both need the Rust source to build library/std from scratch via x.py.

* guix-build — x86_64-pc-windows-msvc in SUPPORTED_HOSTS; MSVC SDK
  detection block modelled on OSX_SDK; --share the SDK into the guix
  container and pass MSVC_SDK into the environment.

* libexec/build.sh — new HOST case with clang-cl as REAL_CC and an
  lld-link wrapper (cross-lld-link) that injects /LIBPATH: for the
  xwin SDK lib directories so neither x.py nor rustc has to know the
  paths.  x.py builds library/std from source using the same pattern
  as darwin (config.toml, checksum regen, host rustlib copy).  The
  host rustlib copy now chmod -R u+w so subsequent `rm -rf distsrc`
  can clean up the /gnu/store-read-only files (latent bug: also
  affected darwin on reruns).  RUSTFLAGS carries /Brepro and
  /DEBUG:NONE for a deterministic PE.

* libexec/rust-linker.sh — dedicated *-pc-windows-msvc case that
  forwards rustc's linker args verbatim to lld-link.  The previous
  *windows* branch is kept for MinGW and now explicitly excludes msvc
  (the two take different flag dialects — GNU-style -Wl,... vs MSVC
  /FLAG).

Patch pipeline refactor (prerequisite):

* Replace the sed-based patch_vendored_crate with a helper,
  apply_vendored_patch, that applies a real .patch file to a vendored
  crate directory and refreshes .cargo-checksum.json afterwards so
  cargo --frozen accepts the modified files.  The existing
  rocksdb-cross-compile-platform.patch was stale (wrong hunk line
  counts, also semantically incorrect for darwin) — replaced with
  ckb-librocksdb-sys-cross-compile.patch, regenerated from a real
  git diff.

* New patches/ckb-vm-msvc-cc-env.patch: ckb-vm 0.24.14's build.rs
  hardcodes build.compiler("gcc") for its is_msvc branch (to route
  its GNU AT&T-syntax execute_x64.S through a GNU assembler, which
  works on a native Windows machine that also has MinGW-w64's gcc
  installed alongside cl.exe).  For cross-compile from Linux, "gcc"
  resolves to the host's Linux cc which cannot emit MSVC COFF.  The
  patch adds a CKB_VM_ASM_CC env-var override — build.sh sets it to
  clang-cl, which handles GNU AT&T .S via LLVM's integrated assembler
  and produces valid MSVC-ABI COFF.

Reproducibility verified:

  x86_64-pc-windows-msvc: e31f5af8e04efde939f09d66cc3b1a77534f1cf575f5f9afc36894bdbbdd6226
    - host run 1, host run 2, docker run: all identical

The existing four targets are unaffected by the patch-pipeline refactor
(mingw re-verified post-refactor at 39901c3e..., matching the pre-refactor
hash byte-for-byte; linux/aarch64-linux never hit that code path).

The xwin SDK is user-provided.  The release flow documents pinning
\`xwin --manifest-version 17 --sdk-version 10.0.22621\` — two xwin
extractions from the same pin produce byte-identical trees (5547 files
+ 2895 symlinks, all matching), so users can either re-run xwin or
consume a pre-extracted tarball.  Microsoft's Visual Studio Build Tools
EULA applies to the SDK; xwin's --accept-license flag handles it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants