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 # add constraints for iOS + watchOS simulator and device triples 267 if system in ["ios", "watchos"]: 268 if arch == "x86_64" or abi == "sim": 269 return ["@build_bazel_apple_support//constraints:simulator"] 270 else: 271 return ["@build_bazel_apple_support//constraints:device"] 272 273 # TODO(bazelbuild/platforms#38): Implement when C++ toolchain is more mature and we 274 # figure out how they're doing this 275 return [] 276 277def triple_to_system(target_triple): 278 """Returns a system name for a given platform triple 279 280 **Deprecated**: Use triple() from triple.bzl directly. 281 282 Args: 283 target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu` 284 285 Returns: 286 str: A system name 287 """ 288 if type(target_triple) == "string": 289 target_triple = triple(target_triple) 290 return target_triple.system 291 292def triple_to_arch(target_triple): 293 """Returns a system architecture name for a given platform triple 294 295 **Deprecated**: Use triple() from triple.bzl directly. 296 297 Args: 298 target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu` 299 300 Returns: 301 str: A cpu architecture 302 """ 303 if type(target_triple) == "string": 304 target_triple = triple(target_triple) 305 return target_triple.arch 306 307def triple_to_abi(target_triple): 308 """Returns a system abi name for a given platform triple 309 310 **Deprecated**: Use triple() from triple.bzl directly. 311 312 Args: 313 target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu` 314 315 Returns: 316 str: The triple's abi 317 """ 318 if type(target_triple) == "string": 319 target_triple = triple(target_triple) 320 return target_triple.system 321 322def system_to_dylib_ext(system): 323 return _SYSTEM_TO_DYLIB_EXT[system] 324 325def system_to_staticlib_ext(system): 326 return _SYSTEM_TO_STATICLIB_EXT[system] 327 328def system_to_binary_ext(system): 329 return _SYSTEM_TO_BINARY_EXT[system] 330 331def system_to_stdlib_linkflags(system): 332 return _SYSTEM_TO_STDLIB_LINKFLAGS[system] 333 334def triple_to_constraint_set(target_triple): 335 """Returns a set of constraints for a given platform triple 336 337 Args: 338 target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu` 339 340 Returns: 341 list: A list of constraints (each represented by a list of strings) 342 """ 343 if target_triple == "wasm32-wasi": 344 return [ 345 "@platforms//cpu:wasm32", 346 "@platforms//os:wasi", 347 ] 348 if target_triple == "wasm32-unknown-unknown": 349 return [ 350 "@platforms//cpu:wasm32", 351 "@platforms//os:none", 352 ] 353 354 triple_struct = triple(target_triple) 355 356 constraint_set = [] 357 constraint_set += cpu_arch_to_constraints( 358 triple_struct.arch, 359 system = triple_struct.system, 360 ) 361 constraint_set += vendor_to_constraints(triple_struct.vendor) 362 constraint_set += system_to_constraints(triple_struct.system) 363 constraint_set += abi_to_constraints( 364 triple_struct.abi, 365 arch = triple_struct.arch, 366 system = triple_struct.system, 367 ) 368 369 return constraint_set 370