1"""Helpers for constructing supported Rust platform triples""" 2 3load("//rust/platform:triple.bzl", "triple") 4 5# All T1 Platforms should be supported, but aren't, see inline notes. 6SUPPORTED_T1_PLATFORM_TRIPLES = [ 7 "aarch64-unknown-linux-gnu", 8 "aarch64-unknown-nixos-gnu", # Same as `aarch64-unknown-linux-gnu` but with `@platforms//os:nixos`. 9 "i686-apple-darwin", 10 "i686-pc-windows-msvc", 11 "i686-unknown-linux-gnu", 12 "x86_64-apple-darwin", 13 "x86_64-pc-windows-msvc", 14 "x86_64-unknown-linux-gnu", 15 "x86_64-unknown-nixos-gnu", # Same as `x86_64-unknown-linux-gnu` but with `@platforms//os:nixos`. 16 # N.B. These "alternative" envs are not supported, as bazel cannot distinguish between them 17 # and others using existing @platforms// config_values 18 # 19 #"i686-pc-windows-gnu", 20 #"x86_64-pc-windows-gnu", 21] 22 23# Some T2 Platforms are supported, provided we have mappings to @platforms// entries. 24# See @rules_rust//rust/platform:triple_mappings.bzl for the complete list. 25SUPPORTED_T2_PLATFORM_TRIPLES = [ 26 "aarch64-apple-darwin", 27 "aarch64-apple-ios-sim", 28 "aarch64-apple-ios", 29 "aarch64-fuchsia", 30 "aarch64-linux-android", 31 "aarch64-pc-windows-msvc", 32 "arm-unknown-linux-gnueabi", 33 "armv7-linux-androideabi", 34 "armv7-unknown-linux-gnueabi", 35 "i686-linux-android", 36 "i686-unknown-freebsd", 37 "powerpc-unknown-linux-gnu", 38 "riscv32imc-unknown-none-elf", 39 "riscv64gc-unknown-none-elf", 40 "s390x-unknown-linux-gnu", 41 "thumbv7em-none-eabi", 42 "thumbv8m.main-none-eabi", 43 "wasm32-unknown-unknown", 44 "wasm32-wasi", 45 "x86_64-apple-ios", 46 "x86_64-fuchsia", 47 "x86_64-linux-android", 48 "x86_64-unknown-freebsd", 49 "x86_64-unknown-none", 50] 51 52SUPPORTED_T3_PLATFORM_TRIPLES = [ 53 "aarch64-unknown-nto-qnx710", 54] 55 56SUPPORTED_PLATFORM_TRIPLES = SUPPORTED_T1_PLATFORM_TRIPLES + SUPPORTED_T2_PLATFORM_TRIPLES + SUPPORTED_T3_PLATFORM_TRIPLES 57 58# CPUs that map to a "@platforms//cpu entry 59_CPU_ARCH_TO_BUILTIN_PLAT_SUFFIX = { 60 "aarch64": "aarch64", 61 "arm": "arm", 62 "armv7": "armv7", 63 "armv7s": None, 64 "asmjs": None, 65 "i386": "i386", 66 "i586": None, 67 "i686": "x86_32", 68 "le32": None, 69 "mips": None, 70 "mipsel": None, 71 "powerpc": "ppc", 72 "powerpc64": None, 73 "powerpc64le": None, 74 "riscv32": "riscv32", 75 "riscv32imc": "riscv32", 76 "riscv64": "riscv64", 77 "riscv64gc": "riscv64", 78 "s390": None, 79 "s390x": "s390x", 80 "thumbv6m": "armv6-m", 81 "thumbv7em": "armv7e-m", 82 "thumbv7m": "armv7-m", 83 "thumbv8m.main": "armv8-m", 84 "wasm32": None, 85 "x86_64": "x86_64", 86} 87 88# Systems that map to a "@platforms//os entry 89_SYSTEM_TO_BUILTIN_SYS_SUFFIX = { 90 "android": "android", 91 "bitrig": None, 92 "darwin": "osx", 93 "dragonfly": None, 94 "eabi": "none", 95 "eabihf": "none", 96 "emscripten": None, 97 "freebsd": "freebsd", 98 "fuchsia": "fuchsia", 99 "ios": "ios", 100 "linux": "linux", 101 "nacl": None, 102 "netbsd": None, 103 "nixos": "nixos", 104 "none": "none", 105 "nto": "qnx", 106 "openbsd": "openbsd", 107 "solaris": None, 108 "unknown": None, 109 "wasi": None, 110 "windows": "windows", 111} 112 113_SYSTEM_TO_BINARY_EXT = { 114 "android": "", 115 "darwin": "", 116 "eabi": "", 117 "eabihf": "", 118 "emscripten": ".js", 119 "freebsd": "", 120 "fuchsia": "", 121 "ios": "", 122 "linux": "", 123 "nixos": "", 124 "none": "", 125 "nto": "", 126 # This is currently a hack allowing us to have the proper 127 # generated extension for the wasm target, similarly to the 128 # windows target 129 "unknown": ".wasm", 130 "wasi": ".wasm", 131 "windows": ".exe", 132} 133 134_SYSTEM_TO_STATICLIB_EXT = { 135 "android": ".a", 136 "darwin": ".a", 137 "eabi": ".a", 138 "eabihf": ".a", 139 "emscripten": ".js", 140 "freebsd": ".a", 141 "fuchsia": ".a", 142 "ios": ".a", 143 "linux": ".a", 144 "nixos": ".a", 145 "none": ".a", 146 "nto": ".a", 147 "unknown": "", 148 "wasi": "", 149 "windows": ".lib", 150} 151 152_SYSTEM_TO_DYLIB_EXT = { 153 "android": ".so", 154 "darwin": ".dylib", 155 "eabi": ".so", 156 "eabihf": ".so", 157 "emscripten": ".js", 158 "freebsd": ".so", 159 "fuchsia": ".so", 160 "ios": ".dylib", 161 "linux": ".so", 162 "nixos": ".so", 163 "none": ".so", 164 "nto": ".a", 165 "unknown": ".wasm", 166 "wasi": ".wasm", 167 "windows": ".dll", 168} 169 170# See https://github.com/rust-lang/rust/blob/master/src/libstd/build.rs 171_SYSTEM_TO_STDLIB_LINKFLAGS = { 172 # NOTE: Rust stdlib `build.rs` treats android as a subset of linux, rust rules treat android 173 # as its own system. 174 "android": ["-ldl", "-llog"], 175 "bitrig": [], 176 # TODO(gregbowyer): If rust stdlib is compiled for cloudabi with the backtrace feature it 177 # includes `-lunwind` but this might not actually be required. 178 # I am not sure which is the common configuration or how we encode it as a link flag. 179 "cloudabi": ["-lunwind", "-lc", "-lcompiler_rt"], 180 "darwin": ["-lSystem", "-lresolv"], 181 "dragonfly": ["-lpthread"], 182 "eabi": [], 183 "eabihf": [], 184 "emscripten": [], 185 # TODO(bazelbuild/rules_cc#75): 186 # 187 # Right now bazel cc rules does not specify the exact flag setup needed for calling out system 188 # libs, that is we dont know given a toolchain if it should be, for example, 189 # `-lxxx` or `/Lxxx` or `xxx.lib` etc. 190 # 191 # We include the flag setup as they are _commonly seen_ on various platforms with a cc_rules 192 # style override for people doing things like gnu-mingw on windows. 193 # 194 # If you are reading this ... sorry! set the env var `BAZEL_RUST_STDLIB_LINKFLAGS` to 195 # what you need for your specific setup, for example like so 196 # `BAZEL_RUST_STDLIB_LINKFLAGS="-ladvapi32:-lws2_32:-luserenv"` 197 "freebsd": ["-lexecinfo", "-lpthread"], 198 "fuchsia": ["-lzircon", "-lfdio"], 199 "illumos": ["-lsocket", "-lposix4", "-lpthread", "-lresolv", "-lnsl", "-lumem"], 200 "ios": ["-lSystem", "-lobjc", "-Wl,-framework,Security", "-Wl,-framework,Foundation", "-lresolv"], 201 # TODO: This ignores musl. Longer term what does Bazel think about musl? 202 "linux": ["-ldl", "-lpthread"], 203 "nacl": [], 204 "netbsd": ["-lpthread", "-lrt"], 205 "nixos": ["-ldl", "-lpthread"], # Same as `linux`. 206 "none": [], 207 "nto": [], 208 "openbsd": ["-lpthread"], 209 "solaris": ["-lsocket", "-lposix4", "-lpthread", "-lresolv"], 210 "unknown": [], 211 "uwp": ["ws2_32.lib"], 212 "wasi": [], 213 "windows": ["advapi32.lib", "ws2_32.lib", "userenv.lib", "Bcrypt.lib"], 214} 215 216def cpu_arch_to_constraints(cpu_arch, *, system = None): 217 """Returns a list of contraint values which represents a triple's CPU. 218 219 Args: 220 cpu_arch (str): The architecture to match constraints for 221 system (str, optional): The system for the associated ABI value. 222 223 Returns: 224 List: A list of labels to constraint values 225 """ 226 if cpu_arch not in _CPU_ARCH_TO_BUILTIN_PLAT_SUFFIX: 227 fail("CPU architecture \"{}\" is not supported by rules_rust".format(cpu_arch)) 228 229 plat_suffix = _CPU_ARCH_TO_BUILTIN_PLAT_SUFFIX[cpu_arch] 230 231 # Patch armv7e-m to mf if hardfloat abi is selected 232 if plat_suffix == "armv7e-m" and system == "eabihf": 233 plat_suffix = "armv7e-mf" 234 235 return ["@platforms//cpu:{}".format(plat_suffix)] 236 237def vendor_to_constraints(_vendor): 238 # TODO(acmcarther): Review: 239 # 240 # My current understanding is that vendors can't have a material impact on 241 # constraint sets. 242 return [] 243 244def system_to_constraints(system): 245 if system not in _SYSTEM_TO_BUILTIN_SYS_SUFFIX: 246 fail("System \"{}\" is not supported by rules_rust".format(system)) 247 248 sys_suffix = _SYSTEM_TO_BUILTIN_SYS_SUFFIX[system] 249 250 return ["@platforms//os:{}".format(sys_suffix)] 251 252def abi_to_constraints(abi, *, arch = None, system = None): 253 """Return a list of constraint values which represents a triple's ABI. 254 255 Note that some ABI values require additional info to accurately match a set of constraints. 256 257 Args: 258 abi (str): The abi value to match constraints for 259 arch (str, optional): The architecture for the associated ABI value. 260 system (str, optional): The system for the associated ABI value. 261 262 Returns: 263 List: A list of labels to constraint values 264 """ 265 266 all_abi_constraints = [] 267 268 # add constraints for MUSL static compilation and linking 269 # to separate the MUSL from the non-MUSL toolchain on x86_64 270 # if abi == "musl" and system == "linux" and arch == "x86_64": 271 # all_abi_constraints.append("//rust/platform/constraints:musl_on") 272 273 # add constraints for iOS + watchOS simulator and device triples 274 if system in ["ios", "watchos"]: 275 if arch == "x86_64" or abi == "sim": 276 all_abi_constraints.append("@build_bazel_apple_support//constraints:simulator") 277 else: 278 all_abi_constraints.append("@build_bazel_apple_support//constraints:device") 279 280 # TODO(bazelbuild/platforms#38): Implement when C++ toolchain is more mature and we 281 # figure out how they're doing this 282 return all_abi_constraints 283 284def triple_to_system(target_triple): 285 """Returns a system name for a given platform triple 286 287 **Deprecated**: Use triple() from triple.bzl directly. 288 289 Args: 290 target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu` 291 292 Returns: 293 str: A system name 294 """ 295 if type(target_triple) == "string": 296 target_triple = triple(target_triple) 297 return target_triple.system 298 299def triple_to_arch(target_triple): 300 """Returns a system architecture name for a given platform triple 301 302 **Deprecated**: Use triple() from triple.bzl directly. 303 304 Args: 305 target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu` 306 307 Returns: 308 str: A cpu architecture 309 """ 310 if type(target_triple) == "string": 311 target_triple = triple(target_triple) 312 return target_triple.arch 313 314def triple_to_abi(target_triple): 315 """Returns a system abi name for a given platform triple 316 317 **Deprecated**: Use triple() from triple.bzl directly. 318 319 Args: 320 target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu` 321 322 Returns: 323 str: The triple's abi 324 """ 325 if type(target_triple) == "string": 326 target_triple = triple(target_triple) 327 return target_triple.system 328 329def system_to_dylib_ext(system): 330 return _SYSTEM_TO_DYLIB_EXT[system] 331 332def system_to_staticlib_ext(system): 333 return _SYSTEM_TO_STATICLIB_EXT[system] 334 335def system_to_binary_ext(system): 336 return _SYSTEM_TO_BINARY_EXT[system] 337 338def system_to_stdlib_linkflags(system): 339 return _SYSTEM_TO_STDLIB_LINKFLAGS[system] 340 341def triple_to_constraint_set(target_triple): 342 """Returns a set of constraints for a given platform triple 343 344 Args: 345 target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu` 346 347 Returns: 348 list: A list of constraints (each represented by a list of strings) 349 """ 350 if target_triple == "wasm32-wasi": 351 return [ 352 "@platforms//cpu:wasm32", 353 "@platforms//os:wasi", 354 ] 355 if target_triple == "wasm32-unknown-unknown": 356 return [ 357 "@platforms//cpu:wasm32", 358 "@platforms//os:none", 359 ] 360 361 triple_struct = triple(target_triple) 362 363 constraint_set = [] 364 constraint_set += cpu_arch_to_constraints( 365 triple_struct.arch, 366 system = triple_struct.system, 367 ) 368 constraint_set += vendor_to_constraints(triple_struct.vendor) 369 constraint_set += system_to_constraints(triple_struct.system) 370 constraint_set += abi_to_constraints( 371 triple_struct.abi, 372 arch = triple_struct.arch, 373 system = triple_struct.system, 374 ) 375 376 return constraint_set 377