112ba7f27STobias Hieta#!/usr/bin/env python3 212ba7f27STobias Hieta 312ba7f27STobias Hieta# This script bumps the version of LLVM in *all* the different places where 412ba7f27STobias Hieta# it needs to be defined. Which is quite a few. 512ba7f27STobias Hieta 612ba7f27STobias Hietaimport sys 712ba7f27STobias Hietaimport argparse 812ba7f27STobias Hietaimport packaging.version 912ba7f27STobias Hietafrom pathlib import Path 1012ba7f27STobias Hietaimport re 1112ba7f27STobias Hietafrom typing import Optional 1212ba7f27STobias Hieta 1312ba7f27STobias Hieta 1412ba7f27STobias Hietaclass Processor: 1520fe2525STobias Hieta def __init__(self, args): 1620fe2525STobias Hieta self.args = args 1720fe2525STobias Hieta 1812ba7f27STobias Hieta def process_line(self, line: str) -> str: 1912ba7f27STobias Hieta raise NotImplementedError() 2012ba7f27STobias Hieta 2112ba7f27STobias Hieta def process_file(self, fpath: Path, version: packaging.version.Version) -> None: 2212ba7f27STobias Hieta self.version = version 2312ba7f27STobias Hieta self.major, self.minor, self.patch, self.suffix = ( 2412ba7f27STobias Hieta version.major, 2512ba7f27STobias Hieta version.minor, 2612ba7f27STobias Hieta version.micro, 2712ba7f27STobias Hieta version.pre, 2812ba7f27STobias Hieta ) 2920fe2525STobias Hieta 3020fe2525STobias Hieta if self.args.rc: 3120fe2525STobias Hieta self.suffix = f"-rc{self.args.rc}" 3220fe2525STobias Hieta 3320fe2525STobias Hieta if self.args.git: 3420fe2525STobias Hieta self.suffix = "git" 3520fe2525STobias Hieta 3612ba7f27STobias Hieta data = fpath.read_text() 3712ba7f27STobias Hieta new_data = [] 3812ba7f27STobias Hieta 3912ba7f27STobias Hieta for line in data.splitlines(True): 4012ba7f27STobias Hieta nline = self.process_line(line) 4112ba7f27STobias Hieta 4212ba7f27STobias Hieta # Print the failing line just to inform the user. 4312ba7f27STobias Hieta if nline != line: 4412ba7f27STobias Hieta print(f"{fpath.name}: {line.strip()} -> {nline.strip()}") 4512ba7f27STobias Hieta 4612ba7f27STobias Hieta new_data.append(nline) 4712ba7f27STobias Hieta 4812ba7f27STobias Hieta fpath.write_text("".join(new_data), newline="\n") 4912ba7f27STobias Hieta 5012ba7f27STobias Hieta # Return a string from the version class 5112ba7f27STobias Hieta # optionally include the suffix (-rcX) 5212ba7f27STobias Hieta def version_str( 5312ba7f27STobias Hieta self, 5412ba7f27STobias Hieta version: Optional[packaging.version.Version] = None, 5512ba7f27STobias Hieta include_suffix: bool = True, 5612ba7f27STobias Hieta ) -> str: 5712ba7f27STobias Hieta if version is None: 5812ba7f27STobias Hieta version = self.version 5912ba7f27STobias Hieta 6012ba7f27STobias Hieta ver = f"{version.major}.{version.minor}.{version.micro}" 6112ba7f27STobias Hieta if include_suffix and version.pre: 6212ba7f27STobias Hieta ver += f"-{version.pre[0]}{version.pre[1]}" 6312ba7f27STobias Hieta return ver 6412ba7f27STobias Hieta 6512ba7f27STobias Hieta 6612ba7f27STobias Hieta# llvm/CMakeLists.txt 6712ba7f27STobias Hietaclass CMakeProcessor(Processor): 6812ba7f27STobias Hieta def process_line(self, line: str) -> str: 6912ba7f27STobias Hieta nline = line 7012ba7f27STobias Hieta 7112ba7f27STobias Hieta # LLVM_VERSION_SUFFIX should be set to -rcX or be blank if we are 7212ba7f27STobias Hieta # building a final version. 7312ba7f27STobias Hieta if "set(LLVM_VERSION_SUFFIX" in line: 7412ba7f27STobias Hieta if self.suffix: 7512ba7f27STobias Hieta nline = re.sub( 7612ba7f27STobias Hieta r"set\(LLVM_VERSION_SUFFIX(.*)\)", 7720fe2525STobias Hieta f"set(LLVM_VERSION_SUFFIX {self.suffix})", 7812ba7f27STobias Hieta line, 7912ba7f27STobias Hieta ) 8012ba7f27STobias Hieta else: 81b71edfaaSTobias Hieta nline = re.sub( 82b71edfaaSTobias Hieta r"set\(LLVM_VERSION_SUFFIX(.*)\)", f"set(LLVM_VERSION_SUFFIX)", line 83b71edfaaSTobias Hieta ) 8412ba7f27STobias Hieta 8512ba7f27STobias Hieta # Check the rest of the LLVM_VERSION_ lines. 8612ba7f27STobias Hieta elif "set(LLVM_VERSION_" in line: 8712ba7f27STobias Hieta for c, cver in ( 8812ba7f27STobias Hieta ("MAJOR", self.major), 8912ba7f27STobias Hieta ("MINOR", self.minor), 9012ba7f27STobias Hieta ("PATCH", self.patch), 9112ba7f27STobias Hieta ): 9212ba7f27STobias Hieta nline = re.sub( 93b71edfaaSTobias Hieta rf"set\(LLVM_VERSION_{c} (\d+)", 94b71edfaaSTobias Hieta rf"set(LLVM_VERSION_{c} {cver}", 9512ba7f27STobias Hieta line, 9612ba7f27STobias Hieta ) 9712ba7f27STobias Hieta if nline != line: 9812ba7f27STobias Hieta break 9912ba7f27STobias Hieta 10012ba7f27STobias Hieta return nline 10112ba7f27STobias Hieta 10212ba7f27STobias Hieta 10312ba7f27STobias Hieta# GN build system 10412ba7f27STobias Hietaclass GNIProcessor(Processor): 10512ba7f27STobias Hieta def process_line(self, line: str) -> str: 10612ba7f27STobias Hieta if "llvm_version_" in line: 10712ba7f27STobias Hieta for c, cver in ( 10812ba7f27STobias Hieta ("major", self.major), 10912ba7f27STobias Hieta ("minor", self.minor), 11012ba7f27STobias Hieta ("patch", self.patch), 11112ba7f27STobias Hieta ): 112b71edfaaSTobias Hieta nline = re.sub( 113b71edfaaSTobias Hieta rf"llvm_version_{c} = \d+", f"llvm_version_{c} = {cver}", line 114b71edfaaSTobias Hieta ) 11512ba7f27STobias Hieta if nline != line: 11612ba7f27STobias Hieta return nline 11712ba7f27STobias Hieta 11812ba7f27STobias Hieta return line 11912ba7f27STobias Hieta 12012ba7f27STobias Hieta 12112ba7f27STobias Hieta# LIT python file, a simple tuple 12212ba7f27STobias Hietaclass LitProcessor(Processor): 12312ba7f27STobias Hieta def process_line(self, line: str) -> str: 12412ba7f27STobias Hieta if "__versioninfo__" in line: 12512ba7f27STobias Hieta nline = re.sub( 126b71edfaaSTobias Hieta rf"__versioninfo__(.*)\((\d+), (\d+), (\d+)\)", 12712ba7f27STobias Hieta f"__versioninfo__\\1({self.major}, {self.minor}, {self.patch})", 12812ba7f27STobias Hieta line, 12912ba7f27STobias Hieta ) 13012ba7f27STobias Hieta return nline 13112ba7f27STobias Hieta return line 13212ba7f27STobias Hieta 13312ba7f27STobias Hieta 13412ba7f27STobias Hieta# Handle libc++ config header 13512ba7f27STobias Hietaclass LibCXXProcessor(Processor): 13612ba7f27STobias Hieta def process_line(self, line: str) -> str: 13712ba7f27STobias Hieta # match #define _LIBCPP_VERSION 160000 in a relaxed way 13812ba7f27STobias Hieta match = re.match(r".*\s_LIBCPP_VERSION\s+(\d{6})$", line) 13912ba7f27STobias Hieta if match: 14012ba7f27STobias Hieta verstr = f"{str(self.major).zfill(2)}{str(self.minor).zfill(2)}{str(self.patch).zfill(2)}" 14112ba7f27STobias Hieta 14212ba7f27STobias Hieta nline = re.sub( 143b71edfaaSTobias Hieta rf"_LIBCPP_VERSION (\d+)", 14412ba7f27STobias Hieta f"_LIBCPP_VERSION {verstr}", 14512ba7f27STobias Hieta line, 14612ba7f27STobias Hieta ) 14712ba7f27STobias Hieta return nline 14812ba7f27STobias Hieta return line 14912ba7f27STobias Hieta 15012ba7f27STobias Hieta 15112ba7f27STobias Hietaif __name__ == "__main__": 15212ba7f27STobias Hieta parser = argparse.ArgumentParser( 15312ba7f27STobias Hieta usage="Call this script with a version and it will bump the version for you" 15412ba7f27STobias Hieta ) 15512ba7f27STobias Hieta parser.add_argument("version", help="Version to bump to, e.g. 15.0.1", default=None) 15612ba7f27STobias Hieta parser.add_argument("--rc", default=None, type=int, help="RC version") 15720fe2525STobias Hieta parser.add_argument("--git", action="store_true", help="Git version") 15812ba7f27STobias Hieta parser.add_argument( 15912ba7f27STobias Hieta "-s", 16012ba7f27STobias Hieta "--source-root", 16112ba7f27STobias Hieta default=None, 16212ba7f27STobias Hieta help="LLVM source root (/path/llvm-project). Defaults to the llvm-project the script is located in.", 16312ba7f27STobias Hieta ) 16412ba7f27STobias Hieta 16512ba7f27STobias Hieta args = parser.parse_args() 16612ba7f27STobias Hieta 16720fe2525STobias Hieta if args.rc and args.git: 16820fe2525STobias Hieta raise RuntimeError("Can't specify --git and --rc at the same time!") 16920fe2525STobias Hieta 17012ba7f27STobias Hieta verstr = args.version 17112ba7f27STobias Hieta 17212ba7f27STobias Hieta # parse the version string with distutils. 17312ba7f27STobias Hieta # note that -rc will end up as version.pre here 17412ba7f27STobias Hieta # since it's a prerelease 17512ba7f27STobias Hieta version = packaging.version.parse(verstr) 17612ba7f27STobias Hieta 17712ba7f27STobias Hieta # Find llvm-project root 17812ba7f27STobias Hieta source_root = Path(__file__).resolve().parents[3] 17912ba7f27STobias Hieta 18012ba7f27STobias Hieta if args.source_root: 18112ba7f27STobias Hieta source_root = Path(args.source_root).resolve() 18212ba7f27STobias Hieta 18312ba7f27STobias Hieta files_to_update = ( 18412ba7f27STobias Hieta # Main CMakeLists. 18520fe2525STobias Hieta (source_root / "cmake" / "Modules" / "LLVMVersion.cmake", CMakeProcessor(args)), 18612ba7f27STobias Hieta # Lit configuration 18712ba7f27STobias Hieta ( 18812ba7f27STobias Hieta "llvm/utils/lit/lit/__init__.py", 18920fe2525STobias Hieta LitProcessor(args), 19012ba7f27STobias Hieta ), 191*cb1a3bb2SAiden Grossman # mlgo-utils configuration 192*cb1a3bb2SAiden Grossman ( 193*cb1a3bb2SAiden Grossman "llvm/utils/mlgo-utils/mlgo/__init__.py", 194*cb1a3bb2SAiden Grossman LitProcessor(args), 195*cb1a3bb2SAiden Grossman ), 19612ba7f27STobias Hieta # GN build system 19712ba7f27STobias Hieta ( 19812ba7f27STobias Hieta "llvm/utils/gn/secondary/llvm/version.gni", 19920fe2525STobias Hieta GNIProcessor(args), 20012ba7f27STobias Hieta ), 20112ba7f27STobias Hieta ( 20212ba7f27STobias Hieta "libcxx/include/__config", 20320fe2525STobias Hieta LibCXXProcessor(args), 20412ba7f27STobias Hieta ), 20512ba7f27STobias Hieta ) 20612ba7f27STobias Hieta 20712ba7f27STobias Hieta for f, processor in files_to_update: 20812ba7f27STobias Hieta processor.process_file(source_root / Path(f), version) 209