Parcourir la source

Improve `-c dbg`, enabling Split DWARF and other enhancements (#4382)

This should substantially reduce the total build size of `-c dbg`
builds, and especially improve cache hits during incremental
development. I'm seeing over 50% reduction total on Linux in just the
raw size of a complete debug build. Even on macOS where we can't use
split DWARF there are substantial reductions.

Note that LLDB and GDB want slightly different flags to have the best
experience with split debug information, and so the build and
documentation have been updated to enable LLDB's flags by default but
provide clear instructions for switching to GDB's flags, and they are
structured so that this can be done persistently for an individual
developer.
Chandler Carruth il y a 1 an
Parent
commit
33954d1f20
3 fichiers modifiés avec 144 ajouts et 16 suppressions
  1. 12 1
      .bazelrc
  2. 91 10
      bazel/cc_toolchains/clang_cc_toolchain_config.bzl
  3. 41 5
      docs/project/contribution_tools.md

+ 12 - 1
.bazelrc

@@ -109,10 +109,21 @@ build --test_env=ASAN_SYMBOLIZER_PATH
 # `en_US`.
 build --action_env=LANG=en_US.UTF-8
 
-# Enable libpfm for google_benchmark on Linux only.
+# Allow per-platform configuration.
 build --enable_platform_specific_config
+
+# Enable libpfm for google_benchmark on Linux only.
 build:linux --define=pfm=1
 
+# Enable split debug info on Linux, which is significantly more space efficient
+# and should work well with modern debuggers. Note that this is Linux specific
+# as macOS has its own approach that is always partially but not completely
+# split.
+#
+# Note: if using GDB, see documentation to get that working:
+# https://docs.carbon-lang.dev/docs/project/contribution_tools.html#debugging-with-gdb-instead-of-lldb
+build:linux --fission=yes
+
 # Disables `actions.declare_symlink`. Done for cross-environment support.
 build --allow_unresolved_symlinks=false
 

+ 91 - 10
bazel/cc_toolchains/clang_cc_toolchain_config.bzl

@@ -259,10 +259,6 @@ def _impl(ctx):
             flag_set(
                 actions = all_link_actions,
                 flag_groups = [
-                    flag_group(
-                        flags = ["-Wl,--gdb-index"],
-                        expand_if_available = "is_using_fission",
-                    ),
                     flag_group(
                         flags = ["-Wl,-S"],
                         expand_if_available = "strip_debug_symbols",
@@ -350,6 +346,7 @@ def _impl(ctx):
     # minimal settings if both are enabled.
     minimal_debug_info_flags = feature(
         name = "minimal_debug_info_flags",
+        implies = ["debug_info_compression_flags"],
         flag_sets = [
             flag_set(
                 actions = codegen_compile_actions,
@@ -361,24 +358,81 @@ def _impl(ctx):
             ),
         ],
     )
-    default_debug_info_flags = feature(
-        name = "default_debug_info_flags",
+    debug_info_flags = feature(
+        name = "debug_info_flags",
+        implies = ["debug_info_compression_flags"],
+        flag_sets = [
+            flag_set(
+                actions = codegen_compile_actions,
+                flag_groups = ([
+                    flag_group(
+                        flags = ["-g", "-gsimple-template-names"],
+                    ),
+                    flag_group(
+                        flags = ["-gsplit-dwarf"],
+                        expand_if_available = "per_object_debug_info_file",
+                    ),
+                ]),
+            ),
+        ],
+    )
+    debug_info_compression_flags = feature(
+        name = "debug_info_compression_flags",
+        flag_sets = [
+            flag_set(
+                actions = codegen_compile_actions + all_link_actions,
+                flag_groups = ([
+                    flag_group(
+                        flags = ["-gz"],
+                    ),
+                ]),
+            ),
+        ],
+    )
+
+    # Define a set of mutually exclusive debugger flags.
+    debugger_flags = feature(name = "debugger_flags")
+    lldb_flags = feature(
+        # Use a convenient name for users to select if needed.
+        name = "lldb_flags",
+        # Default enable LLDB-optimized flags whenever debugging.
         enabled = True,
+        requires = [feature_set(features = ["debug_info_flags"])],
+        provides = ["debugger_flags"],
         flag_sets = [
             flag_set(
                 actions = codegen_compile_actions,
                 flag_groups = ([
                     flag_group(
-                        flags = ["-g"],
+                        flags = ["-glldb", "-gpubnames"],
                     ),
                 ]),
-                with_features = [with_feature_set(features = ["dbg"])],
             ),
+        ],
+    )
+    gdb_flags = feature(
+        # Use a convenient name for users to select if needed.
+        name = "gdb_flags",
+        requires = [feature_set(features = ["debug_info_flags"])],
+        provides = ["debugger_flags"],
+        flag_sets = [
             flag_set(
                 actions = codegen_compile_actions,
+                flag_groups = ([
+                    flag_group(
+                        flags = ["-ggdb"],
+                    ),
+                    flag_group(
+                        flags = ["-ggnu-pubnames"],
+                        expand_if_available = "per_object_debug_info_file",
+                    ),
+                ]),
+            ),
+            flag_set(
+                actions = all_link_actions,
                 flag_groups = [
                     flag_group(
-                        flags = ["-gsplit-dwarf", "-g"],
+                        flags = ["-Wl,--gdb-index"],
                         expand_if_available = "per_object_debug_info_file",
                     ),
                 ],
@@ -386,6 +440,18 @@ def _impl(ctx):
         ],
     )
 
+    # An enabled feature that requires the `dbg` compilation mode. This is used
+    # to toggle on more general features to use by default, while allowing those
+    # general features to be explicitly enabled where needed.
+    enable_in_dbg = feature(
+        name = "enable_in_dbg",
+        enabled = True,
+        requires = [feature_set(["dbg"])],
+        implies = [
+            "debug_info_flags",
+        ],
+    )
+
     # This feature can be enabled in conjunction with any optimizations to
     # ensure accurate call stacks and backtraces for profilers or errors.
     preserve_call_stacks = feature(
@@ -1029,6 +1095,16 @@ def _impl(ctx):
         feature(name = "supports_dynamic_linker", enabled = ctx.attr.target_os == "linux"),
         feature(name = "supports_pic", enabled = True),
         feature(name = "supports_start_end_lib", enabled = ctx.attr.target_os == "linux"),
+
+        # Enable split debug info whenever debug info is requested.
+        feature(
+            name = "per_object_debug_info",
+            enabled = True,
+            # This has to be directly conditioned on requesting debug info at
+            # all, otherwise Bazel will look for an extra output file and not
+            # find one.
+            requires = [feature_set(features = ["debug_info_flags"])],
+        ),
     ]
 
     # The order of the features determines the relative order of flags used.
@@ -1038,7 +1114,12 @@ def _impl(ctx):
         minimal_optimization_flags,
         default_optimization_flags,
         minimal_debug_info_flags,
-        default_debug_info_flags,
+        debug_info_flags,
+        debug_info_compression_flags,
+        debugger_flags,
+        lldb_flags,
+        gdb_flags,
+        enable_in_dbg,
         preserve_call_stacks,
         sysroot_feature,
         sanitizer_common_flags,

+ 41 - 5
docs/project/contribution_tools.md

@@ -27,6 +27,9 @@ contributions.
     -   [Old LLVM versions](#old-llvm-versions)
     -   [Asking for help](#asking-for-help)
 -   [Troubleshooting debug issues](#troubleshooting-debug-issues)
+    -   [Debugging with GDB instead of LLDB](#debugging-with-gdb-instead-of-lldb)
+    -   [Disabling split debug info](#disabling-split-debug-info)
+    -   [Debugging other build modes](#debugging-other-build-modes)
     -   [Debugging on MacOS](#debugging-on-macos)
 
 <!-- tocstop -->
@@ -55,6 +58,7 @@ sudo apt install \
   libc++-dev \
   libc++abi-dev \
   lld \
+  lldb \
   python3 \
   pipx
 
@@ -90,7 +94,8 @@ sudo apt install \
   clang-16 \
   libc++-16-dev \
   libc++abi-16-dev \
-  lld-16
+  lld-16 \
+  lldb-16
 
 # In your Carbon checkout, tell Bazel where to find `clang`. You can also
 # export this path as the `CC` environment variable, or add it directly to
@@ -293,14 +298,32 @@ example:
 bazel build -c dbg //toolchain
 ```
 
-Then debugging works with GDB:
+Then debugging works with LLDB:
 
 ```shell
-gdb bazel-bin/toolchain/install/prefix_root/bin/carbon
+lldb bazel-bin/toolchain/install/prefix_root/bin/carbon
 ```
 
-Note that LLVM uses DWARF v5 debug symbols, which means that GDB version 10.1 or
-newer is required. If you see an error like this:
+Any installed version of LLDB at least as recent as the installed Clang used for
+building should work.
+
+### Debugging with GDB instead of LLDB
+
+If you prefer using GDB, you may want to pass some extra flags to the build:
+
+```shell
+bazel build -c dbg --features=-lldb_flags --features=gdb_flags //toolchain
+```
+
+Or you can add them to your `user.bazelrc`, they are designed to be safe to pass
+at all times and only have effect when building with debug information:
+
+```shell
+echo "build --features=-lldb_flags --features=gdb_flags" >> user.bazelrc
+```
+
+Note that on Linux we use Split DWARF and DWARF v5 debug symbols, which means
+that GDB version 10.1 or newer is required. If you see an error like this:
 
 ```shell
 Dwarf Error: DW_FORM_strx1 found in non-DWO CU
@@ -309,6 +332,19 @@ Dwarf Error: DW_FORM_strx1 found in non-DWO CU
 It means that the version of GDB used is too old, and does not support the DWARF
 v5 format.
 
+### Disabling split debug info
+
+Our build uses split debug info by default on Linux to improve build and
+debugger performance and reduce the size impact of debug information which can
+be extremely large. If you encounter problems, you can disable it by passing
+`--fission=no` to Bazel.
+
+### Debugging other build modes
+
+If you have an issue that only reproduces with another build mode, you can still
+enable debug information in that mode by passing `--feature=debug_info_flags` to
+Bazel.
+
 ### Debugging on MacOS
 
 Bazel sandboxes builds, which on MacOS makes it hard for the debugger to locate