From 87f5db6d93e78bc9ccb5a7f6eded74b3c8630c15 Mon Sep 17 00:00:00 2001 From: Morten larsen Date: Fri, 30 Jan 2026 09:21:22 +0100 Subject: [PATCH 1/4] [feat] add support for dwo_files in DebugPackageInfo on bazel 9 --- cc/common/cc_debug_helper.bzl | 3 +- cc/private/debug_package_info.bzl | 1 + cc/private/rules_impl/cc_binary.bzl | 3 +- tests/debug_files/BUILD | 7 +++ tests/debug_files/dwo_files_test.bzl | 77 ++++++++++++++++++++++++++++ tests/debug_files/impl_lib.cc | 9 ++++ tests/debug_files/impl_lib.h | 8 +++ tests/debug_files/lib.cc | 8 +++ tests/debug_files/lib.h | 11 ++++ tests/debug_files/main.cc | 7 +++ 10 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 tests/debug_files/BUILD create mode 100644 tests/debug_files/dwo_files_test.bzl create mode 100644 tests/debug_files/impl_lib.cc create mode 100644 tests/debug_files/impl_lib.h create mode 100644 tests/debug_files/lib.cc create mode 100644 tests/debug_files/lib.h create mode 100644 tests/debug_files/main.cc diff --git a/cc/common/cc_debug_helper.bzl b/cc/common/cc_debug_helper.bzl index 70e442a08..af1bb51c7 100644 --- a/cc/common/cc_debug_helper.bzl +++ b/cc/common/cc_debug_helper.bzl @@ -62,7 +62,7 @@ def create_debug_packager_actions( dwo_files_list = dwo_files.to_list() if len(dwo_files_list) == 0: ctx.actions.write(dwp_output, "", False) - return + return dwo_files # We apply a hierarchical action structure to limit the maximum number of inputs to any # single action. @@ -98,6 +98,7 @@ def create_debug_packager_actions( inputs = packager["inputs"], outputs = packager["outputs"], ) + return dwo_files def _collect_transitive_dwo_artifacts(cc_compilation_outputs, cc_debug_context, linking_mode, use_pic, lto_backend_artifacts): dwo_files = [] diff --git a/cc/private/debug_package_info.bzl b/cc/private/debug_package_info.bzl index f090d9b61..f6e4194dc 100644 --- a/cc/private/debug_package_info.bzl +++ b/cc/private/debug_package_info.bzl @@ -22,5 +22,6 @@ DebugPackageInfo = provider( "stripped_file": "The stripped file (the explicit '.stripped' target).", "unstripped_file": "The unstripped file (the default executable target).", "dwp_file": "The .dwp file (for fission builds) or null if --fission=no.", + "dwo_files": "The depset of .dwo files (for fission builds) or null if --fission=no", }, ) diff --git a/cc/private/rules_impl/cc_binary.bzl b/cc/private/rules_impl/cc_binary.bzl index b6c3f8655..e86f2b09a 100644 --- a/cc/private/rules_impl/cc_binary.bzl +++ b/cc/private/rules_impl/cc_binary.bzl @@ -714,7 +714,7 @@ def cc_binary_impl(ctx, additional_linkopts, force_linkstatic = False): stripped_file = ctx.outputs.stripped_binary cc_helper.create_strip_action(ctx, cc_toolchain, cpp_config, binary, stripped_file, feature_configuration) dwp_file = ctx.outputs.dwp_file - create_debug_packager_actions( + dwo_files = create_debug_packager_actions( ctx, cc_toolchain, dwp_file, @@ -818,6 +818,7 @@ def cc_binary_impl(ctx, additional_linkopts, force_linkstatic = False): stripped_file = stripped_file, unstripped_file = binary, dwp_file = explicit_dwp_file, + dwo_files = dwo_files, ) binary_info = struct( files = files_to_build, diff --git a/tests/debug_files/BUILD b/tests/debug_files/BUILD new file mode 100644 index 000000000..e841d0dc5 --- /dev/null +++ b/tests/debug_files/BUILD @@ -0,0 +1,7 @@ +load("//tests/debug_files:dwo_files_test.bzl","dwo_files_test_suite") + + + +# Call a macro that defines targets that perform the tests at analysis time, +# and that can be executed with "bazel test" to return the result. +dwo_files_test_suite(name = "dwo_files_test") diff --git a/tests/debug_files/dwo_files_test.bzl b/tests/debug_files/dwo_files_test.bzl new file mode 100644 index 000000000..6e9bb32ba --- /dev/null +++ b/tests/debug_files/dwo_files_test.bzl @@ -0,0 +1,77 @@ +load("@bazel_skylib//lib:unittest.bzl", "asserts", "analysistest") +load("@rules_cc//cc:defs.bzl","cc_library","cc_binary") +load("@rules_cc//cc/common:debug_package_info.bzl","DebugPackageInfo") +load("@bazel_skylib//lib:new_sets.bzl", "sets") +load("@bazel_features//private:util.bzl", _bazel_version_ge = "ge") + +def _dwo_files_contents(ctx): + env = analysistest.begin(ctx) + + target_under_test = analysistest.target_under_test(env) + file_names = sets.make([f.short_path for f in target_under_test[DebugPackageInfo].dwo_files.to_list()]) + asserts.set_equals(env,sets.make([ + "tests/debug_files/_objs/lib/lib.dwo", + "tests/debug_files/_objs/impl_lib/impl_lib.dwo", + "tests/debug_files/_objs/main/main.dwo"]),file_names) + + return analysistest.end(env) + +def _dwo_files_no_contents(ctx): + env = analysistest.begin(ctx) + + target_under_test = analysistest.target_under_test(env) + asserts.equals(env,[],target_under_test[DebugPackageInfo].dwo_files.to_list()) + + return analysistest.end(env) + +dwo_files_contents_test = analysistest.make(_dwo_files_contents, +config_settings = { + "//command_line_option:fission": "yes", + "//command_line_option:features": ["per_object_debug_info"], +},) + +dwo_files_no_contents_test = analysistest.make(_dwo_files_no_contents, +config_settings = { + "//command_line_option:fission": "no", +}) + +def _test_provider_contents(): + cc_library( + name = "impl_lib", + hdrs = ["impl_lib.h"], + srcs = ["impl_lib.cc"], + ) + + cc_library( + name = "lib", + hdrs = ["lib.h"], + srcs = ["lib.cc"], + implementation_deps = [":impl_lib"], + ) + + cc_binary( + name = "main", + srcs = ["main.cc"], + deps = ["lib"], + + ) + + dwo_files_contents_test(name = "dwo_files_content_test", + target_under_test = ":main") + dwo_files_no_contents_test(name = "dwo_files_no_content_test", + target_under_test = ":main") + +def dwo_files_test_suite(name): + if _bazel_version_ge("9.0.0-pre.20250911"): + # we only test this if we are on a version where + # the DebugPackageInfo provider is defined by rules_cc + # and not bazel. + _test_provider_contents() + + native.test_suite( + name = name, + tests = [ + ":dwo_files_content_test", + ":dwo_files_no_content_test", + ], + ) diff --git a/tests/debug_files/impl_lib.cc b/tests/debug_files/impl_lib.cc new file mode 100644 index 000000000..2fafeb0e1 --- /dev/null +++ b/tests/debug_files/impl_lib.cc @@ -0,0 +1,9 @@ +#include "impl_lib.h" +#include + +namespace impl{ + void impl_func(){ + std::cout << "impl_func"; + } + +} diff --git a/tests/debug_files/impl_lib.h b/tests/debug_files/impl_lib.h new file mode 100644 index 000000000..33ee7d69b --- /dev/null +++ b/tests/debug_files/impl_lib.h @@ -0,0 +1,8 @@ +#ifndef TESTS_DEBUG_FILES_IMPL_LIB_H_ +#define TESTS_DEBUG_FILES_IMPL_LIB_H_ + +namespace impl{ + void impl_func(); +} + +#endif diff --git a/tests/debug_files/lib.cc b/tests/debug_files/lib.cc new file mode 100644 index 000000000..cdd721078 --- /dev/null +++ b/tests/debug_files/lib.cc @@ -0,0 +1,8 @@ +#include "lib.h" +#include + +namespace lib{ + void Lib::do_lib(){ + std::cout << "doing lib\n"; + } +} diff --git a/tests/debug_files/lib.h b/tests/debug_files/lib.h new file mode 100644 index 000000000..b39863a03 --- /dev/null +++ b/tests/debug_files/lib.h @@ -0,0 +1,11 @@ +#ifndef TESTS_DEBUG_FILES_LIB_HH_ +#define TESTS_DEBUG_FILES_LIB_HH_ + +namespace lib{ + class Lib{ + public: + void do_lib(); + }; +} + +#endif diff --git a/tests/debug_files/main.cc b/tests/debug_files/main.cc new file mode 100644 index 000000000..b95842541 --- /dev/null +++ b/tests/debug_files/main.cc @@ -0,0 +1,7 @@ +#include "lib.h" + +int main(int argc, char** argv){ + lib::Lib library; + library.do_lib(); + return 0; +} From 53a4d90d191b9faeb0edec1d67745c0f9e644da9 Mon Sep 17 00:00:00 2001 From: Morten larsen Date: Fri, 30 Jan 2026 09:46:56 +0100 Subject: [PATCH 2/4] force pic in the analysis test so the name is stable --- tests/debug_files/dwo_files_test.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/debug_files/dwo_files_test.bzl b/tests/debug_files/dwo_files_test.bzl index 6e9bb32ba..5f002b233 100644 --- a/tests/debug_files/dwo_files_test.bzl +++ b/tests/debug_files/dwo_files_test.bzl @@ -27,6 +27,7 @@ def _dwo_files_no_contents(ctx): dwo_files_contents_test = analysistest.make(_dwo_files_contents, config_settings = { "//command_line_option:fission": "yes", + "//command_line_option:force_pic": "no", "//command_line_option:features": ["per_object_debug_info"], },) From 808b86cbdebec1262c7c70c2056a567a6f50c384 Mon Sep 17 00:00:00 2001 From: Morten larsen Date: Fri, 30 Jan 2026 11:13:01 +0100 Subject: [PATCH 3/4] guard test against platforms that do not support fission + dwo files --- tests/debug_files/dwo_files_test.bzl | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/debug_files/dwo_files_test.bzl b/tests/debug_files/dwo_files_test.bzl index 5f002b233..787847b38 100644 --- a/tests/debug_files/dwo_files_test.bzl +++ b/tests/debug_files/dwo_files_test.bzl @@ -4,30 +4,30 @@ load("@rules_cc//cc/common:debug_package_info.bzl","DebugPackageInfo") load("@bazel_skylib//lib:new_sets.bzl", "sets") load("@bazel_features//private:util.bzl", _bazel_version_ge = "ge") -def _dwo_files_contents(ctx): +def _test_n_dwo_files(ctx, n): env = analysistest.begin(ctx) target_under_test = analysistest.target_under_test(env) - file_names = sets.make([f.short_path for f in target_under_test[DebugPackageInfo].dwo_files.to_list()]) - asserts.set_equals(env,sets.make([ - "tests/debug_files/_objs/lib/lib.dwo", - "tests/debug_files/_objs/impl_lib/impl_lib.dwo", - "tests/debug_files/_objs/main/main.dwo"]),file_names) + # We check if the dwp_file exists as a way to test + # if we should expect dwo files to be present + if target_under_test[DebugPackageInfo].dwp_file != None: + asserts.equals(env,n,len(target_under_test[DebugPackageInfo].dwo_files.to_list())) return analysistest.end(env) -def _dwo_files_no_contents(ctx): - env = analysistest.begin(ctx) - - target_under_test = analysistest.target_under_test(env) - asserts.equals(env,[],target_under_test[DebugPackageInfo].dwo_files.to_list()) +def _dwo_files_contents(ctx): + # We expect the DebugInfoProvider + # to contain one dwo file per "source" file + # and it must include dwo files from implementation deps + return _test_n_dwo_files(ctx,3) - return analysistest.end(env) +def _dwo_files_no_contents(ctx): + # without fission the list should be empty + return _test_n_dwo_files(ctx,0) dwo_files_contents_test = analysistest.make(_dwo_files_contents, config_settings = { "//command_line_option:fission": "yes", - "//command_line_option:force_pic": "no", "//command_line_option:features": ["per_object_debug_info"], },) From 8423021740d7109e9149d9abc2760ceb9d5ed1bb Mon Sep 17 00:00:00 2001 From: Morten larsen Date: Fri, 30 Jan 2026 11:15:46 +0100 Subject: [PATCH 4/4] fix formatting --- cc/common/cc_debug_helper.bzl | 2 + cc/private/rules_impl/cc_binary.bzl | 2 +- tests/debug_files/BUILD | 4 +- tests/debug_files/dwo_files_test.bzl | 55 +++++++++++++++++----------- 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/cc/common/cc_debug_helper.bzl b/cc/common/cc_debug_helper.bzl index af1bb51c7..f86e170bc 100644 --- a/cc/common/cc_debug_helper.bzl +++ b/cc/common/cc_debug_helper.bzl @@ -44,6 +44,8 @@ def create_debug_packager_actions( linking_mode: (str) See cc_helper.bzl%linker_mode use_pic: (bool) lto_artifacts: ([CcLtoBackendArtifacts]) + Returns: + dwo_files: (depset) The dwo_files used to generate the dwp_output """ dwo_files = _collect_transitive_dwo_artifacts( cc_compilation_outputs, diff --git a/cc/private/rules_impl/cc_binary.bzl b/cc/private/rules_impl/cc_binary.bzl index e86f2b09a..255102e3e 100644 --- a/cc/private/rules_impl/cc_binary.bzl +++ b/cc/private/rules_impl/cc_binary.bzl @@ -818,7 +818,7 @@ def cc_binary_impl(ctx, additional_linkopts, force_linkstatic = False): stripped_file = stripped_file, unstripped_file = binary, dwp_file = explicit_dwp_file, - dwo_files = dwo_files, + dwo_files = dwo_files, ) binary_info = struct( files = files_to_build, diff --git a/tests/debug_files/BUILD b/tests/debug_files/BUILD index e841d0dc5..a8f440a76 100644 --- a/tests/debug_files/BUILD +++ b/tests/debug_files/BUILD @@ -1,6 +1,4 @@ -load("//tests/debug_files:dwo_files_test.bzl","dwo_files_test_suite") - - +load("//tests/debug_files:dwo_files_test.bzl", "dwo_files_test_suite") # Call a macro that defines targets that perform the tests at analysis time, # and that can be executed with "bazel test" to return the result. diff --git a/tests/debug_files/dwo_files_test.bzl b/tests/debug_files/dwo_files_test.bzl index 787847b38..02e6089be 100644 --- a/tests/debug_files/dwo_files_test.bzl +++ b/tests/debug_files/dwo_files_test.bzl @@ -1,17 +1,21 @@ -load("@bazel_skylib//lib:unittest.bzl", "asserts", "analysistest") -load("@rules_cc//cc:defs.bzl","cc_library","cc_binary") -load("@rules_cc//cc/common:debug_package_info.bzl","DebugPackageInfo") -load("@bazel_skylib//lib:new_sets.bzl", "sets") +""" This module tests the DebugInfoProvider dwo_files functionality + +""" + load("@bazel_features//private:util.bzl", _bazel_version_ge = "ge") +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") +load("@rules_cc//cc/common:debug_package_info.bzl", "DebugPackageInfo") def _test_n_dwo_files(ctx, n): env = analysistest.begin(ctx) target_under_test = analysistest.target_under_test(env) + # We check if the dwp_file exists as a way to test # if we should expect dwo files to be present if target_under_test[DebugPackageInfo].dwp_file != None: - asserts.equals(env,n,len(target_under_test[DebugPackageInfo].dwo_files.to_list())) + asserts.equals(env, n, len(target_under_test[DebugPackageInfo].dwo_files.to_list())) return analysistest.end(env) @@ -19,22 +23,26 @@ def _dwo_files_contents(ctx): # We expect the DebugInfoProvider # to contain one dwo file per "source" file # and it must include dwo files from implementation deps - return _test_n_dwo_files(ctx,3) + return _test_n_dwo_files(ctx, 3) def _dwo_files_no_contents(ctx): # without fission the list should be empty - return _test_n_dwo_files(ctx,0) + return _test_n_dwo_files(ctx, 0) -dwo_files_contents_test = analysistest.make(_dwo_files_contents, -config_settings = { - "//command_line_option:fission": "yes", - "//command_line_option:features": ["per_object_debug_info"], -},) +dwo_files_contents_test = analysistest.make( + _dwo_files_contents, + config_settings = { + "//command_line_option:fission": "yes", + "//command_line_option:features": ["per_object_debug_info"], + }, +) -dwo_files_no_contents_test = analysistest.make(_dwo_files_no_contents, -config_settings = { - "//command_line_option:fission": "no", -}) +dwo_files_no_contents_test = analysistest.make( + _dwo_files_no_contents, + config_settings = { + "//command_line_option:fission": "no", + }, +) def _test_provider_contents(): cc_library( @@ -53,14 +61,17 @@ def _test_provider_contents(): cc_binary( name = "main", srcs = ["main.cc"], - deps = ["lib"], - + deps = ["lib"], ) - dwo_files_contents_test(name = "dwo_files_content_test", - target_under_test = ":main") - dwo_files_no_contents_test(name = "dwo_files_no_content_test", - target_under_test = ":main") + dwo_files_contents_test( + name = "dwo_files_content_test", + target_under_test = ":main", + ) + dwo_files_no_contents_test( + name = "dwo_files_no_content_test", + target_under_test = ":main", + ) def dwo_files_test_suite(name): if _bazel_version_ge("9.0.0-pre.20250911"):