#!/usr/bin/env python3 # # Copyright 2023 Google LLC # # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # This script runs bazel build [target] [additional_arg] [additional_arg] # and then copies each of the specified outputs from the bazel-bin output # folder under the current working directory. This allows GN to shell out # to Bazel to generate or compile files, but still have them show up where # GN expects (in the output folder). # # The first argument passed in to this script is the Bazel target. # subsequent arguments are treated either as Bazel flags (if they start with # --) or output files to copy (if they do not). # # Output files may contain an equals sign (=), which means the first part is # the Bazel file to copy and the second part is where to copy it. If omitted, # the file will go immediately under the GN output directory. import hashlib import os import shutil import subprocess import sys target = sys.argv[1] outputs = {} bazel_args = [] for arg in sys.argv[2:]: if arg.startswith("--"): bazel_args.append(arg) else: if "=" in arg: # "../../bazel-bin/src/ports/ffi.h=src/core/ffi.h" means to # copy ../../bazel-bin/src/ports/ffi.h to # $GN_OUTPUT/src/core/ffi.h bazel_file, output_path = arg.split("=") outputs[bazel_file] = output_path else: # "../../bazel-bin/src/ports/libstuff.a" means to copy # ../../bazel-bin/src/ports/libstuff.a to # $GN_OUTPUT/libstuff.a outputs[arg] = os.path.basename(arg) print("Invoking bazelisk from ", os.getcwd()) # Forward the remaining args to the bazel invocation subprocess.run(["bazelisk", "build", target ] + bazel_args, check=True) for bazel_file, output_path in outputs.items(): # GN expects files to be created underneath the output directory from which # this script is invoked. expected_output = os.path.join(os.getcwd(), output_path) if not os.path.exists(expected_output): shutil.copyfile(bazel_file, expected_output) os.chmod(expected_output, 0o755) else: # GN uses timestamps to determine if it should re-build a file. If the # two files match (via hash) we should not re-copy the output, which would # re-trigger subsequent rebuilds. created_hash = hashlib.sha256(open(bazel_file, 'rb').read()).hexdigest() existing_hash = hashlib.sha256(open(expected_output, 'rb').read()).hexdigest() if created_hash != existing_hash: os.remove(expected_output) shutil.copyfile(bazel_file, expected_output) os.chmod(expected_output, 0o755)