xref: /aosp_15_r20/external/bazelbuild-rules_rust/rust/platform/triple.bzl (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
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