| #!/usr/bin/env python3 | |
| # Copyright 2026 The IREE Authors | |
| # | |
| # Licensed under the Apache License v2.0 with LLVM Exceptions. | |
| # See https://llvm.org/LICENSE.txt for license information. | |
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| """Emits a header with a hash of the plugin API headers. | |
| This is the single compatibility ID for the entry-point layout, registration | |
| contract, and selected C++ API headers. There is no manual version to bump. | |
| Only the listed IREE headers are hashed. This is not a full ABI fingerprint: | |
| plugins must use the compiler's LLVM/MLIR revision and ABI-affecting build | |
| settings. Symbol renaming isolates namespaces; it does not enforce that match. | |
| """ | |
| import argparse | |
| import hashlib | |
| import pathlib | |
| _GUARD = "IREE_COMPILER_PLUGINAPI_PLUGINABIHASH_H_" | |
| def compute_hash(paths: list[str]) -> str: | |
| digest = hashlib.sha256() | |
| for path in sorted(paths, key=lambda p: pathlib.PurePath(p).name): | |
| # Include names and lengths so moving bytes between headers changes | |
| # the hash even when the concatenated contents would be identical. | |
| for data in ( | |
| pathlib.PurePath(path).name.encode(), | |
| pathlib.Path(path).read_bytes(), | |
| ): | |
| digest.update(len(data).to_bytes(8, "big")) | |
| digest.update(data) | |
| return digest.hexdigest()[:16] | |
| def main() -> None: | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--input", action="append", required=True) | |
| parser.add_argument("--out", required=True) | |
| args = parser.parse_args() | |
| out = pathlib.Path(args.out) | |
| out.parent.mkdir(parents=True, exist_ok=True) | |
| out.write_text( | |
| "// Generated by build_tools/scripts/gen_plugin_abi_hash.py.\n" | |
| f"#ifndef {_GUARD}\n" | |
| f"#define {_GUARD}\n" | |
| "\n" | |
| "#include <stdint.h>\n" | |
| "\n" | |
| f"#define IREE_COMPILER_PLUGIN_ABI_HASH UINT64_C(0x{compute_hash(args.input)})\n" | |
| "\n" | |
| f"#endif // {_GUARD}\n" | |
| ) | |
| if __name__ == "__main__": | |
| main() |