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