diff --git a/.github/actions/install-msys2-mrbind/action.yml b/.github/actions/install-msys2-mrbind/action.yml deleted file mode 100644 index f7fecbfa42ff..000000000000 --- a/.github/actions/install-msys2-mrbind/action.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: 'Install MSYS2 for MRBind' -description: 'Download the MeshLib MSYS2 archive from S3 with retry on transient failures and extract to C:\' -runs: - using: 'composite' - steps: - - name: Install MSYS2 for MRBind - shell: pwsh - run: | - # Retry the S3 fetch -- transient 404 / connection blips have been - # observed against vcpkg-export.s3.us-east-1.amazonaws.com. - $url = "https://vcpkg-export.s3.us-east-1.amazonaws.com/msys64_meshlib_mrbind.zip" - $dest = "./msys64_meshlib_mrbind.zip" - $maxAttempts = 5 - $delay = 10 - for ($i = 1; $i -le $maxAttempts; $i++) { - try { - (New-Object Net.WebClient).DownloadFile($url, $dest) - break - } catch { - if ($i -eq $maxAttempts) { throw } - Write-Host "Download attempt $i failed: $($_.Exception.Message). Retrying in $delay s..." - Start-Sleep -Seconds $delay - $delay *= 2 - } - } - [IO.Compression.ZipFile]::ExtractToDirectory($dest, "C:\") - rm $dest diff --git a/.github/workflows/build-test-windows.yml b/.github/workflows/build-test-windows.yml index 76bf97c38cdc..dd454b42a973 100644 --- a/.github/workflows/build-test-windows.yml +++ b/.github/workflows/build-test-windows.yml @@ -138,23 +138,67 @@ jobs: with: dotnet-version: '8.0.x' - - name: Install MSYS2 for MRBind + - name: Cache pinned MSYS2 packages + # Avoid re-downloading the ~700 MB of 47 .pkg.tar.zst files on every + # run. Cache key tracks the lockfile so any URL/hash bump invalidates. + # The download script uses `wget -nc`, so a cache hit lets it skip + # every file without contacting the server; the install script's + # sha256 verify is the safety net. if: ${{inputs.mrbind || (inputs.mrbind_c && matrix.build_system == 'CMake') || env.BUILD_C_SHARP == 'true'}} - uses: ./.github/actions/install-msys2-mrbind + uses: actions/cache@v5 + with: + path: scripts/mrbind/msys2_packages + key: msys2-mrbind-clang18-${{ hashFiles('scripts/mrbind/msys2_package_hashes_clang18.txt') }} + + - name: Install MRBind toolchain (clang 18.1.8 pinned) into runner MSYS2 + # mrbind's bindings regressed when generated with clang >= ~22 (lost + # the std_vector_const_Mesh registration; surfaces as + # `ImportError: initialization failed` from MRTest's embedded-python + # smoke test). Pin the WHOLE mingw/clang64 toolchain to the era of + # clang 18.1.8-2 — the version the historical + # msys64_meshlib_mrbind.zip bundle shipped, with matching + # crt-git/headers-git/libwinpthread-git/libc++/cmake/ninja from + # late 2024. + # + # Pinning only the clang/llvm packages doesn't work: clang 18's + # cc.exe fails to load (STATUS_DLL_NOT_FOUND, exit 127) when the + # rest of the runtime is at current versions. The pinned URL list + # is in scripts/mrbind/msys2_package_urls_clang18.txt with + # corresponding sha256s in msys2_package_hashes_clang18.txt — bump + # both when MeshLib is ready to move off clang 18. + if: ${{inputs.mrbind || (inputs.mrbind_c && matrix.build_system == 'CMake') || env.BUILD_C_SHARP == 'true'}} + shell: pwsh + run: | + # Download the pinned 18-era set (47 packages) and pacman -U the + # whole thing in one transaction so dep resolution is internally + # consistent — none of these packages knows about the newer + # cc-libs marker, and all transitively pinned to matching + # libwinpthread-git/crt-git/headers-git revisions, so there are + # no version skews. The install script verifies sha256s before + # invoking pacman. `-here` keeps the workflow's checkout dir as + # the shell's cwd so the relative `scripts/mrbind/...` paths + # resolve. We don't `pacman -Sy` first: `pacman -U` operates on + # local files and only needs the runner's preinstalled DB to + # exist (it does, even unsynced). + C:\msys64\msys2_shell.cmd -no-start -defterm -here -c "set -e && bash scripts/mrbind/msys2_download_packages.sh _clang18 && bash scripts/mrbind/msys2_install_packages.sh _clang18" - name: Install gettext utilities if: ${{ inputs.upload_artifacts }} run: | - C:\msys64_meshlib_mrbind\msys2_shell.cmd -clang64 -defterm -no-start -c "pacman -S --noconfirm --needed mingw-w64-clang-x86_64-gettext-tools" + C:\msys64\msys2_shell.cmd -clang64 -defterm -no-start -c "pacman -S --noconfirm --needed mingw-w64-clang-x86_64-gettext-tools" - name: Build MRBind if: ${{inputs.mrbind || (inputs.mrbind_c && matrix.build_system == 'CMake') || env.BUILD_C_SHARP == 'true'}} shell: cmd + env: + MSYS2_DIR: C:\msys64 run: call ./scripts/mrbind/install_mrbind_windows_msys2.bat - name: Generate C bindings if: ${{ (inputs.mrbind_c && matrix.build_system == 'CMake') || env.BUILD_C_SHARP == 'true' }} shell: cmd + env: + MSYS2_DIR: C:\msys64 # Note that `\` doesn't work here as a line continuation, and will lead to weird errors. run: | call "${{matrix.vc-path}}\Common7\Tools\VsDevCmd.bat" -arch=amd64 ${{ fromJSON('["", "-vcvars_ver=14.2"]')[matrix.cxx_compiler == 'msvc-2019'] }} @@ -164,6 +208,8 @@ jobs: - name: Generate C# bindings if: ${{ env.BUILD_C_SHARP == 'true' }} shell: cmd + env: + MSYS2_DIR: C:\msys64 # Note that `\` doesn't work here as a line continuation, and will lead to weird errors. run: | call "${{matrix.vc-path}}\Common7\Tools\VsDevCmd.bat" -arch=amd64 ${{ fromJSON('["", "-vcvars_ver=14.2"]')[matrix.cxx_compiler == 'msvc-2019'] }} @@ -173,7 +219,7 @@ jobs: - name: Build shell: cmd env: - GETTEXT_ROOT: C:\msys64_meshlib_mrbind\clang64 + GETTEXT_ROOT: C:\msys64\clang64 VCPKG_ROOT: C:\vcpkg VCPKG_TARGET_TRIPLET: ${{ matrix.vcpkg_triplet }} # `|| exit /b 1` is used instead of `if errorlevel 1 exit 1` @@ -191,9 +237,71 @@ jobs: msbuild -m source\MeshLib.sln -p:Configuration=${{ matrix.config }} -p:VcpkgTriplet=%VCPKG_TARGET_TRIPLET%${{ fromJSON('["", ";PlatformToolset=v142"]')[matrix.cxx_compiler == 'msvc-2019'] }} || exit /b 1 ) + - name: PROBE — install clang++ argv-logging shim + if: ${{inputs.mrbind && matrix.vcpkg_triplet != 'x64-windows-meshlib-iterator-debug'}} + shell: pwsh + run: | + $diagBin = 'C:\diag\bin' + New-Item -ItemType Directory -Force -Path $diagBin, C:\diag | Out-Null + # Install the shim under the name `clang++` so PATH lookup picks it up. + Copy-Item -Force scripts\diag\clang-argv-shim.sh "$diagBin\clang++" + # Strip CRLF the shim file may have been checked out with (shebang + # parsing fails on `#!/bin/bash`), and `chmod +x`. + C:\msys64\msys2_shell.cmd -no-start -defterm -here -c "set -e && tr -d '\r' < /c/diag/bin/clang++ > /tmp/shim && mv /tmp/shim /c/diag/bin/clang++ && chmod +x /c/diag/bin/clang++ && head -1 /c/diag/bin/clang++ && ls -la /c/diag/bin/" + + - name: PROBE — Generate Python bindings under clang shim (expected to FAIL with macro mismatch) + if: ${{inputs.mrbind && matrix.vcpkg_triplet != 'x64-windows-meshlib-iterator-debug'}} + shell: cmd + env: + MSYS2_DIR: C:\msys64 + continue-on-error: true + # We bypass generate_win.bat so we can inject `/c/diag/bin` first on + # PATH — make's recipes invoke `clang++` which then resolves to our + # shim, which logs argv (text + hex) before exec'ing the real + # `/c/msys64/clang64/bin/clang++.exe`. + run: | + call "${{matrix.vc-path}}\Common7\Tools\VsDevCmd.bat" -arch=amd64 ${{ fromJSON('["", "-vcvars_ver=14.2"]')[matrix.cxx_compiler == 'msvc-2019'] }} + call C:\msys64\msys2_shell.cmd -no-start -defterm -full-path -here -clang64 -c "export PATH=/c/diag/bin:$PATH && which clang++ && time make -f scripts/mrbind/generate.mk MODE=none -B --trace VS_MODE=${{matrix.config}}" + + - name: PROBE — dump tool versions and clang argv log + if: ${{ inputs.mrbind && matrix.vcpkg_triplet != 'x64-windows-meshlib-iterator-debug' && always() }} + shell: pwsh + run: | + Write-Host "================ Tool versions ================" + # Use -full-path so Windows-side tools (Strawberry Perl's gmake, + # chocolatey's make, etc.) are also resolvable — same setup as + # the actual mrbind build. Inline bash got mangled by PowerShell + # escaping last attempt, so dispatch to a checked-in script. + C:\msys64\msys2_shell.cmd -no-start -defterm -full-path -here -clang64 -c "tr -d '\r' < scripts/diag/dump-toolchain-versions.sh > /tmp/dump.sh && bash /tmp/dump.sh" + + $log = 'C:\diag\clang-argv.log' + Write-Host "" + Write-Host "================ clang argv log: $log ================" + if (-not (Test-Path $log)) { + Write-Host " (not produced — shim never invoked)" + return + } + Write-Host "Size: $((Get-Item $log).Length) bytes" + Write-Host "" + Write-Host "---- INVOCATIONS that mention MB_PB11_ADJUST_NAMES ----" + $content = Get-Content $log -Raw + $blocks = $content -split '====\r?\n' + foreach ($b in $blocks) { + if (-not ($b -match 'MB_PB11_ADJUST_NAMES')) { continue } + # Filter to compilations of interest (PCH source, fragments, aliases, helpers). + if (-not ($b -match 'combined_pch\.hpp|combined\.hpp|fragment\.[0-9]+\.o|aliases\.cpp|extra\.helpers')) { continue } + Write-Host "====" + # Print INVOCATION header + every MB_PB11_ADJUST_NAMES line + every compile-target identifier. + $b -split "`n" | Where-Object { + $_ -match 'INVOCATION|MB_PB11_ADJUST_NAMES|combined_pch\.hpp|combined\.hpp|fragment\.[0-9]+\.o|aliases\.cpp|extra\.helpers|-xc\+\+-header' + } | ForEach-Object { Write-Host $_ } + } + - name: Generate and build Python bindings if: ${{inputs.mrbind && matrix.vcpkg_triplet != 'x64-windows-meshlib-iterator-debug'}} shell: cmd + env: + MSYS2_DIR: C:\msys64 # Note that `\` doesn't work here as a line continuation, and will lead to weird errors. run: | call "${{matrix.vc-path}}\Common7\Tools\VsDevCmd.bat" -arch=amd64 ${{ fromJSON('["", "-vcvars_ver=14.2"]')[matrix.cxx_compiler == 'msvc-2019'] }} @@ -241,6 +349,101 @@ jobs: timeout-minutes: 10 run: source\x64\${{ matrix.config }}\MRTest.exe + - name: Diagnostic — Python bindings post-Unit-Tests + # Fires regardless of Unit Tests outcome to capture state when + # MRTest's embedded-python smoke test trips + # `ImportError: initialization failed` (see PR discussion). + # Shows: which .pyd were built, what they export and link to, + # what python.dll MREmbeddedPython.dll resolves, what a + # standalone py -3.12 import does (real traceback instead of + # CPython's wrapped "initialization failed"). + if: ${{ always() }} + shell: pwsh + continue-on-error: true + run: | + $cfg = '${{ matrix.config }}' + $buildDir = Join-Path $Env:GITHUB_WORKSPACE "source\x64\$cfg" + $meshlib = Join-Path $buildDir 'meshlib' + + Write-Host "=== build dir top-level (DLL/PYD/EXE) ===" + if (-not (Test-Path $buildDir)) { Write-Host "MISSING: $buildDir"; exit 0 } + Get-ChildItem $buildDir -File | Where-Object { $_.Name -match '\.(dll|pyd|exe)$' } | Sort-Object Name | Format-Table Name, Length -AutoSize | Out-String -Width 200 + + Write-Host "=== meshlib/ contents ===" + if (Test-Path $meshlib) { + Get-ChildItem $meshlib -Recurse | Sort-Object FullName | Format-Table FullName, Length -AutoSize | Out-String -Width 200 + } else { Write-Host "MISSING: $meshlib" } + + $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + $vs = & $vswhere -latest -property installationPath + $dumpbin = Get-ChildItem -Path "$vs\VC\Tools\MSVC" -Recurse -Filter dumpbin.exe -ErrorAction SilentlyContinue | + Where-Object { $_.FullName -like "*Hostx64\x64*" } | Select-Object -First 1 -ExpandProperty FullName + Write-Host "dumpbin: $dumpbin" + + function Inspect($path) { + if (-not (Test-Path $path)) { Write-Host "MISSING: $path"; return } + Write-Host "" + Write-Host "--- $path ---" + Write-Host "[PyInit_* exports]" + & $dumpbin /exports $path 2>&1 | Select-String -Pattern 'PyInit_' | ForEach-Object { Write-Host $_.Line } + Write-Host "[dependents (python/MR/msvcp/VCRUNTIME/api-ms-win-crt)]" + & $dumpbin /dependents $path 2>&1 | Select-String -Pattern 'python|^\s*MR|msvcp|VCRUNTIME|api-ms-win-crt' | ForEach-Object { Write-Host $_.Line } + } + + Inspect (Join-Path $buildDir 'MRTest.exe') + Inspect (Join-Path $buildDir 'MREmbeddedPython.dll') + Inspect (Join-Path $buildDir 'MRPython.dll') + foreach ($p in @('mrmeshpy.pyd','mrviewerpy.pyd','mrmeshnumpypy.pyd','mrcudapy.pyd')) { + Inspect (Join-Path $meshlib $p) + } + + Write-Host "" + Write-Host "=== py launcher inventory ===" + & py -0p 2>&1 + + Write-Host "" + Write-Host "=== standalone import attempt (py -3.12) ===" + Push-Location $buildDir + try { + $env:PYTHONPATH = $buildDir + & py -3.12 -c @" + import sys, os + print('python:', sys.version) + print('exe:', sys.executable) + print('prefix:', sys.prefix) + print('PYTHONPATH:', os.environ.get('PYTHONPATH')) + print('---') + try: + import meshlib + print('meshlib OK at', meshlib.__file__) + except BaseException as e: + import traceback + traceback.print_exc() + sys.exit(2) + try: + import meshlib.mrmeshpy as m + print('mrmeshpy OK at', m.__file__) + except BaseException as e: + import traceback + traceback.print_exc() + sys.exit(3) + "@ + Write-Host "exit code: $LASTEXITCODE" + } finally { Pop-Location } + + Write-Host "" + Write-Host "=== vcpkg python.dll(s) ===" + foreach ($d in @('C:\vcpkg\installed\x64-windows-meshlib\bin', 'C:\vcpkg\installed\x64-windows-meshlib\debug\bin')) { + if (Test-Path $d) { + Get-ChildItem $d -Filter 'python*.dll' -ErrorAction SilentlyContinue | Format-Table FullName, Length -AutoSize | Out-String -Width 200 + } + } + + Write-Host "" + Write-Host "=== where.exe python3.dll / python312.dll ===" + where.exe python3.dll 2>&1 + where.exe python312.dll 2>&1 + - name: C Unit Tests if: ${{inputs.mrbind_c && matrix.build_system == 'CMake'}} timeout-minutes: 10 diff --git a/.github/workflows/pip-build.yml b/.github/workflows/pip-build.yml index 8279be0b944e..1ab99a6dfabe 100644 --- a/.github/workflows/pip-build.yml +++ b/.github/workflows/pip-build.yml @@ -307,15 +307,23 @@ jobs: - name: Build run: msbuild -m source\MeshLib.sln -p:Configuration=Release - - name: Install MSYS2 for MRBind - uses: ./.github/actions/install-msys2-mrbind + - name: Install MRBind toolchain (clang 18.1.8 pinned) into runner MSYS2 + # See build-test-windows.yml's matching step for rationale. + shell: pwsh + run: | + C:\msys64\msys2_shell.cmd -no-start -defterm -here -c "set -e && pacman -Sy --noconfirm" + C:\msys64\msys2_shell.cmd -no-start -defterm -here -c "set -e && bash scripts/mrbind/msys2_download_packages.sh _clang18 && bash scripts/mrbind/msys2_install_packages.sh _clang18" - name: Build MRBind shell: cmd + env: + MSYS2_DIR: C:\msys64 run: call ./scripts/mrbind/install_mrbind_windows_msys2.bat - name: Generate and build MRBind bindings shell: cmd + env: + MSYS2_DIR: C:\msys64 run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=amd64 call ./scripts/mrbind/generate_win.bat -B --trace FOR_WHEEL=1 diff --git a/scripts/diag/clang-argv-shim.sh b/scripts/diag/clang-argv-shim.sh new file mode 100644 index 000000000000..e8523e1b8bc1 --- /dev/null +++ b/scripts/diag/clang-argv-shim.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Diagnostic shim for clang++. Logs every argv element (text + hex) to +# `$DIAG_LOG_DIR/clang-argv.log`, then exec's the real clang++. +# Used to capture exactly what bash passes to clang during the +# MB_PB11_ADJUST_NAMES PCH ↔ fragment macro-mismatch investigation. + +LOG_DIR="${DIAG_LOG_DIR:-/c/diag}" +mkdir -p "$LOG_DIR" +LOG="$LOG_DIR/clang-argv.log" + +{ + printf '====\nINVOCATION pid=%d ppid=%d argc=%d cwd=%s\n' "$$" "$PPID" "$#" "$(pwd)" + i=0 + for a in "$@"; do + printf 'ARGV[%d]_TEXT: %s\n' "$i" "$a" + printf 'ARGV[%d]_HEX: ' "$i" + printf '%s' "$a" | od -An -tx1 | tr -d ' \n' + printf '\n' + i=$((i+1)) + done +} >> "$LOG" + +exec /c/msys64/clang64/bin/clang++.exe "$@" diff --git a/scripts/diag/diag-bash-shim.sh b/scripts/diag/diag-bash-shim.sh new file mode 100644 index 000000000000..52ef53d3074f --- /dev/null +++ b/scripts/diag/diag-bash-shim.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Diagnostic shim for bash, used as `make SHELL=...`. Logs every argv +# element (text + hex) to `$DIAG_LOG_DIR/shell-recipes.log`, then +# exec's the real bash. Captures the recipe text make passes to bash +# (pre-quote-stripping) so we can compare it against what clang +# actually receives via the clang shim (post-quote-stripping). + +LOG_DIR="${DIAG_LOG_DIR:-/c/diag}" +mkdir -p "$LOG_DIR" +LOG="$LOG_DIR/shell-recipes.log" + +{ + printf '====\nBASH_INVOCATION pid=%d ppid=%d argc=%d\n' "$$" "$PPID" "$#" + i=0 + for a in "$@"; do + printf 'ARG[%d]_TEXT: %s\n' "$i" "$a" + printf 'ARG[%d]_HEX: ' "$i" + printf '%s' "$a" | od -An -tx1 | tr -d ' \n' + printf '\n' + i=$((i+1)) + done +} >> "$LOG" + +exec /usr/bin/bash "$@" diff --git a/scripts/diag/dump-toolchain-versions.sh b/scripts/diag/dump-toolchain-versions.sh new file mode 100644 index 000000000000..6a1f529a3f7c --- /dev/null +++ b/scripts/diag/dump-toolchain-versions.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Dump versions and binary paths of the toolchain components that are +# implicated in the MB_PB11_ADJUST_NAMES PCH/fragment macro-mismatch +# investigation. Run from inside an MSYS2 -clang64 -full-path shell so +# both Windows-side and MSYS2-side tools resolve the same way the +# actual mrbind build does. +set -uo pipefail + +print_section() { + printf '\n== %s ==\n' "$1" +} + +print_tool() { + local cmd=$1 + printf ' which: '; which "$cmd" 2>&1 || true + printf ' ver: '; "$cmd" --version 2>&1 | head -1 || true +} + +print_pacman() { + local pkg=$1 + printf ' %s: ' "$pkg" + if out=$(pacman -Qi "$pkg" 2>/dev/null); then + printf '%s\n' "$out" | awk -F': ' '/^(Name|Version)/{printf "%s=%s ", $1, $2} END{print ""}' + else + printf '(not from pacman)\n' + fi +} + +print_section bash +print_tool bash +print_section make +print_tool make +print_section clang++ +print_tool clang++ +print_section uname +uname -a + +print_section "pacman -Qi (runner's MSYS2 base packages)" +for p in make bash coreutils msys2-runtime ; do + print_pacman "$p" +done diff --git a/scripts/mrbind/README-generating.md b/scripts/mrbind/README-generating.md index 7fb204e4bc12..1fca55ce1b5f 100644 --- a/scripts/mrbind/README-generating.md +++ b/scripts/mrbind/README-generating.md @@ -196,6 +196,12 @@ The resulting Python modules are created next to the MeshLib shared libraries, i * This seems to be a VS2022 bug that's triggered by trying to bind `operator<=>` (taking its address?). We work around this by banning all `operator<=>`s with `--ignore`, see `mrbind_flags.txt`. +* **`ImportError: generic_type: cannot initialize type "...": an object with that name is already defined`** + + * Likely an MRBind bug. Set env variable `MRBIND_DEBUG=3` before importing, and use the logs to determine which two C++ types compete for the same Python type name. + + Then you probably need to fix the `ToPythonName()` function in MRBind to correctly disambiguate the names. + ## 3.2. Generate C bindings Running our script generates the code for the bindings, at `source/MeshLibC2` and `source/MeshLibC2Cuda`. diff --git a/scripts/mrbind/README-updating-clang.md b/scripts/mrbind/README-updating-clang.md index 9fe429f5e617..7804a36dd704 100644 --- a/scripts/mrbind/README-updating-clang.md +++ b/scripts/mrbind/README-updating-clang.md @@ -15,13 +15,3 @@ Perform a fresh MSYS2 installation, open the MSYS2 terminal (run `msys2.exe` in Commit the modified files to Git: `scripts/mrbind/msys2_package_{urls,hashes}.txt`. Running that script downloads some files to `scripts/mrbind/msys2_packages`. You can either delete them to save space, or archive them somewhere in case they stop being available for download. - -Also zip and upload this MSYS2 installation to S3, for our CI to download: - -* Run `pacman -Scc` to clean the package manager cache, reducing the size of the installation. - -* Rename the installation directory to `msys64_meshlib_mrbind`. - -* Zip it into a `.zip`. The archive must contain the installation directory, so e.g. it should contain `msys64_meshlib_mrbind/msys2.exe`. - -* Upload the zip to S3 in place of the old one: https://vcpkg-export.s3.us-east-1.amazonaws.com/msys64_meshlib_mrbind.zip diff --git a/scripts/mrbind/generate.mk b/scripts/mrbind/generate.mk index 839860fce598..f6de8defc70b 100644 --- a/scripts/mrbind/generate.mk +++ b/scripts/mrbind/generate.mk @@ -755,6 +755,7 @@ $($1__CombinedHeaderOutput): $($1__InputFiles) | $(TEMP_OUTPUT_DIR) $$(foreach f,$($1__InputFiles),$$(file >>$$@,#include "$$f"$$(lf))) $(call,### Additional headers to bake into the PCH. The condition is to speed up parsing a bit.) $(if $(is_py),\ + $(call,### PROBE: this branch reverts the MB_PB11_ADJUST_NAMES PCH-source-include fix to reproduce the macro-mismatch error and capture diagnostics around it.)\ $$(if $($1_PyEnablePch),$$(file >>$$@,#ifndef MR_PARSING_FOR_PB11_BINDINGS$$(lf)#include $$(lf)#endif))\ $(call,### This alternative version bakes the whole our `core.h` [which includes `], but for some reason my measurements show it to be a tiny bit slower. Weird.)\ $(call,### #ifndef MR_PARSING_FOR_PB11_BINDINGS$(lf)#define MB_PB11_STAGE -1$(lf)#include MRBIND_HEADER$(lf)#undef MB_PB11_STAGE$(lf)#endif$(lf))\ diff --git a/scripts/mrbind/generate_win.bat b/scripts/mrbind/generate_win.bat index 98ad293dfa98..3fcb911b39b5 100644 --- a/scripts/mrbind/generate_win.bat +++ b/scripts/mrbind/generate_win.bat @@ -15,7 +15,8 @@ set args=%* if not exist %MSYS2_DIR% ( echo MSYS2 was NOT found at `%MSYS2_DIR%`. Run `install_deps_windows_msys2.bat` to build it. -) else ( - echo Found MSYS2 at `%MSYS2_DIR%`. - call %MSYS2_DIR%\msys2_shell.cmd -no-start -defterm -full-path -here -clang64 -c "time make -f '%~dp0generate.mk' %args:"=""% " + exit /b 1 ) + +echo Found MSYS2 at `%MSYS2_DIR%`. +call %MSYS2_DIR%\msys2_shell.cmd -no-start -defterm -full-path -here -clang64 -c "time make -f '%~dp0generate.mk' %args:"=""% " diff --git a/scripts/mrbind/mrbind_pb11_defines.h b/scripts/mrbind/mrbind_pb11_defines.h new file mode 100644 index 000000000000..cae7e37e5d30 --- /dev/null +++ b/scripts/mrbind/mrbind_pb11_defines.h @@ -0,0 +1,37 @@ +// Pulled in from the generated `.combined.hpp` (see the recipe +// in `generate.mk`) so that preprocessor macros whose values are string +// literals containing backslashes (most notably `MB_PB11_ADJUST_NAMES`, +// whose value `"s/\\bMR:::/g"` carries a regex word-boundary `\b`) +// reach clang as C source rather than as a `-D` flag. +// +// Routing such values through the make+bash recipe pipeline is fragile: +// on some MSYS2 environments (confirmed: the runner's preinstalled +// `C:\msys64`) the value reaches clang's PCH-build and per-fragment +// compile inconsistently, producing +// error: definition of macro 'MB_PB11_ADJUST_NAMES' differs between +// the precompiled header ('"s/\bMR:://g"') and the command line +// ('"s/\\bMR:://g"') +// The same clang 18.1.8 + same `-D` flag works correctly on master's +// frozen S3 MSYS2 snapshot, so the trigger is something in newer +// bash/make/coreutils — the exact tool wasn't pinpointed (make's +// `--trace` echoes identical bytes from both recipes, but those bytes +// are evidently processed asymmetrically downstream before reaching +// clang). +// +// Defining the macro inside the PCH source eliminates the round-trip: +// clang stores and validates the same C-source spelling on both ends. +// +// Not routed via `-include`: clang requires the PCH-import `-include` +// to be the first one on the command line, and adding any other +// `-include` would push it out of first position and silently disable +// the PCH. +// +// The recipe wraps the `#include` in `#ifndef MR_PARSING_FOR_PB11_BINDINGS` +// so the mrbind parser pass — which doesn't have `scripts/mrbind/` on +// its include path and doesn't need this macro anyway — skips it. + +#pragma once + +#ifndef MB_PB11_ADJUST_NAMES +#define MB_PB11_ADJUST_NAMES "s/\\bMR:://g" +#endif diff --git a/scripts/mrbind/msys2_download_packages.sh b/scripts/mrbind/msys2_download_packages.sh index 50ee702c239a..d03b92db0c30 100644 --- a/scripts/mrbind/msys2_download_packages.sh +++ b/scripts/mrbind/msys2_download_packages.sh @@ -1,5 +1,17 @@ #!/bin/bash +# Usage: msys2_download_packages.sh [SUFFIX] +# +# Downloads URLs from `msys2_package_urls.txt` (default suffix `''`) +# into `msys2_packages/`. Pass a suffix like `_clang18` to use the alternate +# lockfile `msys2_package_urls_clang18.txt`. set -euo pipefail cd "$(dirname "$BASH_SOURCE")" -echo 'Downloading packages. This can take a while...' -wget -P msys2_packages -i msys2_package_urls.txt -q --show-progress -c +SUFFIX="${1:-}" +URL_FILE="msys2_package_urls${SUFFIX}.txt" +echo "Downloading packages from ${URL_FILE}. This can take a while..." +# `-nc` (no-clobber) skips files already present locally without making a +# network call — the dominant case once the GitHub Actions cache is warm. +# A pinned lockfile means filenames already on disk are never stale. +# Partial / corrupt files are caught by the sha256 verify in +# msys2_install_packages.sh; the cure is invalidating the cache. +wget -P msys2_packages -i "${URL_FILE}" -q --show-progress -nc diff --git a/scripts/mrbind/msys2_install_packages.sh b/scripts/mrbind/msys2_install_packages.sh index 1931c326c4f8..f644588b5ce0 100644 --- a/scripts/mrbind/msys2_install_packages.sh +++ b/scripts/mrbind/msys2_install_packages.sh @@ -1,11 +1,24 @@ #!/bin/bash +# Usage: msys2_install_packages.sh [SUFFIX] +# +# Verifies sha256s and `pacman -U`s the packages listed in +# `msys2_package_hashes.txt` (default suffix `''`). Pass a suffix +# like `_clang18` to use the alternate lockfile +# `msys2_package_hashes_clang18.txt`. set -euo pipefail cd "$(dirname "$BASH_SOURCE")" -sha256sum -c msys2_package_hashes.txt +SUFFIX="${1:-}" +HASH_FILE="msys2_package_hashes${SUFFIX}.txt" -mapfile -t ENTRIES