242 lines
7.6 KiB
Python
Executable File
242 lines
7.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# This script bumps the version of LLVM in *all* the different places where
|
|
# it needs to be defined. Which is quite a few.
|
|
|
|
import sys
|
|
import argparse
|
|
import packaging.version
|
|
from pathlib import Path
|
|
import re
|
|
from typing import Optional
|
|
|
|
|
|
class Processor:
|
|
def process_line(self, line: str) -> str:
|
|
raise NotImplementedError()
|
|
|
|
def process_file(self, fpath: Path, version: packaging.version.Version) -> None:
|
|
self.version = version
|
|
self.major, self.minor, self.patch, self.suffix = (
|
|
version.major,
|
|
version.minor,
|
|
version.micro,
|
|
version.pre,
|
|
)
|
|
data = fpath.read_text()
|
|
new_data = []
|
|
|
|
for line in data.splitlines(True):
|
|
nline = self.process_line(line)
|
|
|
|
# Print the failing line just to inform the user.
|
|
if nline != line:
|
|
print(f"{fpath.name}: {line.strip()} -> {nline.strip()}")
|
|
|
|
new_data.append(nline)
|
|
|
|
fpath.write_text("".join(new_data), newline="\n")
|
|
|
|
# Return a string from the version class
|
|
# optionally include the suffix (-rcX)
|
|
def version_str(
|
|
self,
|
|
version: Optional[packaging.version.Version] = None,
|
|
include_suffix: bool = True,
|
|
) -> str:
|
|
if version is None:
|
|
version = self.version
|
|
|
|
ver = f"{version.major}.{version.minor}.{version.micro}"
|
|
if include_suffix and version.pre:
|
|
ver += f"-{version.pre[0]}{version.pre[1]}"
|
|
return ver
|
|
|
|
|
|
# llvm/CMakeLists.txt
|
|
class CMakeProcessor(Processor):
|
|
def process_line(self, line: str) -> str:
|
|
nline = line
|
|
|
|
# LLVM_VERSION_SUFFIX should be set to -rcX or be blank if we are
|
|
# building a final version.
|
|
if "set(LLVM_VERSION_SUFFIX" in line:
|
|
if self.suffix:
|
|
nline = re.sub(
|
|
r"set\(LLVM_VERSION_SUFFIX(.*)\)",
|
|
f"set(LLVM_VERSION_SUFFIX -{self.suffix[0]}{self.suffix[1]})",
|
|
line,
|
|
)
|
|
else:
|
|
nline = re.sub(r"set\(LLVM_VERSION_SUFFIX(.*)\)", f"set(LLVM_VERSION_SUFFIX)", line)
|
|
|
|
# Check the rest of the LLVM_VERSION_ lines.
|
|
elif "set(LLVM_VERSION_" in line:
|
|
for c, cver in (
|
|
("MAJOR", self.major),
|
|
("MINOR", self.minor),
|
|
("PATCH", self.patch),
|
|
):
|
|
nline = re.sub(
|
|
fr"set\(LLVM_VERSION_{c} (\d+)",
|
|
fr"set(LLVM_VERSION_{c} {cver}",
|
|
line,
|
|
)
|
|
if nline != line:
|
|
break
|
|
|
|
return nline
|
|
|
|
|
|
# Process the many bazel files.
|
|
class BazelProcessor(Processor):
|
|
def process_line(self, line: str) -> str:
|
|
# This matches the CLANG_VERSION line of clang/Config/config.h
|
|
nline = line
|
|
if "CLANG_VERSION " in line:
|
|
nline = re.sub(
|
|
r"#define CLANG_VERSION (.*)'",
|
|
f"#define CLANG_VERSION {self.version_str(include_suffix=False)}'",
|
|
line,
|
|
)
|
|
# Match version strings of LLVM, Clang and LLD overlay headers
|
|
elif "LLVM_VERSION_STRING" in line or "CLANG_VERSION_STRING" in line or "LLD_VERSION_STRING" in line:
|
|
nline = re.sub(
|
|
r"#define (LLVM|CLANG|LLD)_VERSION_STRING ([\\\"]+)[0-9\.rcgit-]+([\\\"]+)",
|
|
rf"#define \g<1>_VERSION_STRING \g<2>{self.version_str()}\g<3>",
|
|
line,
|
|
)
|
|
# Match the split out MAJOR/MINOR/PATCH versions of LLVM and Clang overlay headers
|
|
# in LLVM the define is called _PATCH and in clang it's called _PATCHLEVEL
|
|
elif "LLVM_VERSION_" in line or "CLANG_VERSION_" in line:
|
|
for c, cver in (
|
|
("(MAJOR)", self.major),
|
|
("(MINOR)", self.minor),
|
|
("(PATCH|PATCHLEVEL)", self.patch),
|
|
):
|
|
nline = re.sub(
|
|
fr"(LLVM|CLANG)_VERSION_{c} \d+",
|
|
rf"\g<1>_VERSION_\g<2> {cver}",
|
|
line,
|
|
)
|
|
if nline != line:
|
|
break
|
|
|
|
return nline
|
|
|
|
|
|
# GN build system
|
|
class GNIProcessor(Processor):
|
|
def process_line(self, line: str) -> str:
|
|
if "llvm_version_" in line:
|
|
for c, cver in (
|
|
("major", self.major),
|
|
("minor", self.minor),
|
|
("patch", self.patch),
|
|
):
|
|
nline = re.sub(fr"llvm_version_{c} = \d+", f"llvm_version_{c} = {cver}", line)
|
|
if nline != line:
|
|
return nline
|
|
|
|
return line
|
|
|
|
|
|
# LIT python file, a simple tuple
|
|
class LitProcessor(Processor):
|
|
def process_line(self, line: str) -> str:
|
|
if "__versioninfo__" in line:
|
|
nline = re.sub(
|
|
fr"__versioninfo__(.*)\((\d+), (\d+), (\d+)\)",
|
|
f"__versioninfo__\\1({self.major}, {self.minor}, {self.patch})",
|
|
line,
|
|
)
|
|
return nline
|
|
return line
|
|
|
|
|
|
# Handle libc++ config header
|
|
class LibCXXProcessor(Processor):
|
|
def process_line(self, line: str) -> str:
|
|
# match #define _LIBCPP_VERSION 160000 in a relaxed way
|
|
match = re.match(r".*\s_LIBCPP_VERSION\s+(\d{6})$", line)
|
|
if match:
|
|
verstr = f"{str(self.major).zfill(2)}{str(self.minor).zfill(2)}{str(self.patch).zfill(2)}"
|
|
|
|
nline = re.sub(
|
|
fr"_LIBCPP_VERSION (\d+)",
|
|
f"_LIBCPP_VERSION {verstr}",
|
|
line,
|
|
)
|
|
return nline
|
|
return line
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(
|
|
usage="Call this script with a version and it will bump the version for you"
|
|
)
|
|
parser.add_argument("version", help="Version to bump to, e.g. 15.0.1", default=None)
|
|
parser.add_argument("--rc", default=None, type=int, help="RC version")
|
|
parser.add_argument(
|
|
"-s",
|
|
"--source-root",
|
|
default=None,
|
|
help="LLVM source root (/path/llvm-project). Defaults to the llvm-project the script is located in.",
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
verstr = args.version
|
|
if args.rc:
|
|
verstr += f"-rc{args.rc}"
|
|
|
|
# parse the version string with distutils.
|
|
# note that -rc will end up as version.pre here
|
|
# since it's a prerelease
|
|
version = packaging.version.parse(verstr)
|
|
|
|
# Find llvm-project root
|
|
source_root = Path(__file__).resolve().parents[3]
|
|
|
|
if args.source_root:
|
|
source_root = Path(args.source_root).resolve()
|
|
|
|
files_to_update = (
|
|
# Main CMakeLists.
|
|
(source_root / "llvm" / "CMakeLists.txt", CMakeProcessor()),
|
|
# Lit configuration
|
|
(
|
|
"llvm/utils/lit/lit/__init__.py",
|
|
LitProcessor(),
|
|
),
|
|
# GN build system
|
|
(
|
|
"llvm/utils/gn/secondary/llvm/version.gni",
|
|
GNIProcessor(),
|
|
),
|
|
# Bazel build system
|
|
(
|
|
"utils/bazel/llvm-project-overlay/llvm/include/llvm/Config/llvm-config.h",
|
|
BazelProcessor(),
|
|
),
|
|
(
|
|
"utils/bazel/llvm-project-overlay/clang/BUILD.bazel",
|
|
BazelProcessor(),
|
|
),
|
|
(
|
|
"utils/bazel/llvm-project-overlay/clang/include/clang/Config/config.h",
|
|
BazelProcessor(),
|
|
),
|
|
(
|
|
"utils/bazel/llvm-project-overlay/lld/BUILD.bazel",
|
|
BazelProcessor(),
|
|
),
|
|
(
|
|
"libcxx/include/__config",
|
|
LibCXXProcessor(),
|
|
),
|
|
)
|
|
|
|
for f, processor in files_to_update:
|
|
processor.process_file(source_root / Path(f), version)
|