--- /dev/null 2017-08-22 11:47:07.000000000 -0700 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Options.java 2017-08-22 11:47:07.000000000 -0700 @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import jdk.tools.jaotc.collect.ClassSearch; +import jdk.tools.jaotc.collect.ClassSource; +import jdk.tools.jaotc.collect.SearchFor; +import jdk.tools.jaotc.collect.SearchPath; +import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider; +import jdk.tools.jaotc.collect.directory.DirectorySourceProvider; +import jdk.tools.jaotc.collect.jar.JarSourceProvider; +import jdk.tools.jaotc.collect.module.ModuleSourceProvider; + +final class Options { + List files = new LinkedList<>(); + String osName; + String outputName = defaultOutputName(); + String methodList; + List sources = new ArrayList<>(); + String linkerpath = null; + SearchPath searchPath = new SearchPath(); + + /** + * We don't see scaling beyond 16 threads. + */ + private static final int COMPILER_THREADS = 16; + + int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors()); + + boolean ignoreClassLoadingErrors; + boolean exitOnError; + boolean info; + boolean verbose; + boolean debug; + boolean help; + boolean version; + boolean compileWithAssertions; + boolean tiered; + + private String defaultOutputName() { + osName = System.getProperty("os.name"); + String name = "unnamed."; + String ext; + + switch (osName) { + case "Linux": + case "SunOS": + ext = "so"; + break; + case "Mac OS X": + ext = "dylib"; + break; + default: + if (osName.startsWith("Windows")) { + ext = "dll"; + } else { + ext = "so"; + } + } + + return name + ext; + } + + static class BadArgs extends Exception { + private static final long serialVersionUID = 1L; + final String key; + final Object[] args; + boolean showUsage; + + BadArgs(String key, Object... args) { + super(MessageFormat.format(key, args)); + this.key = key; + this.args = args; + } + + BadArgs showUsage(boolean b) { + showUsage = b; + return this; + } + } + + abstract static class Option { + final String help; + final boolean hasArg; + final String[] aliases; + + Option(String help, boolean hasArg, String... aliases) { + this.help = help; + this.hasArg = hasArg; + this.aliases = aliases; + } + + boolean isHidden() { + return false; + } + + boolean matches(String opt) { + for (String a : aliases) { + if (a.equals(opt)) { + return true; + } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) { + return true; + } + } + return false; + } + + boolean ignoreRest() { + return false; + } + + abstract void process(Main task, String opt, String arg) throws BadArgs; + } + + static Option[] recognizedOptions = {new Option(" --output Output file name", true, "--output") { + @Override + void process(Main task, String opt, String arg) { + String name = arg; + task.options.outputName = name; + } + }, new Option(" --class-name List of classes to compile", true, "--class-name", "--classname") { + @Override + void process(Main task, String opt, String arg) { + task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg)); + } + }, new Option(" --jar List of jar files to compile", true, "--jar") { + @Override + void process(Main task, String opt, String arg) { + task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg)); + } + }, new Option(" --module List of modules to compile", true, "--module") { + @Override + void process(Main task, String opt, String arg) { + task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg)); + } + }, new Option(" --directory List of directories where to search for files to compile", true, "--directory") { + @Override + void process(Main task, String opt, String arg) { + task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg)); + } + }, new Option(" --search-path List of directories where to search for specified files", true, "--search-path") { + @Override + void process(Main task, String opt, String arg) { + String[] elements = arg.split(":"); + task.options.searchPath.add(elements); + } + }, new Option(" --compile-commands Name of file with compile commands", true, "--compile-commands") { + @Override + void process(Main task, String opt, String arg) { + task.options.methodList = arg; + } + }, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") { + @Override + void process(Main task, String opt, String arg) { + task.options.tiered = true; + } + }, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") { + @Override + void process(Main task, String opt, String arg) { + task.options.compileWithAssertions = true; + } + }, new Option(" --compile-threads Number of compilation threads to be used", true, "--compile-threads", "--threads") { + @Override + void process(Main task, String opt, String arg) { + int threads = Integer.parseInt(arg); + final int available = Runtime.getRuntime().availableProcessors(); + if (threads <= 0) { + task.warning("invalid number of threads specified: {0}, using: {1}", threads, available); + threads = available; + } + if (threads > available) { + task.warning("too many threads specified: {0}, limiting to: {1}", threads, available); + } + task.options.threads = Integer.min(threads, available); + } + }, new Option(" --ignore-errors Ignores all exceptions thrown during class loading", false, "--ignore-errors") { + @Override + void process(Main task, String opt, String arg) { + task.options.ignoreClassLoadingErrors = true; + } + }, new Option(" --exit-on-error Exit on compilation errors", false, "--exit-on-error") { + @Override + void process(Main task, String opt, String arg) { + task.options.exitOnError = true; + } + }, new Option(" --info Print information during compilation", false, "--info") { + @Override + void process(Main task, String opt, String arg) throws BadArgs { + task.options.info = true; + } + }, new Option(" --verbose Print verbose information", false, "--verbose") { + @Override + void process(Main task, String opt, String arg) throws BadArgs { + task.options.info = true; + task.options.verbose = true; + } + }, new Option(" --debug Print debug information", false, "--debug") { + @Override + void process(Main task, String opt, String arg) throws BadArgs { + task.options.info = true; + task.options.verbose = true; + task.options.debug = true; + } + }, new Option(" --help Print this usage message", false, "--help") { + @Override + void process(Main task, String opt, String arg) { + task.options.help = true; + } + }, new Option(" --version Version information", false, "--version") { + @Override + void process(Main task, String opt, String arg) { + task.options.version = true; + } + }, new Option(" --linker-path Full path to linker executable", true, "--linker-path") { + @Override + void process(Main task, String opt, String arg) { + task.options.linkerpath = arg; + } + }, new Option(" -J Pass directly to the runtime system", false, "-J") { + @Override + void process(Main task, String opt, String arg) { + } + }}; + + static void handleOptions(Main task, String[] args) throws BadArgs { + if (args.length == 0) { + task.options.help = true; + return; + } + + // Make checkstyle happy. + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + + if (arg.charAt(0) == '-') { + Option option = getOption(arg); + String param = null; + + if (option.hasArg) { + if (arg.startsWith("--") && arg.indexOf('=') > 0) { + param = arg.substring(arg.indexOf('=') + 1, arg.length()); + } else if (i + 1 < args.length) { + param = args[++i]; + } + + if (param == null || param.isEmpty() || param.charAt(0) == '-') { + throw new BadArgs("missing argument for option: {0}", arg).showUsage(true); + } + } + + option.process(task, arg, param); + + if (option.ignoreRest()) { + break; + } + } else { + task.options.files.add(new SearchFor(arg)); + } + } + } + + static Option getOption(String name) throws BadArgs { + for (Option o : recognizedOptions) { + if (o.matches(name)) { + return o; + } + } + throw new BadArgs("unknown option: {0}", name).showUsage(true); + } + +}