#!/usr/bin/env python3 # This script finds and prints the various versions in this project: wasi-sdk # itself, LLVM, and the Git revisions of dependencies. # # Usage: version [wasi-sdk|llvm|llvm-major|dump] [--llvm-dir=] import argparse import os import subprocess import sys # The number of characters to use for the abbreviated Git revision. GIT_REF_LEN = 12 def exec(command, cwd): result = subprocess.run(command, stdout=subprocess.PIPE, universal_newlines=True, check=True, cwd=cwd) return result.stdout.strip() def git_commit(dir): return exec(['git', 'rev-parse', f'--short={GIT_REF_LEN}', 'HEAD'], dir) def parse_git_version(version): # Parse, e.g.: wasi-sdk-$version-0-g317548590b40+m parts = version.replace('+', '-').split('-') assert parts.pop(0) == 'wasi' assert parts.pop(0) == 'sdk' dirty = False git = parts.pop() assert git is not None # If git printed `+m` at the end then we're dirty and the next-to-last part # is now the git commit if git == 'm': dirty = True git = parts.pop() # If the git commit doesn't start with `g` then that's not actually a git # commit. Technically this should look for `GIT_REF_LEN` hexadecimal digits, # but that's left for later. if not git.startswith('g'): parts.append(git) git = None # The next part in the back is the number of commits since the tag, and the # first part in the front is the major version of wasi-sdk itself. commits_since_tag = parts.pop() major_version = parts.pop(0) # If there are 0 commits since the last tag then forcibly drop the git part # as that produces a nice clean version for tagged commits. if commits_since_tag == '0': git = None # Pretend the commits since the tag is a minor version number, and then # add in any other words after the tag to the prerelease part, if any. ret = f'{major_version}.{commits_since_tag}' if len(parts) > 0: ret += '-' + '-'.join(parts) # Throw on git/dirty info if git: ret += git if dirty: ret += '+m' return ret # Some inline tests to check Git version parsing: assert parse_git_version('wasi-sdk-21-1-g317548590b40+m') == '21.1g317548590b40+m' assert parse_git_version('wasi-sdk-21-2+m') == '21.2+m' assert parse_git_version('wasi-sdk-23-0-g317548590b40') == '23.0' assert parse_git_version('wasi-sdk-23-tag-0-g317548590b40') == '23.0-tag' assert parse_git_version('wasi-sdk-23-some-tag-0-g317548590b40') == '23.0-some-tag' assert parse_git_version('wasi-sdk-23-some.tag-0-g317548590b40') == '23.0-some.tag' assert parse_git_version('wasi-sdk-23-tag.rc1-1-g100') == '23.1-tag.rc1g100' def git_version(): version = exec(['git', 'describe', '--long', '--candidates=999', '--match=wasi-sdk-*', '--dirty=+m', f'--abbrev={GIT_REF_LEN}'], os.path.dirname(sys.argv[0])) return parse_git_version(version) def parse_cmake_set(line): return line.split(' ')[1].split(')')[0] def llvm_cmake_version(llvm_dir): path = f'{llvm_dir}/cmake/Modules/LLVMVersion.cmake' if not os.path.exists(path): # Handle older LLVM versions; see #399. path = f'{llvm_dir}/llvm/CMakeLists.txt' with open(path) as file: for line in file: line = line.strip() if line.startswith('set(LLVM_VERSION_MAJOR'): llvm_version_major = parse_cmake_set(line) elif line.startswith('set(LLVM_VERSION_MINOR'): llvm_version_minor = parse_cmake_set(line) elif line.startswith('set(LLVM_VERSION_PATCH'): llvm_version_patch = parse_cmake_set(line) return llvm_version_major, llvm_version_minor, llvm_version_patch def main(action, llvm_dir): if action == 'wasi-sdk': print(git_version()) elif action == 'llvm': major, minor, path = llvm_cmake_version(llvm_dir) print(f'{major}.{minor}.{path}') elif action == 'llvm-major': major, _, _ = llvm_cmake_version(llvm_dir) print(major) elif action == 'dump': print(git_version()) print(f'wasi-libc: {git_commit("src/wasi-libc")}') print(f'llvm: {git_commit(llvm_dir)}') major, minor, path = llvm_cmake_version(llvm_dir) print(f'llvm-version: {major}.{minor}.{path}') print(f'config: {git_commit("src/config")}') if __name__ == '__main__': parser = argparse.ArgumentParser( description='Print the various kinds of versions in wasi-sdk') parser.add_argument('action', choices=['wasi-sdk', 'llvm', 'llvm-major', 'dump'], nargs='?', default='wasi-sdk', help='Which kind of version to print (default: wasi-sdk).') parser.add_argument('--llvm-dir', nargs='?', default='src/llvm-project', help='Override the location of the LLVM source directory (default: src/llvm-project).') args = parser.parse_args() main(args.action, args.llvm_dir) sys.exit(0)