[SmallPtrSet] Remove SmallArray member (NFC) (#118099)
[llvm-project.git] / llvm / utils / release / bump-version.py
blob5db62e88fec1d3f599e8634eeb1d3b932f8239fc
1 #!/usr/bin/env python3
3 # This script bumps the version of LLVM in *all* the different places where
4 # it needs to be defined. Which is quite a few.
6 import sys
7 import argparse
8 import packaging.version
9 from pathlib import Path
10 import re
11 from typing import Optional
14 class Processor:
15 def __init__(self, args):
16 self.args = args
18 def process_line(self, line: str) -> str:
19 raise NotImplementedError()
21 def process_file(self, fpath: Path, version: packaging.version.Version) -> None:
22 self.version = version
23 self.major, self.minor, self.patch, self.suffix = (
24 version.major,
25 version.minor,
26 version.micro,
27 version.pre,
30 if self.args.rc:
31 self.suffix = f"-rc{self.args.rc}"
33 if self.args.git:
34 self.suffix = "git"
36 data = fpath.read_text()
37 new_data = []
39 for line in data.splitlines(True):
40 nline = self.process_line(line)
42 # Print the failing line just to inform the user.
43 if nline != line:
44 print(f"{fpath.name}: {line.strip()} -> {nline.strip()}")
46 new_data.append(nline)
48 fpath.write_text("".join(new_data), newline="\n")
50 # Return a string from the version class
51 # optionally include the suffix (-rcX)
52 def version_str(
53 self,
54 version: Optional[packaging.version.Version] = None,
55 include_suffix: bool = True,
56 ) -> str:
57 if version is None:
58 version = self.version
60 ver = f"{version.major}.{version.minor}.{version.micro}"
61 if include_suffix and version.pre:
62 ver += f"-{version.pre[0]}{version.pre[1]}"
63 return ver
66 # llvm/CMakeLists.txt
67 class CMakeProcessor(Processor):
68 def process_line(self, line: str) -> str:
69 nline = line
71 # LLVM_VERSION_SUFFIX should be set to -rcX or be blank if we are
72 # building a final version.
73 if "set(LLVM_VERSION_SUFFIX" in line:
74 if self.suffix:
75 nline = re.sub(
76 r"set\(LLVM_VERSION_SUFFIX(.*)\)",
77 f"set(LLVM_VERSION_SUFFIX {self.suffix})",
78 line,
80 else:
81 nline = re.sub(
82 r"set\(LLVM_VERSION_SUFFIX(.*)\)", f"set(LLVM_VERSION_SUFFIX)", line
85 # Check the rest of the LLVM_VERSION_ lines.
86 elif "set(LLVM_VERSION_" in line:
87 for c, cver in (
88 ("MAJOR", self.major),
89 ("MINOR", self.minor),
90 ("PATCH", self.patch),
92 nline = re.sub(
93 rf"set\(LLVM_VERSION_{c} (\d+)",
94 rf"set(LLVM_VERSION_{c} {cver}",
95 line,
97 if nline != line:
98 break
100 return nline
103 # GN build system
104 class GNIProcessor(Processor):
105 def process_line(self, line: str) -> str:
106 if "llvm_version_" in line:
107 for c, cver in (
108 ("major", self.major),
109 ("minor", self.minor),
110 ("patch", self.patch),
112 nline = re.sub(
113 rf"llvm_version_{c} = \d+", f"llvm_version_{c} = {cver}", line
115 if nline != line:
116 return nline
118 return line
121 # LIT python file, a simple tuple
122 class LitProcessor(Processor):
123 def process_line(self, line: str) -> str:
124 if "__versioninfo__" in line:
125 nline = re.sub(
126 rf"__versioninfo__(.*)\((\d+), (\d+), (\d+)\)",
127 f"__versioninfo__\\1({self.major}, {self.minor}, {self.patch})",
128 line,
130 return nline
131 return line
134 # Handle libc++ config header
135 class LibCXXProcessor(Processor):
136 def process_line(self, line: str) -> str:
137 # match #define _LIBCPP_VERSION 160000 in a relaxed way
138 match = re.match(r".*\s_LIBCPP_VERSION\s+(\d{6})$", line)
139 if match:
140 verstr = f"{str(self.major).zfill(2)}{str(self.minor).zfill(2)}{str(self.patch).zfill(2)}"
142 nline = re.sub(
143 rf"_LIBCPP_VERSION (\d+)",
144 f"_LIBCPP_VERSION {verstr}",
145 line,
147 return nline
148 return line
151 if __name__ == "__main__":
152 parser = argparse.ArgumentParser(
153 usage="Call this script with a version and it will bump the version for you"
155 parser.add_argument("version", help="Version to bump to, e.g. 15.0.1", default=None)
156 parser.add_argument("--rc", default=None, type=int, help="RC version")
157 parser.add_argument("--git", action="store_true", help="Git version")
158 parser.add_argument(
159 "-s",
160 "--source-root",
161 default=None,
162 help="LLVM source root (/path/llvm-project). Defaults to the llvm-project the script is located in.",
165 args = parser.parse_args()
167 if args.rc and args.git:
168 raise RuntimeError("Can't specify --git and --rc at the same time!")
170 verstr = args.version
172 # parse the version string with distutils.
173 # note that -rc will end up as version.pre here
174 # since it's a prerelease
175 version = packaging.version.parse(verstr)
177 # Find llvm-project root
178 source_root = Path(__file__).resolve().parents[3]
180 if args.source_root:
181 source_root = Path(args.source_root).resolve()
183 files_to_update = (
184 # Main CMakeLists.
185 (source_root / "cmake" / "Modules" / "LLVMVersion.cmake", CMakeProcessor(args)),
186 # Lit configuration
188 "llvm/utils/lit/lit/__init__.py",
189 LitProcessor(args),
191 # mlgo-utils configuration
193 "llvm/utils/mlgo-utils/mlgo/__init__.py",
194 LitProcessor(args),
196 # GN build system
198 "llvm/utils/gn/secondary/llvm/version.gni",
199 GNIProcessor(args),
202 "libcxx/include/__config",
203 LibCXXProcessor(args),
207 for f, processor in files_to_update:
208 processor.process_file(source_root / Path(f), version)