diff --git a/.github/actions/build-electron/action.yml b/.github/actions/build-electron/action.yml index 77b3eeeaf4f6..98bf9105ecfa 100644 --- a/.github/actions/build-electron/action.yml +++ b/.github/actions/build-electron/action.yml @@ -17,9 +17,6 @@ inputs: is-release: description: 'Is release build' required: true - strip-binaries: - description: 'Strip binaries (Linux only)' - required: false generate-symbols: description: 'Generate symbols' required: true @@ -66,14 +63,6 @@ runs: NINJA_SUMMARIZE_BUILD=1 e build cp out/Default/.ninja_log out/electron_ninja_log node electron/script/check-symlinks.js - - name: Strip Electron Binaries ${{ inputs.step-suffix }} - shell: bash - if: ${{ inputs.strip-binaries == 'true' }} - run: | - cd src - electron/script/copy-debug-symbols.py --target-cpu="${{ inputs.target-arch }}" --out-dir=out/Default/debug --compress - electron/script/strip-binaries.py --target-cpu="${{ inputs.target-arch }}" --verbose - electron/script/add-debug-link.py --target-cpu="${{ inputs.target-arch }}" --debug-dir=out/Default/debug - name: Build Electron dist.zip ${{ inputs.step-suffix }} shell: bash run: | @@ -100,19 +89,6 @@ runs: sed $SEDOPTION '/.*builtins-pgo/d' out/Default/mksnapshot_args sed $SEDOPTION '/--turbo-profiling-input/d' out/Default/mksnapshot_args - if [ "${{ inputs.target-platform }}" = "linux" ]; then - if [ "${{ inputs.target-arch }}" = "arm" ]; then - electron/script/strip-binaries.py --file $PWD/out/Default/clang_x86_v8_arm/mksnapshot - electron/script/strip-binaries.py --file $PWD/out/Default/clang_x86_v8_arm/v8_context_snapshot_generator - elif [ "${{ inputs.target-arch }}" = "arm64" ]; then - electron/script/strip-binaries.py --file $PWD/out/Default/clang_x64_v8_arm64/mksnapshot - electron/script/strip-binaries.py --file $PWD/out/Default/clang_x64_v8_arm64/v8_context_snapshot_generator - else - electron/script/strip-binaries.py --file $PWD/out/Default/mksnapshot - electron/script/strip-binaries.py --file $PWD/out/Default/v8_context_snapshot_generator - fi - fi - e build --target electron:electron_mksnapshot_zip if [ "${{ inputs.target-platform }}" = "win" ]; then cd out/Default diff --git a/.github/workflows/linux-publish.yml b/.github/workflows/linux-publish.yml index 62b09a4e30ee..5903fc925c4b 100644 --- a/.github/workflows/linux-publish.yml +++ b/.github/workflows/linux-publish.yml @@ -50,7 +50,6 @@ jobs: is-release: true gn-build-type: release generate-symbols: true - strip-binaries: true upload-to-storage: ${{ inputs.upload-to-storage }} secrets: inherit @@ -66,7 +65,6 @@ jobs: is-release: true gn-build-type: release generate-symbols: true - strip-binaries: true upload-to-storage: ${{ inputs.upload-to-storage }} secrets: inherit @@ -82,6 +80,5 @@ jobs: is-release: true gn-build-type: release generate-symbols: true - strip-binaries: true upload-to-storage: ${{ inputs.upload-to-storage }} secrets: inherit diff --git a/.github/workflows/pipeline-segment-electron-build.yml b/.github/workflows/pipeline-segment-electron-build.yml index a6708c6065f6..b634e2b67570 100644 --- a/.github/workflows/pipeline-segment-electron-build.yml +++ b/.github/workflows/pipeline-segment-electron-build.yml @@ -48,11 +48,6 @@ on: required: true type: string default: '0' - strip-binaries: - description: 'Strip the binaries before release (Linux only)' - required: false - type: boolean - default: false is-asan: description: 'Building the Address Sanitizer (ASan) Linux build' required: false @@ -198,7 +193,6 @@ jobs: artifact-platform: ${{ inputs.target-platform == 'macos' && 'darwin' || inputs.target-platform }} is-release: '${{ inputs.is-release }}' generate-symbols: '${{ inputs.generate-symbols }}' - strip-binaries: '${{ inputs.strip-binaries }}' upload-to-storage: '${{ inputs.upload-to-storage }}' is-asan: '${{ inputs.is-asan }}' - name: Set GN_EXTRA_ARGS for MAS Build diff --git a/BUILD.gn b/BUILD.gn index 61968c074fe8..3ffb61f2021e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -44,6 +44,7 @@ if (is_mac) { if (is_linux) { import("//build/config/linux/pkg_config.gni") + import("//electron/build/linux/strip_binary.gni") import("//tools/generate_stubs/rules.gni") pkg_config("gio_unix") { @@ -1422,6 +1423,18 @@ dist_zip("electron_dist_zip") { ":licenses", ] if (is_linux) { + if (is_official_build) { + data_deps += [ + ":strip_chrome_crashpad_handler", + ":strip_chrome_sandbox", + ":strip_electron_binary", + ":strip_libEGL_shlib", + ":strip_libGLESv2_shlib", + ":strip_libffmpeg_shlib", + ":strip_libvk_swiftshader_shlib", + ] + } + data_deps += [ "//sandbox/linux:chrome_sandbox" ] } deps = data_deps @@ -1467,6 +1480,16 @@ group("electron_mksnapshot") { dist_zip("electron_mksnapshot_zip") { data_deps = mksnapshot_deps + if (is_linux && is_official_build) { + data_deps += [ + ":strip_libEGL_shlib", + ":strip_libGLESv2_shlib", + ":strip_libffmpeg_shlib", + ":strip_libvk_swiftshader_shlib", + ":strip_mksnapshot_binary", + ":strip_v8_context_snapshot_generator_binary", + ] + } deps = data_deps outputs = [ "$root_build_dir/mksnapshot.zip" ] } @@ -1591,3 +1614,78 @@ group("copy_node_headers") { group("node_headers") { public_deps = [ ":tar_node_headers" ] } + +if (is_linux && is_official_build) { + strip_binary("strip_electron_binary") { + binary_input = "$root_out_dir/$electron_project_name" + symbol_output = "$root_out_dir/debug/$electron_project_name.debug" + compress_debug_sections = true + deps = [ ":electron_app" ] + } + + strip_binary("strip_chrome_crashpad_handler") { + binary_input = "$root_out_dir/chrome_crashpad_handler" + symbol_output = "$root_out_dir/debug/chrome_crashpad_handler.debug" + compress_debug_sections = true + deps = [ "//components/crash/core/app:chrome_crashpad_handler" ] + } + + strip_binary("strip_chrome_sandbox") { + binary_input = "$root_out_dir/chrome_sandbox" + symbol_output = "$root_out_dir/debug/chrome-sandbox.debug" + compress_debug_sections = true + deps = [ "//sandbox/linux:chrome_sandbox" ] + } + + strip_binary("strip_libEGL_shlib") { + binary_input = "$root_out_dir/libEGL.so" + symbol_output = "$root_out_dir/debug/libEGL.so.debug" + compress_debug_sections = true + deps = [ "//third_party/angle:libEGL" ] + } + + strip_binary("strip_libGLESv2_shlib") { + binary_input = "$root_out_dir/libGLESv2.so" + symbol_output = "$root_out_dir/debug/libGLESv2.so.debug" + compress_debug_sections = true + deps = [ "//third_party/angle:libGLESv2" ] + } + + strip_binary("strip_libffmpeg_shlib") { + binary_input = "$root_out_dir/libffmpeg.so" + symbol_output = "$root_out_dir/debug/libffmpeg.so.debug" + compress_debug_sections = true + deps = [ "//third_party/ffmpeg" ] + } + + strip_binary("strip_libvk_swiftshader_shlib") { + binary_input = "$root_out_dir/libvk_swiftshader.so" + symbol_output = "$root_out_dir/debug/libvk_swiftshader.so.debug" + compress_debug_sections = true + deps = [ "//third_party/swiftshader/src/Vulkan:swiftshader_libvulkan" ] + } + + strip_binary("strip_mksnapshot_binary") { + _binary_path = rebase_path( + get_label_info( + ":v8_context_snapshot_generator($v8_snapshot_toolchain)", + "root_out_dir") + "/mksnapshot", + root_build_dir) + binary_input = "$root_out_dir/$_binary_path" + symbol_output = "$root_out_dir/debug/${_binary_path}.debug" + compress_debug_sections = true + deps = mksnapshot_deps + } + + strip_binary("strip_v8_context_snapshot_generator_binary") { + _binary_path = rebase_path( + get_label_info( + ":v8_context_snapshot_generator($v8_snapshot_toolchain)", + "root_out_dir") + "/v8_context_snapshot_generator", + root_build_dir) + binary_input = "$root_out_dir/$_binary_path" + symbol_output = "$root_out_dir/debug/${_binary_path}.debug" + compress_debug_sections = true + deps = mksnapshot_deps + } +} diff --git a/build/args/all.gn b/build/args/all.gn index fdeb59e8b58e..1f79dea5ca71 100644 --- a/build/args/all.gn +++ b/build/args/all.gn @@ -69,3 +69,6 @@ v8_expose_public_symbols = true # Disable snapshotting a page when printing for its content to be analyzed for # sensitive content by enterprise users. enterprise_cloud_content_analysis = false + +# We don't use anything from here, and it causes target collisions +enable_linux_installer = false diff --git a/build/linux/strip_binary.gni b/build/linux/strip_binary.gni new file mode 100644 index 000000000000..6e10a9da60e0 --- /dev/null +++ b/build/linux/strip_binary.gni @@ -0,0 +1,70 @@ +# Copyright 2021 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This has been adapted from https://source.chromium.org/chromium/chromium/src/+/main:build/linux/strip_binary.gni;drc=c220a41e0422d45f1657c28146d32e99cc53640b +# The notable difference is it has an option to compress the debug sections + +import("//build/config/clang/clang.gni") +import("//build/toolchain/toolchain.gni") + +# Extracts symbols from a binary into a symbol file. +# +# Args: +# binary_input: Path to the binary containing symbols to extract, e.g.: +# "$root_out_dir/chrome" +# symbol_output: Desired output file for symbols, e.g.: +# "$root_out_dir/chrome.debug" +# stripped_binary_output: Desired output file for stripped file, e.g.: +# "$root_out_dir/chrome.stripped" +# compress_debug_sections: If true, compress the extracted debug sections +template("strip_binary") { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + action("${target_name}") { + llvm_strip_binary = "${clang_base_path}/bin/llvm-strip" + llvm_objcopy_binary = "${clang_base_path}/bin/llvm-objcopy" + script = "//electron/build/linux/strip_binary.py" + + if (defined(invoker.stripped_binary_output)) { + stripped_binary_output = invoker.stripped_binary_output + } else { + stripped_binary_output = invoker.binary_input + ".stripped" + } + if (defined(invoker.symbol_output)) { + symbol_output = invoker.symbol_output + } else { + symbol_output = invoker.binary_input + ".debug" + } + + inputs = [ + invoker.binary_input, + llvm_strip_binary, + llvm_objcopy_binary, + ] + outputs = [ + symbol_output, + stripped_binary_output, + ] + args = [ + "--llvm-strip-binary-path", + rebase_path(llvm_strip_binary, root_build_dir), + "--llvm-objcopy-binary-path", + rebase_path(llvm_objcopy_binary, root_build_dir), + "--symbol-output", + rebase_path(symbol_output, root_build_dir), + "--stripped-binary-output", + rebase_path(stripped_binary_output, root_build_dir), + "--binary-input", + rebase_path(invoker.binary_input, root_build_dir), + ] + + if (defined(invoker.compress_debug_sections) && + invoker.compress_debug_sections) { + args += [ "--compress-debug-sections" ] + } + } +} diff --git a/build/linux/strip_binary.py b/build/linux/strip_binary.py new file mode 100644 index 000000000000..015295f1f888 --- /dev/null +++ b/build/linux/strip_binary.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# +# Copyright 2021 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This has been adapted from https://source.chromium.org/chromium/chromium/src/+/main:build/linux/strip_binary.py;drc=c220a41e0422d45f1657c28146d32e99cc53640b +# The notable difference is it has an option to compress the debug sections + +import argparse +import subprocess +import sys + + +def main() -> int: + parser = argparse.ArgumentParser(description="Strip binary using LLVM tools.") + parser.add_argument("--llvm-strip-binary-path", + help="Path to llvm-strip executable.") + parser.add_argument("--llvm-objcopy-binary-path", + required=True, + help="Path to llvm-objcopy executable.") + parser.add_argument("--binary-input", help="Input ELF binary.") + parser.add_argument("--symbol-output", + help="File to write extracted debug info (.debug).") + parser.add_argument("--compress-debug-sections", + action="store_true", + help="Compress extracted debug info.") + parser.add_argument("--stripped-binary-output", + help="File to write stripped binary.") + args = parser.parse_args() + + # Replicate the behavior of: + # eu-strip -o -f + + objcopy_args = [ + "--only-keep-debug", + args.binary_input, + args.symbol_output, + ] + + if args.compress_debug_sections: + objcopy_args.insert(0, "--compress-debug-sections") + + subprocess.check_output([args.llvm_objcopy_binary_path] + objcopy_args) + subprocess.check_output([ + args.llvm_strip_binary_path, + "--strip-debug", + "--strip-unneeded", + "-o", + args.stripped_binary_output, + args.binary_input, + ]) + subprocess.check_output([ + args.llvm_objcopy_binary_path, + f"--add-gnu-debuglink={args.symbol_output}", + args.stripped_binary_output, + ]) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/build/zip.py b/build/zip.py index 86e1ea7c563d..ff9b83405488 100644 --- a/build/zip.py +++ b/build/zip.py @@ -41,6 +41,8 @@ PATHS_TO_SKIP = [ 'resources/inspector', 'gen/third_party/devtools-frontend/src', 'gen/ui/webui', + # Skip because these get zipped separately in script/zip-symbols.py + 'debug', ] def skip_path(dep, dist_zip, target_cpu): @@ -80,6 +82,11 @@ def main(argv): dep = dep.strip() if not skip_path(dep, dist_zip, target_cpu): dist_files.add(dep) + # On Linux, filter out any files which have a .stripped companion + if sys.platform == 'linux': + dist_files = { + dep for dep in dist_files if f"{dep.removeprefix('./')}.stripped" not in dist_files + } if sys.platform == 'darwin' and not should_flatten: execute(['zip', '-r', '-y', dist_zip] + list(dist_files)) else: @@ -96,10 +103,13 @@ def main(argv): dirname = os.path.dirname(dep) arcname = ( os.path.join(dirname, 'chrome-sandbox') - if basename == 'chrome_sandbox' + if basename.removesuffix('.stripped') == 'chrome_sandbox' else dep ) name_to_write = arcname + # On Linux, strip the .stripped suffix from the name before zipping + if sys.platform == 'linux': + name_to_write = name_to_write.removesuffix('.stripped') if should_flatten: if flatten_relative_to: if name_to_write.startswith(flatten_relative_to): diff --git a/docs/development/build-instructions-gn.md b/docs/development/build-instructions-gn.md index 2efd0ba8d9dc..8a050a2f7929 100644 --- a/docs/development/build-instructions-gn.md +++ b/docs/development/build-instructions-gn.md @@ -191,12 +191,6 @@ $ ./out/Testing/electron ### Packaging -On linux, first strip the debugging and symbol information: - -```sh -$ electron/script/strip-binaries.py -d out/Release -``` - To package the electron build as a distributable zip file: ```sh diff --git a/script/add-debug-link.py b/script/add-debug-link.py deleted file mode 100755 index 49dda09caac9..000000000000 --- a/script/add-debug-link.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import sys - -from lib.config import PLATFORM -from lib.util import execute, get_linux_binaries, get_out_dir - -def add_debug_link_into_binaries(directory, target_cpu, debug_dir): - for binary in get_linux_binaries(): - binary_path = os.path.join(directory, binary) - if os.path.isfile(binary_path): - add_debug_link_into_binary(binary_path, target_cpu, debug_dir) - -def add_debug_link_into_binary(binary_path, target_cpu, debug_dir): - if PLATFORM == 'linux' and target_cpu in ('x86', 'arm', 'arm64'): - # Skip because no objcopy binary on the given target. - return - - debug_name = get_debug_name(binary_path) - # Make sure the path to the binary is not relative because of cwd param. - real_binary_path = os.path.realpath(binary_path) - cmd = ['objcopy', '--add-gnu-debuglink=' + debug_name, real_binary_path] - execute(cmd, cwd=debug_dir) - -def get_debug_name(binary_path): - return os.path.basename(binary_path) + '.debug' - -def main(): - args = parse_args() - if args.file: - add_debug_link_into_binary(args.file, args.target_cpu, args.debug_dir) - else: - add_debug_link_into_binaries(args.directory, args.target_cpu, - args.debug_dir) - -def parse_args(): - parser = argparse.ArgumentParser(description='Add debug link to binaries') - parser.add_argument('-d', '--directory', - help='Path to the dir that contains files to add links', - default=get_out_dir(), - required=False) - parser.add_argument('-f', '--file', - help='Path to a specific file to add debug link', - required=False) - parser.add_argument('-s', '--debug-dir', - help='Path to the dir that contain the debugs', - default=None, - required=True) - parser.add_argument('-v', '--verbose', - action='store_true', - help='Prints the output of the subprocesses') - parser.add_argument('--target-cpu', - default='', - required=False, - help='Target cpu of binaries to add debug link') - - return parser.parse_args() - -if __name__ == '__main__': - sys.exit(main()) diff --git a/script/copy-debug-symbols.py b/script/copy-debug-symbols.py deleted file mode 100755 index c49d6a423607..000000000000 --- a/script/copy-debug-symbols.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import sys - -from lib.config import PLATFORM -from lib.util import execute, get_linux_binaries, get_out_dir, safe_mkdir - -# It has to be done before stripping the binaries. -def copy_debug_from_binaries(directory, out_dir, target_cpu, compress): - for binary in get_linux_binaries(): - binary_path = os.path.join(directory, binary) - if os.path.isfile(binary_path): - copy_debug_from_binary(binary_path, out_dir, target_cpu, compress) - -def copy_debug_from_binary(binary_path, out_dir, target_cpu, compress): - if PLATFORM == 'linux' and target_cpu in ('x86', 'arm', 'arm64'): - # Skip because no objcopy binary on the given target. - return - debug_name = get_debug_name(binary_path) - cmd = ['objcopy', '--only-keep-debug'] - if compress: - cmd.extend(['--compress-debug-sections']) - cmd.extend([binary_path, os.path.join(out_dir, debug_name)]) - execute(cmd) - -def get_debug_name(binary_path): - return os.path.basename(binary_path) + '.debug' - -def main(): - args = parse_args() - safe_mkdir(args.out_dir) - if args.file: - copy_debug_from_binary(args.file, args.out_dir, args.target_cpu, - args.compress) - else: - copy_debug_from_binaries(args.directory, args.out_dir, args.target_cpu, - args.compress) - -def parse_args(): - parser = argparse.ArgumentParser(description='Copy debug from binaries') - parser.add_argument('-d', '--directory', - help='Path to the dir that contains files to copy', - default=get_out_dir(), - required=False) - parser.add_argument('-f', '--file', - help='Path to a specific file to copy debug symbols', - required=False) - parser.add_argument('-o', '--out-dir', - help='Path to the dir that will contain the debugs', - default=None, - required=True) - parser.add_argument('-v', '--verbose', - action='store_true', - help='Prints the output of the subprocesses') - parser.add_argument('--target-cpu', - default='', - required=False, - help='Target cpu of binaries to copy debug symbols') - parser.add_argument('--compress', - action='store_true', - required=False, - help='Compress the debug symbols') - - return parser.parse_args() - -if __name__ == '__main__': - sys.exit(main()) diff --git a/script/lib/util.py b/script/lib/util.py index bc70cb2ed1b5..38bb70cc8d02 100644 --- a/script/lib/util.py +++ b/script/lib/util.py @@ -207,14 +207,3 @@ def get_depot_tools_executable(name): if sys.platform == 'win32': path += '.bat' return path - -def get_linux_binaries(): - return [ - 'chrome-sandbox', - 'chrome_crashpad_handler', - get_electron_branding()['project_name'], - 'libEGL.so', - 'libGLESv2.so', - 'libffmpeg.so', - 'libvk_swiftshader.so', - ] diff --git a/script/strip-binaries.py b/script/strip-binaries.py deleted file mode 100755 index 61fd54386294..000000000000 --- a/script/strip-binaries.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import sys - -from lib.config import set_verbose_mode, is_verbose_mode, verbose_mode_print -from lib.util import execute, get_linux_binaries, get_out_dir - -def get_size(path): - size = os.path.getsize(path) - units = ["bytes", "KB", "MB", "GB"] - for unit in units: - if size < 1024: - return f"{size:.2f} {unit}" - size /= 1024 - raise ValueError("File size is too large to be processed") - -def strip_binaries(directory, target_cpu): - if not os.path.isdir(directory): - verbose_mode_print('Directory ' + directory + ' does not exist.') - return - - verbose_mode_print('Stripping binaries in ' + directory) - for binary in get_linux_binaries(): - verbose_mode_print('\nStripping ' + binary) - binary_path = os.path.join(directory, binary) - if os.path.isfile(binary_path): - strip_binary(binary_path, target_cpu) - -def strip_binary(binary_path, target_cpu): - if target_cpu == 'arm': - strip = 'arm-linux-gnueabihf-strip' - elif target_cpu == 'arm64': - strip = 'aarch64-linux-gnu-strip' - else: - strip = 'strip' - - strip_args = [strip, - '--discard-all', - '--strip-debug', - '--preserve-dates', - binary_path] - if (is_verbose_mode()): - strip_args.insert(1, '--verbose') - verbose_mode_print('Binary size before stripping: ' + - str(get_size(binary_path))) - execute(strip_args) - verbose_mode_print('Binary size after stripping: ' + - str(get_size(binary_path))) - -def main(): - args = parse_args() - set_verbose_mode(args.verbose) - if args.file: - strip_binary(args.file, args.target_cpu) - else: - strip_binaries(args.directory, args.target_cpu) - -def parse_args(): - parser = argparse.ArgumentParser(description='Strip linux binaries') - parser.add_argument('-d', '--directory', - help='Path to the dir that contains files to strip.', - default=get_out_dir(), - required=False) - parser.add_argument('-f', '--file', - help='Path to a specific file to strip.', - required=False) - parser.add_argument('-v', '--verbose', - default=False, - action='store_true', - help='Prints the output of the subprocesses') - parser.add_argument('--target-cpu', - default='', - required=False, - help='Target cpu of binaries to strip') - - return parser.parse_args() - -if __name__ == '__main__': - sys.exit(main())