diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6cc5310..66c54e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,6 +120,7 @@ jobs: --version "${{ env.LLVM_VERSION }}" --archive "${{ matrix.llvm-archive }}" --dest /project/.llvm + --prefix-file /project/.llvm-prefix CIBW_REPAIR_WHEEL_COMMAND_LINUX: >- auditwheel repair --plat ${{ matrix.auditwheel-plat }} -w {dest_dir} {wheel} @@ -135,6 +136,7 @@ jobs: --version "${{ env.LLVM_VERSION }}" --archive "${{ matrix.llvm-archive }}" --dest "${{ github.workspace }}/.llvm" + --prefix-file "${{ github.workspace }}/.llvm-prefix" # Windows wheels are built on the hosted runner. The CMake install # step copies LLVM-C.dll next to llvm/__init__.pyd. @@ -146,6 +148,7 @@ jobs: --version "${{ env.LLVM_VERSION }}" --archive "${{ matrix.llvm-archive }}" --dest "${{ github.workspace }}\\.llvm" + --prefix-file "${{ github.workspace }}\\.llvm-prefix" - name: Check wheel metadata shell: bash diff --git a/run_tests.py b/run_tests.py index 4e20296..51ccbe6 100755 --- a/run_tests.py +++ b/run_tests.py @@ -181,9 +181,11 @@ def run_regression_tests(): # Print progress print(f"[{status}] {test_name}") - # Show error output if failed - if status == "FAIL" and stderr: - for line in stderr.splitlines()[:10]: # First 10 lines of error + # Show captured output if failed. Pytest usually writes assertion + # details to stdout, while crashes/import errors often use stderr. + if status == "FAIL": + failure_output = stderr or stdout + for line in failure_output.splitlines()[:20]: print(f" {line}") # Summary diff --git a/tests/regressions/test_ollvm_obf_semantic_parity.py b/tests/regressions/test_ollvm_obf_semantic_parity.py index 276d226..3bc69df 100644 --- a/tests/regressions/test_ollvm_obf_semantic_parity.py +++ b/tests/regressions/test_ollvm_obf_semantic_parity.py @@ -17,6 +17,7 @@ from functools import lru_cache from pathlib import Path import shutil import subprocess +import sys import textwrap import pytest @@ -478,6 +479,10 @@ def find_clang() -> Path | None: @lru_cache(maxsize=1) +def is_x86_target(target: str) -> bool: + return any(arch in target for arch in ("x86_64", "amd64", "i386", "i686")) + + def clang_target_triple(clang_exe: Path) -> str: proc = subprocess.run( [str(clang_exe), "-dumpmachine"], @@ -495,6 +500,14 @@ def clang_exe() -> Path: clang = find_clang() if clang is None: pytest.skip("clang not found in PATH; semantic parity tests require an external compiler") + + target = clang_target_triple(clang) + if sys.platform == "darwin" and not is_x86_target(target): + pytest.skip( + "semantic parity tests execute generated native code and are currently " + f"skipped on non-x86 macOS targets (got {target or 'unknown'})" + ) + return clang @@ -537,7 +550,7 @@ def test_ollvm_obf_semantic_preservation( ) -> None: if case.clang_flags: target = clang_target_triple(clang_exe) - if not any(arch in target for arch in ("x86_64", "amd64", "i386", "i686")): + if not is_x86_target(target): pytest.skip(f"{case.name} requires an x86 clang target (got {target or 'unknown'})") input_path = tmp_path / "input.ll" diff --git a/tools/ci/install_llvm.py b/tools/ci/install_llvm.py index e395e88..29da066 100644 --- a/tools/ci/install_llvm.py +++ b/tools/ci/install_llvm.py @@ -44,6 +44,11 @@ def parse_args() -> argparse.Namespace: type=Path, help="Destination LLVM root directory.", ) + parser.add_argument( + "--prefix-file", + type=Path, + help="Optional .llvm-prefix file to write with the installed LLVM root.", + ) return parser.parse_args() @@ -133,8 +138,15 @@ def main() -> int: llvm_root = find_llvm_root(extract_dir) install_tree(llvm_root, args.dest) - print(f"Installed LLVM to {args.dest}", flush=True) - llvm_config = args.dest / "bin" / ("llvm-config.exe" if os.name == "nt" else "llvm-config") + installed_root = args.dest.resolve() + installed_root_for_cmake = installed_root.as_posix() + print(f"Installed LLVM to {installed_root}", flush=True) + if args.prefix_file is not None: + args.prefix_file.parent.mkdir(parents=True, exist_ok=True) + args.prefix_file.write_text(installed_root_for_cmake + "\n", encoding="utf-8") + print(f"Wrote LLVM prefix file: {args.prefix_file}", flush=True) + + llvm_config = installed_root / "bin" / ("llvm-config.exe" if os.name == "nt" else "llvm-config") if llvm_config.exists(): version = subprocess.check_output([str(llvm_config), "--version"], text=True).strip() print(f"LLVM version: {version}", flush=True)