def fetch_jdk(args): """fetches required JDK version If mx is not passed the --quiet flag, menu will be printed for available JDK selection. """ args = _parse_fetchsettings(args) distribution = args["java-distribution"] base_path = args["base-path"] artifact = distribution.get_folder_name() final_path = distribution.get_final_path(base_path) url = mx_urlrewrites.rewriteurl(distribution.get_url()) sha_url = url + ".sha1" archive_name = distribution.get_archive_name() archive_target_location = join(base_path, archive_name) if not is_quiet(): if not mx.ask_yes_no("Install {} to {}".format(artifact, final_path), default='y'): mx.abort("JDK installation canceled") if exists(final_path): if args["keep-archive"]: mx.warn( "The --keep-archive option is ignored when the JDK is already installed." ) mx.log("Requested JDK is already installed at {}".format(final_path)) else: # Try to extract on the same file system as the target to be able to atomically move the result. with mx.TempDir(parent_dir=base_path) as temp_dir: mx.log("Fetching {} archive from {}...".format(artifact, url)) archive_location = join(temp_dir, archive_name) mx._opts.no_download_progress = is_quiet() sha1_hash = mx._hashFromUrl(sha_url).decode('utf-8') mx.download_file_with_sha1(artifact, archive_location, [url], sha1_hash, archive_location + '.sha1', resolve=True, mustExist=True, sources=False) untar = mx.TarExtractor(archive_location) mx.log("Installing {} to {}...".format(artifact, final_path)) extracted_path = join(temp_dir, 'extracted') try: untar.extract(extracted_path) except: mx.rmtree(temp_dir, ignore_errors=True) mx.abort("Error parsing archive. Please try again") jdk_root_folder = get_extracted_jdk_archive_root_folder( extracted_path) if args["keep-archive"]: atomic_file_move_with_fallback(archive_location, archive_target_location) atomic_file_move_with_fallback( archive_location + '.sha1', archive_target_location + ".sha1") mx.log( "Archive is located at {}".format(archive_target_location)) atomic_file_move_with_fallback( join(extracted_path, jdk_root_folder), final_path) curr_path = final_path if mx.is_darwin() and exists(join(final_path, 'Contents', 'Home')): if args["strip-contents-home"]: with mx.TempDir(parent_dir=final_path) as tmp_path: shutil.move(final_path, tmp_path) shutil.move(join(tmp_path, 'Contents', 'Home'), final_path) else: final_path = join(final_path, 'Contents', 'Home') if "alias" in args: alias_full_path = join(base_path, args["alias"]) if exists(alias_full_path): mx.rmtree(alias_full_path) if not (mx.is_windows() or mx.is_cygwin()): os.symlink(abspath(curr_path), alias_full_path) else: mx.copytree(curr_path, alias_full_path, symlinks=True) # fallback for windows final_path = alias_full_path mx.log("Run the following to set JAVA_HOME in your shell:") shell = os.environ.get("SHELL") if shell is None: shell = '' print(get_setvar_format(shell) % ("JAVA_HOME", abspath(final_path)))
def fetch_jdk(args): """ Installs a JDK based on the coordinates in `args`. See ``mx fetch-jdk --help`` for more info. Note that if a JDK already exists at the installation location denoted by `args`, no action is taken. :return str: the JAVA_HOME for the JDK at the installation location denoted by `args` """ settings = _parse_args(args) jdk_binary = settings["jdk-binary"] jdks_dir = settings["jdks-dir"] artifact = jdk_binary._folder_name final_path = jdk_binary.get_final_path(jdks_dir) url = mx_urlrewrites.rewriteurl(jdk_binary._url) sha_url = url + ".sha1" archive_name = jdk_binary._archive archive_target_location = join(jdks_dir, archive_name) if not is_quiet(): if not mx.ask_yes_no("Install {} to {}".format(artifact, final_path), default='y'): mx.abort("JDK installation canceled") if exists(final_path): if settings["keep-archive"]: mx.warn( "The --keep-archive option is ignored when the JDK is already installed." ) mx.log("Requested JDK is already installed at {}".format(final_path)) else: # Try to extract on the same file system as the target to be able to atomically move the result. with mx.TempDir(parent_dir=jdks_dir) as temp_dir: mx.log("Fetching {} archive from {}...".format(artifact, url)) archive_location = join(temp_dir, archive_name) mx._opts.no_download_progress = is_quiet() try: sha1_hash = mx._hashFromUrl(sha_url).decode('utf-8') except Exception as e: #pylint: disable=broad-except mx.abort('Error retrieving {}: {}'.format(sha_url, e)) mx.download_file_with_sha1(artifact, archive_location, [url], sha1_hash, archive_location + '.sha1', resolve=True, mustExist=True, sources=False) untar = mx.TarExtractor(archive_location) mx.log("Installing {} to {}...".format(artifact, final_path)) extracted_path = join(temp_dir, 'extracted') try: untar.extract(extracted_path) except: mx.rmtree(temp_dir, ignore_errors=True) mx.abort("Error parsing archive. Please try again") jdk_root_folder = _get_extracted_jdk_archive_root_folder( extracted_path) if settings["keep-archive"]: atomic_file_move_with_fallback(archive_location, archive_target_location) atomic_file_move_with_fallback( archive_location + '.sha1', archive_target_location + ".sha1") mx.log( "Archive is located at {}".format(archive_target_location)) atomic_file_move_with_fallback( join(extracted_path, jdk_root_folder), final_path) curr_path = final_path if exists(join(final_path, 'Contents', 'Home')): if settings["strip-contents-home"]: with mx.TempDir() as tmp_path: tmp_jdk = join(tmp_path, 'jdk') shutil.move(final_path, tmp_jdk) shutil.move(join(tmp_jdk, 'Contents', 'Home'), final_path) else: final_path = join(final_path, 'Contents', 'Home') alias = settings.get('alias') if alias: alias_full_path = join(jdks_dir, alias) if not exists(alias_full_path) or os.path.realpath( alias_full_path) != os.path.realpath(abspath(curr_path)): if os.path.islink(alias_full_path): os.unlink(alias_full_path) elif exists(alias_full_path): mx.abort( alias_full_path + ' exists and it is not an existing symlink so it can not be used for a new symlink. Please remove it manually.' ) if mx.can_symlink(): if isabs(alias): os.symlink(curr_path, alias_full_path) else: reldir = os.path.relpath(dirname(curr_path), dirname(alias_full_path)) if reldir == '.': alias_target = basename(curr_path) else: alias_target = join(reldir, basename(curr_path)) os.symlink(alias_target, alias_full_path) else: mx.copytree(curr_path, alias_full_path) final_path = alias_full_path mx.log("Run the following to set JAVA_HOME in your shell:") shell = os.environ.get("SHELL") if shell is None: shell = '' if not settings["strip-contents-home"] and exists( join(final_path, 'Contents', 'Home')): java_home = join(final_path, 'Contents', 'Home') else: java_home = final_path mx.log(get_setvar_format(shell) % ("JAVA_HOME", abspath(java_home))) return final_path
def _parse_fetchsettings(args): settings = {} settings["keep-archive"] = False settings["base-path"] = default_base_path() common_location = join(_mx_home, 'common.json') parser = ArgumentParser(prog='mx fetch-jdk') parser.add_argument( '--java-distribution', action='store', help= 'JDK distribution that should be downloaded (e.g., "labsjdk-ce-11" or "openjdk8")' ) parser.add_argument( '--configuration', action='store', help='location of configuration json file (default: \'{}\')'.format( common_location)) parser.add_argument( '--to', action='store', help='location where JDK would be downloaded (default: \'{}\')'.format( settings["base-path"])) parser.add_argument('--alias', action='store', help='name of symlink to JDK') parser.add_argument('--keep-archive', action='store_true', help='keep downloaded JDK archive') if mx.is_darwin(): parser.add_argument('--strip-contents-home', action='store_true', help='strip Contents/Home') parser.add_argument('remainder', nargs=REMAINDER, metavar='...') args = parser.parse_args(args) if args.to is not None: settings["base-path"] = args.to if not check_write_access(settings["base-path"]): mx.abort( "JDK installation directory {} is not writeable.".format( settings["base-path"]) + os.linesep + "Either re-run with elevated privileges (e.g. sudo) or specify a writeable directory with the --to option." ) if args.configuration is not None: common_location = args.configuration else: if mx.primary_suite() is not None: common_location = join(mx.primary_suite().vc_dir, 'common.json') # Try fetching suite config else: common_location = join(os.getcwd(), 'common.json') # Fallback to same folder if not exists(common_location): common_location = join(_mx_home, 'common.json') # Fallback to mx mx.warn( "Selected `{}` as configuration location, since no location is provided" .format(common_location)) if not exists(common_location): mx.abort("Configuration file doesn't exist") parse_common_json(common_location) if args.java_distribution is not None: settings["java-distribution"] = JdkDistribution.by_name( args.java_distribution) else: settings["java-distribution"] = JdkDistribution.choose_dist(is_quiet()) if args.alias is not None: settings["alias"] = args.alias if args.keep_archive is not None: settings["keep-archive"] = args.keep_archive if mx.is_darwin() and (args.strip_contents_home is not None): settings["strip-contents-home"] = args.strip_contents_home return settings
def _parse_args(args): """ Defines and parses the command line arguments in `args` for the ``fetch-jdk`` command. :return dict: a dictionary configuring the action to be taken by ``fetch-jdk``. The entries are: "keep-archive": True if the downloaded archive is to be retained after extraction, False if it is to be deleted "jdks-dir": directory in which archive is to be extracted "jdk-binary": a _JdkBinary object "alias": path of a symlink to create to the extracted JDK "strip-contents-home": True if the ``Contents/Home`` should be stripped if it exists from the extracted JDK """ settings = {} settings["keep-archive"] = False settings["jdks-dir"] = join(mx.dot_mx_dir(), 'jdks') # Order in which to look for common.json: # 1. Primary suite path (i.e. -p mx option) # 2. Current working directory # 4. $MX_HOME/common.json path_list = PathList() if mx._primary_suite_path: path_list.add(_find_file(mx._primary_suite_path, 'common.json')) path_list.add(_find_file(os.getcwd(), 'common.json')) path_list.add(join(_mx_home, 'common.json')) default_jdk_versions_location = path_list.paths[0] # Order in which to look for jdk-binaries.json: # 1. Primary suite path (i.e. -p mx option) # 2. Current working directory # 4. $MX_HOME/jdk-binaries.json path_list = PathList() if mx._primary_suite_path: path_list.add(_find_file(mx._primary_suite_path, 'jdk-binaries.json')) path_list.add(_find_file(os.getcwd(), 'jdk-binaries.json')) path_list.add(join(_mx_home, 'jdk-binaries.json')) default_jdk_binaries_location = str(path_list) parser = ArgumentParser(prog='mx fetch-jdk', usage='%(prog)s [options]' + """ Download and install JDKs. The set of JDKS available for download are specified by the "jdks" field of the JSON object loaded by --configuration. The "jdks" field is itself is an object whose field names are JDK identifiers and whose field values include a version. For example: { "jdks": { "openjdk8": {"version": "8u302+02-jvmci-21.2-b02" }, "labsjdk-ce-11": {"version": "ce-11.0.11+8-jvmci-21.2-b02" }, } } The location of binaries matching these JDK definitions is specified by the "jdk-binaries" field of the JSON object loaded by --jdk-binaries (can be the same value as --configuration). For example: { "jdk-binaries": { "openjdk8": { "filename": "openjdk-{version}-{platform}", "url": "https://github.com/graalvm/graal-jvmci-8/releases/download/{version|jvmci}/{filename}.tar.gz" }, "labsjdk-ce-11": { "filename": "labsjdk-{version}-{platform}", "url": "https://github.com/graalvm/labs-openjdk-11/releases/download/{version|jvmci}/{filename}.tar.gz" } } } The "jdk-binaries.<id>" object specifies the URL at which a JDK binary for the "jdks.<id>" object is found. The "filename" and "url" attributes of a JDK binary object are template strings with curly braces denoting keywords that will be replaced with their values. The supported keywords and their value for a "jdk-binaries.<id>" object are: version The value of "jdks.<id>.version". platform The value denoting the operating system and architecture (e.g. "linux-amd64"). filename The value of "jdk-binaries.<id>.filename". Each keyword value can be processed by a filter by appending "|<filter>" to the keyword selector. The supported filters are: jvmci Extracts the first string that looks like a jvmci version (e.g. "8u302+05-jvmci-21.2-b01" -> "21.2-b01"). jvmci-tag Extracts the first string that looks like a jvmci tag (e.g. "8u302+05-jvmci-21.2-b01" -> "jvmci-21.2-b01"). """) parser.add_argument( '--jdk-id', '--java-distribution', action='store', metavar='<id>', help= 'Identifier of the JDK that should be downloaded (e.g., "labsjdk-ce-11" or "openjdk8")' ) parser.add_argument( '--configuration', action='store', metavar='<path>', help='location of JSON file containing JDK definitions (default: {})'. format(default_jdk_versions_location)) parser.add_argument( '--jdk-binaries', action='store', metavar='<path>', help= '{} separated JSON files specifying location of JDK binaries (default: {})' .format(os.pathsep, default_jdk_binaries_location)) parser.add_argument( '--to', action='store', metavar='<dir>', help= 'location where JDK will be installed. Specify <system> to use the system default location. (default: {})' .format(settings["jdks-dir"])) parser.add_argument( '--alias', action='store', metavar='<path>', help= 'name under which the extracted JDK should be made available (e.g. via a symlink). A relative path will be resolved against the value of the --to option.' ) parser.add_argument('--keep-archive', action='store_true', help='keep downloaded JDK archive') parser.add_argument( '--strip-contents-home', action='store_true', help='strip Contents/Home if it exists from installed JDK') args = parser.parse_args(args) if args.to is not None: if args.to == '<system>': args.to = _default_system_jdks_dir() settings["jdks-dir"] = args.to if not _check_write_access(settings["jdks-dir"]): mx.abort( "JDK installation directory {} is not writeable.".format( settings["jdks-dir"]) + os.linesep + "Either re-run with elevated privileges (e.g. sudo) or specify a writeable directory with the --to option." ) jdk_versions_location = _check_exists_or_None( args.configuration) or default_jdk_versions_location jdk_binaries_locations = (args.jdk_binaries or default_jdk_binaries_location).split( os.pathsep) jdk_versions = _parse_jdk_versions(jdk_versions_location) jdk_binaries = _parse_jdk_binaries(jdk_binaries_locations, jdk_versions) if args.jdk_id is not None: settings["jdk-binary"] = _get_jdk_binary_or_abort( jdk_binaries, args.jdk_id) else: settings["jdk-binary"] = _choose_jdk_binary(jdk_binaries, is_quiet()) if args.alias is not None: settings["alias"] = args.alias if args.keep_archive is not None: settings["keep-archive"] = args.keep_archive settings["strip-contents-home"] = args.strip_contents_home return settings