| # Copyright 2020 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import os |
| from recipe_engine import recipe_api |
| |
| |
| class DebugSymbolsApi(recipe_api.RecipeApi): |
| """APIs for fetching and uploading debug symbols.""" |
| |
| def fetch_and_upload(self, project, checkout_root, import_in, remote, |
| project_dir, packages, debug_symbol_attribute, |
| debug_symbol_gcs_buckets): |
| """ |
| Fetch debug symbol archives, unpack them, and upload debug symbols. |
| |
| Args: |
| project (str): Jiri remote manifest project. |
| checkout_root (Path): Path to the location where the source code was |
| already checked out. |
| import_in (str): Path to the edited manifest relative to $project |
| containing debug symbol packages. |
| remote (str): Remote manifest repository. |
| project_dir (Path): Project root path of $import_in. |
| packages (seq(str)): The list of CIPD packages updated in $import_in. |
| debug_symbol_attribute (str): Jiri attribute to match debug symbol packages. |
| debug_symbol_gcs_buckets (seq(str)): GCS buckets to upload debug symbols to. |
| """ |
| with self.m.context(infra_steps=True): |
| self.m.jiri.init( |
| use_lock_file=True, |
| attributes=(debug_symbol_attribute,), |
| ) |
| # Fetch debug symbol packages using locally edited manifest. |
| self.m.jiri.import_manifest( |
| manifest=import_in, |
| remote=remote, |
| name=project, |
| ) |
| self.m.jiri.fetch_packages(local_manifest=True) |
| |
| with self.m.step.nest('build'): |
| gn_results = self.m.build.gen( |
| checkout_root=checkout_root, |
| fuchsia_build_dir=checkout_root.join('out', 'default'), |
| target='x64', |
| build_type='debug', |
| product='products/bringup.gni', |
| # //bundles:infratools is necessary to build upload_debug_symbols. |
| packages=['//bundles:infratools'], |
| ) |
| |
| upload_debug_symbols_target = os.path.relpath( |
| str(gn_results.tool('upload_debug_symbols')), |
| str(gn_results.fuchsia_build_dir), |
| ) |
| self.m.build.ninja( |
| gn_results=gn_results, |
| build_zircon=False, |
| targets=[upload_debug_symbols_target], |
| ) |
| |
| build_id_dirs = [] |
| for package in packages: |
| # Find archives for each debug symbol package. |
| with self.m.context(cwd=project_dir): |
| package_def = self.m.jiri.read_manifest_element( |
| manifest=import_in, |
| element_type='package', |
| element_name=package, |
| ) |
| # Skip non debug symbol packages. |
| if debug_symbol_attribute not in package_def.get('attributes', ''): |
| continue |
| |
| package_path = checkout_root.join(package_def['path']) |
| archives = self.m.file.glob_paths( |
| name='find archives for %s' % package, |
| source=package_path, |
| pattern='**/*.tar.bz2', |
| test_data=(package_path.join('symbols.tar.bz2'),), |
| ) |
| |
| # Unpack archives into .build-id dirs. |
| for archive in archives: |
| # Extract API requires a unique, non-existent directory. |
| archive_basename = os.path.basename(self.m.path.abspath(archive)) |
| output_dir = checkout_root.join(package, archive_basename) |
| self.m.archive.extract( |
| step_name='extract %s' % archive, |
| archive_file=archive, |
| output=output_dir, |
| ) |
| build_id_dirs.append(output_dir) |
| |
| for debug_symbol_gcs_bucket in debug_symbol_gcs_buckets: |
| self.m.upload_debug_symbols( |
| step_name='upload debug symbols', |
| upload_debug_symbols_path=gn_results.tool('upload_debug_symbols'), |
| bucket=debug_symbol_gcs_bucket, |
| build_id_dirs=build_id_dirs, |
| ) |