1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package jdk.tools.jaotc; 25 26 import java.text.MessageFormat; 27 import java.util.ArrayList; 28 import java.util.LinkedList; 29 import java.util.List; 30 31 import jdk.tools.jaotc.collect.ClassSearch; 32 import jdk.tools.jaotc.collect.ClassSource; 33 import jdk.tools.jaotc.collect.SearchFor; 34 import jdk.tools.jaotc.collect.SearchPath; 35 import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider; 36 import jdk.tools.jaotc.collect.directory.DirectorySourceProvider; 37 import jdk.tools.jaotc.collect.jar.JarSourceProvider; 38 import jdk.tools.jaotc.collect.module.ModuleSourceProvider; 39 40 final class Options { 41 List<SearchFor> files = new LinkedList<>(); 42 String osName; 43 String outputName = defaultOutputName(); 44 String methodList; 45 List<ClassSource> sources = new ArrayList<>(); 46 String linkerpath = null; 47 SearchPath searchPath = new SearchPath(); 48 49 /** 50 * We don't see scaling beyond 16 threads. 51 */ 52 private static final int COMPILER_THREADS = 16; 53 54 int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors()); 55 56 boolean ignoreClassLoadingErrors; 57 boolean exitOnError; 58 boolean info; 59 boolean verbose; 60 boolean debug; 61 boolean help; 62 boolean version; 63 boolean compileWithAssertions; 64 boolean tiered; 65 66 private String defaultOutputName() { 67 osName = System.getProperty("os.name"); 68 String name = "unnamed."; 69 String ext; 70 71 switch (osName) { 72 case "Linux": 73 case "SunOS": 74 ext = "so"; 75 break; 76 case "Mac OS X": 77 ext = "dylib"; 78 break; 79 default: 80 if (osName.startsWith("Windows")) { 81 ext = "dll"; 82 } else { 83 ext = "so"; 84 } 85 } 86 87 return name + ext; 88 } 89 90 static class BadArgs extends Exception { 91 private static final long serialVersionUID = 1L; 92 final String key; 93 final Object[] args; 94 boolean showUsage; 95 96 BadArgs(String key, Object... args) { 97 super(MessageFormat.format(key, args)); 98 this.key = key; 99 this.args = args; 100 } 101 102 BadArgs showUsage(boolean b) { 103 showUsage = b; 104 return this; 105 } 106 } 107 108 abstract static class Option { 109 final String help; 110 final boolean hasArg; 111 final String[] aliases; 112 113 Option(String help, boolean hasArg, String... aliases) { 114 this.help = help; 115 this.hasArg = hasArg; 116 this.aliases = aliases; 117 } 118 119 boolean isHidden() { 120 return false; 121 } 122 123 boolean matches(String opt) { 124 for (String a : aliases) { 125 if (a.equals(opt)) { 126 return true; 127 } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) { 128 return true; 129 } 130 } 131 return false; 132 } 133 134 boolean ignoreRest() { 135 return false; 136 } 137 138 abstract void process(Main task, String opt, String arg) throws BadArgs; 139 } 140 141 static Option[] recognizedOptions = {new Option(" --output <file> Output file name", true, "--output") { 142 @Override 143 void process(Main task, String opt, String arg) { 144 String name = arg; 145 task.options.outputName = name; 146 } 147 }, new Option(" --class-name <class names> List of classes to compile", true, "--class-name", "--classname") { 148 @Override 149 void process(Main task, String opt, String arg) { 150 task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg)); 151 } 152 }, new Option(" --jar <jarfiles> List of jar files to compile", true, "--jar") { 153 @Override 154 void process(Main task, String opt, String arg) { 155 task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg)); 156 } 157 }, new Option(" --module <modules> List of modules to compile", true, "--module") { 158 @Override 159 void process(Main task, String opt, String arg) { 160 task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg)); 161 } 162 }, new Option(" --directory <dirs> List of directories where to search for files to compile", true, "--directory") { 163 @Override 164 void process(Main task, String opt, String arg) { 165 task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg)); 166 } 167 }, new Option(" --search-path <dirs> List of directories where to search for specified files", true, "--search-path") { 168 @Override 169 void process(Main task, String opt, String arg) { 170 String[] elements = arg.split(":"); 171 task.options.searchPath.add(elements); 172 } 173 }, new Option(" --compile-commands <file> Name of file with compile commands", true, "--compile-commands") { 174 @Override 175 void process(Main task, String opt, String arg) { 176 task.options.methodList = arg; 177 } 178 }, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") { 179 @Override 180 void process(Main task, String opt, String arg) { 181 task.options.tiered = true; 182 } 183 }, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") { 184 @Override 185 void process(Main task, String opt, String arg) { 186 task.options.compileWithAssertions = true; 187 } 188 }, new Option(" --compile-threads <number> Number of compilation threads to be used", true, "--compile-threads", "--threads") { 189 @Override 190 void process(Main task, String opt, String arg) { 191 int threads = Integer.parseInt(arg); 192 final int available = Runtime.getRuntime().availableProcessors(); 193 if (threads <= 0) { 194 task.warning("invalid number of threads specified: {0}, using: {1}", threads, available); 195 threads = available; 196 } 197 if (threads > available) { 198 task.warning("too many threads specified: {0}, limiting to: {1}", threads, available); 199 } 200 task.options.threads = Integer.min(threads, available); 201 } 202 }, new Option(" --ignore-errors Ignores all exceptions thrown during class loading", false, "--ignore-errors") { 203 @Override 204 void process(Main task, String opt, String arg) { 205 task.options.ignoreClassLoadingErrors = true; 206 } 207 }, new Option(" --exit-on-error Exit on compilation errors", false, "--exit-on-error") { 208 @Override 209 void process(Main task, String opt, String arg) { 210 task.options.exitOnError = true; 211 } 212 }, new Option(" --info Print information during compilation", false, "--info") { 213 @Override 214 void process(Main task, String opt, String arg) throws BadArgs { 215 task.options.info = true; 216 } 217 }, new Option(" --verbose Print verbose information", false, "--verbose") { 218 @Override 219 void process(Main task, String opt, String arg) throws BadArgs { 220 task.options.info = true; 221 task.options.verbose = true; 222 } 223 }, new Option(" --debug Print debug information", false, "--debug") { 224 @Override 225 void process(Main task, String opt, String arg) throws BadArgs { 226 task.options.info = true; 227 task.options.verbose = true; 228 task.options.debug = true; 229 } 230 }, new Option(" -? -h --help Print this help message", false, "--help", "-h", "-?") { 231 @Override 232 void process(Main task, String opt, String arg) { 233 task.options.help = true; 234 } 235 }, new Option(" --version Version information", false, "--version") { 236 @Override 237 void process(Main task, String opt, String arg) { 238 task.options.version = true; 239 } 240 }, new Option(" --linker-path Full path to linker executable", true, "--linker-path") { 241 @Override 242 void process(Main task, String opt, String arg) { 243 task.options.linkerpath = arg; 244 } 245 }, new Option(" -J<flag> Pass <flag> directly to the runtime system", false, "-J") { 246 @Override 247 void process(Main task, String opt, String arg) { 248 } 249 }}; 250 251 static void handleOptions(Main task, String[] args) throws BadArgs { 252 if (args.length == 0) { 253 task.options.help = true; 254 return; 255 } 256 257 // Make checkstyle happy. 258 for (int i = 0; i < args.length; i++) { 259 String arg = args[i]; 260 261 if (arg.charAt(0) == '-') { 262 Option option = getOption(arg); 263 String param = null; 264 265 if (option.hasArg) { 266 if (arg.startsWith("--") && arg.indexOf('=') > 0) { 267 param = arg.substring(arg.indexOf('=') + 1, arg.length()); 268 } else if (i + 1 < args.length) { 269 param = args[++i]; 270 } 271 272 if (param == null || param.isEmpty() || param.charAt(0) == '-') { 273 throw new BadArgs("missing argument for option: {0}", arg).showUsage(true); 274 } 275 } 276 277 option.process(task, arg, param); 278 279 if (option.ignoreRest()) { 280 break; 281 } 282 } else { 283 task.options.files.add(new SearchFor(arg)); 284 } 285 } 286 } 287 288 static Option getOption(String name) throws BadArgs { 289 for (Option o : recognizedOptions) { 290 if (o.matches(name)) { 291 return o; 292 } 293 } 294 throw new BadArgs("unknown option: {0}", name).showUsage(true); 295 } 296 297 }