| #!/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) |