Skip to content

Instantly share code, notes, and snippets.

@ognevny
Last active April 13, 2026 11:01
Show Gist options
  • Select an option

  • Save ognevny/6b1fa2589b8851cde5a8f762f1f21bd0 to your computer and use it in GitHub Desktop.

Select an option

Save ognevny/6b1fa2589b8851cde5a8f762f1f21bd0 to your computer and use it in GitHub Desktop.
Maintaining Rust-based packages in MSYS2

Developing packages compiled with Rust in MSYS2

This is a guideline made for maintainers and contributors to understand specific workarounds and solutions used to compile some Rust-based software in MSYS2 distribution

Understanding the template

It's assumed you've read PKGBUILD(5) manual and understand the fields used for MSYS2 only

Fetching Cargo crates

prepare() function appears to be

prepare() {
  cd "${_realname}-${pkgver}"

  patch -Np1 -i "${srcdir}"/0001-A-really-important-fix.patch
  patch -Np1 -i "${srcdir}"/0002-A-less-important-fix.patch

  # if cargo wants to make an http request at build stage, use `cargo fetch --locked` instead
  cargo fetch --locked --target "$(rustc -vV | sed -n 's/host: //p')"
}

The comment above cargo fetch is a maintainers message and shouldn't be in actual recipes.

By default cargo fetch downloads sources from https://crates.io for ALL packages listed in Cargo.lock file. --target flag is used to reduce number of downloaded packages specific for certain target. For instance, Alacritty contains lots of OS-specific dependencies, and using --target flag reduced the number of deps by ~x2 times.

Executable installation

cargo install by default searches for a package in https://crates.io and installs it under $HOME/.cargo/bin directory. Custom sources can be specified, run cargo help install to read the manual.

In our case we install locally compiled packages, various options (--root, --path and --no-track) are used to make Cargo to do a simple move from target directory to $MINGW_PREFIX/bin.

Sometimes you can see that after running cargo install cargo recompiles the whole program. To prevent this, check the following:

  1. Does the package compiled for custom profile? If so, use same --profile option like in build step.
  2. Do you install proper package? Sometimes you need to install package-cli, but you specify the path of the whole workspace
  3. Ensure that compile-time features (--feature option) are correctly set for both build and install

Sometimes you may do plain install -Dm755 invocation instead of trying to deal with cargo install.

Workarounds and fixes

It's the list of used methods to improve/fix some builds

Patching crates

In MSYS2 some Rust-based packages use patched crates. Usually it's zstd-sys and ntapi-rs. The first crate is patched to link zstd dynamically, which reduces the size of binaries. The second crate is patched to properly link Windows system libs (ntapi-rs is orphaned but still used in some repos).

A common way to patch crates is (example with zstd-sys):

  1. Download the source from crates.io. To do so, add this line to source() field: zstd-sys.tar.gz::https://crates.io/api/v1/crates/zstd-sys/2.0.15+zstd.1.5.7/download. You may use another name instead of zstd-sys.tar.gz; 2.0.15+zstd.1.5.7 is the crate version, you can find it in Cargo.lock file.
  2. Apply patch. The procedure of patching is similar to patching source, but usually (when you're under package source) need to specify directory with source, e.g. patch -d "../zstd-sys-2.0.15+zstd.1.5.7" -i "../zstd-sys-remove-statik.patch".
  3. Tell cargo to use patched source. There may be 2 cases:
    1. Root Cargo.toml has [patch.crates-io] field. You can append a new line after it with sed: sed -i '/\[patch\.crates-io\]/a zstd-sys = { path = "../zstd-sys-2.0.15+zstd.1.5.7" }' Cargo.toml
    2. Root Cargo.toml doesn't have mentioned field. You can append it to the end of file with cat command:
cat >> Cargo.toml <<END

[patch.crates-io]
zstd-sys = { path = "../zstd-sys-2.0.15+zstd.1.5.7" }
END
  1. Run cargo update so the package source will be changed in lockfile: cargo update -p zstd-sys.

The patch for zstd-sys is found under zstd-sys-remove-statik.patch name.

These are patches we use for Rust packages:

ntapi-rs (link proper libraries on arm64): https://github.com/msys2/MINGW-packages/blob/27b8057165bd943cc8d1b148d8b5abcb11c86ff1/mingw-w64-dust/ntapi-link-ntdll-arm64.patch

zstd-sys (link zstd dynamically): https://github.com/msys2/MINGW-packages/blob/27b8057165bd943cc8d1b148d8b5abcb11c86ff1/mingw-w64-zed/zstd-sys-remove-statik.patch

bzip2-sys (use pkgconfig for MinGW): https://github.com/msys2/MINGW-packages/blob/27b8057165bd943cc8d1b148d8b5abcb11c86ff1/mingw-w64-uv/bzip2-use-pkgconfig.patch

curl-sys (use pkgconfig for MinGW): https://github.com/msys2/MINGW-packages/blob/7438ebe84f25551db3423a725cad6b2206f3ac48/mingw-w64-zed/curl-sys-use-pkgconfig.patch

Linking system deps dynamically

Some packages use existing C libraries for a faster runtime. They're usually used with -sys crates, which do raw FFI bindings and (sometimes) add high-level abstractions over them. Advanced -sys crates have a way to link an external C library instead of compiling your own. See my another gist for a (not complete) list of -sys crates. Note that pkgconf package should be available for most of them.

For *-pc-windows-gnullvm package you can link libunwind.dll instead of static library. In makepkg confs it's set to use static library (with -Ctarget-feature=+crt-static) due to *-pc-windows-gnu targets lacking support for dynamic crt libraries (see upstream issue). To link libunwind.dll you need to add RUSTFLAGS="${RUSTFLAGS/+crt-static/-crt-static}" before running cargo build.

Various issues/errors

  1. Fails to compile aws-lc-sys on CLANG* environments with pthread symbols error (thrown by linker): ensure that aws-lc-rs crate has version at least 1.13.1. You can update it with cargo update -p aws-lc-rs --precise 1.13.1 command. Also check that ${MINGW_PACKAGE_PREFIX}-nasm and ${MINGW_PACKAGE_PREFIX}-rust-bindgen packges from MSYS2 are used.
    1. Absolutely the same, but this time there are hundreds of errors!!! This time you need to update aws-lc-rs to 1.15.4 and higher because there was a regression in build-script: cargo update -p aws-lc-rs --precise 1.15.4. Once again, ensure that ${MINGW_PACKAGE_PREFIX}-nasm and ${MINGW_PACKAGE_PREFIX}-rust-bindgen are presented in makedepends
  2. Fails to compile C source via cc-rs crate: ensure that cc crate has version at least 1.1.10. You can update it with cargo update -p cc --precise 1.1.10.
  3. Fails to fetch git deps with a strange SSL certificate error: add --config='net.git-fetch-with-cli=true' option to cargo fetch command
  4. Failed to fetch pet crate (usually via git repo): enable long paths system-wide (GitHub Actions machines have it enabled by default) and change git config via git config --global core.longpaths true.
  5. Package uses Rust nightly features: if the package is already provided for some distributions (which makes it at least a bit good to have in our repos) you need to set RUSTC_BOOTSTRAP environment variable for each build/install step (e.g. RUSTC_BOOTSTRAP=1 cargo build). Another approach is to use rustup package, then you need to add export RUSTUP_TOOLCHAIN=nightly-${RUST_CHOST} before each cargo invocation.
  6. bindgen failed with ClangDiagnostic errors on GCC-based environments: first, you have to put ${MINGW_PACKAGE_PREFIX}-clang package into makedepends field, then add export LIBCLANG_PATH="${MINGW_PREFIX}/bin" before the build command.
    1. bindgen failed, but on CLANG envieonments: if this is follow by "llvm is wrong in name", you need to manually specify bindgen target with export BINDGEN_EXTRA_CLANG_ARGS="--target=${CARCH}-pc-windows-gnu"

Cygwin reference

Since August 2025 there is a msys package for rust and some tools (rustdoc, rustfmt and clippy). This package is used to get some specific libraries/build tools so we can adapt more packages for cygwin. Compared to other toolchains, Rust package is a pure cygwin with only one difference - mssy2-runtime is linked instead of cygwin1.dll.

All low-level crates must be adapted to work on Cygwin. Thanks to @Berrysoft and other contributors for working on this! This is a reference table with crates that support Cygwin environment

crate name minimal version related PRs
getrandom 0.3.2, 0.2.16 rust-random/getrandom#626, rust-random/getrandom#654
rustix 1.0.3 bytecodealliance/rustix#1410
psm 0.1.26 rust-lang/stacker#122
libc1 0.2.171 rust-lang/libc#4279
socket2 0.6.0, 0.5.10 rust-lang/socket2#568, rust-lang/socket2#578
nix1 0.30.0 nix-rust/nix#2610
backtrace 0.3.76 rust-lang/backtrace-rs#704
ring2 - briansmith/ring#2730

In other cases it's very likely that dependencies should be updated, check that these crates use right version of deps above.

Footnotes

  1. note that some features are missing/were added in later versions 2

  2. example of patching ring@0.17.14 is available here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment