[sw] Prepare for GCC and Clang (Combined) Toolchain
Signed-off-by: Sam Elliott <selliott@lowrisc.org>
diff --git a/util/get-toolchain.py b/util/get-toolchain.py
index 73d82e3..278ea38 100755
--- a/util/get-toolchain.py
+++ b/util/get-toolchain.py
@@ -16,15 +16,28 @@
log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s")
-ASSET_PREFIX = "lowrisc-toolchain-gcc-rv32imc-"
+# the keys in this dictionary specify valid toolchain kinds
+ASSET_PREFIXES = {
+ # kind : prefix,
+ "combined": "lowrisc-toolchain-rv32imc-",
+ "gcc-only": "lowrisc-toolchain-gcc-rv32imc-",
+}
ASSET_SUFFIX = ".tar.xz"
RELEASES_URL_BASE = 'https://api.github.com/repos/lowRISC/lowrisc-toolchains/releases'
TARGET_DIR = '/tools/riscv'
TOOLCHAIN_VERSION = 'latest'
+TOOLCHAIN_KIND = 'gcc-only'
+
+FILE_PATTERNS_TO_REWRITE = [
+ "riscv32-unknown-elf-*.cmake",
+ "meson-riscv32-unknown-elf-*.txt",
+]
-def get_available_toolchain_info(version):
+def get_available_toolchain_info(version, kind):
+ assert kind in ASSET_PREFIXES
+
if version == 'latest':
releases_url = '%s/%s' % (RELEASES_URL_BASE, version)
else:
@@ -33,13 +46,20 @@
with urlopen(releases_url) as f:
release_info = json.loads(f.read().decode('utf-8'))
- download_url = [
- a["browser_download_url"] for a in release_info["assets"]
- if (a["name"].startswith(ASSET_PREFIX) and
- a["name"].endswith(ASSET_SUFFIX))
- ][0]
+ for asset in release_info["assets"]:
+ if (asset["name"].startswith(ASSET_PREFIXES[kind]) and
+ asset["name"].endswith(ASSET_SUFFIX)):
+ return {
+ 'download_url': asset['browser_download_url'],
+ 'name': asset['name'],
+ 'version': release_info['tag_name'],
+ 'kind': kind
+ }
- return {'download_url': download_url, 'version': release_info['tag_name']}
+ # No matching asset found for the toolchain kind requested
+ log.error("No available downloads found for %s toolchain version: %s",
+ kind, release_info['tag_name'])
+ raise SystemExit(1)
def get_installed_toolchain_info(install_path):
@@ -49,6 +69,13 @@
buildinfo = {}
with open(str(install_path / 'buildinfo.json'), 'r') as f:
buildinfo = json.loads(f.read())
+
+ # Toolchains before 20200602-4 contained a `buildinfo.json` without a
+ # 'kind' field. Setting it to 'unknown' will ensure we never skip
+ # updating because we think it's the same as the existing toolchain.
+ if 'kind' not in buildinfo:
+ buildinfo['kind'] = 'unknown'
+
return buildinfo
except Exception as e:
# buildinfo.json might not exist in older builds
@@ -65,7 +92,7 @@
log.warning("Unable extract version from %s",
str(buildinfo_txt_path))
return None
- return {'version': match.group("version")}
+ return {'version': match.group("version"), 'kind': 'unknown'}
except Exception as e:
log.error("Unable to read %s: %s", str(buildinfo_txt_path), str(e))
return None
@@ -75,6 +102,7 @@
log.info("Downloading toolchain from %s", url)
tmpfile = tempfile.mkstemp()[1]
urlretrieve(url, tmpfile)
+ log.info("Download complete")
return Path(tmpfile)
@@ -82,12 +110,27 @@
target_dir.mkdir(parents=True, exist_ok=True)
cmd = [
- 'tar', '-x', '-f', str(archive_file), '--strip-components=1', '-C',
- str(target_dir)
+ 'tar', '-x', '-f', str(archive_file), '--strip-components=1', '-C', str(target_dir),
]
subprocess.run(cmd, check=True)
+def postinstall_rewrite_configs(install_path):
+ """This rewrites the toolchain configuration files to point to install_path"""
+ if str(install_path) == TARGET_DIR:
+ return
+
+ for file_pattern in FILE_PATTERNS_TO_REWRITE:
+ for config_file_path in install_path.glob(file_pattern):
+ # Rewrite TARGET_DIR to the requested target dir.
+ log.info("Updating toolchain paths in %s",
+ str(config_file_path))
+ with open(str(config_file_path)) as f:
+ original = f.read()
+ with open(str(config_file_path), "w") as f:
+ f.write(original.replace(TARGET_DIR, str(install_path)))
+
+
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--target-dir',
@@ -100,6 +143,11 @@
required=False,
default=TOOLCHAIN_VERSION,
help="Toolchain version (default: %(default)s)")
+ parser.add_argument('--kind',
+ required=False,
+ default=TOOLCHAIN_KIND,
+ choices=ASSET_PREFIXES.keys(),
+ help="Toolchain kind (default: %(default)s)")
parser.add_argument(
'--update',
'-u',
@@ -111,28 +159,40 @@
target_dir = Path(args.target_dir)
- available_toolchain = get_available_toolchain_info(args.release_version)
+ available_toolchain = get_available_toolchain_info(args.release_version,
+ args.kind)
+ log.info("Found available %s toolchain version %s, %s",
+ available_toolchain['kind'], available_toolchain['version'],
+ available_toolchain['name'])
if args.update and target_dir.is_dir():
installed_toolchain = get_installed_toolchain_info(target_dir)
if installed_toolchain is None:
sys.exit('Unable to extract current toolchain version. '
- 'Delete target directory and try again.')
+ 'Delete target directory %s and try again.' %
+ str(target_dir))
- if available_toolchain['version'] == installed_toolchain['version']:
+ version_matches = available_toolchain['version'] == installed_toolchain['version']
+ kind_matches = available_toolchain['kind'] == installed_toolchain['kind']
+
+ if installed_toolchain['kind'] != 'unknown' and version_matches and kind_matches:
log.info(
- 'Toolchain version %s already installed at %s. Skipping '
- 'install.', installed_toolchain['version'], str(target_dir))
+ 'Downloaded %s toolchain is version %s, '
+ 'same as the %s toolchain installed at %s (version %s).',
+ available_toolchain['kind'], available_toolchain['version'],
+ installed_toolchain['kind'], installed_toolchain['version'],
+ str(target_dir))
+ log.warning("Skipping install.")
sys.exit(0)
log.info(
- "Found installed toolchain version %s, updating to version %s.",
- installed_toolchain['version'], available_toolchain['version'])
+ "Found installed %s toolchain version %s, updating to %s toolchain version %s.",
+ installed_toolchain['kind'], installed_toolchain['version'],
+ available_toolchain['kind'], available_toolchain['version'])
else:
if target_dir.exists():
- sys.exit(
- 'Target directory %s already exists. Delete it first, or use --update.'
- % str(target_dir))
+ sys.exit('Target directory %s already exists. '
+ 'Delete it first, or use --update.' % str(target_dir))
archive_file = None
try:
@@ -144,12 +204,14 @@
shutil.rmtree(target_dir)
install(archive_file, target_dir)
+ postinstall_rewrite_configs(target_dir.resolve())
finally:
if archive_file:
archive_file.unlink()
- log.info('Toolchain version %s downloaded and installed to %s.',
- available_toolchain['version'], str(target_dir))
+ log.info('Installed %s toolchain version %s to %s.',
+ available_toolchain['kind'], available_toolchain['version'],
+ str(target_dir))
if __name__ == "__main__":