From 7f73cf67bb926e4443603d2e425ffcafdd78f208 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Fri, 16 Dec 2022 05:31:40 -0600 Subject: [PATCH] omnitrace-install.py (#221) - omnitrace-install.py will be uploaded as a release asset - script simplifies selecting the correct installer script [ROCm/rocprofiler-systems commit: 1f818054ce64c4513c441439ef1038a6c0719cf3] --- .../.github/workflows/cpack.yml | 11 +- projects/rocprofiler-systems/.gitignore | 2 + .../cmake/Templates/omnitrace-install.py.in | 244 ++++++++++++++++++ .../scripts/write-omnitrace-install.cmake | 19 ++ 4 files changed, 275 insertions(+), 1 deletion(-) create mode 100755 projects/rocprofiler-systems/cmake/Templates/omnitrace-install.py.in create mode 100644 projects/rocprofiler-systems/scripts/write-omnitrace-install.cmake diff --git a/projects/rocprofiler-systems/.github/workflows/cpack.yml b/projects/rocprofiler-systems/.github/workflows/cpack.yml index 1dcd1681f0..e5c60aac00 100644 --- a/projects/rocprofiler-systems/.github/workflows/cpack.yml +++ b/projects/rocprofiler-systems/.github/workflows/cpack.yml @@ -28,11 +28,20 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 + - name: Generate generic installer script + shell: bash + run: | + apt-get update + apt-get install -y cmake + cmake -D OUTPUT_DIR=${PWD} -P scripts/write-omnitrace-install.cmake - name: Generate Release uses: softprops/action-gh-release@v1 with: - draft: True + draft: False generate_release_notes: True + fail_on_unmatched_files: True + files: | + omnitrace-install.py release-docs: if: github.repository == 'AMDResearch/omnitrace' && (startsWith(github.ref, 'refs/tags/') || contains(github.ref, 'releases/')) diff --git a/projects/rocprofiler-systems/.gitignore b/projects/rocprofiler-systems/.gitignore index 12f6880bfb..d6a299e234 100644 --- a/projects/rocprofiler-systems/.gitignore +++ b/projects/rocprofiler-systems/.gitignore @@ -39,3 +39,5 @@ /.cache /.clangd /compile_commands.json +/omnitrace-install.py +/scripts/omnitrace-install.py diff --git a/projects/rocprofiler-systems/cmake/Templates/omnitrace-install.py.in b/projects/rocprofiler-systems/cmake/Templates/omnitrace-install.py.in new file mode 100755 index 0000000000..9bed2498bd --- /dev/null +++ b/projects/rocprofiler-systems/cmake/Templates/omnitrace-install.py.in @@ -0,0 +1,244 @@ +#!/usr/bin/env python3 + +import os +import re +import sys +import stat +import argparse +import tempfile +import subprocess as sp +from urllib import request +from urllib.error import HTTPError + +omnitrace_version = "@OMNITRACE_VERSION@" +_rocm_path = os.environ.get("ROCM_PATH", "/opt/rocm") +_rocm_version = None + + +def get_rocm_version(rocm_hint): + global _rocm_path + global _rocm_version + + if rocm_hint is not None and rocm_hint is not True: + if rocm_hint.replace(".", "0").isnumeric(): + _rocm_version = rocm_hint + else: + _rocm_path = rocm_hint + + def _parse_version(_v): + return re.split(r"[\\.-]", _v) if _v is not None else None + + _version = _parse_version(_rocm_version) + for fname in [ + "version", + "version-dev", + "version-hip-libraries", + "version-hiprt", + "version-hiprt-devel", + "version-hip-sdk", + "version-libs", + "version-utils", + ]: + if _version is not None and len(_version) > 0: + break + _fname = os.path.join(_rocm_path, ".info", fname) + if os.path.exists(_fname): + with open(_fname, "r") as f: + _version = _parse_version(f.readlines()[0].strip("\n")) + + if _version is not None and len(_version) > 0: + _major = int(_version[0]) + _minor = int(_version[1]) if len(_version) >= 2 else 0 + _rocm_version = f"{_major}.{_minor}" + return "-ROCm-{}".format((10000 * _major) + (100 * _minor)) + return None + + +def get_os_info(os_distrib, os_version): + + _os_info = {} + with open("/etc/os-release", "r") as f: + for line in [_v.strip() for _v in f.readlines()]: + _key, _data = line.split("=", 1) + _os_info[_key] = _data.strip('"') + + if os_distrib is None or os_distrib == "auto": + if "debian" in _os_info["ID_LIKE"]: + os_distrib = "ubuntu" + elif "suse" in _os_info["ID_LIKE"]: + os_distrib = "opensuse" + else: + raise RuntimeError( + "Unknown ID_LIKE value in /etc/os-release: {}".format(_os_info["ID_LIKE"]) + ) + + if os_version is None: + + def _parse_version(_v): + _version = re.split(r"[\\.-]", _v) + return "{}.{}".format(_version[0], _version[1]) + + os_version = _parse_version(_os_info["VERSION_ID"]) + + return (os_distrib, os_version) + + +def print_log(*args, **kwargs): + + sys.stdout.flush() + sys.stderr.flush() + sys.stderr.write("### ") + sys.stderr.write(*args, **kwargs) + sys.stderr.write("\n") + sys.stderr.flush() + + +def run(*args, **kwargs): + + print_log("Executing: {}\n".format(" ".join(*args))) + sp.run(*args, **kwargs, check=True) + sys.stderr.write("\n") + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser() + + parser.add_argument( + "--version", + help="Print omnitrace version which will be installed", + action="store_true", + ) + parser.add_argument( + "-p", "--prefix", help="Installation prefix", type=str, default="/opt/omnitrace" + ) + parser.add_argument( + "-i", + "--interactive", + help="Prompt to accept the license and include/exclude subdirectory", + action="store_true", + ) + parser.add_argument( + "-D", + "--download-path", + help="Download directory (default: temporary directory)", + type=str, + default=None, + ) + parser.add_argument( + "-d", + "--os-distrib", + help="Target OS distribution", + type=str, + default=None, + choices=("auto", "ubuntu", "opensuse"), + ) + parser.add_argument( + "-v", "--os-version", help="Target OS version", type=str, default=None + ) + parser.add_argument( + "-k", + "--keep-download", + help="Do not delete downloaded file as installation", + action="store_true", + ) + parser.add_argument( + "--rocm", + help="Install omnitrace with ROCm support. Accepts either a ROCm version (e.g. '5.4') or the root path to the ROCm install containing .info/version* file(s) (e.g. /opt/rocm if /opt/rocm/.info/version exists). If no argument is provided, the ROCm version will attempted to be deduced from $ENV{ROCM_PATH}/.info/version", + nargs="?", + default=None, + const=True, + metavar="VERSION or ROCM_PATH with .info/version file(s)", + ) + # right now, only valid set of extensions are: papi + ompt + python3 + # in the future, this might change, e.g. MPI variants + parser.add_argument( + "-e", + "--extensions", + help="Omnitrace extensions, e.g. PAPI, OMPT, and Python3", + nargs="*", + default=("papi", "ompt", "python3"), + choices=("papi", "ompt", "python3"), + ) + + args = parser.parse_args() + + if args.version: + print(f"omnitrace {omnitrace_version}") + sys.exit(0) + + os_distrib, os_version = get_os_info(args.os_distrib, args.os_version) + rocm_version = get_rocm_version(args.rocm) if args.rocm is not None else "" + extensions = "" + if "papi" in args.extensions: + extensions += "-PAPI" + if "ompt" in args.extensions: + extensions += "-OMPT" + if "python3" in args.extensions: + extensions += "-Python3" + + if rocm_version is None: + raise RuntimeError( + f"Error! ROCm version could not be determined from {_rocm_path}/.info/version*. Please provide a ROCm version or the root path to the ROCm install containing the .info directory, e.g. '--rocm 5.4' or '--rocm /path/to/rocm/install'" + ) + + script = f"omnitrace-{omnitrace_version}-{os_distrib}-{os_version}{rocm_version}{extensions}.sh" + url = f"https://github.com/AMDResearch/omnitrace/releases/download/v{omnitrace_version}/{script}" + download_dir = ( + tempfile.mkdtemp(prefix="omnitrace-install-") + if args.download_path is None + else args.download_path + ) + install_script = os.path.join(download_dir, script) + + try: + if not os.path.exists(download_dir): + print_log(f"Creating download directory: {download_dir} ...") + os.makedirs(download_dir) + + print_log(f"Downloading {url} ...") + + try: + response = request.urlretrieve(url, install_script) + except HTTPError as e: + print_log(f"") + print_log(f"Error: {e}") + print_log(f"") + print_log(f"Error: Installer script download from {url} failed!") + if args.rocm is not None: + print_log( + f"There may not be a pre-built installer for ROCm version {_rocm_version}" + ) + sys.exit(-1) + + if os.path.exists(install_script): + print_log(f"Download completed: {install_script}") + else: + raise RuntimeError(f"Download completed but {install_script} does not exist") + + os.chmod(install_script, stat.S_IRWXU) + + if not os.path.exists(args.prefix): + print_log(f"Creating directory: {args.prefix} ...") + os.makedirs(args.prefix) + + install_args = ( + ["--exclude-subdir", "--skip-license"] if not args.interactive else [] + ) + + print_log(f"Installing omnitrace to {args.prefix} ...") + + run([install_script, f"--prefix={args.prefix}"] + install_args) + + print_log( + f"omnitrace v{omnitrace_version} installation to {args.prefix} succeeded!" + ) + + finally: + if not args.keep_download: + print_log(f"Removing install script {install_script} ...") + os.remove(install_script) + # remove the directory if it is a temporary directory + if args.download_path is None: + print_log(f"Removing temporary directory {download_dir} ...") + os.rmdir(download_dir) diff --git a/projects/rocprofiler-systems/scripts/write-omnitrace-install.cmake b/projects/rocprofiler-systems/scripts/write-omnitrace-install.cmake new file mode 100644 index 0000000000..d823c57008 --- /dev/null +++ b/projects/rocprofiler-systems/scripts/write-omnitrace-install.cmake @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.8) + +if(NOT DEFINED OMNITRACE_VERSION) + file(READ "${CMAKE_CURRENT_LIST_DIR}/../VERSION" FULL_VERSION_STRING LIMIT_COUNT 1) + string(REGEX REPLACE "(\n|\r)" "" FULL_VERSION_STRING "${FULL_VERSION_STRING}") + string(REGEX REPLACE "([0-9]+)\.([0-9]+)\.([0-9]+)(.*)" "\\1.\\2.\\3" + OMNITRACE_VERSION "${FULL_VERSION_STRING}") +endif() + +if(NOT DEFINED OUTPUT_DIR) + set(OUTPUT_DIR ${CMAKE_CURRENT_LIST_DIR}) +endif() + +message( + STATUS + "Writing ${OUTPUT_DIR}/omnitrace-install.py for omnitrace v${OMNITRACE_VERSION}") + +configure_file(${CMAKE_CURRENT_LIST_DIR}/../cmake/Templates/omnitrace-install.py.in + ${OUTPUT_DIR}/omnitrace-install.py @ONLY)