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