1"""Triples are a way to define information about a platform/system. This module provides 2a way to convert a triple string into a well structured object to avoid constant string 3parsing in starlark code, and a way for a repository_rule to extract the target triple 4of the host platform. 5 6Triples can be described at the following link: 7https://clang.llvm.org/docs/CrossCompilation.html#target-triple 8""" 9 10def triple(triple): 11 """Constructs a struct containing each component of the provided triple 12 13 Args: 14 triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu` 15 16 Returns: 17 struct: 18 - arch (str): The triple's CPU architecture 19 - vendor (str): The vendor of the system 20 - system (str): The name of the system 21 - abi (str, optional): The abi to use or None if abi does not apply. 22 - str (str): Original string representation of the triple 23 """ 24 if triple == "wasm32-wasi": 25 return struct( 26 arch = "wasm32", 27 system = "wasi", 28 vendor = "wasi", 29 abi = None, 30 str = triple, 31 ) 32 elif triple in ("aarch64-fuchsia", "x86_64-fuchsia"): 33 return struct( 34 arch = triple.split("-")[0], 35 system = "fuchsia", 36 vendor = "fuchsia", 37 abi = None, 38 str = triple, 39 ) 40 41 component_parts = triple.split("-") 42 if len(component_parts) < 3: 43 fail("Expected target triple to contain at least three sections separated by '-'") 44 45 cpu_arch = component_parts[0] 46 vendor = component_parts[1] 47 system = component_parts[2] 48 abi = None 49 50 if cpu_arch.startswith(("thumbv8m", "thumbv7m", "thumbv7e", "thumbv6m")): 51 abi = system 52 system = vendor 53 vendor = None 54 55 if system == "androideabi": 56 system = "android" 57 abi = "eabi" 58 59 if len(component_parts) == 4: 60 abi = component_parts[3] 61 62 return struct( 63 arch = cpu_arch, 64 vendor = vendor, 65 system = system, 66 abi = abi, 67 str = triple, 68 ) 69 70def _validate_cpu_architecture(arch, expected_archs): 71 """Validate the host CPU architecture 72 73 Args: 74 arch (string): a CPU architecture 75 expected_archs (list): A list of expected architecture strings 76 """ 77 if arch not in expected_archs: 78 fail("{} is not a expected cpu architecture {}".format( 79 arch, 80 expected_archs, 81 )) 82 83def get_host_triple(repository_ctx, abi = None): 84 """Query host information for the appropriate triple to use with load_arbitrary_tool or the crate_universe resolver 85 86 Example: 87 88 ```python 89 load("@rules_rust//rust:repositories.bzl", "load_arbitrary_tool") 90 load("@rules_rust//rust/platform:triple.bzl", "get_host_triple") 91 92 def _impl(repository_ctx): 93 host_triple = get_host_triple(repository_ctx) 94 95 load_arbitrary_tool( 96 ctx = repository_ctx, 97 tool_name = "cargo", 98 tool_subdirectories = ["cargo"], 99 target_triple = host_triple.str, 100 ) 101 102 example = repository_rule(implementation = _impl) 103 ``` 104 105 Args: 106 repository_ctx (repository_ctx): The repository_rule's context object 107 abi (str): Since there's no consistent way to check for ABI, this info 108 may be explicitly provided 109 110 Returns: 111 struct: A triple struct; see the `triple` function in this module 112 """ 113 114 # Detect the host's cpu architecture 115 116 supported_architectures = { 117 "linux": ["aarch64", "x86_64"], 118 "macos": ["aarch64", "x86_64"], 119 "windows": ["aarch64", "x86_64"], 120 } 121 122 arch = repository_ctx.os.arch 123 if arch == "amd64": 124 arch = "x86_64" 125 126 if "linux" in repository_ctx.os.name: 127 _validate_cpu_architecture(arch, supported_architectures["linux"]) 128 return triple("{}-unknown-linux-{}".format( 129 arch, 130 abi or "gnu", 131 )) 132 133 if "mac" in repository_ctx.os.name: 134 _validate_cpu_architecture(arch, supported_architectures["macos"]) 135 return triple("{}-apple-darwin".format(arch)) 136 137 if "win" in repository_ctx.os.name: 138 _validate_cpu_architecture(arch, supported_architectures["windows"]) 139 return triple("{}-pc-windows-{}".format( 140 arch, 141 abi or "msvc", 142 )) 143 144 fail("Unhandled host os: {}", repository_ctx.os.name) 145