@@ -884,9 +884,14 @@ def _should_add_oso_prefix(toolchain):
884884def _extract_allowed_unstable_features_from_flags (rust_flags , all_allowed_unstable_features ):
885885 other_flags = []
886886 for flag in rust_flags :
887- if flag .startswith ("-Zallow-features=" ):
888- all_allowed_unstable_features .extend (flag .removeprefix ("-Zallow-features=" ).split ("," ))
887+ if type (flag ) == "string" :
888+ if flag .startswith ("-Zallow-features=" ):
889+ all_allowed_unstable_features .extend (flag .removeprefix ("-Zallow-features=" ).split ("," ))
890+ else :
891+ other_flags .append (flag )
889892 else :
893+ # It's a tuple/list (format_string, File), or at least not a string.
894+ # We assume it's not a -Zallow-features flag.
890895 other_flags .append (flag )
891896 return other_flags
892897
@@ -961,21 +966,22 @@ def construct_arguments(
961966 ambiguous_libs (dict): Ambiguous libs, see `_disambiguate_libs`
962967 output_hash (str): The hashed path of the crate root
963968 rust_flags (list or Args): Additional flags to pass to rustc. Accepts
964- either a plain `list[str]` (folded into the main `rustc_flags`
965- `Args` so flags intermix with the rest of the command line,
966- with any `-Zallow-features=` entries extracted and merged
967- with `unstable_rust_features_config`) or a `ctx.actions.args()`
968- `Args` object (returned on the `args` struct as
969- `extra_rustc_flags` and appended to `args.all` as a separate
969+ either a plain `list[str | (str, File) ]` (folded into the main
970+ `rustc_flags` ` Args` so flags intermix with the rest of the
971+ command line, with any `-Zallow-features=` entries extracted and
972+ merged with `unstable_rust_features_config`) or a
973+ `ctx.actions.args()` ` Args` object (returned on the `args` struct
974+ as `extra_rustc_flags` and appended to `args.all` as a separate
970975 entry, since `Args` cannot be merged with one another). The
971976 `Args` form is opaque at analysis time, so any
972977 `-Zallow-features=` it carries passes through to rustc
973978 unchanged — callers that need it merged with
974- `unstable_rust_features_config` should keep using the
975- `list[str]` form. Use the `Args` form when the caller needs
976- `Args.add_all` features such as `map_each` (e.g. for
977- `File`-derived flags that must be rewritten by Bazel path
978- mapping).
979+ `unstable_rust_features_config` should keep using the list form.
980+ Use the `Args` form when the caller needs `Args.add_all` features
981+ such as `map_each`. For individual `File`-derived flags that must
982+ be rewritten by Bazel path mapping, they can be passed as
983+ `(format_string, File)` tuples within the list form (e.g.
984+ `("-Zsplit-dwarf-out-dir=%s", dwo_outputs)`).
979985 out_dir (File, optional): The build script's output directory.
980986 When provided, the directory is handed to `process_wrapper`
981987 via an explicit `--out-dir <path>` arg sourced from a
@@ -1237,27 +1243,37 @@ def construct_arguments(
12371243 uniquify = True ,
12381244 )
12391245
1240- # `rust_flags` is either a plain `list[str]` or a `ctx.actions.args()`
1241- # `Args` object. Lists are folded into the main `rustc_flags` `Args`
1242- # here, with any `-Zallow-features=` entries extracted into
1243- # `all_allowed_unstable_features` so they can be merged with
1244- # `unstable_rust_features_config` and re-emitted as a single arg
1245- # below. `Args` inputs cannot be merged with another `Args` and are
1246- # opaque at analysis time, so we capture the caller's `Args` here
1247- # and append it as a separate entry in `args.all` (after the
1248- # main `rustc_flags` `Args`, consistent with the existing "later
1249- # flags win" semantics). Any `-Zallow-features=` baked into an
1250- # `Args` value passes through to rustc unchanged — callers that
1251- # need it merged with `unstable_rust_features_config` should keep
1252- # using the `list[str]` form.
1246+ # `rust_flags` is either a plain `list[str | (format_string, File)]` or a
1247+ # `ctx.actions.args()` `Args` object.
1248+ #
1249+ # - Lists are folded into the main `rustc_flags` `Args` here, with any
1250+ # `-Zallow-features=` entries extracted into
1251+ # `all_allowed_unstable_features` so they can be merged with
1252+ # `unstable_rust_features_config` and re-emitted as a single arg below.
1253+ #
1254+ # - `Args` inputs cannot be merged with another `Args` and are opaque at
1255+ # analysis time, so we capture the caller's `Args` here and append it as a
1256+ # separate entry in `args.all` (after the main `rustc_flags` `Args`,
1257+ # consistent with the existing "later flags win" semantics). Any
1258+ # `-Zallow-features=` baked into an `Args` value passes through to rustc
1259+ # unchanged — callers that need it merged with
1260+ # `unstable_rust_features_config` should keep using the list form.
12531261 rust_flags_args = None
12541262 if type (rust_flags ) == "Args" :
12551263 rust_flags_args = rust_flags
12561264 elif rust_flags :
1257- rustc_flags .add_all (
1258- _extract_allowed_unstable_features_from_flags (rust_flags , all_allowed_unstable_features ),
1259- map_each = map_flag ,
1260- )
1265+ for flag in _extract_allowed_unstable_features_from_flags (rust_flags , all_allowed_unstable_features ):
1266+ if type (flag ) in ["tuple" , "list" ] and len (flag ) == 2 :
1267+ rustc_flags .add_all (
1268+ [flag [1 ]],
1269+ format_each = flag [0 ],
1270+ expand_directories = False ,
1271+ )
1272+ else :
1273+ if map_flag :
1274+ flag = map_flag (flag )
1275+ if flag != None :
1276+ rustc_flags .add (flag )
12611277
12621278 # Gather data path from crate_info since it is inherited from real crate for rust_doc and rust_test
12631279 # Deduplicate data paths due to https://github.com/bazelbuild/bazel/issues/14681
@@ -1706,6 +1722,22 @@ def rustc_compile_action(
17061722 elif ctx .attr .require_explicit_unstable_features == - 1 :
17071723 require_explicit_unstable_features = toolchain .require_explicit_unstable_features
17081724
1725+ use_split_debuginfo = (
1726+ feature_configuration and
1727+ cc_common .is_enabled (feature_configuration = feature_configuration , feature_name = "per_object_debug_info" ) and
1728+ ctx .fragments .cpp .fission_active_for_current_compilation_mode ()
1729+ )
1730+ if use_split_debuginfo :
1731+ rust_flags = rust_flags + [
1732+ "--codegen=split-debuginfo=unpacked" ,
1733+ "--codegen=debuginfo=full" ,
1734+ ]
1735+ fission_directory = crate_info .name + "_fission"
1736+ if output_hash :
1737+ fission_directory = fission_directory + "-" + output_hash
1738+ dwo_outputs = ctx .actions .declare_directory (fission_directory , sibling = crate_info .output )
1739+ rust_flags .append (("-Zsplit-dwarf-out-dir=%s" , dwo_outputs ))
1740+
17091741 args , env_from_args = construct_arguments (
17101742 ctx = ctx ,
17111743 attr = attr ,
@@ -1801,6 +1833,9 @@ def rustc_compile_action(
18011833 dsym_folder = ctx .actions .declare_directory (crate_info .output .basename + ".dSYM" , sibling = crate_info .output )
18021834 action_outputs .append (dsym_folder )
18031835
1836+ if use_split_debuginfo :
1837+ action_outputs .append (dwo_outputs ) # buildifier: disable=uninitialized
1838+
18041839 if ctx .executable ._process_wrapper :
18051840 # Run as normal
18061841 ctx .actions .run (
@@ -1864,15 +1899,19 @@ def rustc_compile_action(
18641899 else :
18651900 fail ("No process wrapper was defined for {}" .format (ctx .label ))
18661901
1902+ cco_args = {}
18671903 if experimental_use_cc_common_link :
18681904 # Wrap the main `.o` file into a compilation output suitable for
18691905 # cc_common.link. The main `.o` file is useful in both PIC and non-PIC
18701906 # modes.
1871- compilation_outputs = cc_common .create_compilation_outputs (
1872- objects = depset ([output_o ]),
1873- pic_objects = depset ([output_o ]),
1874- )
1875-
1907+ cco_args ["objects" ] = depset ([output_o ])
1908+ cco_args ["pic_objects" ] = depset ([output_o ])
1909+ if use_split_debuginfo :
1910+ cco_args ["dwo_objects" ] = depset ([dwo_outputs ]) # buildifier: disable=uninitialized
1911+ cco_args ["pic_dwo_objects" ] = depset ([dwo_outputs ]) # buildifier: disable=uninitialized
1912+ compilation_outputs = cc_common .create_compilation_outputs (** cco_args )
1913+ debug_context = cc_common .create_debug_context (compilation_outputs )
1914+ if experimental_use_cc_common_link :
18761915 malloc_library = ctx .attr ._custom_malloc or ctx .attr .malloc
18771916
18781917 # Collect the linking contexts of the standard library and dependencies.
@@ -2045,7 +2084,7 @@ def rustc_compile_action(
20452084 else :
20462085 providers .extend ([crate_info , dep_info ])
20472086
2048- providers += establish_cc_info (ctx , attr , crate_info , toolchain , cc_toolchain , feature_configuration , interface_library )
2087+ providers += establish_cc_info (ctx , attr , crate_info , toolchain , cc_toolchain , feature_configuration , interface_library , debug_context )
20492088
20502089 output_group_info = {}
20512090
@@ -2179,7 +2218,7 @@ def _add_codegen_units_flags(toolchain, emit, args):
21792218
21802219 args .add ("-Ccodegen-units={}" .format (toolchain ._codegen_units ))
21812220
2182- def establish_cc_info (ctx , attr , crate_info , toolchain , cc_toolchain , feature_configuration , interface_library ):
2221+ def establish_cc_info (ctx , attr , crate_info , toolchain , cc_toolchain , feature_configuration , interface_library , debug_context = None ):
21832222 """If the produced crate is suitable yield a CcInfo to allow for interop with cc rules
21842223
21852224 Args:
@@ -2190,6 +2229,7 @@ def establish_cc_info(ctx, attr, crate_info, toolchain, cc_toolchain, feature_co
21902229 cc_toolchain (CcToolchainInfo): The current `CcToolchainInfo`
21912230 feature_configuration (FeatureConfiguration): Feature configuration to be queried.
21922231 interface_library (File): Optional interface library for cdylib crates on Windows.
2232+ debug_context (CcDebugContextInfo): The current debug context.
21932233
21942234 Returns:
21952235 list: A list containing the `CcInfo` provider and optionally `AllocatorLibrariesImplInfo`
@@ -2258,7 +2298,10 @@ def establish_cc_info(ctx, attr, crate_info, toolchain, cc_toolchain, feature_co
22582298 )
22592299
22602300 cc_infos = [
2261- CcInfo (linking_context = linking_context ),
2301+ CcInfo (
2302+ linking_context = linking_context ,
2303+ debug_context = debug_context ,
2304+ ),
22622305 toolchain .stdlib_linkflags ,
22632306 ]
22642307
0 commit comments