diff --git a/.github/ci-windows-cross.py b/.github/ci-windows-cross.py index 01695424cc8..355d8fb78d9 100755 --- a/.github/ci-windows-cross.py +++ b/.github/ci-windows-cross.py @@ -5,6 +5,7 @@ import argparse import os +import re import shlex import subprocess import sys @@ -28,6 +29,31 @@ def print_version(): run([str(bitcoind), "-version"]) +def check_imports(): + bitcoind = Path.cwd() / "bin" / "bitcoind.exe" + output = run( + ["dumpbin.exe", "/imports", str(bitcoind)], + capture_output=True, + text=True, + ).stdout + dlls = re.findall(r"^\s*(\S+\.dll)\s*$", output, re.IGNORECASE | re.MULTILINE) + print("\n".join(dlls)) + + # Ensure the executable is linked against the expected C runtime. + dlls = {name.lower() for name in dlls} + uses_msvcrt = "msvcrt.dll" in dlls + uses_ucrt = any(name.startswith("api-ms-win-crt-") for name in dlls) + crt = os.environ["CRT"] + if crt == "msvcrt": + crt_ok = uses_msvcrt and not uses_ucrt + elif crt == "ucrt": + crt_ok = uses_ucrt and not uses_msvcrt + else: + sys.exit(f"Unexpected CRT value: {crt!r}") + if not crt_ok: + sys.exit(f"Imported DLLs do not match the expected {crt!r} C runtime.") + + def check_manifests(): release_dir = Path.cwd() / "bin" manifest_path = release_dir / "bitcoind.manifest" @@ -143,6 +169,7 @@ def main(): parser = argparse.ArgumentParser(description="Utility to run Windows CI steps.") steps = list(map(lambda f: f.__name__, [ print_version, + check_imports, check_manifests, prepare_tests, run_unit_tests, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bce9c6038b3..d8d48eecb35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -403,6 +403,11 @@ jobs: - *IMPORT_VS_ENV + - name: Check imported DLLs + env: + CRT: ${{ matrix.crt }} + run: py -3 .github/ci-windows-cross.py check_imports + - name: Check executable manifests run: py -3 .github/ci-windows-cross.py check_manifests