1*760c253cSXin Li#!/usr/bin/env python3 2*760c253cSXin Li# Copyright 2019 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"""Returns the latest LLVM version's hash.""" 7*760c253cSXin Li 8*760c253cSXin Liimport argparse 9*760c253cSXin Liimport contextlib 10*760c253cSXin Liimport functools 11*760c253cSXin Liimport os 12*760c253cSXin Lifrom pathlib import Path 13*760c253cSXin Liimport re 14*760c253cSXin Liimport shutil 15*760c253cSXin Liimport subprocess 16*760c253cSXin Liimport sys 17*760c253cSXin Liimport tempfile 18*760c253cSXin Lifrom typing import Iterator, Optional, Tuple, Union 19*760c253cSXin Li 20*760c253cSXin Liimport chroot 21*760c253cSXin Liimport git_llvm_rev 22*760c253cSXin Liimport llvm_next 23*760c253cSXin Liimport manifest_utils 24*760c253cSXin Liimport subprocess_helpers 25*760c253cSXin Li 26*760c253cSXin Li 27*760c253cSXin Li_LLVM_GIT_URL = ( 28*760c253cSXin Li "https://chromium.googlesource.com/external/github.com/llvm/llvm-project" 29*760c253cSXin Li) 30*760c253cSXin Li 31*760c253cSXin LiKNOWN_HASH_SOURCES = ( 32*760c253cSXin Li "google3", 33*760c253cSXin Li "google3-unstable", 34*760c253cSXin Li "llvm", 35*760c253cSXin Li "llvm-next", 36*760c253cSXin Li "tot", 37*760c253cSXin Li) 38*760c253cSXin Li 39*760c253cSXin Li 40*760c253cSXin Lidef GetVersionFrom(src_dir: Union[Path, str], git_hash: str) -> int: 41*760c253cSXin Li """Obtain an SVN-style version number based on the LLVM git hash passed in. 42*760c253cSXin Li 43*760c253cSXin Li Args: 44*760c253cSXin Li src_dir: LLVM's source directory. 45*760c253cSXin Li git_hash: The git hash. 46*760c253cSXin Li 47*760c253cSXin Li Returns: 48*760c253cSXin Li An SVN-style version number associated with the git hash. 49*760c253cSXin Li """ 50*760c253cSXin Li 51*760c253cSXin Li version = git_llvm_rev.translate_sha_to_rev( 52*760c253cSXin Li git_llvm_rev.LLVMConfig(remote="origin", dir=src_dir), git_hash 53*760c253cSXin Li ) 54*760c253cSXin Li # Note: branches aren't supported 55*760c253cSXin Li assert version.branch == git_llvm_rev.MAIN_BRANCH, version.branch 56*760c253cSXin Li return version.number 57*760c253cSXin Li 58*760c253cSXin Li 59*760c253cSXin Lidef GetGitHashFrom(src_dir: Union[Path, str], version: int) -> str: 60*760c253cSXin Li """Finds the commit hash(es) of the LLVM version in the git log history. 61*760c253cSXin Li 62*760c253cSXin Li Args: 63*760c253cSXin Li src_dir: The LLVM source tree. 64*760c253cSXin Li version: The version number. 65*760c253cSXin Li 66*760c253cSXin Li Returns: 67*760c253cSXin Li A git hash string corresponding to the version number. 68*760c253cSXin Li 69*760c253cSXin Li Raises: 70*760c253cSXin Li subprocess.CalledProcessError: Failed to find a git hash. 71*760c253cSXin Li """ 72*760c253cSXin Li 73*760c253cSXin Li return git_llvm_rev.translate_rev_to_sha( 74*760c253cSXin Li git_llvm_rev.LLVMConfig(remote="origin", dir=src_dir), 75*760c253cSXin Li git_llvm_rev.Rev(branch=git_llvm_rev.MAIN_BRANCH, number=version), 76*760c253cSXin Li ) 77*760c253cSXin Li 78*760c253cSXin Li 79*760c253cSXin Lidef CheckoutBranch(src_dir: Union[Path, str], branch: str) -> None: 80*760c253cSXin Li """Checks out and pulls from a branch in a git repo. 81*760c253cSXin Li 82*760c253cSXin Li Args: 83*760c253cSXin Li src_dir: The LLVM source tree. 84*760c253cSXin Li branch: The git branch to checkout in src_dir. 85*760c253cSXin Li 86*760c253cSXin Li Raises: 87*760c253cSXin Li ValueError: Failed to checkout or pull branch version 88*760c253cSXin Li """ 89*760c253cSXin Li subprocess_helpers.CheckCommand(["git", "-C", src_dir, "checkout", branch]) 90*760c253cSXin Li subprocess_helpers.CheckCommand(["git", "-C", src_dir, "pull"]) 91*760c253cSXin Li 92*760c253cSXin Li 93*760c253cSXin Lidef ParseLLVMMajorVersion(cmakelist: str) -> Optional[str]: 94*760c253cSXin Li """Reads CMakeList.txt file contents for LLVMMajor Version. 95*760c253cSXin Li 96*760c253cSXin Li Args: 97*760c253cSXin Li cmakelist: contents of CMakeList.txt 98*760c253cSXin Li 99*760c253cSXin Li Returns: 100*760c253cSXin Li The major version number as a string, or None if it couldn't be found. 101*760c253cSXin Li """ 102*760c253cSXin Li match = re.search( 103*760c253cSXin Li r"\n\s+set\(LLVM_VERSION_MAJOR (?P<major>\d+)\)", cmakelist 104*760c253cSXin Li ) 105*760c253cSXin Li if not match: 106*760c253cSXin Li return None 107*760c253cSXin Li return match.group("major") 108*760c253cSXin Li 109*760c253cSXin Li 110*760c253cSXin Li@functools.lru_cache(maxsize=1) 111*760c253cSXin Lidef GetLLVMMajorVersion(git_hash: Optional[str] = None) -> str: 112*760c253cSXin Li """Reads llvm/CMakeList.txt file contents for LLVMMajor Version. 113*760c253cSXin Li 114*760c253cSXin Li Args: 115*760c253cSXin Li git_hash: git hash of llvm version as string or None for top of trunk 116*760c253cSXin Li 117*760c253cSXin Li Returns: 118*760c253cSXin Li The major version number as a string 119*760c253cSXin Li 120*760c253cSXin Li Raises: 121*760c253cSXin Li ValueError: The major version cannot be parsed from cmakelist or 122*760c253cSXin Li there was a failure to checkout git_hash version 123*760c253cSXin Li FileExistsError: The src directory doe not contain CMakeList.txt 124*760c253cSXin Li """ 125*760c253cSXin Li src_dir = GetAndUpdateLLVMProjectInLLVMTools() 126*760c253cSXin Li 127*760c253cSXin Li # b/325895866#comment36: the LLVM version number was moved from 128*760c253cSXin Li # `llvm/CMakeLists.txt` to `cmake/Modules/LLVMVersion.cmake` in upstream 129*760c253cSXin Li # commit 81e20472a0c5a4a8edc5ec38dc345d580681af81 (r530225). Until we no 130*760c253cSXin Li # longer care about looking before that, we need to support searching both 131*760c253cSXin Li # files. 132*760c253cSXin Li cmakelists_paths = ( 133*760c253cSXin Li Path(src_dir) / "llvm" / "CMakeLists.txt", 134*760c253cSXin Li Path(src_dir) / "cmake" / "Modules" / "LLVMVersion.cmake", 135*760c253cSXin Li ) 136*760c253cSXin Li 137*760c253cSXin Li with contextlib.ExitStack() as on_exit: 138*760c253cSXin Li if git_hash: 139*760c253cSXin Li subprocess_helpers.CheckCommand( 140*760c253cSXin Li ["git", "-C", src_dir, "checkout", git_hash] 141*760c253cSXin Li ) 142*760c253cSXin Li on_exit.callback(CheckoutBranch, src_dir, git_llvm_rev.MAIN_BRANCH) 143*760c253cSXin Li 144*760c253cSXin Li for path in cmakelists_paths: 145*760c253cSXin Li try: 146*760c253cSXin Li file_contents = path.read_text(encoding="utf-8") 147*760c253cSXin Li except FileNotFoundError: 148*760c253cSXin Li # If this file DNE (yet), ignore it. 149*760c253cSXin Li continue 150*760c253cSXin Li 151*760c253cSXin Li if version := ParseLLVMMajorVersion(file_contents): 152*760c253cSXin Li return version 153*760c253cSXin Li 154*760c253cSXin Li raise ValueError( 155*760c253cSXin Li f"Major version could not be parsed from any of {cmakelists_paths}" 156*760c253cSXin Li ) 157*760c253cSXin Li 158*760c253cSXin Li 159*760c253cSXin Li@contextlib.contextmanager 160*760c253cSXin Lidef CreateTempLLVMRepo(temp_dir: str) -> Iterator[str]: 161*760c253cSXin Li """Adds a LLVM worktree to 'temp_dir'. 162*760c253cSXin Li 163*760c253cSXin Li Creating a worktree because the LLVM source tree in 164*760c253cSXin Li '../toolchain-utils/llvm_tools/llvm-project-copy' should not be modified. 165*760c253cSXin Li 166*760c253cSXin Li This is useful for applying patches to a source tree but do not want to 167*760c253cSXin Li modify the actual LLVM source tree in 'llvm-project-copy'. 168*760c253cSXin Li 169*760c253cSXin Li Args: 170*760c253cSXin Li temp_dir: An absolute path to the temporary directory to put the 171*760c253cSXin Li worktree in (obtained via 'tempfile.mkdtemp()'). 172*760c253cSXin Li 173*760c253cSXin Li Yields: 174*760c253cSXin Li The absolute path to 'temp_dir'. 175*760c253cSXin Li 176*760c253cSXin Li Raises: 177*760c253cSXin Li subprocess.CalledProcessError: Failed to remove the worktree. 178*760c253cSXin Li ValueError: Failed to add a worktree. 179*760c253cSXin Li """ 180*760c253cSXin Li 181*760c253cSXin Li abs_path_to_llvm_project_dir = GetAndUpdateLLVMProjectInLLVMTools() 182*760c253cSXin Li subprocess_helpers.CheckCommand( 183*760c253cSXin Li [ 184*760c253cSXin Li "git", 185*760c253cSXin Li "-C", 186*760c253cSXin Li abs_path_to_llvm_project_dir, 187*760c253cSXin Li "worktree", 188*760c253cSXin Li "add", 189*760c253cSXin Li "--detach", 190*760c253cSXin Li temp_dir, 191*760c253cSXin Li "origin/%s" % git_llvm_rev.MAIN_BRANCH, 192*760c253cSXin Li ] 193*760c253cSXin Li ) 194*760c253cSXin Li 195*760c253cSXin Li try: 196*760c253cSXin Li yield temp_dir 197*760c253cSXin Li finally: 198*760c253cSXin Li if os.path.isdir(temp_dir): 199*760c253cSXin Li subprocess_helpers.check_output( 200*760c253cSXin Li [ 201*760c253cSXin Li "git", 202*760c253cSXin Li "-C", 203*760c253cSXin Li abs_path_to_llvm_project_dir, 204*760c253cSXin Li "worktree", 205*760c253cSXin Li "remove", 206*760c253cSXin Li "-f", 207*760c253cSXin Li temp_dir, 208*760c253cSXin Li ] 209*760c253cSXin Li ) 210*760c253cSXin Li 211*760c253cSXin Li 212*760c253cSXin Lidef GetAndUpdateLLVMProjectInLLVMTools() -> str: 213*760c253cSXin Li """Gets the absolute path to 'llvm-project-copy' directory in 'llvm_tools'. 214*760c253cSXin Li 215*760c253cSXin Li The intent of this function is to avoid cloning the LLVM repo and then 216*760c253cSXin Li discarding the contents of the repo. The function will create a directory 217*760c253cSXin Li in '../toolchain-utils/llvm_tools' called 'llvm-project-copy' if this 218*760c253cSXin Li directory does not exist yet. If it does not exist, then it will use the 219*760c253cSXin Li LLVMHash() class to clone the LLVM repo into 'llvm-project-copy'. 220*760c253cSXin Li Otherwise, it will clean the contents of that directory and then fetch from 221*760c253cSXin Li the chromium LLVM mirror. In either case, this function will return the 222*760c253cSXin Li absolute path to 'llvm-project-copy' directory. 223*760c253cSXin Li 224*760c253cSXin Li Returns: 225*760c253cSXin Li Absolute path to 'llvm-project-copy' directory in 'llvm_tools' 226*760c253cSXin Li 227*760c253cSXin Li Raises: 228*760c253cSXin Li ValueError: LLVM repo (in 'llvm-project-copy' dir.) has changes or 229*760c253cSXin Li failed to checkout to main or failed to fetch from chromium mirror of 230*760c253cSXin Li LLVM. 231*760c253cSXin Li """ 232*760c253cSXin Li 233*760c253cSXin Li abs_path_to_llvm_tools_dir = os.path.dirname(os.path.abspath(__file__)) 234*760c253cSXin Li 235*760c253cSXin Li abs_path_to_llvm_project_dir = os.path.join( 236*760c253cSXin Li abs_path_to_llvm_tools_dir, "llvm-project-copy" 237*760c253cSXin Li ) 238*760c253cSXin Li 239*760c253cSXin Li if not os.path.isdir(abs_path_to_llvm_project_dir): 240*760c253cSXin Li print( 241*760c253cSXin Li f"Checking out LLVM to {abs_path_to_llvm_project_dir}\n" 242*760c253cSXin Li "so that we can map between commit hashes and revision numbers.\n" 243*760c253cSXin Li "This may take a while, but only has to be done once.", 244*760c253cSXin Li file=sys.stderr, 245*760c253cSXin Li ) 246*760c253cSXin Li os.mkdir(abs_path_to_llvm_project_dir) 247*760c253cSXin Li 248*760c253cSXin Li LLVMHash().CloneLLVMRepo(abs_path_to_llvm_project_dir) 249*760c253cSXin Li else: 250*760c253cSXin Li # `git status` has a '-s'/'--short' option that shortens the output. 251*760c253cSXin Li # With the '-s' option, if no changes were made to the LLVM repo, then 252*760c253cSXin Li # the output (assigned to 'repo_status') would be empty. 253*760c253cSXin Li repo_status = subprocess_helpers.check_output( 254*760c253cSXin Li ["git", "-C", abs_path_to_llvm_project_dir, "status", "-s"] 255*760c253cSXin Li ) 256*760c253cSXin Li 257*760c253cSXin Li if repo_status.rstrip(): 258*760c253cSXin Li raise ValueError( 259*760c253cSXin Li "LLVM repo in %s has changes, please remove." 260*760c253cSXin Li % abs_path_to_llvm_project_dir 261*760c253cSXin Li ) 262*760c253cSXin Li 263*760c253cSXin Li CheckoutBranch(abs_path_to_llvm_project_dir, git_llvm_rev.MAIN_BRANCH) 264*760c253cSXin Li 265*760c253cSXin Li return abs_path_to_llvm_project_dir 266*760c253cSXin Li 267*760c253cSXin Li 268*760c253cSXin Lidef GetGoogle3LLVMVersion(stable: bool) -> int: 269*760c253cSXin Li """Gets the latest google3 LLVM version. 270*760c253cSXin Li 271*760c253cSXin Li Args: 272*760c253cSXin Li stable: boolean, use the stable version or the unstable version 273*760c253cSXin Li 274*760c253cSXin Li Returns: 275*760c253cSXin Li The latest LLVM SVN version as an integer. 276*760c253cSXin Li 277*760c253cSXin Li Raises: 278*760c253cSXin Li subprocess.CalledProcessError: An invalid path has been provided to the 279*760c253cSXin Li `cat` command. 280*760c253cSXin Li """ 281*760c253cSXin Li 282*760c253cSXin Li subdir = "stable" if stable else "llvm_unstable" 283*760c253cSXin Li 284*760c253cSXin Li # Cmd to get latest google3 LLVM version. 285*760c253cSXin Li cmd = [ 286*760c253cSXin Li "cat", 287*760c253cSXin Li os.path.join( 288*760c253cSXin Li "/google/src/head/depot/google3/third_party/crosstool/v18", 289*760c253cSXin Li subdir, 290*760c253cSXin Li "installs/llvm/git_origin_rev_id", 291*760c253cSXin Li ), 292*760c253cSXin Li ] 293*760c253cSXin Li 294*760c253cSXin Li # Get latest version. 295*760c253cSXin Li git_hash = subprocess_helpers.check_output(cmd) 296*760c253cSXin Li 297*760c253cSXin Li # Change type to an integer 298*760c253cSXin Li return GetVersionFrom( 299*760c253cSXin Li GetAndUpdateLLVMProjectInLLVMTools(), git_hash.rstrip() 300*760c253cSXin Li ) 301*760c253cSXin Li 302*760c253cSXin Li 303*760c253cSXin Lidef IsSvnOption(svn_option: str) -> Union[int, str]: 304*760c253cSXin Li """Validates whether the argument (string) is a git hash option. 305*760c253cSXin Li 306*760c253cSXin Li The argument is used to find the git hash of LLVM. 307*760c253cSXin Li 308*760c253cSXin Li Args: 309*760c253cSXin Li svn_option: The option passed in as a command line argument. 310*760c253cSXin Li 311*760c253cSXin Li Returns: 312*760c253cSXin Li lowercase svn_option if it is a known hash source, otherwise the 313*760c253cSXin Li svn_option as an int 314*760c253cSXin Li 315*760c253cSXin Li Raises: 316*760c253cSXin Li ValueError: Invalid svn option provided. 317*760c253cSXin Li """ 318*760c253cSXin Li 319*760c253cSXin Li if svn_option.lower() in KNOWN_HASH_SOURCES: 320*760c253cSXin Li return svn_option.lower() 321*760c253cSXin Li 322*760c253cSXin Li try: 323*760c253cSXin Li svn_version = int(svn_option) 324*760c253cSXin Li 325*760c253cSXin Li return svn_version 326*760c253cSXin Li 327*760c253cSXin Li # Unable to convert argument to an int, so the option is invalid. 328*760c253cSXin Li # 329*760c253cSXin Li # Ex: 'one'. 330*760c253cSXin Li except ValueError: 331*760c253cSXin Li pass 332*760c253cSXin Li 333*760c253cSXin Li raise ValueError("Invalid LLVM git hash option provided: %s" % svn_option) 334*760c253cSXin Li 335*760c253cSXin Li 336*760c253cSXin Lidef GetLLVMHashAndVersionFromSVNOption( 337*760c253cSXin Li svn_option: Union[int, str] 338*760c253cSXin Li) -> Tuple[str, int]: 339*760c253cSXin Li """Gets the LLVM hash and LLVM version based off of the svn option. 340*760c253cSXin Li 341*760c253cSXin Li Args: 342*760c253cSXin Li svn_option: A valid svn option obtained from the command line. 343*760c253cSXin Li Ex. 'google3', 'tot', or <svn_version> such as 365123. 344*760c253cSXin Li 345*760c253cSXin Li Returns: 346*760c253cSXin Li A tuple that is the LLVM git hash and LLVM version. 347*760c253cSXin Li """ 348*760c253cSXin Li 349*760c253cSXin Li new_llvm_hash = LLVMHash() 350*760c253cSXin Li 351*760c253cSXin Li # Determine which LLVM git hash to retrieve. 352*760c253cSXin Li if svn_option == "tot": 353*760c253cSXin Li git_hash = new_llvm_hash.GetTopOfTrunkGitHash() 354*760c253cSXin Li version = GetVersionFrom(GetAndUpdateLLVMProjectInLLVMTools(), git_hash) 355*760c253cSXin Li elif isinstance(svn_option, int): 356*760c253cSXin Li version = svn_option 357*760c253cSXin Li git_hash = GetGitHashFrom(GetAndUpdateLLVMProjectInLLVMTools(), version) 358*760c253cSXin Li else: 359*760c253cSXin Li assert svn_option in ("google3", "google3-unstable") 360*760c253cSXin Li version = GetGoogle3LLVMVersion(stable=svn_option == "google3") 361*760c253cSXin Li 362*760c253cSXin Li git_hash = GetGitHashFrom(GetAndUpdateLLVMProjectInLLVMTools(), version) 363*760c253cSXin Li 364*760c253cSXin Li return git_hash, version 365*760c253cSXin Li 366*760c253cSXin Li 367*760c253cSXin Lidef GetCrOSCurrentLLVMHash(chromeos_tree: Path) -> str: 368*760c253cSXin Li """Retrieves the current ChromeOS LLVM hash. 369*760c253cSXin Li 370*760c253cSXin Li Args: 371*760c253cSXin Li chromeos_tree: A ChromeOS source tree. This is allowed to be 372*760c253cSXin Li arbitrary subdirectory of an actual ChromeOS tree, for convenience. 373*760c253cSXin Li 374*760c253cSXin Li Raises: 375*760c253cSXin Li ManifestValueError if the toolchain manifest doesn't match the 376*760c253cSXin Li expected structure. 377*760c253cSXin Li """ 378*760c253cSXin Li chromeos_root = chroot.FindChromeOSRootAbove(chromeos_tree) 379*760c253cSXin Li return manifest_utils.extract_current_llvm_hash(chromeos_root) 380*760c253cSXin Li 381*760c253cSXin Li 382*760c253cSXin Liclass LLVMHash: 383*760c253cSXin Li """Provides methods to retrieve a LLVM hash.""" 384*760c253cSXin Li 385*760c253cSXin Li @staticmethod 386*760c253cSXin Li @contextlib.contextmanager 387*760c253cSXin Li def CreateTempDirectory() -> Iterator: 388*760c253cSXin Li temp_dir = tempfile.mkdtemp() 389*760c253cSXin Li 390*760c253cSXin Li try: 391*760c253cSXin Li yield temp_dir 392*760c253cSXin Li finally: 393*760c253cSXin Li if os.path.isdir(temp_dir): 394*760c253cSXin Li shutil.rmtree(temp_dir, ignore_errors=True) 395*760c253cSXin Li 396*760c253cSXin Li def CloneLLVMRepo(self, temp_dir: str) -> None: 397*760c253cSXin Li """Clones the LLVM repo. 398*760c253cSXin Li 399*760c253cSXin Li Args: 400*760c253cSXin Li temp_dir: The temporary directory to clone the repo to. 401*760c253cSXin Li 402*760c253cSXin Li Raises: 403*760c253cSXin Li ValueError: Failed to clone the LLVM repo. 404*760c253cSXin Li """ 405*760c253cSXin Li clone_cmd = ["git", "clone", _LLVM_GIT_URL, temp_dir] 406*760c253cSXin Li clone_cmd_obj = subprocess.run( 407*760c253cSXin Li clone_cmd, check=False, stderr=subprocess.PIPE 408*760c253cSXin Li ) 409*760c253cSXin Li if clone_cmd_obj.returncode: 410*760c253cSXin Li raise ValueError( 411*760c253cSXin Li "Failed to clone the LLVM repo; stderr: " 412*760c253cSXin Li f"{repr(clone_cmd_obj.stderr)}" 413*760c253cSXin Li ) 414*760c253cSXin Li 415*760c253cSXin Li def GetLLVMHash(self, version: int) -> str: 416*760c253cSXin Li """Retrieves the LLVM hash corresponding to the LLVM version passed in. 417*760c253cSXin Li 418*760c253cSXin Li Args: 419*760c253cSXin Li version: The LLVM version to use as a delimiter. 420*760c253cSXin Li 421*760c253cSXin Li Returns: 422*760c253cSXin Li The hash as a string that corresponds to the LLVM version. 423*760c253cSXin Li """ 424*760c253cSXin Li hash_value = GetGitHashFrom( 425*760c253cSXin Li GetAndUpdateLLVMProjectInLLVMTools(), version 426*760c253cSXin Li ) 427*760c253cSXin Li return hash_value 428*760c253cSXin Li 429*760c253cSXin Li def GetCrOSCurrentLLVMHash(self, chromeos_tree: Path) -> str: 430*760c253cSXin Li """Retrieves the current ChromeOS LLVM hash.""" 431*760c253cSXin Li return GetCrOSCurrentLLVMHash(chromeos_tree) 432*760c253cSXin Li 433*760c253cSXin Li def GetCrOSLLVMNextHash(self) -> str: 434*760c253cSXin Li """Retrieves the current ChromeOS llvm-next hash.""" 435*760c253cSXin Li return llvm_next.LLVM_NEXT_HASH 436*760c253cSXin Li 437*760c253cSXin Li def GetGoogle3LLVMHash(self) -> str: 438*760c253cSXin Li """Retrieves the google3 LLVM hash.""" 439*760c253cSXin Li return self.GetLLVMHash(GetGoogle3LLVMVersion(stable=True)) 440*760c253cSXin Li 441*760c253cSXin Li def GetGoogle3UnstableLLVMHash(self) -> str: 442*760c253cSXin Li """Retrieves the LLVM hash of google3's unstable compiler.""" 443*760c253cSXin Li return self.GetLLVMHash(GetGoogle3LLVMVersion(stable=False)) 444*760c253cSXin Li 445*760c253cSXin Li def GetTopOfTrunkGitHash(self) -> str: 446*760c253cSXin Li """Gets the latest git hash from top of trunk of LLVM.""" 447*760c253cSXin Li 448*760c253cSXin Li path_to_main_branch = "refs/heads/main" 449*760c253cSXin Li llvm_tot_git_hash = subprocess_helpers.check_output( 450*760c253cSXin Li ["git", "ls-remote", _LLVM_GIT_URL, path_to_main_branch] 451*760c253cSXin Li ) 452*760c253cSXin Li return llvm_tot_git_hash.rstrip().split()[0] 453*760c253cSXin Li 454*760c253cSXin Li 455*760c253cSXin Lidef main() -> None: 456*760c253cSXin Li """Prints the git hash of LLVM. 457*760c253cSXin Li 458*760c253cSXin Li Parses the command line for the optional command line 459*760c253cSXin Li arguments. 460*760c253cSXin Li """ 461*760c253cSXin Li my_dir = Path(__file__).parent.resolve() 462*760c253cSXin Li 463*760c253cSXin Li # Create parser and add optional command-line arguments. 464*760c253cSXin Li parser = argparse.ArgumentParser(description="Finds the LLVM hash.") 465*760c253cSXin Li parser.add_argument( 466*760c253cSXin Li "--llvm_version", 467*760c253cSXin Li type=IsSvnOption, 468*760c253cSXin Li required=True, 469*760c253cSXin Li help="which git hash of LLVM to find. Either a svn revision, or one " 470*760c253cSXin Li "of %s" % sorted(KNOWN_HASH_SOURCES), 471*760c253cSXin Li ) 472*760c253cSXin Li parser.add_argument( 473*760c253cSXin Li "--chromeos_tree", 474*760c253cSXin Li type=Path, 475*760c253cSXin Li required=True, 476*760c253cSXin Li help=""" 477*760c253cSXin Li Path to a ChromeOS tree. If not passed, one will be inferred. If none 478*760c253cSXin Li can be inferred, this script will fail. 479*760c253cSXin Li """, 480*760c253cSXin Li ) 481*760c253cSXin Li 482*760c253cSXin Li # Parse command-line arguments. 483*760c253cSXin Li args_output = parser.parse_args() 484*760c253cSXin Li 485*760c253cSXin Li cur_llvm_version = args_output.llvm_version 486*760c253cSXin Li chromeos_tree = args_output.chromeos_tree 487*760c253cSXin Li if not chromeos_tree: 488*760c253cSXin Li # Try to infer this unconditionally, so mishandling of this script can 489*760c253cSXin Li # be more easily detected (which allows more flexibility in the 490*760c253cSXin Li # implementation in the future for things outside of what directly 491*760c253cSXin Li # needs this value). 492*760c253cSXin Li chromeos_tree = chroot.FindChromeOSRootAbove(my_dir) 493*760c253cSXin Li 494*760c253cSXin Li new_llvm_hash = LLVMHash() 495*760c253cSXin Li if isinstance(cur_llvm_version, int): 496*760c253cSXin Li # Find the git hash of the specific LLVM version. 497*760c253cSXin Li print(new_llvm_hash.GetLLVMHash(cur_llvm_version)) 498*760c253cSXin Li elif cur_llvm_version == "llvm": 499*760c253cSXin Li print(new_llvm_hash.GetCrOSCurrentLLVMHash(chromeos_tree)) 500*760c253cSXin Li elif cur_llvm_version == "llvm-next": 501*760c253cSXin Li print(new_llvm_hash.GetCrOSLLVMNextHash()) 502*760c253cSXin Li elif cur_llvm_version == "google3": 503*760c253cSXin Li print(new_llvm_hash.GetGoogle3LLVMHash()) 504*760c253cSXin Li elif cur_llvm_version == "google3-unstable": 505*760c253cSXin Li print(new_llvm_hash.GetGoogle3UnstableLLVMHash()) 506*760c253cSXin Li else: 507*760c253cSXin Li assert cur_llvm_version == "tot" 508*760c253cSXin Li print(new_llvm_hash.GetTopOfTrunkGitHash()) 509*760c253cSXin Li 510*760c253cSXin Li 511*760c253cSXin Liif __name__ == "__main__": 512*760c253cSXin Li main() 513