1 /* 2 * Copyright (c) 1999, 2007, 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 extends Platform { 121 public void setupFileTemplates() { 122 inclFileTemplate = new FileName(this, 123 "incls\\", "_", "", ".incl", "", "" 124 ); 125 giFileTemplate = new FileName(this, 126 "incls\\", "", "_precompiled", ".incl", "", "" 127 ); 128 gdFileTemplate = new FileName(this, 129 "", "", "Dependencies", "", "", "" 130 ); 131 } 132 133 private static String[] suffixes = { ".cpp", ".c" }; 134 135 public String[] outerSuffixes() { 136 return suffixes; 137 } 138 139 public String objFileSuffix() { 140 return ".obj"; 141 } 142 143 public String asmFileSuffix() { 144 return ".i"; 145 } 146 147 public String dependentPrefix() { 148 return "$(VM_PATH)"; 149 } 150 151 public boolean includeGIInEachIncl() { 152 return false; 153 } 154 155 public boolean fileNameStringEquality(String s1, String s2) { 156 return s1.equalsIgnoreCase(s2); 157 } 158 159 static void usage() throws IllegalArgumentException { 160 System.err.println("WinGammaPlatform platform-specific options:"); 161 System.err.println(" -sourceBase <path to directory (workspace) " + 162 "containing source files; no trailing slash>"); 163 System.err.println(" -projectFileName <full pathname to which project file " + 164 "will be written; all parent directories must " + 165 "already exist>"); 166 System.err.println(" If any of the above are specified, "+ 167 "they must all be."); 168 System.err.println(" Additional, optional arguments, which can be " + 169 "specified multiple times:"); 170 System.err.println(" -absoluteInclude <string containing absolute " + 171 "path to include directory>"); 172 System.err.println(" -relativeInclude <string containing include " + 173 "directory relative to -sourceBase>"); 174 System.err.println(" -define <preprocessor flag to be #defined " + 175 "(note: doesn't yet support " + 176 "#define (flag) (value))>"); 177 System.err.println(" -startAt <subdir of sourceBase>"); 178 System.err.println(" -additionalFile <file not in database but " + 179 "which should show up in project file, like " + 180 "includeDB_core>"); 181 System.err.println(" -additionalGeneratedFile <absolute path to " + 182 "directory containing file; no trailing slash> " + 183 "<name of file generated later in the build process>"); 184 throw new IllegalArgumentException(); 185 } 186 187 188 public void addPerFileLine(Hashtable table, 189 String fileName, 190 String line) { 191 Vector v = (Vector) table.get(fileName); 192 if (v != null) { 193 v.add(line); 194 } else { 195 v = new Vector(); 196 v.add(line); 197 table.put(fileName, v); 198 } 199 } 200 201 protected static class PerFileCondData { 202 public String releaseString; 203 public String debugString; 204 } 205 206 protected void addConditionalPerFileLine(Hashtable table, 207 String fileName, 208 String releaseLine, 209 String debugLine) { 210 PerFileCondData data = new PerFileCondData(); 211 data.releaseString = releaseLine; 212 data.debugString = debugLine; 213 Vector v = (Vector) table.get(fileName); 214 if (v != null) { 215 v.add(data); 216 } else { 217 v = new Vector(); 218 v.add(data); 219 table.put(fileName, v); 220 } 221 } 222 223 protected static class PrelinkCommandData { 224 String description; 225 String commands; 226 } 227 228 protected void addPrelinkCommand(Hashtable table, 229 String build, 230 String description, 231 String commands) { 232 PrelinkCommandData data = new PrelinkCommandData(); 233 data.description = description; 234 data.commands = commands; 235 table.put(build, data); 236 } 237 238 public boolean findString(Vector v, String s) { 239 for (Iterator iter = v.iterator(); iter.hasNext(); ) { 240 if (((String) iter.next()).equals(s)) { 241 return true; 242 } 243 } 244 245 return false; 246 } 247 248 /* This returns a String containing the full path to the passed 249 file name, or null if an error occurred. If the file was not 250 found or was a duplicate and couldn't be resolved using the 251 preferred paths, the file name is added to the appropriate 252 Vector of Strings. */ 253 private String findFileInDirectory(String fileName, 254 DirectoryTree directory, 255 Vector preferredPaths, 256 Vector filesNotFound, 257 Vector filesDuplicate) { 258 List locationsInTree = directory.findFile(fileName); 259 int rootNameLength = directory.getRootNodeName().length(); 260 String name = null; 261 if ((locationsInTree == null) || 262 (locationsInTree.size() == 0)) { 263 filesNotFound.add(fileName); 264 } else if (locationsInTree.size() > 1) { 265 // We shouldn't have duplicate file names in our workspace. 266 System.err.println(); 267 System.err.println("There are multiple files named as: " + fileName); 268 System.exit(-1); 269 // The following code could be safely removed if we don't need duplicate 270 // file names. 271 272 // Iterate through them, trying to find one with a 273 // preferred path 274 search: 275 { 276 for (Iterator locIter = locationsInTree.iterator(); 277 locIter.hasNext(); ) { 278 DirectoryTreeNode node = 279 (DirectoryTreeNode) locIter.next(); 280 String tmpName = node.getName(); 281 for (Iterator prefIter = preferredPaths.iterator(); 282 prefIter.hasNext(); ) { 283 // We need to make sure the preferred path is 284 // found from the file path not including the root node name. 285 if (tmpName.indexOf((String)prefIter.next(), 286 rootNameLength) != -1) { 287 name = tmpName; 288 break search; 289 } 290 } 291 } 292 } 293 294 if (name == null) { 295 filesDuplicate.add(fileName); 296 } 297 } else { 298 name = ((DirectoryTreeNode) locationsInTree.get(0)).getName(); 299 } 300 301 return name; 302 } 303 304 protected boolean databaseAllFilesEqual(Database previousDB, 305 Database currentDB) { 306 Iterator i1 = previousDB.getAllFiles().iterator(); 307 Iterator i2 = currentDB.getAllFiles().iterator(); 308 309 while (i1.hasNext() && i2.hasNext()) { 310 FileList fl1 = (FileList) i1.next(); 311 FileList fl2 = (FileList) i2.next(); 312 if (!fl1.getName().equals(fl2.getName())) { 313 return false; 314 } 315 } 316 317 if (i1.hasNext() != i2.hasNext()) { 318 // Different lengths 319 return false; 320 } 321 322 return true; 323 } 324 325 protected String envVarPrefixedFileName(String fileName, 326 int sourceBaseLen, 327 DirectoryTree tree, 328 Vector preferredPaths, 329 Vector filesNotFound, 330 Vector filesDuplicate) { 331 String fullName = findFileInDirectory(fileName, 332 tree, 333 preferredPaths, 334 filesNotFound, 335 filesDuplicate); 336 return fullName; 337 } 338 339 String getProjectName(String fullPath, String extension) 340 throws IllegalArgumentException, IOException { 341 File file = new File(fullPath).getCanonicalFile(); 342 fullPath = file.getCanonicalPath(); 343 String parent = file.getParent(); 344 345 if (!fullPath.endsWith(extension)) { 346 throw new IllegalArgumentException("project file name \"" + 347 fullPath + 348 "\" does not end in "+extension); 349 } 350 351 if ((parent != null) && 352 (!fullPath.startsWith(parent))) { 353 throw new RuntimeException( 354 "Internal error: parent of file name \"" + parent + 355 "\" does not match file name \"" + fullPath + "\"" 356 ); 357 } 358 359 int len = parent.length(); 360 if (!parent.endsWith(Util.sep)) { 361 len += Util.sep.length(); 362 } 363 364 int end = fullPath.length() - extension.length(); 365 366 if (len == end) { 367 throw new RuntimeException( 368 "Internal error: file name was empty" 369 ); 370 } 371 372 return fullPath.substring(len, end); 373 } 374 375 protected abstract String getProjectExt(); 376 377 public void writePlatformSpecificFiles(Database previousDB, 378 Database currentDB, String[] args) 379 throws IllegalArgumentException, IOException { 380 381 parseArguments(args); 382 383 String projectFileName = BuildConfig.getFieldString(null, "ProjectFileName"); 384 String ext = getProjectExt(); 385 386 // Compare contents of allFiles of previousDB and includeDB. 387 // If these haven't changed, then skip writing the .vcproj file. 388 if (false && databaseAllFilesEqual(previousDB, currentDB) && 389 new File(projectFileName).exists()) { 390 System.out.println( 391 " Databases unchanged; skipping overwrite of "+ext+" file." 392 ); 393 return; 394 } 395 396 String projectName = getProjectName(projectFileName, ext); 397 398 writeProjectFile(projectFileName, projectName, createAllConfigs()); 399 } 400 401 protected void writePrologue(String[] args) { 402 System.err.println("WinGammaPlatform platform-specific arguments:"); 403 for (int i = 0; i < args.length; i++) { 404 System.err.print(args[i] + " "); 405 } 406 System.err.println(); 407 } 408 409 410 void setInclFileTemplate(FileName val) { 411 this.inclFileTemplate = val; 412 } 413 414 void setGIFileTemplate(FileName val) { 415 this.giFileTemplate = val; 416 } 417 418 419 void parseArguments(String[] args) { 420 new ArgsParser(args, 421 new ArgRule[] 422 { 423 new HsArgRule("-sourceBase", 424 "SourceBase", 425 " (Did you set the HotSpotWorkSpace environment variable?)", 426 HsArgHandler.STRING 427 ), 428 429 new HsArgRule("-buildBase", 430 "BuildBase", 431 " (Did you set the HotSpotBuildSpace environment variable?)", 432 HsArgHandler.STRING 433 ), 434 435 new HsArgRule("-projectFileName", 436 "ProjectFileName", 437 null, 438 HsArgHandler.STRING 439 ), 440 441 new HsArgRule("-jdkTargetRoot", 442 "JdkTargetRoot", 443 " (Did you set the HotSpotJDKDist environment variable?)", 444 HsArgHandler.STRING 445 ), 446 447 new HsArgRule("-compiler", 448 "CompilerVersion", 449 " (Did you set the VcVersion correctly?)", 450 HsArgHandler.STRING 451 ), 452 453 new HsArgRule("-platform", 454 "Platform", 455 null, 456 HsArgHandler.STRING 457 ), 458 459 new HsArgRule("-absoluteInclude", 460 "AbsoluteInclude", 461 null, 462 HsArgHandler.VECTOR 463 ), 464 465 new HsArgRule("-relativeInclude", 466 "RelativeInclude", 467 null, 468 HsArgHandler.VECTOR 469 ), 470 471 new HsArgRule("-define", 472 "Define", 473 null, 474 HsArgHandler.VECTOR 475 ), 476 477 new HsArgRule("-useToGeneratePch", 478 "UseToGeneratePch", 479 null, 480 HsArgHandler.STRING 481 ), 482 483 new ArgRuleSpecific("-perFileLine", 484 new HsArgHandler() { 485 public void handle(ArgIterator it) { 486 String cfg = getCfg(it.get()); 487 if (nextNotKey(it)) { 488 String fileName = it.get(); 489 if (nextNotKey(it)) { 490 String line = it.get(); 491 BuildConfig.putFieldHash(cfg, "PerFileLine", fileName, line); 492 it.next(); 493 return; 494 } 495 } 496 empty(null, "** Error: wrong number of args to -perFileLine"); 497 } 498 } 499 ), 500 501 new ArgRuleSpecific("-conditionalPerFileLine", 502 new HsArgHandler() { 503 public void handle(ArgIterator it) { 504 String cfg = getCfg(it.get()); 505 if (nextNotKey(it)) { 506 String fileName = it.get(); 507 if (nextNotKey(it)) { 508 String productLine = it.get(); 509 if (nextNotKey(it)) { 510 String debugLine = it.get(); 511 BuildConfig.putFieldHash(cfg+"_debug", "CondPerFileLine", 512 fileName, debugLine); 513 BuildConfig.putFieldHash(cfg+"_product", "CondPerFileLine", 514 fileName, productLine); 515 it.next(); 516 return; 517 } 518 } 519 } 520 521 empty(null, "** Error: wrong number of args to -conditionalPerFileLine"); 522 } 523 } 524 ), 525 526 new HsArgRule("-disablePch", 527 "DisablePch", 528 null, 529 HsArgHandler.HASH 530 ), 531 532 new ArgRule("-startAt", 533 new HsArgHandler() { 534 public void handle(ArgIterator it) { 535 if (BuildConfig.getField(null, "StartAt") != null) { 536 empty(null, "** Error: multiple -startAt"); 537 } 538 if (nextNotKey(it)) { 539 BuildConfig.putField(null, "StartAt", it.get()); 540 it.next(); 541 } else { 542 empty("-startAt", null); 543 } 544 } 545 } 546 ), 547 548 new HsArgRule("-ignoreFile", 549 "IgnoreFile", 550 null, 551 HsArgHandler.HASH 552 ), 553 554 new HsArgRule("-additionalFile", 555 "AdditionalFile", 556 null, 557 HsArgHandler.VECTOR 558 ), 559 560 new ArgRuleSpecific("-additionalGeneratedFile", 561 new HsArgHandler() { 562 public void handle(ArgIterator it) { 563 String cfg = getCfg(it.get()); 564 if (nextNotKey(it)) { 565 String dir = it.get(); 566 if (nextNotKey(it)) { 567 String fileName = it.get(); 568 // we ignore files that we know are generated, so we coudn't 569 // find them in sources 570 BuildConfig.putFieldHash(cfg, "IgnoreFile", fileName, "1"); 571 BuildConfig.putFieldHash(cfg, "AdditionalGeneratedFile", 572 Util.normalize(dir + Util.sep + fileName), 573 fileName); 574 it.next(); 575 return; 576 } 577 } 578 empty(null, "** Error: wrong number of args to -additionalGeneratedFile"); 579 } 580 } 581 ), 582 583 new HsArgRule("-includeDB", 584 "IncludeDB", 585 null, 586 HsArgHandler.STRING 587 ), 588 589 new ArgRule("-prelink", 590 new HsArgHandler() { 591 public void handle(ArgIterator it) { 592 if (nextNotKey(it)) { 593 String build = it.get(); 594 if (nextNotKey(it)) { 595 String description = it.get(); 596 if (nextNotKey(it)) { 597 String command = it.get(); 598 BuildConfig.putField(null, "PrelinkDescription", description); 599 BuildConfig.putField(null, "PrelinkCommand", command); 600 it.next(); 601 return; 602 } 603 } 604 } 605 606 empty(null, "** Error: wrong number of args to -prelink"); 607 } 608 } 609 ) 610 }, 611 new ArgHandler() { 612 public void handle(ArgIterator it) { 613 614 throw new RuntimeException("Arg Parser: unrecognized option "+it.get()); 615 } 616 } 617 ); 618 if (BuildConfig.getField(null, "SourceBase") == null || 619 BuildConfig.getField(null, "BuildBase") == null || 620 BuildConfig.getField(null, "ProjectFileName") == null || 621 BuildConfig.getField(null, "CompilerVersion") == null) { 622 usage(); 623 } 624 625 if (BuildConfig.getField(null, "UseToGeneratePch") == null) { 626 throw new RuntimeException("ERROR: need to specify one file to compute PCH, with -useToGeneratePch flag"); 627 } 628 629 BuildConfig.putField(null, "PlatformObject", this); 630 } 631 632 Vector createAllConfigs() { 633 Vector allConfigs = new Vector(); 634 635 allConfigs.add(new C1DebugConfig()); 636 637 boolean b = true; 638 if (b) { 639 allConfigs.add(new C1FastDebugConfig()); 640 allConfigs.add(new C1ProductConfig()); 641 642 allConfigs.add(new C2DebugConfig()); 643 allConfigs.add(new C2FastDebugConfig()); 644 allConfigs.add(new C2ProductConfig()); 645 646 allConfigs.add(new TieredDebugConfig()); 647 allConfigs.add(new TieredFastDebugConfig()); 648 allConfigs.add(new TieredProductConfig()); 649 650 allConfigs.add(new CoreDebugConfig()); 651 allConfigs.add(new CoreFastDebugConfig()); 652 allConfigs.add(new CoreProductConfig()); 653 654 allConfigs.add(new KernelDebugConfig()); 655 allConfigs.add(new KernelFastDebugConfig()); 656 allConfigs.add(new KernelProductConfig()); 657 } 658 659 return allConfigs; 660 } 661 662 class FileAttribute { 663 int numConfigs; 664 Vector configs; 665 String shortName; 666 boolean noPch, pchRoot; 667 668 FileAttribute(String shortName, BuildConfig cfg, int numConfigs) { 669 this.shortName = shortName; 670 this.noPch = (cfg.lookupHashFieldInContext("DisablePch", shortName) != null); 671 this.pchRoot = shortName.equals(BuildConfig.getFieldString(null, "UseToGeneratePch")); 672 this.numConfigs = numConfigs; 673 674 configs = new Vector(); 675 add(cfg.get("Name")); 676 } 677 678 void add(String confName) { 679 configs.add(confName); 680 681 // if presented in all configs 682 if (configs.size() == numConfigs) { 683 configs = null; 684 } 685 } 686 } 687 688 class FileInfo implements Comparable { 689 String full; 690 FileAttribute attr; 691 692 FileInfo(String full, FileAttribute attr) { 693 this.full = full; 694 this.attr = attr; 695 } 696 697 public int compareTo(Object o) { 698 FileInfo oo = (FileInfo)o; 699 // Don't squelch identical short file names where the full 700 // paths are different 701 if (!attr.shortName.equals(oo.attr.shortName)) 702 return attr.shortName.compareTo(oo.attr.shortName); 703 return full.compareTo(oo.full); 704 } 705 706 boolean isHeader() { 707 return attr.shortName.endsWith(".h") || attr.shortName.endsWith(".hpp"); 708 } 709 } 710 711 712 TreeSet sortFiles(Hashtable allFiles) { 713 TreeSet rv = new TreeSet(); 714 Enumeration e = allFiles.keys(); 715 while (e.hasMoreElements()) { 716 String fullPath = (String)e.nextElement(); 717 rv.add(new FileInfo(fullPath, (FileAttribute)allFiles.get(fullPath))); 718 } 719 return rv; 720 } 721 722 Hashtable computeAttributedFiles(Vector allConfigs) { 723 Hashtable ht = new Hashtable(); 724 int numConfigs = allConfigs.size(); 725 726 for (Iterator i = allConfigs.iterator(); i.hasNext(); ) { 727 BuildConfig bc = (BuildConfig)i.next(); 728 Hashtable confFiles = (Hashtable)bc.getSpecificField("AllFilesHash"); 729 String confName = bc.get("Name"); 730 731 for (Enumeration e=confFiles.keys(); e.hasMoreElements(); ) { 732 String filePath = (String)e.nextElement(); 733 FileAttribute fa = (FileAttribute)ht.get(filePath); 734 735 if (fa == null) { 736 fa = new FileAttribute((String)confFiles.get(filePath), bc, numConfigs); 737 ht.put(filePath, fa); 738 } else { 739 fa.add(confName); 740 } 741 } 742 } 743 744 return ht; 745 } 746 747 Hashtable computeAttributedFiles(BuildConfig bc) { 748 Hashtable ht = new Hashtable(); 749 Hashtable confFiles = (Hashtable)bc.getSpecificField("AllFilesHash"); 750 751 for (Enumeration e = confFiles.keys(); e.hasMoreElements(); ) { 752 String filePath = (String)e.nextElement(); 753 ht.put(filePath, new FileAttribute((String)confFiles.get(filePath), bc, 1)); 754 } 755 756 return ht; 757 } 758 759 PrintWriter printWriter; 760 761 public void writeProjectFile(String projectFileName, String projectName, 762 Vector allConfigs) throws IOException { 763 throw new RuntimeException("use compiler version specific version"); 764 } 765 }