1 /* 2 * Copyright (c) 1999, 2010, 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 import java.io.*; 26 import java.util.*; 27 28 abstract class HsArgHandler extends ArgHandler { 29 static final int STRING = 1; 30 static final int VECTOR = 2; 31 static final int HASH = 3; 32 33 boolean nextNotKey(ArgIterator it) { 34 if (it.next()) { 35 String s = it.get(); 36 return (s.length() == 0) || (s.charAt(0) != '-'); 37 } else { 38 return false; 39 } 40 } 41 42 void empty(String key, String message) { 43 if (key != null) { 44 System.err.println("** Error: empty " + key); 45 } 46 if (message != null) { 47 System.err.println(message); 48 } 49 WinGammaPlatform.usage(); 50 } 51 52 static String getCfg(String val) { 53 int under = val.indexOf('_'); 54 int len = val.length(); 55 if (under != -1 && under < len - 1) { 56 return val.substring(under+1, len); 57 } else { 58 return null; 59 } 60 } 61 } 62 63 class ArgRuleSpecific extends ArgRule { 64 ArgRuleSpecific(String arg, ArgHandler handler) { 65 super(arg, handler); 66 } 67 68 boolean match(String rulePattern, String arg) { 69 return rulePattern.startsWith(arg); 70 } 71 } 72 73 74 class SpecificHsArgHandler extends HsArgHandler { 75 76 String message, argKey, valKey; 77 int type; 78 79 public void handle(ArgIterator it) { 80 String cfg = getCfg(it.get()); 81 if (nextNotKey(it)) { 82 String val = it.get(); 83 switch (type) { 84 case VECTOR: 85 BuildConfig.addFieldVector(cfg, valKey, val); 86 break; 87 case HASH: 88 BuildConfig.putFieldHash(cfg, valKey, val, "1"); 89 break; 90 case STRING: 91 BuildConfig.putField(cfg, valKey, val); 92 break; 93 default: 94 empty(valKey, "Unknown type: "+type); 95 } 96 it.next(); 97 98 } else { 99 empty(argKey, message); 100 } 101 } 102 103 SpecificHsArgHandler(String argKey, String valKey, String message, int type) { 104 this.argKey = argKey; 105 this.valKey = valKey; 106 this.message = message; 107 this.type = type; 108 } 109 } 110 111 112 class HsArgRule extends ArgRuleSpecific { 113 114 HsArgRule(String argKey, String valKey, String message, int type) { 115 super(argKey, new SpecificHsArgHandler(argKey, valKey, message, type)); 116 } 117 118 } 119 120 public abstract class WinGammaPlatform { 121 122 public boolean fileNameStringEquality(String s1, String s2) { 123 return s1.equalsIgnoreCase(s2); 124 } 125 126 static void usage() throws IllegalArgumentException { 127 System.err.println("WinGammaPlatform platform-specific options:"); 128 System.err.println(" -sourceBase <path to directory (workspace) " + 129 "containing source files; no trailing slash>"); 130 System.err.println(" -projectFileName <full pathname to which project file " + 131 "will be written; all parent directories must " + 132 "already exist>"); 133 System.err.println(" If any of the above are specified, "+ 134 "they must all be."); 135 System.err.println(" Additional, optional arguments, which can be " + 136 "specified multiple times:"); 137 System.err.println(" -absoluteInclude <string containing absolute " + 138 "path to include directory>"); 139 System.err.println(" -relativeInclude <string containing include " + 140 "directory relative to -sourceBase>"); 141 System.err.println(" -define <preprocessor flag to be #defined " + 142 "(note: doesn't yet support " + 143 "#define (flag) (value))>"); 144 System.err.println(" -startAt <subdir of sourceBase>"); 145 System.err.println(" -additionalFile <file not in database but " + 146 "which should show up in project file>"); 147 System.err.println(" -additionalGeneratedFile <absolute path to " + 148 "directory containing file; no trailing slash> " + 149 "<name of file generated later in the build process>"); 150 throw new IllegalArgumentException(); 151 } 152 153 154 public void addPerFileLine(Hashtable table, 155 String fileName, 156 String line) { 157 Vector v = (Vector) table.get(fileName); 158 if (v != null) { 159 v.add(line); 160 } else { 161 v = new Vector(); 162 v.add(line); 163 table.put(fileName, v); 164 } 165 } 166 167 protected static class PerFileCondData { 168 public String releaseString; 169 public String debugString; 170 } 171 172 protected void addConditionalPerFileLine(Hashtable table, 173 String fileName, 174 String releaseLine, 175 String debugLine) { 176 PerFileCondData data = new PerFileCondData(); 177 data.releaseString = releaseLine; 178 data.debugString = debugLine; 179 Vector v = (Vector) table.get(fileName); 180 if (v != null) { 181 v.add(data); 182 } else { 183 v = new Vector(); 184 v.add(data); 185 table.put(fileName, v); 186 } 187 } 188 189 protected static class PrelinkCommandData { 190 String description; 191 String commands; 192 } 193 194 protected void addPrelinkCommand(Hashtable table, 195 String build, 196 String description, 197 String commands) { 198 PrelinkCommandData data = new PrelinkCommandData(); 199 data.description = description; 200 data.commands = commands; 201 table.put(build, data); 202 } 203 204 public boolean findString(Vector v, String s) { 205 for (Iterator iter = v.iterator(); iter.hasNext(); ) { 206 if (((String) iter.next()).equals(s)) { 207 return true; 208 } 209 } 210 211 return false; 212 } 213 214 /* This returns a String containing the full path to the passed 215 file name, or null if an error occurred. If the file was not 216 found or was a duplicate and couldn't be resolved using the 217 preferred paths, the file name is added to the appropriate 218 Vector of Strings. */ 219 private String findFileInDirectory(String fileName, 220 DirectoryTree directory, 221 Vector preferredPaths, 222 Vector filesNotFound, 223 Vector filesDuplicate) { 224 List locationsInTree = directory.findFile(fileName); 225 int rootNameLength = directory.getRootNodeName().length(); 226 String name = null; 227 if ((locationsInTree == null) || 228 (locationsInTree.size() == 0)) { 229 filesNotFound.add(fileName); 230 } else if (locationsInTree.size() > 1) { 231 // We shouldn't have duplicate file names in our workspace. 232 System.err.println(); 233 System.err.println("There are multiple files named as: " + fileName); 234 System.exit(-1); 235 // The following code could be safely removed if we don't need duplicate 236 // file names. 237 238 // Iterate through them, trying to find one with a 239 // preferred path 240 search: 241 { 242 for (Iterator locIter = locationsInTree.iterator(); 243 locIter.hasNext(); ) { 244 DirectoryTreeNode node = 245 (DirectoryTreeNode) locIter.next(); 246 String tmpName = node.getName(); 247 for (Iterator prefIter = preferredPaths.iterator(); 248 prefIter.hasNext(); ) { 249 // We need to make sure the preferred path is 250 // found from the file path not including the root node name. 251 if (tmpName.indexOf((String)prefIter.next(), 252 rootNameLength) != -1) { 253 name = tmpName; 254 break search; 255 } 256 } 257 } 258 } 259 260 if (name == null) { 261 filesDuplicate.add(fileName); 262 } 263 } else { 264 name = ((DirectoryTreeNode) locationsInTree.get(0)).getName(); 265 } 266 267 return name; 268 } 269 270 protected String envVarPrefixedFileName(String fileName, 271 int sourceBaseLen, 272 DirectoryTree tree, 273 Vector preferredPaths, 274 Vector filesNotFound, 275 Vector filesDuplicate) { 276 String fullName = findFileInDirectory(fileName, 277 tree, 278 preferredPaths, 279 filesNotFound, 280 filesDuplicate); 281 return fullName; 282 } 283 284 String getProjectName(String fullPath, String extension) 285 throws IllegalArgumentException, IOException { 286 File file = new File(fullPath).getCanonicalFile(); 287 fullPath = file.getCanonicalPath(); 288 String parent = file.getParent(); 289 290 if (!fullPath.endsWith(extension)) { 291 throw new IllegalArgumentException("project file name \"" + 292 fullPath + 293 "\" does not end in "+extension); 294 } 295 296 if ((parent != null) && 297 (!fullPath.startsWith(parent))) { 298 throw new RuntimeException( 299 "Internal error: parent of file name \"" + parent + 300 "\" does not match file name \"" + fullPath + "\"" 301 ); 302 } 303 304 int len = parent.length(); 305 if (!parent.endsWith(Util.sep)) { 306 len += Util.sep.length(); 307 } 308 309 int end = fullPath.length() - extension.length(); 310 311 if (len == end) { 312 throw new RuntimeException( 313 "Internal error: file name was empty" 314 ); 315 } 316 317 return fullPath.substring(len, end); 318 } 319 320 protected abstract String getProjectExt(); 321 322 public void createVcproj(String[] args) 323 throws IllegalArgumentException, IOException { 324 325 parseArguments(args); 326 327 String projectFileName = BuildConfig.getFieldString(null, "ProjectFileName"); 328 String ext = getProjectExt(); 329 330 String projectName = getProjectName(projectFileName, ext); 331 332 writeProjectFile(projectFileName, projectName, createAllConfigs()); 333 } 334 335 protected void writePrologue(String[] args) { 336 System.err.println("WinGammaPlatform platform-specific arguments:"); 337 for (int i = 0; i < args.length; i++) { 338 System.err.print(args[i] + " "); 339 } 340 System.err.println(); 341 } 342 343 344 void parseArguments(String[] args) { 345 new ArgsParser(args, 346 new ArgRule[] 347 { 348 new HsArgRule("-sourceBase", 349 "SourceBase", 350 " (Did you set the HotSpotWorkSpace environment variable?)", 351 HsArgHandler.STRING 352 ), 353 354 new HsArgRule("-buildBase", 355 "BuildBase", 356 " (Did you set the HotSpotBuildSpace environment variable?)", 357 HsArgHandler.STRING 358 ), 359 360 new HsArgRule("-projectFileName", 361 "ProjectFileName", 362 null, 363 HsArgHandler.STRING 364 ), 365 366 new HsArgRule("-jdkTargetRoot", 367 "JdkTargetRoot", 368 " (Did you set the HotSpotJDKDist environment variable?)", 369 HsArgHandler.STRING 370 ), 371 372 new HsArgRule("-compiler", 373 "CompilerVersion", 374 " (Did you set the VcVersion correctly?)", 375 HsArgHandler.STRING 376 ), 377 378 new HsArgRule("-platform", 379 "Platform", 380 null, 381 HsArgHandler.STRING 382 ), 383 384 new HsArgRule("-absoluteInclude", 385 "AbsoluteInclude", 386 null, 387 HsArgHandler.VECTOR 388 ), 389 390 new HsArgRule("-relativeInclude", 391 "RelativeInclude", 392 null, 393 HsArgHandler.VECTOR 394 ), 395 396 new HsArgRule("-define", 397 "Define", 398 null, 399 HsArgHandler.VECTOR 400 ), 401 402 new HsArgRule("-useToGeneratePch", 403 "UseToGeneratePch", 404 null, 405 HsArgHandler.STRING 406 ), 407 408 new ArgRuleSpecific("-perFileLine", 409 new HsArgHandler() { 410 public void handle(ArgIterator it) { 411 String cfg = getCfg(it.get()); 412 if (nextNotKey(it)) { 413 String fileName = it.get(); 414 if (nextNotKey(it)) { 415 String line = it.get(); 416 BuildConfig.putFieldHash(cfg, "PerFileLine", fileName, line); 417 it.next(); 418 return; 419 } 420 } 421 empty(null, "** Error: wrong number of args to -perFileLine"); 422 } 423 } 424 ), 425 426 new ArgRuleSpecific("-conditionalPerFileLine", 427 new HsArgHandler() { 428 public void handle(ArgIterator it) { 429 String cfg = getCfg(it.get()); 430 if (nextNotKey(it)) { 431 String fileName = it.get(); 432 if (nextNotKey(it)) { 433 String productLine = it.get(); 434 if (nextNotKey(it)) { 435 String debugLine = it.get(); 436 BuildConfig.putFieldHash(cfg+"_debug", "CondPerFileLine", 437 fileName, debugLine); 438 BuildConfig.putFieldHash(cfg+"_product", "CondPerFileLine", 439 fileName, productLine); 440 it.next(); 441 return; 442 } 443 } 444 } 445 446 empty(null, "** Error: wrong number of args to -conditionalPerFileLine"); 447 } 448 } 449 ), 450 451 new HsArgRule("-disablePch", 452 "DisablePch", 453 null, 454 HsArgHandler.HASH 455 ), 456 457 new ArgRule("-startAt", 458 new HsArgHandler() { 459 public void handle(ArgIterator it) { 460 if (BuildConfig.getField(null, "StartAt") != null) { 461 empty(null, "** Error: multiple -startAt"); 462 } 463 if (nextNotKey(it)) { 464 BuildConfig.putField(null, "StartAt", it.get()); 465 it.next(); 466 } else { 467 empty("-startAt", null); 468 } 469 } 470 } 471 ), 472 473 new HsArgRule("-ignoreFile", 474 "IgnoreFile", 475 null, 476 HsArgHandler.HASH 477 ), 478 479 new HsArgRule("-ignorePath", 480 "IgnorePath", 481 null, 482 HsArgHandler.VECTOR 483 ), 484 485 new HsArgRule("-additionalFile", 486 "AdditionalFile", 487 null, 488 HsArgHandler.VECTOR 489 ), 490 491 new ArgRuleSpecific("-additionalGeneratedFile", 492 new HsArgHandler() { 493 public void handle(ArgIterator it) { 494 String cfg = getCfg(it.get()); 495 if (nextNotKey(it)) { 496 String dir = it.get(); 497 if (nextNotKey(it)) { 498 String fileName = it.get(); 499 // we ignore files that we know are generated, so we coudn't 500 // find them in sources 501 BuildConfig.putFieldHash(cfg, "IgnoreFile", fileName, "1"); 502 BuildConfig.putFieldHash(cfg, "AdditionalGeneratedFile", 503 Util.normalize(dir + Util.sep + fileName), 504 fileName); 505 it.next(); 506 return; 507 } 508 } 509 empty(null, "** Error: wrong number of args to -additionalGeneratedFile"); 510 } 511 } 512 ), 513 514 new ArgRule("-prelink", 515 new HsArgHandler() { 516 public void handle(ArgIterator it) { 517 if (nextNotKey(it)) { 518 String build = it.get(); 519 if (nextNotKey(it)) { 520 String description = it.get(); 521 if (nextNotKey(it)) { 522 String command = it.get(); 523 BuildConfig.putField(null, "PrelinkDescription", description); 524 BuildConfig.putField(null, "PrelinkCommand", command); 525 it.next(); 526 return; 527 } 528 } 529 } 530 531 empty(null, "** Error: wrong number of args to -prelink"); 532 } 533 } 534 ) 535 }, 536 new ArgHandler() { 537 public void handle(ArgIterator it) { 538 539 throw new RuntimeException("Arg Parser: unrecognized option "+it.get()); 540 } 541 } 542 ); 543 if (BuildConfig.getField(null, "SourceBase") == null || 544 BuildConfig.getField(null, "BuildBase") == null || 545 BuildConfig.getField(null, "ProjectFileName") == null || 546 BuildConfig.getField(null, "CompilerVersion") == null) { 547 usage(); 548 } 549 550 if (BuildConfig.getField(null, "UseToGeneratePch") == null) { 551 throw new RuntimeException("ERROR: need to specify one file to compute PCH, with -useToGeneratePch flag"); 552 } 553 554 BuildConfig.putField(null, "PlatformObject", this); 555 } 556 557 Vector createAllConfigs() { 558 Vector allConfigs = new Vector(); 559 560 allConfigs.add(new C1DebugConfig()); 561 562 boolean b = true; 563 if (b) { 564 allConfigs.add(new C1FastDebugConfig()); 565 allConfigs.add(new C1ProductConfig()); 566 567 allConfigs.add(new C2DebugConfig()); 568 allConfigs.add(new C2FastDebugConfig()); 569 allConfigs.add(new C2ProductConfig()); 570 571 allConfigs.add(new TieredDebugConfig()); 572 allConfigs.add(new TieredFastDebugConfig()); 573 allConfigs.add(new TieredProductConfig()); 574 575 allConfigs.add(new CoreDebugConfig()); 576 allConfigs.add(new CoreFastDebugConfig()); 577 allConfigs.add(new CoreProductConfig()); 578 579 allConfigs.add(new KernelDebugConfig()); 580 allConfigs.add(new KernelFastDebugConfig()); 581 allConfigs.add(new KernelProductConfig()); 582 } 583 584 return allConfigs; 585 } 586 587 class FileAttribute { 588 int numConfigs; 589 Vector configs; 590 String shortName; 591 boolean noPch, pchRoot; 592 593 FileAttribute(String shortName, BuildConfig cfg, int numConfigs) { 594 this.shortName = shortName; 595 this.noPch = (cfg.lookupHashFieldInContext("DisablePch", shortName) != null); 596 this.pchRoot = shortName.equals(BuildConfig.getFieldString(null, "UseToGeneratePch")); 597 this.numConfigs = numConfigs; 598 599 configs = new Vector(); 600 add(cfg.get("Name")); 601 } 602 603 void add(String confName) { 604 configs.add(confName); 605 606 // if presented in all configs 607 if (configs.size() == numConfigs) { 608 configs = null; 609 } 610 } 611 } 612 613 class FileInfo implements Comparable { 614 String full; 615 FileAttribute attr; 616 617 FileInfo(String full, FileAttribute attr) { 618 this.full = full; 619 this.attr = attr; 620 } 621 622 public int compareTo(Object o) { 623 FileInfo oo = (FileInfo)o; 624 // Don't squelch identical short file names where the full 625 // paths are different 626 if (!attr.shortName.equals(oo.attr.shortName)) 627 return attr.shortName.compareTo(oo.attr.shortName); 628 return full.compareTo(oo.full); 629 } 630 631 boolean isHeader() { 632 return attr.shortName.endsWith(".h") || attr.shortName.endsWith(".hpp"); 633 } 634 } 635 636 637 TreeSet sortFiles(Hashtable allFiles) { 638 TreeSet rv = new TreeSet(); 639 Enumeration e = allFiles.keys(); 640 while (e.hasMoreElements()) { 641 String fullPath = (String)e.nextElement(); 642 rv.add(new FileInfo(fullPath, (FileAttribute)allFiles.get(fullPath))); 643 } 644 return rv; 645 } 646 647 Hashtable computeAttributedFiles(Vector allConfigs) { 648 Hashtable ht = new Hashtable(); 649 int numConfigs = allConfigs.size(); 650 651 for (Iterator i = allConfigs.iterator(); i.hasNext(); ) { 652 BuildConfig bc = (BuildConfig)i.next(); 653 Hashtable confFiles = (Hashtable)bc.getSpecificField("AllFilesHash"); 654 String confName = bc.get("Name"); 655 656 for (Enumeration e=confFiles.keys(); e.hasMoreElements(); ) { 657 String filePath = (String)e.nextElement(); 658 FileAttribute fa = (FileAttribute)ht.get(filePath); 659 660 if (fa == null) { 661 fa = new FileAttribute((String)confFiles.get(filePath), bc, numConfigs); 662 ht.put(filePath, fa); 663 } else { 664 fa.add(confName); 665 } 666 } 667 } 668 669 return ht; 670 } 671 672 Hashtable computeAttributedFiles(BuildConfig bc) { 673 Hashtable ht = new Hashtable(); 674 Hashtable confFiles = (Hashtable)bc.getSpecificField("AllFilesHash"); 675 676 for (Enumeration e = confFiles.keys(); e.hasMoreElements(); ) { 677 String filePath = (String)e.nextElement(); 678 ht.put(filePath, new FileAttribute((String)confFiles.get(filePath), bc, 1)); 679 } 680 681 return ht; 682 } 683 684 PrintWriter printWriter; 685 686 public void writeProjectFile(String projectFileName, String projectName, 687 Vector allConfigs) throws IOException { 688 throw new RuntimeException("use compiler version specific version"); 689 } 690 }