1# Copyright (C) 2022 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 15""" 16platform_utils.bzl defines a platform_utils rule, and several 17utility functions that accept an instance of that rule and return 18information about the target platform. One instance of the platform_utils 19rule is defined in //build/bazel/platforms:platform_utils. All rules 20that need it can depend on that target, and then call the util 21functions by doing something like `is_target_linux(ctx.attr._platform_utils)`. 22This works because child targets inherit their parent's configuration. 23""" 24 25_name_to_constraint = { 26 "_x86_constraint": "//build/bazel_common_rules/platforms/arch:x86", 27 "_x86_64_constraint": "//build/bazel_common_rules/platforms/arch:x86_64", 28 "_arm_constraint": "//build/bazel_common_rules/platforms/arch:arm", 29 "_arm64_constraint": "//build/bazel_common_rules/platforms/arch:arm64", 30 "_secondary_x86_constraint": "//build/bazel_common_rules/platforms/arch:secondary_x86", 31 "_secondary_x86_64_constraint": "//build/bazel_common_rules/platforms/arch:secondary_x86_64", 32 "_secondary_arm_constraint": "//build/bazel_common_rules/platforms/arch:secondary_arm", 33 "_secondary_arm64_constraint": "//build/bazel_common_rules/platforms/arch:secondary_arm64", 34 "_android_constraint": "//build/bazel_common_rules/platforms/os:android", 35 "_linux_constraint": "//build/bazel_common_rules/platforms/os:linux", 36 "_linux_musl_constraint": "//build/bazel_common_rules/platforms/os:linux_musl", 37 "_linux_bionic_constraint": "//build/bazel_common_rules/platforms/os:linux_bionic", 38 "_darwin_constraint": "//build/bazel_common_rules/platforms/os:darwin", 39} 40 41_AndroidPlatformUtilsInfo = provider( 42 "_AndroidPlatformUtilsInfo exports metadata about what platform the code is being run on.", 43 fields = { 44 "target" + name: "Whether the target platform has the constraint %s" % constraint 45 for name, constraint in _name_to_constraint.items() 46 }, 47) 48 49def _platform_utils_impl(ctx): 50 return [ 51 _AndroidPlatformUtilsInfo(**{ 52 "target" + name: ctx.target_platform_has_constraint(getattr(ctx.attr, name)[platform_common.ConstraintValueInfo]) 53 for name in _name_to_constraint 54 }), 55 ] 56 57platform_utils = rule( 58 implementation = _platform_utils_impl, 59 attrs = { 60 name: attr.label( 61 default = Label(constraint), 62 doc = "An internal reference to the constraint so it can be used in the rule implementation.", 63 ) 64 for name, constraint in _name_to_constraint.items() 65 }, 66) 67 68def _get_platform_info(utils): 69 if _AndroidPlatformUtilsInfo not in utils: 70 fail("Provided object was not an instance of platform_utils. " + 71 "You should depend on //build/bazel/platforms:platform_utils and then pass " + 72 "ctx.attr._platform_utils to this function.") 73 return utils[_AndroidPlatformUtilsInfo] 74 75def _is_target_linux(utils): 76 """Returns if the target platform is linux with any variation of libc.""" 77 platforminfo = _get_platform_info(utils) 78 return (platforminfo.target_linux_constraint or 79 platforminfo.target_linux_musl_constraint or 80 platforminfo.target_linux_bionic_constraint) 81 82def _is_target_android(utils): 83 """Returns if the target platform is android.""" 84 return _get_platform_info(utils).target_android_constraint 85 86def _is_target_darwin(utils): 87 """Returns if the target platform is darwin.""" 88 return _get_platform_info(utils).target_darwin_constraint 89 90def _is_target_linux_or_android(utils): 91 """Returns if the target platform is linux with any variation of libc, or android.""" 92 return _is_target_linux(utils) or _is_target_android(utils) 93 94def _is_target_bionic(utils): 95 """Returns if the target platform uses the Bionic libc""" 96 return _is_target_linux_bionic(utils) or _is_target_android(utils) 97 98def _is_target_linux_bionic(utils): 99 """Returns if the target platform runs (non-Android) Linux and uses the Bionic libc""" 100 return _get_platform_info(utils).target_linux_bionic_constraint 101 102def _get_target_bitness(utils): 103 """Returns 32 or 64 depending on the bitness of the target platform.""" 104 platforminfo = _get_platform_info(utils) 105 106 if platforminfo.target_x86_constraint or platforminfo.target_arm_constraint: 107 return 32 108 elif platforminfo.target_x86_64_constraint or platforminfo.target_arm64_constraint: 109 return 64 110 fail("Unable to determine target bitness") 111 112def _get_target_arch(utils): 113 """Returns 'x86', 'x86_64', 'arm', or 'arm64' depending on the target platform.""" 114 platforminfo = _get_platform_info(utils) 115 116 if platforminfo.target_x86_constraint: 117 return "x86" 118 elif platforminfo.target_x86_64_constraint: 119 return "x86_64" 120 elif platforminfo.target_arm_constraint: 121 return "arm" 122 elif platforminfo.target_arm64_constraint: 123 return "arm64" 124 125 fail("Unable to determine target arch") 126 127def _get_target_secondary_arch(utils): 128 """ 129 Returns 'x86', 'x86_64', 'arm', 'arm64', or '' depending on the target platform. 130 131 If the secondary arch is the same as the primary arch, an empty string will be returned. 132 This is supposed to indicate that no secondary arch exists. The main motivation for this 133 behavior is in soong.variables, DeviceSecondaryArch and related variables are empty 134 strings when they don't exist, so a lot of code revolves around that. However in bazel 135 a constraint setting must always have a value, and a "none" value would probably 136 introduce more problems, so instead the secondary arch copies the primary arch if it 137 doesn't exist. 138 """ 139 platforminfo = _get_platform_info(utils) 140 141 result = "" 142 if platforminfo.target_secondary_x86_constraint: 143 result = "x86" 144 elif platforminfo.target_secondary_x86_64_constraint: 145 result = "x86_64" 146 elif platforminfo.target_secondary_arm_constraint: 147 result = "arm" 148 elif platforminfo.target_secondary_arm64_constraint: 149 result = "arm64" 150 else: 151 fail("Unable to determine target secondary arch") 152 153 if _get_target_arch(utils) == result: 154 return "" 155 return result 156 157platforms = struct( 158 is_target_linux = _is_target_linux, 159 is_target_android = _is_target_android, 160 is_target_bionic = _is_target_bionic, 161 is_target_darwin = _is_target_darwin, 162 is_target_linux_or_android = _is_target_linux_or_android, 163 get_target_bitness = _get_target_bitness, 164 get_target_arch = _get_target_arch, 165 get_target_secondary_arch = _get_target_secondary_arch, 166) 167