Skip to content

Commit

Permalink
bazel: Add custom rule to produce android debug info
Browse files Browse the repository at this point in the history
When building the jni dylib for android, we previously stripped all
debug info to decrease the artifact size. With this change we now
produce the same stripped binary as before, but before stripping it we
create a dump of the debug info suitable for crash reporting.

This is made overly difficult for a few reasons:

1. Bazel doesn't support fission for Android bazelbuild/bazel#14765
2. Extra outputs from rules are not propagated up the dependency tree,
   so just building `android_dist` at the top level, isn't enough to get
   the extra outputs built as well
3. Building the library manually alongside the android artifact on the
   command line results in 2 separate builds, one for android as a
   transitive dependency of `android_dist` and one for the host
   platform

This change avoids #1 fission for now, but the same approach could be used
once that change makes its way to a bazel release.

This change ignores #2 but fixes #3 so it requires you to explicitly
build the library as part of the command line invocation if you want
debug info, like:

```
./bazelw build --fat_apk_cpu=... android_dist //library/common/jni:libenvoy_jni.so.debug_info
```

Theoretically we could probably shove this artifact into the aar to make
sure it was correctly produced, but that risks us accidentally shipping
that in the aar.

Signed-off-by: Keith Smiley <[email protected]>
  • Loading branch information
keith committed Feb 9, 2022
1 parent da9bc54 commit 7647bbd
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ build:tsan-dev --test_env="TSAN_OPTIONS=report_atomic_races=0"

# Exclude debug info from the release binary since it makes it too large to fit
# into a zip file. This shouldn't affect crash reports.
build:release-common --define=no_debug_info=1
build:release-ios --define=no_debug_info=1

# Flags for release builds targeting iOS
build:release-ios --apple_bitcode=embedded
Expand Down
60 changes: 60 additions & 0 deletions bazel/android_debug_info.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""
Rule to create objdump debug info from a native dynamic library built for
Android.
This is a workaround for generally not being able to produce dwp files for
Android https://github.com/bazelbuild/bazel/pull/14765
But even if we could create those we'd need to get them out of the build
somehow, this rule provides a separate --output_group for this
"""

def _impl(ctx):
library_outputs = []
objdump_outputs = []
for platform, dep in ctx.split_attr.dep.items():
# When --fat_apk_cpu isn't set, the platform is None
if len(dep.files.to_list()) != 1:
fail("Expected exactly one file in the library")

cc_toolchain = ctx.split_attr._cc_toolchain[platform][cc_common.CcToolchainInfo]
lib = dep.files.to_list()[0]
platform_name = platform or ctx.fragments.android.android_cpu
objdump_output = ctx.actions.declare_file(platform_name + "/symbols.objdump")

ctx.actions.run_shell(
inputs = [lib],
outputs = [objdump_output],
command = cc_toolchain.objdump_executable + " --dwarf=info --dwarf=rawline " + lib.path + ">" + objdump_output.path,
tools = [cc_toolchain.all_files],
)

strip_output = ctx.actions.declare_file(platform_name + "/" + lib.basename)
ctx.actions.run_shell(
inputs = [lib],
outputs = [strip_output],
command = cc_toolchain.strip_executable + " --strip-debug " + lib.path + " -o " + strip_output.path,
tools = [cc_toolchain.all_files],
)

library_outputs.append(strip_output)
objdump_outputs.append(objdump_output)

return [
DefaultInfo(files = depset(library_outputs + objdump_outputs)),
]

android_debug_info = rule(
implementation = _impl,
attrs = dict(
dep = attr.label(
providers = [CcInfo],
cfg = android_common.multi_cpu_configuration,
),
_cc_toolchain = attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
cfg = android_common.multi_cpu_configuration,
),
),
fragments = ["cpp", "android"],
)
8 changes: 7 additions & 1 deletion library/common/jni/BUILD
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("//bazel:kotlin_lib.bzl", "envoy_mobile_so_to_jni_lib")
load("//bazel:android_debug_info.bzl", "android_debug_info")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
load("@envoy//bazel:envoy_build_system.bzl", "envoy_package")
load("//bazel:envoy_mobile_test_extensions.bzl", "TEST_EXTENSIONS")
Expand Down Expand Up @@ -59,7 +60,7 @@ cc_binary(
"-llog",
] + select({
"@envoy//bazel:dbg_build": ["-Wl,--build-id=sha1"],
"//conditions:default": ["-Wl,-s"],
"//conditions:default": [],
}),
linkshared = True,
deps = [
Expand All @@ -68,6 +69,11 @@ cc_binary(
],
)

android_debug_info(
name = "libenvoy_jni.so.debug_info",
dep = "libenvoy_jni.so",
)

## Targets for local execution
# OS X binary (.jnilib) for NDK testing
envoy_mobile_so_to_jni_lib(
Expand Down
2 changes: 1 addition & 1 deletion library/kotlin/io/envoyproxy/envoymobile/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ android_artifacts(
archive_name = "envoy",
manifest = "EnvoyManifest.xml",
native_deps = [
"//library/common/jni:libenvoy_jni.so",
"//library/common/jni:libenvoy_jni.so.debug_info",
],
proguard_rules = "//library:proguard_rules",
visibility = ["//visibility:public"],
Expand Down

0 comments on commit 7647bbd

Please sign in to comment.