# ---------------------------------------------------------------------------
# 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:

    # 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
      shell: msys2 {0}
      run: |
        set -eux
        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 /tmp/jemalloc-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=/tmp/jemalloc-prefix
        make -j$(nproc)
        make install_lib_static install_include
        # MinGW → jemalloc_s.lib; rename for JEMALLOC_OVERRIDE (strips "lib")
        cp /tmp/jemalloc-prefix/lib/jemalloc_s.lib \
           /tmp/jemalloc-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.
    - name: Create dummy liballoc.a for -lalloc linker flag
      shell: msys2 {0}
      run: |
        set -eux
        printf 'void __dummy_alloc_ignore(void) {}\n' | \
          gcc -xc -c - -o /tmp/jemalloc-prefix/lib/dummy.o
        ar crs /tmp/jemalloc-prefix/lib/liballoc.a \
              /tmp/jemalloc-prefix/lib/dummy.o
        rm -f /tmp/jemalloc-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 (/tmp/...).  cygpath -w produces a proper
    # absolute Windows path (e.g. D:\a\_temp\msys64\tmp\...) that the
    # native linker can open.
    - name: Export Windows-native paths as outputs
      id: set-paths
      shell: msys2 {0}
      run: |
        set -eux
        echo "jemalloc-override=$(cygpath -w /tmp/jemalloc-prefix/lib/libjemalloc.a)" >> $GITHUB_OUTPUT
        echo "dummy-dir=$(cygpath -w /tmp/jemalloc-prefix/lib)" >> $GITHUB_OUTPUT
