diff --git a/rs/private/BUILD.bazel b/rs/private/BUILD.bazel index 69f82c7..6dd9746 100644 --- a/rs/private/BUILD.bazel +++ b/rs/private/BUILD.bazel @@ -1,11 +1,14 @@ load("@bazel_lib//:bzl_library.bzl", "bzl_library") +load("@bazel_lib//lib:write_source_files.bzl", "write_source_files") load("@bazel_skylib//rules:common_settings.bzl", "bool_setting") load("@rules_rust//rust:rust_stdlib_filegroup.bzl", "rust_stdlib_filegroup") +load("//rs/platforms:triples.bzl", "ALL_TARGET_TRIPLES") load(":all_crate_deps_test.bzl", "all_crate_deps_tests") load(":bindgen_test.bzl", "bindgen_tests") load(":bpf_linker_repository_test.bzl", "bpf_linker_repository_tests") load(":cargo_toml_utils_test.bzl", "cargo_toml_utils_tests") load(":cargo_workspace_graph_test.bzl", "cargo_workspace_graph_tests") +load(":cfg_oracle.bzl", "cfg_oracle_data") load(":cfg_parser_test.bzl", "cfg_parser_tests") load(":lint_flags_test.bzl", "lint_flags_tests") load(":registry_utils_test.bzl", "registry_utils_tests") @@ -36,6 +39,19 @@ cargo_workspace_graph_tests() cfg_parser_tests() +cfg_oracle_data( + name = "generated_cfg_target_data", + tags = ["manual"], + triples = ALL_TARGET_TRIPLES, +) + +write_source_files( + name = "update_cfg_target_data", + files = { + "cfg_target_data.bzl": ":generated_cfg_target_data.bzl", + }, +) + lint_flags_tests() registry_utils_tests() @@ -360,6 +376,17 @@ bzl_library( name = "cfg_parser", srcs = ["cfg_parser.bzl"], visibility = ["//rs:__subpackages__"], + deps = [":cfg_target_data"], +) + +bzl_library( + name = "cfg_target_data", + srcs = ["cfg_target_data.bzl"], +) + +bzl_library( + name = "cfg_oracle", + srcs = ["cfg_oracle.bzl"], ) bzl_library( diff --git a/rs/private/cfg_oracle.bzl b/rs/private/cfg_oracle.bzl new file mode 100644 index 0000000..e2de2a9 --- /dev/null +++ b/rs/private/cfg_oracle.bzl @@ -0,0 +1,43 @@ +"""Hermetically generates Cargo cfg oracle data from the registered rustc.""" + +def _cfg_oracle_data_impl(ctx): + rustc_info = ctx.attr._rustc[DefaultInfo] + rustc_files = rustc_info.files.to_list() + if len(rustc_files) != 1: + fail("expected exactly one rustc executable, got {}".format(rustc_files)) + + output = ctx.outputs.output + args = ctx.actions.args() + args.add("--rustc", rustc_files[0]) + args.add("--output", output) + args.add_all(ctx.attr.triples, before_each = "--triple") + + ctx.actions.run( + arguments = [args], + executable = ctx.executable._generator, + mnemonic = "GenerateCargoCfgOracle", + outputs = [output], + progress_message = "Generating Cargo cfg oracle data for %{label}", + tools = [depset(transitive = [rustc_info.files, rustc_info.default_runfiles.files])], + ) + + return [DefaultInfo(files = depset([output]))] + +cfg_oracle_data = rule( + implementation = _cfg_oracle_data_impl, + attrs = { + "triples": attr.string_list(mandatory = True), + "_generator": attr.label( + cfg = "exec", + default = Label("//tools/cfg_oracle:cfg_oracle_generator"), + executable = True, + ), + "_rustc": attr.label( + cfg = "exec", + default = Label("@rules_rust//rust/toolchain:current_rustc_files"), + ), + }, + outputs = { + "output": "%{name}.bzl", + }, +) diff --git a/rs/private/cfg_parser.bzl b/rs/private/cfg_parser.bzl index fd5eaf8..97607af 100644 --- a/rs/private/cfg_parser.bzl +++ b/rs/private/cfg_parser.bzl @@ -1,7 +1,6 @@ -def _get(xs, index, default): - if index < len(xs): - return xs[index] - return default +"""Parses and evaluates Cargo cfg predicates for Rust target triples.""" + +load(":cfg_target_data.bzl", "CFG_ATOMS", "CFG_ATOM_IDS_BY_TRIPLE") def _emit_pending(frames, pending_ident, pending_eq_key): # Moves any pending identifier into a predicate node in the current frame. @@ -67,6 +66,15 @@ def _cfg_tokenize(expr): ############################################ def cfg_parse(expr): + """Parses a cfg predicate into its evaluator representation. + + Args: + expr: The cfg predicate body to parse. + + Returns: + A tuple containing the parsed syntax tree and whether it uses package + feature cfgs. + """ tokens = _cfg_tokenize(expr) frames = [{"fn": "__ROOT__", "args": []}] pending_ident = None @@ -141,114 +149,36 @@ def cfg_parse(expr): return root_args[0], uses_feature_cfg -############################################ -# Triple → cfg attribute derivation -############################################ - -def _normalize_os(os_raw): - if os_raw == "darwin": - return "macos" - return os_raw - -def _normalize_arch(arch_raw): - # RISC-V target triples encode the enabled ISA extensions in their first - # component, while Rust's cfg(target_arch) exposes only the register width. - if arch_raw.startswith("riscv32"): - return "riscv32" - if arch_raw.startswith("riscv64"): - return "riscv64" - return arch_raw - -def _family_for_os(os_name): - if os_name == "windows": - return "windows" - if os_name in [ - "linux", "macos", "ios", "freebsd", "netbsd", "openbsd", "dragonfly", - "android", "solaris", "illumos", "aix", "haiku", "hurd", - ]: - return "unix" - return "" - -def _family_for_arch_and_os(arch, os_name): - if arch.startswith("wasm"): - return "wasm" - return _family_for_os(os_name) - -def _pointer_width_for_arch(arch): - # Common targets - arch64 = ["s390x","bpfel","bpfeb"] - if "64" in arch or arch in arch64: - return "64" - - arch32 = [ - "i686","i586","i386","x86","arm","armv7","thumbv7","thumbv6","mips","mipsel", - "powerpc","ppc","sparc","riscv32","wasm32","m68k","loongarch32", - ] - if "32" in arch or arch in arch32: - return "32" - - return "64" - -def _endian_for_arch(arch): - big_set = ["m68k","s390x","sparc","sparc64","powerpc","powerpc64"] - if arch.endswith("be") or arch.endswith("eb") or arch in big_set: - return "big" - if arch.startswith("mips") and (not arch.endswith("el")): - return "big" - - # Most contemporary targets are little-endian: - return "little" - -def _abi_from_env(env): - # Very rough: surface a few commonly referenced ABIs - abi_pieces = ["eabi", "eabihf", "elf", "gnuabi64"] - for abi_piece in abi_pieces: - if abi_piece in env: - return abi_piece - return "" - -def _target_has_feature(ctx, feature): - # x86_64 baseline implies SSE2. - if feature == "sse2": - return ctx["target_arch"] == "x86_64" - - # AArch64 baseline implies NEON. - if feature == "neon": - return ctx["target_arch"] == "aarch64" - - return False - -def triple_to_cfg_attrs(triple): - parts = triple.split("-") - arch_part = _normalize_arch(_get(parts, 0, "")) - vendor_part = _get(parts, 1, "unknown") - os_raw_part = _get(parts, 2, "none") - env_part = "-".join(parts[3:]) - os_norm = _normalize_os(os_raw_part) - fam = _family_for_arch_and_os(arch_part, os_norm) - width = _pointer_width_for_arch(arch_part) - endian = _endian_for_arch(arch_part) - abi_guess = _abi_from_env(env_part) - - return { +def _cfg_context(triple, atoms): + ctx = { "_triple": triple, - - "target_arch": arch_part, - "target_vendor": vendor_part, - "target_os": os_norm, - "target_env": env_part, - "target_family": fam, - "target_endian": endian, - "target_pointer_width": width, - "target_abi": abi_guess, - - # convenience booleans for bare predicates "true": True, "false": False, - "unix": fam == "unix", - "windows": fam == "windows", - "wasm": fam == "wasm", } + for atom in atoms: + pieces = atom.split("=", 1) + if len(pieces) == 1: + ctx[atom] = True + continue + + key = pieces[0] + encoded_value = pieces[1] + value = encoded_value[1:-1] + key_values = ctx.get(key) + if key_values == None: + key_values = set() + ctx[key] = key_values + key_values.add(value) + return ctx + +def cfg_atoms_for_triple(triple): + atom_ids = CFG_ATOM_IDS_BY_TRIPLE.get(triple) + if atom_ids == None: + fail("Unsupported target triple '{}'; expected one of ALL_TARGET_TRIPLES".format(triple)) + return [CFG_ATOMS[atom_id] for atom_id in atom_ids] + +def triple_to_cfg_attrs(triple): + return _cfg_context(triple, cfg_atoms_for_triple(triple)) ############################################ # Evaluator (non-recursive; explicit stack) @@ -257,17 +187,7 @@ def triple_to_cfg_attrs(triple): def _eval_eq(ctx, key, value, features): if key == "feature": return value in features - if key == "target_feature": - return _target_has_feature(ctx, value) - known = [ - "target_os","target_family","target_arch","target_env", - "target_vendor","target_endian","target_pointer_width","target_abi", - ] - if key in known: - return ctx.get(key, "") == value - # Unknown keys evaluate to False - # fail("Unknown key %s" % key) - return False + return value in ctx.get(key, ()) def _eval_pred(ctx, name): return ctx.get(name, False) diff --git a/rs/private/cfg_parser_test.bzl b/rs/private/cfg_parser_test.bzl index d7e4e44..2ae6265 100644 --- a/rs/private/cfg_parser_test.bzl +++ b/rs/private/cfg_parser_test.bzl @@ -1,5 +1,9 @@ +"""Tests for Cargo cfg parsing and target cfg derivation.""" + load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest") -load(":cfg_parser.bzl", "cfg_matches", "cfg_matches_expr_for_cfg_attrs", "cfg_matches_expr_for_triples", "triple_to_cfg_attrs") +load("//rs/platforms:triples.bzl", "ALL_TARGET_TRIPLES") +load(":cfg_parser.bzl", "cfg_atoms_for_triple", "cfg_matches", "cfg_matches_expr_for_cfg_attrs", "cfg_matches_expr_for_triples", "triple_to_cfg_attrs") +load(":cfg_target_data.bzl", "CFG_ATOMS", "CFG_ATOM_IDS_BY_TRIPLE") def _cfg(expr): return "cfg(%s)" % expr @@ -38,10 +42,11 @@ def _cfg_parser_smoke_test_impl(ctx): asserts.true(env, cfg_matches(_cfg('target_family = "windows"'), win)) asserts.true(env, cfg_matches(_cfg('target_pointer_width = "64"'), win)) asserts.true(env, cfg_matches(_cfg('target_env = "gnu"'), win_gnu)) - asserts.true(env, cfg_matches(_cfg('target_env = "gnullvm"'), win_gnullvm)) + asserts.true(env, cfg_matches(_cfg('target_env = "gnu"'), win_gnullvm)) + asserts.true(env, cfg_matches(_cfg('target_abi = "llvm"'), win_gnullvm)) # Wasm facts - asserts.true(env, cfg_matches(_cfg("wasm"), wasm)) + asserts.false(env, cfg_matches(_cfg("wasm"), wasm)) asserts.false(env, cfg_matches(_cfg("unix"), wasm)) asserts.false(env, cfg_matches(_cfg("windows"), wasm)) asserts.true(env, cfg_matches(_cfg('target_arch = "wasm32"'), wasm)) @@ -120,8 +125,35 @@ def _cfg_parser_smoke_test_impl(ctx): cfg_parser_smoke_test = unittest.make(_cfg_parser_smoke_test_impl) +def _cfg_parser_oracle_test_impl(ctx): + env = unittest.begin(ctx) + + asserts.equals(env, sorted(ALL_TARGET_TRIPLES), sorted(CFG_ATOM_IDS_BY_TRIPLE.keys())) + + for triple in ALL_TARGET_TRIPLES: + expected_atoms = [CFG_ATOMS[atom_id] for atom_id in CFG_ATOM_IDS_BY_TRIPLE[triple]] + expected_set = set(expected_atoms) + asserts.equals( + env, + expected_atoms, + cfg_atoms_for_triple(triple), + "computed cfg atoms differ for {}".format(triple), + ) + for atom in CFG_ATOMS: + asserts.equals( + env, + atom in expected_set, + cfg_matches(_cfg(atom), triple), + "cfg({}) differs for {}".format(atom, triple), + ) + + return unittest.end(env) + +cfg_parser_oracle_test = unittest.make(_cfg_parser_oracle_test_impl) + def cfg_parser_tests(): return unittest.suite( "cfg_parser_tests", + cfg_parser_oracle_test, cfg_parser_smoke_test, ) diff --git a/rs/private/cfg_target_data.bzl b/rs/private/cfg_target_data.bzl new file mode 100644 index 0000000..506052d --- /dev/null +++ b/rs/private/cfg_target_data.bzl @@ -0,0 +1,232 @@ +"""Generated Cargo cfg data. Do not edit by hand. + +Generated by //rs/private:generated_cfg_target_data. +Oracle: rustc 1.92.0 (ded5c06cf 2025-12-08) +""" + +CFG_ATOMS = [ + "debug_assertions", + "panic=\"abort\"", + "panic=\"unwind\"", + "target_abi=\"\"", + "target_abi=\"eabi\"", + "target_abi=\"eabihf\"", + "target_abi=\"elfv1\"", + "target_abi=\"elfv2\"", + "target_abi=\"llvm\"", + "target_abi=\"macabi\"", + "target_abi=\"sim\"", + "target_abi=\"softfloat\"", + "target_arch=\"aarch64\"", + "target_arch=\"arm\"", + "target_arch=\"bpf\"", + "target_arch=\"loongarch64\"", + "target_arch=\"powerpc\"", + "target_arch=\"powerpc64\"", + "target_arch=\"riscv32\"", + "target_arch=\"riscv64\"", + "target_arch=\"s390x\"", + "target_arch=\"sparc64\"", + "target_arch=\"wasm32\"", + "target_arch=\"wasm64\"", + "target_arch=\"x86\"", + "target_arch=\"x86_64\"", + "target_endian=\"big\"", + "target_endian=\"little\"", + "target_env=\"\"", + "target_env=\"gnu\"", + "target_env=\"macabi\"", + "target_env=\"msvc\"", + "target_env=\"musl\"", + "target_env=\"nto71\"", + "target_env=\"p1\"", + "target_env=\"p2\"", + "target_env=\"sim\"", + "target_family=\"unix\"", + "target_family=\"wasm\"", + "target_family=\"windows\"", + "target_feature=\"a\"", + "target_feature=\"aes\"", + "target_feature=\"bulk-memory\"", + "target_feature=\"c\"", + "target_feature=\"cmpxchg16b\"", + "target_feature=\"crc\"", + "target_feature=\"crt-static\"", + "target_feature=\"d\"", + "target_feature=\"dit\"", + "target_feature=\"dotprod\"", + "target_feature=\"dpb\"", + "target_feature=\"dpb2\"", + "target_feature=\"f\"", + "target_feature=\"fcma\"", + "target_feature=\"fhm\"", + "target_feature=\"flagm\"", + "target_feature=\"fp16\"", + "target_feature=\"frintts\"", + "target_feature=\"fxsr\"", + "target_feature=\"jsconv\"", + "target_feature=\"lor\"", + "target_feature=\"lse\"", + "target_feature=\"lsx\"", + "target_feature=\"m\"", + "target_feature=\"multivalue\"", + "target_feature=\"mutable-globals\"", + "target_feature=\"neon\"", + "target_feature=\"nontrapping-fptoint\"", + "target_feature=\"paca\"", + "target_feature=\"pacg\"", + "target_feature=\"pan\"", + "target_feature=\"pmuv3\"", + "target_feature=\"popcnt\"", + "target_feature=\"ras\"", + "target_feature=\"rcpc\"", + "target_feature=\"rcpc2\"", + "target_feature=\"rdm\"", + "target_feature=\"reference-types\"", + "target_feature=\"sb\"", + "target_feature=\"sha2\"", + "target_feature=\"sha3\"", + "target_feature=\"sign-ext\"", + "target_feature=\"ssbs\"", + "target_feature=\"sse\"", + "target_feature=\"sse2\"", + "target_feature=\"sse3\"", + "target_feature=\"sse4.1\"", + "target_feature=\"ssse3\"", + "target_feature=\"vh\"", + "target_feature=\"zba\"", + "target_feature=\"zbb\"", + "target_feature=\"zbs\"", + "target_has_atomic=\"128\"", + "target_has_atomic=\"16\"", + "target_has_atomic=\"32\"", + "target_has_atomic=\"64\"", + "target_has_atomic=\"8\"", + "target_has_atomic=\"ptr\"", + "target_os=\"android\"", + "target_os=\"emscripten\"", + "target_os=\"freebsd\"", + "target_os=\"fuchsia\"", + "target_os=\"ios\"", + "target_os=\"linux\"", + "target_os=\"macos\"", + "target_os=\"netbsd\"", + "target_os=\"none\"", + "target_os=\"nto\"", + "target_os=\"openbsd\"", + "target_os=\"uefi\"", + "target_os=\"unknown\"", + "target_os=\"wasi\"", + "target_os=\"windows\"", + "target_pointer_width=\"32\"", + "target_pointer_width=\"64\"", + "target_vendor=\"apple\"", + "target_vendor=\"pc\"", + "target_vendor=\"unknown\"", + "unix", + "windows", +] + +CFG_ATOM_IDS_BY_TRIPLE = { + "aarch64-apple-darwin": [0, 2, 3, 12, 27, 28, 37, 41, 45, 48, 49, 50, 51, 53, 54, 55, 56, 57, 59, 60, 61, 66, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 80, 82, 88, 92, 93, 94, 95, 96, 97, 104, 114, 115, 118], + "aarch64-apple-ios": [0, 2, 3, 12, 27, 28, 37, 41, 66, 71, 79, 92, 93, 94, 95, 96, 97, 102, 114, 115, 118], + "aarch64-apple-ios-macabi": [0, 2, 9, 12, 27, 30, 37, 41, 45, 50, 53, 56, 59, 60, 61, 66, 68, 69, 70, 71, 73, 74, 76, 79, 88, 92, 93, 94, 95, 96, 97, 102, 114, 115, 118], + "aarch64-apple-ios-sim": [0, 2, 10, 12, 27, 36, 37, 41, 45, 50, 53, 56, 59, 60, 61, 66, 68, 69, 70, 71, 73, 74, 76, 79, 88, 92, 93, 94, 95, 96, 97, 102, 114, 115, 118], + "aarch64-linux-android": [0, 2, 3, 12, 27, 28, 37, 66, 92, 93, 94, 95, 96, 97, 98, 114, 117, 118], + "aarch64-pc-windows-gnullvm": [0, 2, 8, 12, 27, 29, 39, 66, 92, 93, 94, 95, 96, 97, 112, 114, 116, 119], + "aarch64-pc-windows-msvc": [0, 2, 3, 12, 27, 31, 39, 66, 92, 93, 94, 95, 96, 97, 112, 114, 116, 119], + "aarch64-unknown-freebsd": [0, 2, 3, 12, 27, 28, 37, 66, 92, 93, 94, 95, 96, 97, 100, 114, 117, 118], + "aarch64-unknown-fuchsia": [0, 2, 3, 12, 27, 28, 37, 41, 45, 66, 79, 92, 93, 94, 95, 96, 97, 101, 114, 117, 118], + "aarch64-unknown-linux-gnu": [0, 2, 3, 12, 27, 29, 37, 66, 92, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "aarch64-unknown-linux-musl": [0, 2, 3, 12, 27, 32, 37, 46, 66, 92, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "aarch64-unknown-netbsd": [0, 2, 3, 12, 27, 28, 37, 66, 92, 93, 94, 95, 96, 97, 105, 114, 117, 118], + "aarch64-unknown-none": [0, 1, 3, 12, 27, 28, 66, 92, 93, 94, 95, 96, 97, 106, 114, 117], + "aarch64-unknown-none-softfloat": [0, 1, 11, 12, 27, 28, 92, 93, 94, 95, 96, 97, 106, 114, 117], + "aarch64-unknown-nto-qnx710": [0, 2, 3, 12, 27, 33, 37, 66, 92, 93, 94, 95, 96, 97, 107, 114, 117, 118], + "aarch64-unknown-openbsd": [0, 2, 3, 12, 27, 28, 37, 66, 92, 93, 94, 95, 96, 97, 108, 114, 117, 118], + "aarch64-unknown-uefi": [0, 1, 3, 12, 27, 28, 66, 92, 93, 94, 95, 96, 97, 109, 114, 117], + "arm-linux-androideabi": [0, 2, 4, 13, 27, 28, 37, 93, 94, 96, 97, 98, 113, 117, 118], + "arm-unknown-linux-gnueabi": [0, 2, 4, 13, 27, 29, 37, 93, 94, 95, 96, 97, 103, 113, 117, 118], + "arm-unknown-linux-gnueabihf": [0, 2, 5, 13, 27, 29, 37, 93, 94, 95, 96, 97, 103, 113, 117, 118], + "arm-unknown-linux-musleabi": [0, 2, 4, 13, 27, 32, 37, 46, 93, 94, 95, 96, 97, 103, 113, 117, 118], + "arm-unknown-linux-musleabihf": [0, 2, 5, 13, 27, 32, 37, 46, 93, 94, 95, 96, 97, 103, 113, 117, 118], + "arm64e-apple-darwin": [0, 2, 3, 12, 27, 28, 37, 41, 45, 48, 49, 50, 51, 53, 54, 55, 56, 57, 59, 60, 61, 66, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 80, 82, 88, 92, 93, 94, 95, 96, 97, 104, 114, 115, 118], + "arm64e-apple-ios": [0, 2, 3, 12, 27, 28, 37, 41, 45, 50, 53, 56, 59, 60, 61, 66, 68, 69, 70, 71, 73, 74, 76, 79, 88, 92, 93, 94, 95, 96, 97, 102, 114, 115, 118], + "armv7-linux-androideabi": [0, 2, 4, 13, 27, 28, 37, 93, 94, 95, 96, 97, 98, 113, 117, 118], + "armv7-unknown-freebsd": [0, 2, 5, 13, 27, 28, 37, 93, 94, 95, 96, 97, 100, 113, 117, 118], + "armv7-unknown-linux-gnueabi": [0, 2, 4, 13, 27, 29, 37, 93, 94, 95, 96, 97, 103, 113, 117, 118], + "armv7-unknown-linux-gnueabihf": [0, 2, 5, 13, 27, 29, 37, 93, 94, 95, 96, 97, 103, 113, 117, 118], + "armv7-unknown-linux-musleabi": [0, 2, 4, 13, 27, 32, 37, 46, 93, 94, 95, 96, 97, 103, 113, 117, 118], + "armv7-unknown-linux-musleabihf": [0, 2, 5, 13, 27, 32, 37, 46, 93, 94, 95, 96, 97, 103, 113, 117, 118], + "armv7-unknown-netbsd-eabihf": [0, 2, 5, 13, 27, 28, 37, 93, 94, 95, 96, 97, 105, 113, 117, 118], + "bpfeb-unknown-none": [0, 1, 3, 14, 26, 28, 106, 114, 117], + "bpfel-unknown-none": [0, 1, 3, 14, 27, 28, 106, 114, 117], + "i386-apple-ios": [0, 2, 10, 24, 27, 36, 37, 44, 58, 83, 84, 85, 86, 87, 93, 94, 95, 96, 97, 102, 113, 115, 118], + "i686-apple-darwin": [0, 2, 3, 24, 27, 28, 37, 44, 58, 83, 84, 85, 86, 87, 93, 94, 95, 96, 97, 104, 113, 115, 118], + "i686-linux-android": [0, 2, 3, 24, 27, 28, 37, 58, 83, 84, 85, 87, 93, 94, 95, 96, 97, 98, 113, 117, 118], + "i686-pc-windows-gnu": [0, 2, 3, 24, 27, 29, 39, 58, 83, 84, 93, 94, 95, 96, 97, 112, 113, 116, 119], + "i686-pc-windows-gnullvm": [0, 2, 8, 24, 27, 29, 39, 58, 83, 84, 93, 94, 95, 96, 97, 112, 113, 116, 119], + "i686-pc-windows-msvc": [0, 2, 3, 24, 27, 31, 39, 58, 83, 84, 93, 94, 95, 96, 97, 112, 113, 116, 119], + "i686-unknown-freebsd": [0, 2, 3, 24, 27, 28, 37, 58, 83, 84, 93, 94, 95, 96, 97, 100, 113, 117, 118], + "i686-unknown-linux-gnu": [0, 2, 3, 24, 27, 29, 37, 58, 83, 84, 93, 94, 95, 96, 97, 103, 113, 117, 118], + "i686-unknown-linux-musl": [0, 2, 3, 24, 27, 32, 37, 46, 58, 83, 84, 93, 94, 95, 96, 97, 103, 113, 117, 118], + "i686-unknown-netbsd": [0, 2, 3, 24, 27, 28, 37, 58, 83, 84, 93, 94, 95, 96, 97, 105, 113, 117, 118], + "i686-unknown-openbsd": [0, 2, 3, 24, 27, 28, 37, 58, 83, 84, 93, 94, 95, 96, 97, 108, 113, 117, 118], + "i686-unknown-uefi": [0, 1, 3, 24, 27, 28, 58, 93, 94, 95, 96, 97, 109, 113, 117], + "loongarch64-unknown-linux-gnu": [0, 2, 3, 15, 27, 29, 37, 47, 52, 62, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "loongarch64-unknown-linux-musl": [0, 2, 3, 15, 27, 32, 37, 47, 52, 62, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "loongarch64-unknown-none": [0, 1, 3, 15, 27, 28, 47, 52, 93, 94, 95, 96, 97, 106, 114, 117], + "powerpc-unknown-freebsd": [0, 2, 3, 16, 26, 28, 37, 93, 94, 96, 97, 100, 113, 117, 118], + "powerpc-unknown-linux-gnu": [0, 2, 3, 16, 26, 29, 37, 93, 94, 96, 97, 103, 113, 117, 118], + "powerpc-unknown-linux-musl": [0, 2, 3, 16, 26, 32, 37, 93, 94, 96, 97, 103, 113, 117, 118], + "powerpc-unknown-netbsd": [0, 2, 3, 16, 26, 28, 37, 93, 94, 96, 97, 105, 113, 117, 118], + "powerpc-unknown-openbsd": [0, 2, 3, 16, 26, 28, 37, 93, 94, 96, 97, 108, 113, 117, 118], + "powerpc64-unknown-freebsd": [0, 2, 7, 17, 26, 28, 37, 93, 94, 95, 96, 97, 100, 114, 117, 118], + "powerpc64-unknown-linux-gnu": [0, 2, 6, 17, 26, 29, 37, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "powerpc64-unknown-openbsd": [0, 2, 7, 17, 26, 28, 37, 93, 94, 95, 96, 97, 108, 114, 117, 118], + "powerpc64le-unknown-freebsd": [0, 2, 7, 17, 27, 28, 37, 93, 94, 95, 96, 97, 100, 114, 117, 118], + "powerpc64le-unknown-linux-gnu": [0, 2, 7, 17, 27, 29, 37, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "powerpc64le-unknown-linux-musl": [0, 2, 7, 17, 27, 32, 37, 46, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "riscv32imac-unknown-none-elf": [0, 1, 3, 18, 27, 28, 40, 43, 63, 93, 94, 96, 97, 106, 113, 117], + "riscv32imc-unknown-none-elf": [0, 1, 3, 18, 27, 28, 43, 63, 106, 113, 117], + "riscv64-linux-android": [0, 2, 3, 19, 27, 28, 37, 40, 43, 63, 89, 90, 91, 93, 94, 95, 96, 97, 98, 114, 117, 118], + "riscv64gc-unknown-freebsd": [0, 2, 3, 19, 27, 28, 37, 40, 43, 63, 93, 94, 95, 96, 97, 100, 114, 117, 118], + "riscv64gc-unknown-fuchsia": [0, 2, 3, 19, 27, 28, 37, 40, 43, 63, 93, 94, 95, 96, 97, 101, 114, 117, 118], + "riscv64gc-unknown-linux-gnu": [0, 2, 3, 19, 27, 29, 37, 40, 43, 63, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "riscv64gc-unknown-linux-musl": [0, 2, 3, 19, 27, 32, 37, 40, 43, 63, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "riscv64gc-unknown-netbsd": [0, 2, 3, 19, 27, 28, 37, 40, 43, 63, 93, 94, 95, 96, 97, 105, 114, 117, 118], + "riscv64gc-unknown-none-elf": [0, 1, 3, 19, 27, 28, 40, 43, 63, 93, 94, 95, 96, 97, 106, 114, 117], + "riscv64gc-unknown-openbsd": [0, 2, 3, 19, 27, 28, 37, 40, 43, 63, 93, 94, 95, 96, 97, 108, 114, 117, 118], + "s390x-unknown-linux-gnu": [0, 2, 3, 20, 26, 29, 37, 92, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "s390x-unknown-linux-musl": [0, 2, 3, 20, 26, 32, 37, 92, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "sparc64-unknown-linux-gnu": [0, 2, 3, 21, 26, 29, 37, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "sparc64-unknown-netbsd": [0, 2, 3, 21, 26, 28, 37, 93, 94, 95, 96, 97, 105, 114, 117, 118], + "sparc64-unknown-openbsd": [0, 2, 3, 21, 26, 28, 37, 93, 94, 95, 96, 97, 108, 114, 117, 118], + "thumbv6m-none-eabi": [0, 1, 4, 13, 27, 28, 106, 113, 117], + "thumbv7em-none-eabi": [0, 1, 4, 13, 27, 28, 93, 94, 96, 97, 106, 113, 117], + "thumbv7em-none-eabihf": [0, 1, 5, 13, 27, 28, 93, 94, 96, 97, 106, 113, 117], + "thumbv7m-none-eabi": [0, 1, 4, 13, 27, 28, 93, 94, 96, 97, 106, 113, 117], + "thumbv8m.main-none-eabi": [0, 1, 4, 13, 27, 28, 93, 94, 96, 97, 106, 113, 117], + "thumbv8m.main-none-eabihf": [0, 1, 5, 13, 27, 28, 93, 94, 96, 97, 106, 113, 117], + "wasm32-unknown-emscripten": [0, 2, 3, 22, 27, 28, 37, 38, 42, 64, 65, 67, 77, 81, 93, 94, 95, 96, 97, 99, 113, 117, 118], + "wasm32-unknown-unknown": [0, 1, 3, 22, 27, 28, 38, 42, 64, 65, 67, 77, 81, 93, 94, 95, 96, 97, 110, 113, 117], + "wasm32-wasip1": [0, 1, 3, 22, 27, 34, 38, 42, 46, 64, 65, 67, 77, 81, 93, 94, 95, 96, 97, 111, 113, 117], + "wasm32-wasip1-threads": [0, 1, 3, 22, 27, 34, 38, 42, 46, 64, 65, 67, 77, 81, 93, 94, 95, 96, 97, 111, 113, 117], + "wasm32-wasip2": [0, 1, 3, 22, 27, 35, 38, 42, 46, 64, 65, 67, 77, 81, 93, 94, 95, 96, 97, 111, 113, 117], + "wasm64-unknown-unknown": [0, 1, 3, 23, 27, 28, 38, 42, 64, 65, 67, 77, 81, 93, 94, 95, 96, 97, 110, 114, 117], + "x86_64-apple-darwin": [0, 2, 3, 25, 27, 28, 37, 44, 58, 83, 84, 85, 86, 87, 92, 93, 94, 95, 96, 97, 104, 114, 115, 118], + "x86_64-apple-ios": [0, 2, 10, 25, 27, 36, 37, 44, 58, 83, 84, 85, 86, 87, 92, 93, 94, 95, 96, 97, 102, 114, 115, 118], + "x86_64-apple-ios-macabi": [0, 2, 9, 25, 27, 30, 37, 44, 58, 83, 84, 85, 86, 87, 92, 93, 94, 95, 96, 97, 102, 114, 115, 118], + "x86_64-linux-android": [0, 2, 3, 25, 27, 28, 37, 58, 72, 83, 84, 85, 86, 87, 93, 94, 95, 96, 97, 98, 114, 117, 118], + "x86_64-pc-windows-gnu": [0, 2, 3, 25, 27, 29, 39, 44, 58, 83, 84, 85, 92, 93, 94, 95, 96, 97, 112, 114, 116, 119], + "x86_64-pc-windows-gnullvm": [0, 2, 8, 25, 27, 29, 39, 44, 58, 83, 84, 85, 92, 93, 94, 95, 96, 97, 112, 114, 116, 119], + "x86_64-pc-windows-msvc": [0, 2, 3, 25, 27, 31, 39, 44, 58, 83, 84, 85, 92, 93, 94, 95, 96, 97, 112, 114, 116, 119], + "x86_64-unknown-freebsd": [0, 2, 3, 25, 27, 28, 37, 58, 83, 84, 93, 94, 95, 96, 97, 100, 114, 117, 118], + "x86_64-unknown-fuchsia": [0, 2, 3, 25, 27, 28, 37, 44, 58, 72, 83, 84, 85, 86, 87, 92, 93, 94, 95, 96, 97, 101, 114, 117, 118], + "x86_64-unknown-linux-gnu": [0, 2, 3, 25, 27, 29, 37, 58, 83, 84, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "x86_64-unknown-linux-musl": [0, 2, 3, 25, 27, 32, 37, 46, 58, 83, 84, 93, 94, 95, 96, 97, 103, 114, 117, 118], + "x86_64-unknown-netbsd": [0, 2, 3, 25, 27, 28, 37, 58, 83, 84, 93, 94, 95, 96, 97, 105, 114, 117, 118], + "x86_64-unknown-none": [0, 1, 3, 25, 27, 28, 58, 93, 94, 95, 96, 97, 106, 114, 117], + "x86_64-unknown-openbsd": [0, 2, 3, 25, 27, 28, 37, 58, 83, 84, 93, 94, 95, 96, 97, 108, 114, 117, 118], + "x86_64-unknown-uefi": [0, 1, 3, 25, 27, 28, 58, 93, 94, 95, 96, 97, 109, 114, 117], +} diff --git a/tools/cfg_oracle/BUILD.bazel b/tools/cfg_oracle/BUILD.bazel new file mode 100644 index 0000000..0a3802c --- /dev/null +++ b/tools/cfg_oracle/BUILD.bazel @@ -0,0 +1,8 @@ +load("//rs:rust_binary.bzl", "rust_binary") + +rust_binary( + name = "cfg_oracle_generator", + srcs = ["main.rs"], + edition = "2021", + visibility = ["//rs/private:__pkg__"], +) diff --git a/tools/cfg_oracle/README.md b/tools/cfg_oracle/README.md new file mode 100644 index 0000000..9c13a3f --- /dev/null +++ b/tools/cfg_oracle/README.md @@ -0,0 +1,21 @@ +# Cargo cfg oracle data + +`rules_rs` uses the registered Rust compiler's baseline cfg values when it +evaluates Cargo target predicates. The checked-in table is generated for every +triple in `ALL_TARGET_TRIPLES` by running: + +```text +rustc --print=cfg --target= +``` + +Regenerate the tables after changing the registered Rust version or the list +of supported triples: + +```sh +bazel run //rs/private:update_cfg_target_data +bazel test //rs/private:cfg_parser_tests +bazel test //rs/private:update_cfg_target_data_tests +``` + +The generated-source test reruns the oracle and detects stale data. Target +triples not present in `ALL_TARGET_TRIPLES` are rejected. diff --git a/tools/cfg_oracle/main.rs b/tools/cfg_oracle/main.rs new file mode 100644 index 0000000..b62b8f5 --- /dev/null +++ b/tools/cfg_oracle/main.rs @@ -0,0 +1,163 @@ +use std::collections::{BTreeMap, BTreeSet}; +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::{Command, ExitCode}; + +struct Options { + rustc: PathBuf, + output: PathBuf, + triples: Vec, +} + +fn parse_options() -> Result { + let mut args = env::args().skip(1); + let mut rustc = None; + let mut output = None; + let mut triples = Vec::new(); + + while let Some(arg) = args.next() { + let value = args + .next() + .ok_or_else(|| format!("missing value for {arg}"))?; + match arg.as_str() { + "--rustc" => rustc = Some(PathBuf::from(value)), + "--output" => output = Some(PathBuf::from(value)), + "--triple" => triples.push(value), + _ => return Err(format!("unknown argument: {arg}")), + } + } + + if triples.is_empty() { + return Err("at least one --triple is required".to_owned()); + } + triples.sort(); + if triples.windows(2).any(|pair| pair[0] == pair[1]) { + return Err("duplicate target triple".to_owned()); + } + + Ok(Options { + rustc: rustc.ok_or("--rustc is required")?, + output: output.ok_or("--output is required")?, + triples, + }) +} + +fn run_rustc(rustc: &Path, args: &[&str]) -> Result { + let output = Command::new(rustc) + .args(args) + .output() + .map_err(|error| format!("failed to execute {}: {error}", rustc.display()))?; + if !output.status.success() { + return Err(format!( + "{} {} failed:\n{}", + rustc.display(), + args.join(" "), + String::from_utf8_lossy(&output.stderr) + )); + } + String::from_utf8(output.stdout) + .map_err(|error| format!("rustc emitted non-UTF-8 output: {error}")) +} + +fn starlark_string(value: &str) -> String { + let mut result = String::from("\""); + for ch in value.chars() { + match ch { + '\\' => result.push_str("\\\\"), + '"' => result.push_str("\\\""), + '\n' => result.push_str("\\n"), + '\r' => result.push_str("\\r"), + '\t' => result.push_str("\\t"), + _ => result.push(ch), + } + } + result.push('"'); + result +} + +fn header(version: &str) -> String { + format!( + "\"\"\"Generated Cargo cfg data. Do not edit by hand.\n\nGenerated by //rs/private:generated_cfg_target_data.\nOracle: {version}\n\"\"\"\n\n" + ) +} + +fn render(version: &str, cfgs: &BTreeMap>) -> String { + let atoms: BTreeSet<&str> = cfgs + .values() + .flat_map(|values| values.iter().map(String::as_str)) + .collect(); + let atoms: Vec<&str> = atoms.into_iter().collect(); + let atom_ids: BTreeMap<&str, usize> = atoms + .iter() + .enumerate() + .map(|(index, atom)| (*atom, index)) + .collect(); + + let mut output = header(version); + output.push_str("CFG_ATOMS = [\n"); + for atom in &atoms { + output.push_str(" "); + output.push_str(&starlark_string(atom)); + output.push_str(",\n"); + } + output.push_str("]\n\nCFG_ATOM_IDS_BY_TRIPLE = {\n"); + for (triple, values) in cfgs { + output.push_str(" "); + output.push_str(&starlark_string(triple)); + output.push_str(": ["); + for (index, value) in values.iter().enumerate() { + if index != 0 { + output.push_str(", "); + } + output.push_str(&atom_ids[value.as_str()].to_string()); + } + output.push_str("],\n"); + } + output.push_str("}\n"); + output +} + +fn write(path: &Path, content: &str) -> Result<(), String> { + if let Some(parent) = path.parent() { + fs::create_dir_all(parent) + .map_err(|error| format!("failed to create {}: {error}", parent.display()))?; + } + fs::write(path, content).map_err(|error| format!("failed to write {}: {error}", path.display())) +} + +fn run() -> Result<(), String> { + let options = parse_options()?; + let verbose_version = run_rustc(&options.rustc, &["--version", "--verbose"])?; + let version = verbose_version + .lines() + .next() + .ok_or("rustc --version --verbose returned no output")?; + + let mut cfgs = BTreeMap::new(); + for triple in options.triples { + let output = run_rustc( + &options.rustc, + &["--print=cfg", &format!("--target={triple}")], + )?; + let values: BTreeSet = output + .lines() + .filter(|line| !line.is_empty()) + .map(str::to_owned) + .collect(); + cfgs.insert(triple, values.into_iter().collect()); + } + + write(&options.output, &render(version, &cfgs))?; + Ok(()) +} + +fn main() -> ExitCode { + match run() { + Ok(()) => ExitCode::SUCCESS, + Err(error) => { + eprintln!("{error}"); + ExitCode::FAILURE + } + } +}