xref: /aosp_15_r20/external/skia/gn/bazel_build.py (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*c8dee2aaSAndroid Build Coastguard Worker#
3*c8dee2aaSAndroid Build Coastguard Worker# Copyright 2023 Google LLC
4*c8dee2aaSAndroid Build Coastguard Worker#
5*c8dee2aaSAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
6*c8dee2aaSAndroid Build Coastguard Worker# found in the LICENSE file.
7*c8dee2aaSAndroid Build Coastguard Worker#
8*c8dee2aaSAndroid Build Coastguard Worker# This script runs bazel build [target] [additional_arg] [additional_arg]
9*c8dee2aaSAndroid Build Coastguard Worker# and then copies each of the specified outputs from the bazel-bin output
10*c8dee2aaSAndroid Build Coastguard Worker# folder under the current working directory. This allows GN to shell out
11*c8dee2aaSAndroid Build Coastguard Worker# to Bazel to generate or compile files, but still have them show up where
12*c8dee2aaSAndroid Build Coastguard Worker# GN expects (in the output folder).
13*c8dee2aaSAndroid Build Coastguard Worker#
14*c8dee2aaSAndroid Build Coastguard Worker# The first argument passed in to this script is the Bazel target.
15*c8dee2aaSAndroid Build Coastguard Worker# subsequent arguments are treated either as Bazel flags (if they start with
16*c8dee2aaSAndroid Build Coastguard Worker# --) or output files to copy (if they do not).
17*c8dee2aaSAndroid Build Coastguard Worker#
18*c8dee2aaSAndroid Build Coastguard Worker# Output files may contain an equals sign (=), which means the first part is
19*c8dee2aaSAndroid Build Coastguard Worker# the Bazel file to copy and the second part is where to copy it. If omitted,
20*c8dee2aaSAndroid Build Coastguard Worker# the file will go immediately under the GN output directory.
21*c8dee2aaSAndroid Build Coastguard Worker
22*c8dee2aaSAndroid Build Coastguard Workerimport hashlib
23*c8dee2aaSAndroid Build Coastguard Workerimport os
24*c8dee2aaSAndroid Build Coastguard Workerimport shutil
25*c8dee2aaSAndroid Build Coastguard Workerimport subprocess
26*c8dee2aaSAndroid Build Coastguard Workerimport sys
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard Workertarget = sys.argv[1]
29*c8dee2aaSAndroid Build Coastguard Workeroutputs = {}
30*c8dee2aaSAndroid Build Coastguard Workerbazel_args = []
31*c8dee2aaSAndroid Build Coastguard Workerfor arg in sys.argv[2:]:
32*c8dee2aaSAndroid Build Coastguard Worker    if arg.startswith("--"):
33*c8dee2aaSAndroid Build Coastguard Worker        bazel_args.append(arg)
34*c8dee2aaSAndroid Build Coastguard Worker    else:
35*c8dee2aaSAndroid Build Coastguard Worker        if "=" in arg:
36*c8dee2aaSAndroid Build Coastguard Worker            # "../../bazel-bin/src/ports/ffi.h=src/core/ffi.h" means to
37*c8dee2aaSAndroid Build Coastguard Worker            # copy ../../bazel-bin/src/ports/ffi.h to
38*c8dee2aaSAndroid Build Coastguard Worker            # $GN_OUTPUT/src/core/ffi.h
39*c8dee2aaSAndroid Build Coastguard Worker            bazel_file, output_path = arg.split("=")
40*c8dee2aaSAndroid Build Coastguard Worker            outputs[bazel_file] = output_path
41*c8dee2aaSAndroid Build Coastguard Worker        else:
42*c8dee2aaSAndroid Build Coastguard Worker            # "../../bazel-bin/src/ports/libstuff.a" means to copy
43*c8dee2aaSAndroid Build Coastguard Worker            # ../../bazel-bin/src/ports/libstuff.a to
44*c8dee2aaSAndroid Build Coastguard Worker            # $GN_OUTPUT/libstuff.a
45*c8dee2aaSAndroid Build Coastguard Worker            outputs[arg] = os.path.basename(arg)
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Workerprint("Invoking bazelisk from ", os.getcwd())
48*c8dee2aaSAndroid Build Coastguard Worker# Forward the remaining args to the bazel invocation
49*c8dee2aaSAndroid Build Coastguard Workersubprocess.run(["bazelisk", "build", target ] + bazel_args, check=True)
50*c8dee2aaSAndroid Build Coastguard Worker
51*c8dee2aaSAndroid Build Coastguard Workerfor bazel_file, output_path in outputs.items():
52*c8dee2aaSAndroid Build Coastguard Worker    # GN expects files to be created underneath the output directory from which
53*c8dee2aaSAndroid Build Coastguard Worker    # this script is invoked.
54*c8dee2aaSAndroid Build Coastguard Worker    expected_output = os.path.join(os.getcwd(), output_path)
55*c8dee2aaSAndroid Build Coastguard Worker    if not os.path.exists(expected_output):
56*c8dee2aaSAndroid Build Coastguard Worker        shutil.copyfile(bazel_file, expected_output)
57*c8dee2aaSAndroid Build Coastguard Worker        os.chmod(expected_output, 0o755)
58*c8dee2aaSAndroid Build Coastguard Worker    else:
59*c8dee2aaSAndroid Build Coastguard Worker        # GN uses timestamps to determine if it should re-build a file. If the
60*c8dee2aaSAndroid Build Coastguard Worker        # two files match (via hash) we should not re-copy the output, which would
61*c8dee2aaSAndroid Build Coastguard Worker        # re-trigger subsequent rebuilds.
62*c8dee2aaSAndroid Build Coastguard Worker        created_hash = hashlib.sha256(open(bazel_file, 'rb').read()).hexdigest()
63*c8dee2aaSAndroid Build Coastguard Worker        existing_hash = hashlib.sha256(open(expected_output, 'rb').read()).hexdigest()
64*c8dee2aaSAndroid Build Coastguard Worker        if created_hash != existing_hash:
65*c8dee2aaSAndroid Build Coastguard Worker            os.remove(expected_output)
66*c8dee2aaSAndroid Build Coastguard Worker            shutil.copyfile(bazel_file, expected_output)
67*c8dee2aaSAndroid Build Coastguard Worker            os.chmod(expected_output, 0o755)
68