1 /* 2 * Copyright (c) 2017, 2018, 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 25 26 package jdk.tools.jaotc; 27 28 import java.text.MessageFormat; 29 import java.util.ArrayList; 30 import java.util.LinkedList; 31 import java.util.List; 32 33 import jdk.tools.jaotc.collect.ClassSearch; 34 import jdk.tools.jaotc.collect.ClassSource; 35 import jdk.tools.jaotc.collect.SearchFor; 36 import jdk.tools.jaotc.collect.SearchPath; 37 import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider; 38 import jdk.tools.jaotc.collect.directory.DirectorySourceProvider; 39 import jdk.tools.jaotc.collect.jar.JarSourceProvider; 40 import jdk.tools.jaotc.collect.module.ModuleSourceProvider; 41 42 final class Options { 43 List<SearchFor> files = new LinkedList<>(); 44 String osName; 45 String outputName = defaultOutputName(); 46 String methodList; 47 List<ClassSource> sources = new ArrayList<>(); 48 String linkerpath = null; 49 SearchPath searchPath = new SearchPath(); 50 51 /** 52 * We don't see scaling beyond 16 threads. 53 */ 54 private static final int COMPILER_THREADS = 16; 55 56 int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors()); 57 58 boolean ignoreClassLoadingErrors; 59 boolean exitOnError; 60 boolean info; 61 boolean verbose; 62 boolean debug; 63 boolean help; 64 boolean version; 65 boolean compileWithAssertions; 66 boolean tiered; 67 68 private String defaultOutputName() { 69 osName = System.getProperty("os.name"); 70 String name = "unnamed."; 71 String ext; 72 73 switch (osName) { 74 case "Linux": 75 case "SunOS": 76 ext = "so"; 77 break; 78 case "Mac OS X": 79 ext = "dylib"; 80 break; 81 default: 82 if (osName.startsWith("Windows")) { 83 ext = "dll"; 84 } else { 85 ext = "so"; 86 } 87 } 88 89 return name + ext; 90 } 91 92 static class BadArgs extends Exception { 93 private static final long serialVersionUID = 1L; 94 final String key; 95 final Object[] args; 96 boolean showUsage; 97 98 BadArgs(String key, Object... args) { 99 super(MessageFormat.format(key, args)); 100 this.key = key; 101 this.args = args; 102 } 103 104 BadArgs showUsage(boolean b) { 105 showUsage = b; 106 return this; 107 } 108 } 109 110 abstract static class Option { 111 final String help; 112 final boolean hasArg; 113 final String[] aliases; 114 115 Option(String help, boolean hasArg, String... aliases) { 116 this.help = help; 117 this.hasArg = hasArg; 118 this.aliases = aliases; 119 } 120 121 boolean isHidden() { 122 return false; 123 } 124 125 boolean matches(String opt) { 126 for (String a : aliases) { 127 if (a.equals(opt)) { 128 return true; 129 } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) { 130 return true; 131 } 132 } 133 return false; 134 } 135 136 boolean ignoreRest() { 137 return false; 138 } 139 140 abstract void process(Main task, String opt, String arg) throws BadArgs; 141 } 142 143 static Option[] recognizedOptions = {new Option(" --output <file> Output file name", true, "--output") { 144 @Override 145 void process(Main task, String opt, String arg) { 146 String name = arg; 147 task.options.outputName = name; 148 } 149 }, new Option(" --class-name <class names> List of classes to compile", true, "--class-name", "--classname") { 150 @Override 151 void process(Main task, String opt, String arg) { 152 task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg)); 153 } 154 }, new Option(" --jar <jarfiles> List of jar files to compile", true, "--jar") { 155 @Override 156 void process(Main task, String opt, String arg) { 157 task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg)); 158 } 159 }, new Option(" --module <modules> List of modules to compile", true, "--module") { 160 @Override 161 void process(Main task, String opt, String arg) { 162 task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg)); 163 } 164 }, new Option(" --directory <dirs> List of directories where to search for files to compile", true, "--directory") { 165 @Override 166 void process(Main task, String opt, String arg) { 167 task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg)); 168 } 169 }, new Option(" --search-path <dirs> List of directories where to search for specified files", true, "--search-path") { 170 @Override 171 void process(Main task, String opt, String arg) { 172 String[] elements = arg.split(":"); 173 task.options.searchPath.add(elements); 174 } 175 }, new Option(" --compile-commands <file> Name of file with compile commands", true, "--compile-commands") { 176 @Override 177 void process(Main task, String opt, String arg) { 178 task.options.methodList = arg; 179 } 180 }, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") { 181 @Override 182 void process(Main task, String opt, String arg) { 183 task.options.tiered = true; 184 } 185 }, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") { 186 @Override 187 void process(Main task, String opt, String arg) { 188 task.options.compileWithAssertions = true; 189 } 190 }, new Option(" --compile-threads <number> Number of compilation threads to be used", true, "--compile-threads", "--threads") { 191 @Override 192 void process(Main task, String opt, String arg) { 193 int threads = Integer.parseInt(arg); 194 final int available = Runtime.getRuntime().availableProcessors(); 195 if (threads <= 0) { 196 task.warning("invalid number of threads specified: {0}, using: {1}", threads, available); 197 threads = available; 198 } 199 if (threads > available) { 200 task.warning("too many threads specified: {0}, limiting to: {1}", threads, available); 201 } 202 task.options.threads = Integer.min(threads, available); 203 } 204 }, new Option(" --ignore-errors Ignores all exceptions thrown during class loading", false, "--ignore-errors") { 205 @Override 206 void process(Main task, String opt, String arg) { 207 task.options.ignoreClassLoadingErrors = true; 208 } 209 }, new Option(" --exit-on-error Exit on compilation errors", false, "--exit-on-error") { 210 @Override 211 void process(Main task, String opt, String arg) { 212 task.options.exitOnError = true; 213 } 214 }, new Option(" --info Print information during compilation", false, "--info") { 215 @Override 216 void process(Main task, String opt, String arg) throws BadArgs { 217 task.options.info = true; 218 } 219 }, new Option(" --verbose Print verbose information", false, "--verbose") { 220 @Override 221 void process(Main task, String opt, String arg) throws BadArgs { 222 task.options.info = true; 223 task.options.verbose = true; 224 } 225 }, new Option(" --debug Print debug information", false, "--debug") { 226 @Override 227 void process(Main task, String opt, String arg) throws BadArgs { 228 task.options.info = true; 229 task.options.verbose = true; 230 task.options.debug = true; 231 } 232 }, new Option(" -? -h --help Print this help message", false, "--help", "-h", "-?") { 233 @Override 234 void process(Main task, String opt, String arg) { 235 task.options.help = true; 236 } 237 }, new Option(" --version Version information", false, "--version") { 238 @Override 239 void process(Main task, String opt, String arg) { 240 task.options.version = true; 241 } 242 }, new Option(" --linker-path Full path to linker executable", true, "--linker-path") { 243 @Override 244 void process(Main task, String opt, String arg) { 245 task.options.linkerpath = arg; 246 } 247 }, new Option(" -J<flag> Pass <flag> directly to the runtime system", false, "-J") { 248 @Override 249 void process(Main task, String opt, String arg) { 250 } 251 }}; 252 253 static void handleOptions(Main task, String[] args) throws BadArgs { 254 if (args.length == 0) { 255 task.options.help = true; 256 return; 257 } 258 259 // Make checkstyle happy. 260 int i = 0; 261 while (i < args.length) { 262 String arg = args[i]; 263 264 if (arg.charAt(0) == '-') { 265 Option option = getOption(arg); 266 String param = null; 267 268 if (option.hasArg) { 269 if (arg.startsWith("--") && arg.indexOf('=') > 0) { 270 param = arg.substring(arg.indexOf('=') + 1, arg.length()); 271 } else if (i + 1 < args.length) { 272 param = args[++i]; 273 } 274 275 if (param == null || param.isEmpty() || param.charAt(0) == '-') { 276 throw new BadArgs("missing argument for option: {0}", arg).showUsage(true); 277 } 278 } 279 280 option.process(task, arg, param); 281 282 if (option.ignoreRest()) { 283 break; 284 } 285 } else { 286 task.options.files.add(new SearchFor(arg)); 287 } 288 i++; 289 } 290 } 291 292 static Option getOption(String name) throws BadArgs { 293 for (Option o : recognizedOptions) { 294 if (o.matches(name)) { 295 return o; 296 } 297 } 298 throw new BadArgs("unknown option: {0}", name).showUsage(true); 299 } 300 301 }