blob: ad0ac4814166c84dc978de6568db350bc5fad852 [file]
#!/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()