1# Copyright (C) 2023 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15load("@bazel_skylib//lib:paths.bzl", "paths") 16load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") 17 18def _impl(ctx): 19 target = ctx.attr.target 20 device_name = ctx.attr._device_name[BuildSettingInfo].value 21 target = target.replace("$(DeviceName)", device_name) 22 23 if paths.normalize(target) != target: 24 fail("file path must be normalized: " + target) 25 if target.startswith("/") or target.startswith("../"): 26 fail("file path must not start with / or ../: " + target) 27 28 data = { 29 "target": target, 30 "depend_on_target": ctx.attr.depend_on_target, 31 } 32 if ctx.attr.implicit_deps: 33 data["implicit_deps"] = [d.replace("$(DeviceName)", device_name) for d in ctx.attr.implicit_deps] 34 35 device_name = ctx.attr._device_name[BuildSettingInfo].value 36 37 out = ctx.actions.declare_symlink(ctx.label.name) 38 ctx.actions.symlink( 39 output = out, 40 # the bazel_sandwich: prefix signals to the mixed build handler to treat this specially 41 target_path = "bazel_sandwich:" + json.encode(data), 42 ) 43 return [ 44 DefaultInfo(files = depset([out])), 45 ] 46 47_bazel_sandwich_imported_file = rule( 48 implementation = _impl, 49 attrs = { 50 "target": attr.string( 51 mandatory = True, 52 doc = "The target of the symlink. It's a path relative to the root of the output dir " + 53 " to import. In this attribute, $(DeviceName) will be replaced with the device name " + 54 "product variable.", 55 ), 56 "depend_on_target": attr.bool( 57 default = True, 58 doc = "Whether or not a dependency should be added from the symlink to the file it's " + 59 "targeting. In most cases you want this to be true.", 60 ), 61 "implicit_deps": attr.string_list( 62 doc = "Paths to other make-generated files to use as implicit deps. This is useful " + 63 "when you want to import a folder to bazel, you can add an implicit dep on a " + 64 "stamp file that depends on all contents of the foler. In this attribute, " + 65 "$(DeviceName) will be replaced with the device name product variable.", 66 ), 67 "_device_name": attr.label( 68 default = "//build/bazel/product_config:device_name", 69 ), 70 }, 71) 72 73def bazel_sandwich_imported_file(target_compatible_with = [], **kwargs): 74 _bazel_sandwich_imported_file( 75 target_compatible_with = ["//build/bazel/platforms:mixed_builds"] + target_compatible_with, 76 **kwargs 77 ) 78