1*760c253cSXin Li#!/usr/bin/env python3 2*760c253cSXin Li# Copyright 2024 The ChromiumOS Authors 3*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be 4*760c253cSXin Li# found in the LICENSE file. 5*760c253cSXin Li 6*760c253cSXin Li"""Updates the Manifest file for LLVM. 7*760c253cSXin Li 8*760c253cSXin LiOften used to pull a new PGO profile in. 9*760c253cSXin Li""" 10*760c253cSXin Li 11*760c253cSXin Liimport argparse 12*760c253cSXin Liimport contextlib 13*760c253cSXin Liimport logging 14*760c253cSXin Lifrom pathlib import Path 15*760c253cSXin Liimport re 16*760c253cSXin Liimport subprocess 17*760c253cSXin Liimport sys 18*760c253cSXin Lifrom typing import Generator, List 19*760c253cSXin Li 20*760c253cSXin Liimport pgo_tools 21*760c253cSXin Li 22*760c253cSXin Li 23*760c253cSXin Li@contextlib.contextmanager 24*760c253cSXin Lidef temporarily_add_llvm_next_pgo_to_src_uri( 25*760c253cSXin Li llvm_9999_ebuild: Path, 26*760c253cSXin Li) -> Generator[None, None, None]: 27*760c253cSXin Li old_contents = llvm_9999_ebuild.read_text(encoding="utf-8") 28*760c253cSXin Li 29*760c253cSXin Li profdata_prefix = "gs://chromeos-localmirror/distfiles/llvm-profdata-" 30*760c253cSXin Li profdata_re = re.compile( 31*760c253cSXin Li # Leave room for a suffix on this, in case we're on the Nth version of 32*760c253cSXin Li # llvm-profdata for some reason. 33*760c253cSXin Li re.escape(profdata_prefix + "${LLVM_HASH}") 34*760c253cSXin Li + r"\S*\.xz\s" 35*760c253cSXin Li ) 36*760c253cSXin Li found_urls = list(profdata_re.finditer(old_contents)) 37*760c253cSXin Li if len(found_urls) != 1: 38*760c253cSXin Li raise ValueError( 39*760c253cSXin Li f"Want 1 instance of {profdata_re} in {llvm_9999_ebuild}; found " 40*760c253cSXin Li f"{len(found_urls)}" 41*760c253cSXin Li ) 42*760c253cSXin Li 43*760c253cSXin Li # Insert the new profdata URL right after the old one. The combination of 44*760c253cSXin Li # USE variables gating this file doesn't have to make sense; the URL just 45*760c253cSXin Li # has to be visible to Portage. 46*760c253cSXin Li 47*760c253cSXin Li # Note that the regex ended with `\s`, so `.end()` will be after a space. 48*760c253cSXin Li insert_url = profdata_prefix + "${LLVM_NEXT_HASH}.xz " 49*760c253cSXin Li insert_point = found_urls[0].end() 50*760c253cSXin Li new_contents = ( 51*760c253cSXin Li old_contents[:insert_point] + insert_url + old_contents[insert_point:] 52*760c253cSXin Li ) 53*760c253cSXin Li 54*760c253cSXin Li llvm_9999_ebuild.write_text(new_contents, encoding="utf-8") 55*760c253cSXin Li try: 56*760c253cSXin Li yield 57*760c253cSXin Li finally: 58*760c253cSXin Li llvm_9999_ebuild.write_text(old_contents, encoding="utf-8") 59*760c253cSXin Li 60*760c253cSXin Li 61*760c253cSXin Lidef update_manifest(llvm_9999_ebuild: Path): 62*760c253cSXin Li subprocess.run( 63*760c253cSXin Li ["ebuild", llvm_9999_ebuild, "manifest"], 64*760c253cSXin Li check=True, 65*760c253cSXin Li stdin=subprocess.DEVNULL, 66*760c253cSXin Li ) 67*760c253cSXin Li 68*760c253cSXin Li 69*760c253cSXin Lidef main(argv: List[str]) -> None: 70*760c253cSXin Li logging.basicConfig( 71*760c253cSXin Li format=">> %(asctime)s: %(levelname)s: %(filename)s:%(lineno)d: " 72*760c253cSXin Li "%(message)s", 73*760c253cSXin Li level=logging.INFO, 74*760c253cSXin Li ) 75*760c253cSXin Li 76*760c253cSXin Li pgo_tools.exit_if_not_in_chroot() 77*760c253cSXin Li 78*760c253cSXin Li my_dir = Path(__file__).resolve().parent 79*760c253cSXin Li parser = argparse.ArgumentParser( 80*760c253cSXin Li description=__doc__, 81*760c253cSXin Li formatter_class=argparse.RawDescriptionHelpFormatter, 82*760c253cSXin Li ) 83*760c253cSXin Li parser.add_argument( 84*760c253cSXin Li "--llvm-next", 85*760c253cSXin Li action="store_true", 86*760c253cSXin Li help="Also update for the llvm-next PGO profile.", 87*760c253cSXin Li ) 88*760c253cSXin Li parser.add_argument( 89*760c253cSXin Li "--chromiumos-overlay", 90*760c253cSXin Li default=my_dir.parent.parent / "chromiumos-overlay", 91*760c253cSXin Li type=Path, 92*760c253cSXin Li help="The chromiumos-overlay directory to work in. Default %(default)s", 93*760c253cSXin Li ) 94*760c253cSXin Li opts = parser.parse_args(argv) 95*760c253cSXin Li 96*760c253cSXin Li llvm_9999 = opts.chromiumos_overlay / "sys-devel/llvm/llvm-9999.ebuild" 97*760c253cSXin Li if opts.llvm_next: 98*760c253cSXin Li with temporarily_add_llvm_next_pgo_to_src_uri(llvm_9999): 99*760c253cSXin Li update_manifest(llvm_9999) 100*760c253cSXin Li else: 101*760c253cSXin Li update_manifest(llvm_9999) 102*760c253cSXin Li 103*760c253cSXin Li 104*760c253cSXin Liif __name__ == "__main__": 105*760c253cSXin Li main(sys.argv[1:]) 106