# --------------------------------------------------------------------------- # windows-jemalloc — build jemalloc from source under MSYS2/MinGW # # WHY THIS EXISTS: # tikv-jemalloc-sys's built-in autotools step fails on Windows CI because # the HOST env var (x86_64-pc-windows-msvc) maps to --build=x86_64-pc-win32, # which jemalloc 5.3.0's config.sub rejects. This action pre-builds jemalloc # externally and uses JEMALLOC_OVERRIDE to bypass the build script entirely. # # PITFALLS (read before modifying): # 1. Use the RELEASE TARBALL, not the git tag — the tag lacks configure. # 2. Pass --with-jemalloc-prefix=_rjem_ — tikv-jemallocator expects _rjem_*. # 3. MinGW installs jemalloc_s.lib not libjemalloc.a — rename needed. # 4. JEMALLOC_OVERRIDE needs a Windows-native path (cygpath -w). # 5. Provide dummy liballoc.a for -lalloc linker flag. # # USAGE: # - uses: msys2/setup-msys2@v2 (first, in the caller workflow) # - uses: dtolnay/rust-toolchain@stable (first, with targets) # - name: Setup jemalloc for Windows # uses: ./.github/actions/windows-jemalloc # - name: Build # shell: msys2 {0} # env: # JEMALLOC_OVERRIDE: ${{ steps.jemalloc.outputs.jemalloc-override }} # CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUSTFLAGS: -L ${{ steps.jemalloc.outputs.dummy-dir }} # run: cargo build --release --target x86_64-pc-windows-gnu # --------------------------------------------------------------------------- name: 'Windows jemalloc' description: Build jemalloc 5.3.0 from source under MSYS2/MinGW for Windows CI outputs: jemalloc-override: description: Windows-native path to libjemalloc.a for JEMALLOC_OVERRIDE value: ${{ steps.set-paths.outputs.jemalloc-override }} dummy-dir: description: Windows-native path to directory containing dummy liballoc.a value: ${{ steps.set-paths.outputs.dummy-dir }} runs: using: composite steps: # Cache the compiled jemalloc prefix across runs — building it from # source (configure + make) takes real minutes and never changes unless # this action's build recipe does. Cached under the workspace (a stable, # known Windows-native path) rather than MSYS2's /tmp, whose real # location is an implementation detail of the msys2/setup-msys2 action. - name: Cache jemalloc build id: jemalloc-cache uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ${{ github.workspace }}\.jemalloc-prefix key: windows-jemalloc-5.3.0-${{ hashFiles('.github/actions/windows-jemalloc/action.yml') }} # Step 1 — compile jemalloc 5.3.0 from the GitHub Release tarball # --------------------------------------------------------------- # Git tag 5.3.0 only has configure.ac / Makefile.in — the generated # configure script is shipped in the release tarball exclusively. # We must pass --with-jemalloc-prefix=_rjem_ (tikv-jemallocator expects # _rjem_malloc symbols) and rename the MinGW .lib to the expected name. - name: Build jemalloc 5.3.0 from release tarball if: steps.jemalloc-cache.outputs.cache-hit != 'true' shell: msys2 {0} run: | set -eux PREFIX="$(cygpath -u "$GITHUB_WORKSPACE")/.jemalloc-prefix" curl -fsSL https://github.com/jemalloc/jemalloc/releases/download/5.3.0/jemalloc-5.3.0.tar.bz2 \ -o /tmp/jemalloc.tar.bz2 mkdir -p /tmp/jemalloc-build "$PREFIX/lib" tar -xf /tmp/jemalloc.tar.bz2 -C /tmp/jemalloc-build --strip-components=1 cd /tmp/jemalloc-build # config.sub from 2021 doesn't know win32* (MSYS2's build triple) sed -i 's/^\tmingw32\* | mingw64\*/\tmingw32* | mingw64* | win32*/' build-aux/config.sub ./configure --host=x86_64-w64-mingw32 \ --disable-cxx --enable-shared=no \ --with-jemalloc-prefix=_rjem_ \ --with-private-namespace=_rjem_ \ --prefix="$PREFIX" make -j$(nproc) make install_lib_static install_include # MinGW → jemalloc_s.lib; rename for JEMALLOC_OVERRIDE (strips "lib") cp "$PREFIX/lib/jemalloc_s.lib" "$PREFIX/lib/libjemalloc.a" # Step 2 — create a dummy liballoc.a # ----------------------------------- # #[global_allocator] on x86_64-pc-windows-gnu causes the Rust compiler # to emit -lalloc. The alloc crate ships as .rlib only for this target # (no liballoc.a exists). An empty archive with a single object file # satisfies the flag — real symbols come from the .rlib that is already # linked statically upstream of the native-library resolution pass. # Cheap either way, so it isn't gated on the cache hit — reruns # harmlessly on a cache hit too. - name: Create dummy liballoc.a for -lalloc linker flag shell: msys2 {0} run: | set -eux PREFIX="$(cygpath -u "$GITHUB_WORKSPACE")/.jemalloc-prefix" printf 'void __dummy_alloc_ignore(void) {}\n' | \ gcc -xc -c - -o "$PREFIX/lib/dummy.o" ar crs "$PREFIX/lib/liballoc.a" "$PREFIX/lib/dummy.o" rm -f "$PREFIX/lib/dummy.o" # Step 3 — export Windows-native paths for subsequent build steps # ---------------------------------------------------------------- # The Rust build script is a native Windows process and cannot resolve # MSYS2 virtual paths. cygpath -w produces a proper absolute Windows # path that the native linker can open. - name: Export Windows-native paths as outputs id: set-paths shell: msys2 {0} run: | set -eux PREFIX="$(cygpath -u "$GITHUB_WORKSPACE")/.jemalloc-prefix" echo "jemalloc-override=$(cygpath -w "$PREFIX/lib/libjemalloc.a")" >> $GITHUB_OUTPUT echo "dummy-dir=$(cygpath -w "$PREFIX/lib")" >> $GITHUB_OUTPUT