1 20 21 package cpmake; 22 23 import bsh.*; 24 import java.util.regex.*; 25 import java.util.*; 26 import java.io.*; 27 import java.net.*; 28 import java.lang.reflect.*; 29 30 31 34 35 public class CPMake 36 { 37 41 public static final int RECURSE = 0x00000001; 42 45 public static final int INCLUDE_PATH = 0x00000002; 46 50 public static final int RELATIVE_PATH = 0x00000004; 51 52 private Vector m_rules; 53 private Vector m_dependencies; 54 private ScriptInterpreter m_interpreter; 55 private Vector m_searchPaths; 56 private String m_defaultTarget; 57 private LinkedList m_buildQueue; 58 private int m_threadCount; private LinkedList m_threadQueue; private int m_waitingThreadCnt; private int m_activeThreadCnt; private Properties m_properties; 63 private CPMakeException m_makeException; 64 private boolean m_verbose; 65 private boolean m_buildInProgress; 66 private String m_currentTarget; 67 private String m_primaryTarget; 68 private String m_buildFile; 69 private InputWatcher m_inputWatcher; 70 private Vector m_autoCleanDirs; private boolean m_modifiedEnv; 72 private DependencyCache m_depCache; 73 private File m_workingDir; private Map m_scriptObjects; 76 77 private static final int DO_NOT_BUILD = 0; 78 private static final int UNBUILT_DEPENDENCIES = 1; 79 private static final int OUT_OF_DATE = 2; 80 81 private static final String VERSION = "1.2.0 beta 1"; 82 83 private static boolean s_printDebug = false; 84 85 119 public static void main(String [] args) 120 { 121 long startTime; 122 long stopTime; 123 CommandLine cl = new CommandLine(args); 124 String [] targets; 125 CPMake make = null; 126 String buildFile = ""; 127 int threadCount = 0; 128 boolean verbose = false; 129 int err = 0; 130 131 132 cl.setBooleanOptions("?vda"); 133 cl.setValueOptions("ft"); 134 135 if (cl.isSet('?')) 136 { 137 printHelp(); 138 System.exit(0); 139 } 140 141 try 142 { 143 if (cl.isSet('v')) 144 verbose = true; 145 146 if (cl.isSet('f')) 147 buildFile = cl.getOptionValue('f'); 148 else 149 { 150 File f = new File("build.bsh"); 151 if (!f.exists()) 152 f = new File("build.py"); 153 154 if (!f.exists()) 155 f = new File("build.gvy"); 156 157 if (!f.exists()) 158 f = new File("build.groovy"); 159 160 if (!f.exists()) 161 { 162 System.out.println("No build file specified"); 163 System.exit(-1); 164 } 165 else 166 buildFile = f.getName(); 167 } 168 169 if (cl.isSet('d')) 170 s_printDebug = true; 171 172 if (cl.isSet('t')) 173 { 174 threadCount = Integer.parseInt(cl.getOptionValue('t')); 175 } 176 177 startTime = System.currentTimeMillis(); 178 targets = cl.getNonOptions(); 179 if (targets.length > 0) 180 for (int I = 0; I < targets.length; I++) 181 { 182 make = new CPMake(buildFile, targets[I]); 183 if (threadCount != 0) 184 make.setThreadCount(threadCount); 185 if (make.getProperty("cpmake.debug", "off").equals("on")) 186 s_printDebug = true; 187 make.setVerbose(verbose); 188 make.processBuildFile(); 189 } 190 else 191 { 192 make = new CPMake(buildFile, null); 193 if (threadCount != 0) 194 make.setThreadCount(threadCount); 195 if (make.getProperty("cpmake.debug", "off").equals("on")) 196 s_printDebug = true; 197 make.setVerbose(verbose); 198 make.processBuildFile(); 199 } 200 201 stopTime = System.currentTimeMillis(); 202 long totalTime = stopTime - startTime; 203 long seconds = totalTime / 1000; 204 long minutes = seconds / 60; 205 long hours = minutes / 60; 206 seconds -= minutes * 60; 207 minutes -= hours * 60; 208 Object pargs[] = new Object [] {new Long (hours), new Long (minutes), 209 new Long (seconds)}; 210 System.out.println(Printf.print("Build time: %02d:%02d:%02d", pargs)); 211 } 213 catch (CPMakeException cpme) 214 { 215 System.out.println(cpme.getDescription()); 216 err = cpme.getReturnError(); 217 } 219 catch (Exception e) 220 { 221 System.out.println(e.getMessage()); 222 e.printStackTrace(); 223 } 224 225 File env = new File("env.properties"); 227 if (env.exists()) 228 env.delete(); 229 230 try 231 { 232 debugPrint("Saving cache file"); 233 DependencyCache.writeDependencyCache(); 234 } 235 catch (IOException ioe) 236 { 237 debugPrint(ioe.getMessage()); 238 StringWriter sw = new StringWriter(); 239 ioe.printStackTrace(new PrintWriter(sw)); 240 debugPrint(sw.toString()); 241 System.out.println("Unable to save cache file "+DependencyCache.getCacheFile()); 242 } 243 244 if (cl.isSet('a')||(make.getProperty("cpmake.finishNotify", "off").equals("on"))) 245 { 246 System.out.write(7); 247 System.out.flush(); 248 } 249 250 System.exit(err); 252 } 253 254 private static void printHelp() 256 { 257 System.out.println("CPMake the Cross Platform Make Utility (version = " + VERSION+")"); 258 System.out.println("Copyright (C) 2004, Brian Hawkins"); 259 System.out.println("Licensed under GNU General Public License\n"); 260 System.out.println("CPMake Command line help."); 261 System.out.println("Usage: java -jar cpmake.jar [-v] [-f <build file>] [-t <thread count>] [<targets>]"); 262 System.out.println(" -v : Verbose output"); 263 System.out.println(" -f : Build file to process"); 264 System.out.println(" -t : Number of threads to use"); 265 System.out.println(" -d : Print debug messages"); 266 System.out.println(" -a : System beep when build is done"); 267 268 } 269 270 public static void debugPrint(String msg) 272 { 273 if (s_printDebug) 274 System.out.println("CPMake-Debug: "+msg); 275 } 276 277 private int getActiveThreadCnt() 279 { 280 return (m_activeThreadCnt); 281 } 282 283 private String [] getEnvArr() 285 { 286 Enumeration e = m_properties.propertyNames(); 287 String key; 288 Vector env = new Vector(); 289 290 if (!m_modifiedEnv) 291 return (null); 292 293 while (e.hasMoreElements()) 294 { 295 key = (String )e.nextElement(); 296 env.add(key+"="+m_properties.getProperty(key)); 297 } 298 299 return ((String [])env.toArray(new String [0])); 300 } 301 302 private Rule getRule(String target) 304 throws CPMakeException 305 { 306 Iterator it = m_rules.iterator(); 307 Rule rule = null; 308 Rule ret = null; 309 Rule patret = null; 310 boolean patexists = false; 311 boolean tmpexists = false; 312 313 while (it.hasNext()) 314 { 315 rule = (Rule)it.next(); 316 317 if (rule.matchTarget(target)) 318 { 319 if (rule instanceof PatternRule) 320 { 321 if (patret != null) 322 { 323 tmpexists = locateFile(rule.getPrerequisites(target)[0]) != null; 324 if (patexists && tmpexists) 325 throw new CPMakeException("Multiple pattern rules for target: "+target, -1); 326 else if (tmpexists) 327 { 328 patexists = true; 329 patret = rule; 330 } 331 } 332 else 333 { 334 patret = rule; 335 patexists = (locateFile(patret.getPrerequisites(target)[0]) != null); 336 } 337 } 338 else if (ret != null) 339 throw new CPMakeException("Multiple rules for target: "+target, -1); 340 else 341 ret = rule; 342 } 343 } 344 345 if (ret == null) 347 ret = patret; 348 349 return (ret); 350 } 351 352 353 private File getFile(String file) 355 { 356 File f = locateFile(file); 357 if (f == null) 358 f = new File(m_workingDir, file); 359 360 return (f); 361 } 362 363 private void loadVector(Vector v, String [] s) 365 { 366 if (s.length > 0) 367 { 368 for (int I = 0; I < s.length; I++) 369 { 370 if (s[I].length() != 0) 371 v.add(s[I]); 372 } 374 } 375 } 376 377 private String [] getPrerequisites(String target, Rule rule, boolean useDepCache) 379 throws CPMakeException 380 { 381 Vector prereqs = new Vector(); 382 Dependency dep; 383 String [] rulePre; 384 385 rulePre = rule.getPrerequisites(target); 386 387 loadVector(prereqs, rulePre); 388 389 390 if ((!getProperty("cpmake.dependencyCheck", "on").equals("off")) && 391 (useDepCache)) 392 { 393 if ((rulePre.length > 0) && (m_depCache.canParse(rulePre[0]))) 394 prereqs.addAll(m_depCache.getDependencies(this, rulePre[0])); 395 else if (m_depCache.canParse(target)) 396 prereqs.addAll(m_depCache.getDependencies(this, target)); 397 } 398 399 if (m_dependencies.size() > 0) 400 { 401 for (int I = 0; I < m_dependencies.size(); I++) 402 { 403 dep = (Dependency)m_dependencies.elementAt(I); 404 if (dep.matchTarget(target)) 405 { 406 loadVector(prereqs, dep.getDependencies(target)); 407 } 408 } 409 } 410 411 412 return ((String [])prereqs.toArray(new String [0])); 413 } 414 415 private BuildAction[] rebuildTarget(String target, Rule rule) 417 throws CPMakeException 418 { 419 String [] prereqs = getPrerequisites(target, rule, true); 420 BuildAction[] ret = null; 421 Vector buildDep = new Vector(); 422 BuildAction ba; 423 long targetTime = 0; 424 File f; 425 boolean tExists = true; 426 boolean tDir = false; 427 boolean tPhony = true; 428 429 430 if (!(rule instanceof PhonyRule)) 432 { 433 File t = getFile(target); 434 435 targetTime = t.lastModified(); 436 tExists = t.exists(); 437 tDir = t.isDirectory(); 438 tPhony = false; 439 } 440 441 if (prereqs.length > 0) 443 { 444 for (int I = 0; I < prereqs.length; I++) 445 { 446 f = getFile(prereqs[I]); 447 if ((ba = addToBuildQueue(prereqs[I])) != null) 448 buildDep.add(ba); 449 else if ( (ret == null) && (((!tDir) && (!f.isDirectory()) && (!tPhony)) && 450 (f.lastModified() > targetTime) || (!tExists) )) 451 { 452 ret = new BuildAction[0]; 453 } 454 } 455 456 if (buildDep.size() > 0) 457 ret = (BuildAction[])buildDep.toArray(new BuildAction[0]); 458 } 459 else if (((!tExists) && (!tPhony)) || (tPhony && target.equals(m_primaryTarget))) 460 { 461 debugPrint("target: "+target+" does not exist."); 462 ret = new BuildAction[0]; 463 } 464 465 return (ret); 466 } 467 468 private BuildAction addToBuildQueue(String target) 470 throws CPMakeException 471 { 472 return (addToBuildQueue(target, false)); 473 } 474 475 private BuildAction addToBuildQueue(String target, boolean primaryTarget) 477 throws CPMakeException 478 { 479 Rule rule = getRule(target); 480 File targetFile = null; 481 BuildAction[] buildDep = null; 482 BuildAction ba = null; 483 484 if ((rule == null)&&(target.equals("clean"))) 485 rule = new CleanRule(this); 486 487 if (rule == null) 488 { 489 targetFile = getFile(target); 490 491 if (!targetFile.exists()) 492 { 493 throw new CPMakeException("Unable to locate rule for " + target, -1); 494 } 495 } 496 else 497 { 498 ba = new BuildAction(target, rule); 499 int index; 500 501 if ((index = m_buildQueue.indexOf(ba)) != -1) 502 { 503 debugPrint("target: "+target+" already in build queue."); 504 ba = (BuildAction)m_buildQueue.get(index); 506 } 507 else if ((buildDep = rebuildTarget(target, rule)) != null) 508 { 509 debugPrint("Adding target: "+target+" to build queue."); 510 ba.addDependencies(buildDep); 511 512 m_buildQueue.addFirst(ba); 513 } 514 else if (primaryTarget && (rule instanceof PhonyRule)) 515 { 516 debugPrint("Adding primary target: "+target+" to build queue."); 517 m_buildQueue.addFirst(ba); 518 } 519 else 520 { 521 ba = null; 523 } 524 } 525 526 return (ba); 527 } 528 529 private void processBuildQueue() 531 throws CPMakeException 532 { 533 BuildAction ba; 534 Rule rule; 535 String target; 536 Thread t; 537 String param1 = "param1t" + Thread.currentThread().getName(); 540 String param2 = "param2t" + Thread.currentThread().getName(); 541 542 do 543 { 544 synchronized (this) 545 { 546 try 547 { 548 ba = (BuildAction)m_buildQueue.removeLast(); 549 } 550 catch (NoSuchElementException nsee) 551 { 552 ba = new BuildAction(null, null); 553 } 554 555 if (m_threadCount > 1) 556 { 557 int depCount = ba.getDependencyCount(); 558 if ((m_waitingThreadCnt > 0)||(depCount > 0)) 559 { 560 m_threadQueue.addFirst(Thread.currentThread()); 561 if (depCount > 0) 562 m_waitingThreadCnt++; 563 564 if (m_threadQueue.size() == m_threadCount) 565 { 566 t = (Thread )m_threadQueue.getLast(); 567 t.interrupt(); 568 } 569 570 do 571 { 572 try 573 { 574 wait(); 575 } 576 catch (InterruptedException ie) 577 { 578 Thread.interrupted(); } 580 } while ((ba.getDependencyCount() > 0)&&(m_makeException == null)); 581 582 if (m_makeException != null) 583 { 584 notifyAll(); 585 throw m_makeException; 586 } 587 588 m_threadQueue.removeLast(); if (depCount > 0) 590 m_waitingThreadCnt--; 591 592 try 593 { 594 t = (Thread )m_threadQueue.getLast(); 595 t.interrupt(); } 597 catch (NoSuchElementException nsee) {} 598 } 599 } 600 } 601 602 rule = ba.getTargetRule(); 603 target = ba.getTarget(); 604 if ((rule != null)&&(rule.hasAction())) 605 { 606 rule.callAction(fixPath(target)); 607 608 if (rule.getScriptCall() != null) 609 { 610 m_interpreter.set(param1, fixPath(target)); 611 m_interpreter.set(param2, rule.getPrerequisites(target)); 612 613 debugPrint("Calling "+rule.getScriptCall()+" for "+target); 614 m_interpreter.call(rule.getScriptCall(), param1, param2); 615 } 616 617 if (rule.verify()) 618 { 619 File f = new File(m_workingDir, target); 620 if (!f.exists()) 621 { 622 throw new CPMakeException("Unable to verify target "+target, -1); 623 } 624 } 625 626 ba.complete(); } 628 } while ((ba.getTarget() != null)&&(m_makeException == null)); 629 630 if (m_makeException != null) 633 throw m_makeException; 634 } 635 636 private void loadPropertiesFile(String fileName) 638 { 639 PropertiesFile pf = new PropertiesFile(new File(m_workingDir, fileName).getAbsolutePath()); 640 641 loadProperties(pf); 642 } 643 644 private void loadProperties(Properties prop) 646 { 647 Enumeration en = prop.propertyNames(); 648 String name; 649 650 while (en.hasMoreElements()) 651 { 652 name = (String )en.nextElement(); 653 654 setProperty(name, prop.getProperty(name)); 655 } 656 } 657 658 private void loadProperties(Reader input) 660 { 661 BufferedReader br; 662 String line; 663 String [] split; 664 665 try 666 { 667 br = new BufferedReader(input); 668 while ((line = br.readLine()) != null) 669 { 670 split = line.split("=", 2); 671 setProperty(split[0], split[1]); 672 } 673 br.close(); 674 } 675 catch (IOException e) 676 { 677 debugPrint(e.getMessage()); 678 } 679 } 680 681 private void loadEnvProperties() 683 { 684 File f = new File("env.properties"); 685 Process proc; 686 String cmd; 687 688 if (f.exists()) 689 { 690 m_modifiedEnv = true; 691 try 692 { 693 loadProperties(new FileReader(f)); 694 } 695 catch (FileNotFoundException fnfe) {} 696 } 697 else 698 { 699 if (System.getProperty("os.name").startsWith("Windows")) 700 cmd = "cmd /D /C set"; 701 else 702 cmd = "printenv"; 703 704 try 705 { 706 proc = Runtime.getRuntime().exec(cmd); 707 708 loadProperties(new InputStreamReader(proc.getInputStream())); 709 710 proc.waitFor(); 711 } 712 catch (Exception e) 713 { 714 debugPrint(e.getMessage()); 715 } 716 } 717 } 718 719 private void runThread() 721 { 722 try 723 { 724 synchronized(this) 725 { 726 m_activeThreadCnt++; 727 } 728 processBuildQueue(); 729 synchronized(this) 730 { 731 m_activeThreadCnt--; 732 if (m_activeThreadCnt == 0) 733 notify(); 734 } 735 } 736 catch (CPMakeException cpme) 737 { 738 m_makeException = cpme; 739 synchronized(this) 740 { 741 notifyAll(); 742 } 743 } 744 } 745 746 747 757 public CPMake(String buildFile, String primaryTarget) 758 { 759 this(null, buildFile, primaryTarget); 760 } 761 762 773 public CPMake(CPMake make, String buildFile, String primaryTarget) 774 { 775 m_rules = new Vector(); 776 m_dependencies = new Vector(); 777 m_searchPaths = new Vector(); 778 m_buildFile = buildFile; 779 m_primaryTarget = primaryTarget; 780 m_defaultTarget = null; 781 m_buildInProgress = false; 782 m_threadQueue = new LinkedList(); 783 m_waitingThreadCnt = 0; 784 m_properties = new Properties(System.getProperties()); 785 m_inputWatcher = InputWatcher.getInputWatcher(); 786 m_autoCleanDirs = new Vector(); 787 m_modifiedEnv = false; 788 m_depCache = DependencyCache.getDependencyCache(".cpmakecache"); 789 m_scriptObjects = new HashMap(); 790 791 m_workingDir = new File(m_buildFile).getParentFile(); 792 793 if (make == null) 794 { 795 File f = new File(m_workingDir, "cpmake.properties"); 796 if (f.exists()) 797 loadPropertiesFile("cpmake.properties"); 798 loadEnvProperties(); 799 800 m_activeThreadCnt = 0; 801 m_makeException = null; 802 m_threadCount = Integer.parseInt(getProperty("cpmake.threadCount", "1")); 803 } 804 else 805 { 806 m_threadCount = make.m_threadCount; 807 loadProperties(make.m_properties); 808 m_verbose = make.m_verbose; 809 } 810 } 811 812 816 public void processBuildFile() 817 throws CPMakeException 818 { 819 if (m_buildFile.endsWith(".bsh")) 820 { 821 try 822 { 823 m_interpreter = new BeanShellInterpreter(); 824 } 825 catch (NoClassDefFoundError ncdfe) 826 { 827 throw new CPMakeException("Unable to find Bean shell interpreter", -1); 828 } 829 } 830 else if (m_buildFile.endsWith(".py")) 831 { 832 try 833 { 834 m_interpreter = new JythonShellInterpreter(this); 835 } 836 catch (NoClassDefFoundError ncdfe) 837 { 838 throw new CPMakeException("Unable to find Jython interpreter", -1); 839 } 840 } 841 else if (m_buildFile.endsWith(".groovy")||(m_buildFile.endsWith(".gvy"))) 842 { 843 try 844 { 845 m_interpreter = new GroovyShellInterpreter(); 846 } 847 catch (NoClassDefFoundError ncdfe) 848 { 849 throw new CPMakeException("Unable to find Groovy interpreter\n" + ncdfe.toString(), -1); 850 } 851 } 852 else 853 throw new CPMakeException("Unknown build script type", -1); 854 855 try 856 { 857 String name; 858 Iterator it = m_scriptObjects.keySet().iterator(); 859 while (it.hasNext()) 860 { 861 name = (String )it.next(); 862 m_interpreter.set(name, m_scriptObjects.get(name)); 863 } 864 m_interpreter.set("make", this); 865 debugPrint("Processing "+m_buildFile); 866 m_interpreter.source(m_buildFile); 867 868 if (m_primaryTarget == null) 869 throw new CPMakeException("No target specified", -1); 870 debugPrint("Building target "+m_primaryTarget); 871 buildTarget(m_primaryTarget); 872 m_interpreter.cleanup(); 873 } 874 catch(CPMakeException cpme) 875 { 876 m_makeException = cpme; 877 synchronized(this) 878 { 879 notifyAll(); 880 } 881 throw cpme; 882 } 883 catch(IOException ioe) 884 { 885 m_makeException = new CPMakeException("Unable to load "+m_buildFile, -1); 886 synchronized(this) 887 { 888 notifyAll(); 889 } 890 throw m_makeException; 891 } 892 893 } 894 895 902 public String getPrimaryTarget() 903 { 904 return (m_primaryTarget); 905 } 906 907 924 public void createPatternRule(String pattern, String replacement, String scriptCall, boolean verify) 925 { 926 m_rules.add(new PatternRule(this, pattern, replacement, scriptCall, verify)); 927 } 928 929 943 public void createExplicitRule(String target, String prerequisites, String scriptCall, boolean verify) 944 throws CPMakeException 945 { 946 if (prerequisites == null) 947 createExplicitRule(target, new String [0], scriptCall, verify); 948 else 949 createExplicitRule(target, prerequisites.split(" "), scriptCall, verify); 950 } 951 952 965 public void createExplicitRule(String target, String [] prerequisites, String scriptCall, boolean verify) 966 throws CPMakeException 967 { 968 Rule r; 969 if (prerequisites == null) 970 prerequisites = new String [0]; 971 972 983 m_rules.add(new ExplicitRule(target, prerequisites, scriptCall, verify)); 984 } 985 986 989 public void createDirectoryRule(String directory, String [] prerequisites, boolean echo) 990 throws CPMakeException 991 { 992 Rule r; 993 if (prerequisites == null) 994 prerequisites = new String [0]; 995 996 m_autoCleanDirs.add(fullPath(directory)); 997 998 m_rules.add(new DirectoryRule(this, directory, prerequisites, echo)); 999 } 1000 1013 public void createPhonyRule(String target, String prerequisites, String scriptCall) 1014 { 1015 if (prerequisites == null) 1016 createPhonyRule(target, new String [0], scriptCall); 1017 else 1018 createPhonyRule(target, prerequisites.split(" "), scriptCall); 1019 } 1020 1021 1033 public void createPhonyRule(String target, String [] prerequisites, String scriptCall) 1034 { 1035 if (prerequisites == null) 1036 prerequisites = new String [0]; 1037 1038 m_rules.add(new PhonyRule(target, prerequisites, scriptCall)); 1039 } 1040 1041 1056 public void createPatternDependency(String pattern, String replacement) 1057 { 1058 m_dependencies.add(new PatternDependency(this, pattern, replacement)); 1059 } 1060 1061 1071 public void createPatternDependency(String pattern, String [] prerequisites) 1072 { 1073 for (int I = 0; I < prerequisites.length; I++) 1074 m_dependencies.add(new PatternDependency(this, pattern, prerequisites[I])); 1075 } 1076 1077 1085 public void createExplicitDependency(String target, String prerequisites) 1086 { 1087 if (prerequisites == null) 1088 createExplicitDependency(target, new String [0]); 1089 else 1090 createExplicitDependency(target, prerequisites.split(" ")); 1091 } 1092 1093 1101 public void createExplicitDependency(String target, String [] prerequisites) 1102 { 1103 1108 m_dependencies.add(new ExplicitDependency(this, new File(m_workingDir, target), prerequisites)); 1109 } 1110 1111 1122 public void buildTarget(String target) 1123 throws CPMakeException 1124 { 1125 buildTarget(target, true); 1126 } 1127 1128 1140 public void buildTarget(String target, boolean prep) 1141 throws CPMakeException 1142 { 1143 Rule rule = getRule(target); 1144 File targetFile = null; 1145 Thread t; 1146 Dependency d; 1147 1148 if (prep) 1149 { 1150 try 1151 { 1152 m_interpreter.set("currentBuildTarget", target); 1153 m_interpreter.call("prepForTarget", "currentBuildTarget"); 1154 } 1155 catch (Exception e) 1156 { 1157 } 1159 } 1160 1161 if (m_buildInProgress) 1162 throw new CPMakeException("Build already in progress for "+m_currentTarget, -1); 1163 1164 1169 1170 1171 m_currentTarget = target; 1172 m_buildInProgress = true; 1173 m_buildQueue = new LinkedList(); 1174 if (addToBuildQueue(target, true) != null) 1175 { 1176 if (m_verbose) 1177 System.out.println("Using " + m_threadCount +" threads"); 1178 Thread.currentThread().setName("0"); 1181 if (m_threadCount > 1) 1182 for (int I = 1; I < m_threadCount; I++) 1183 { 1184 t = new Thread (new Runnable () 1185 { 1186 public void run() 1187 { 1188 runThread(); 1189 } 1190 }); 1191 t.setName("" + I); 1192 t.start(); 1193 } 1194 1195 processBuildQueue(); 1196 } 1197 1198 try 1199 { 1200 synchronized(this) 1201 { 1202 if (getActiveThreadCnt() > 0) 1203 wait(); 1204 } 1205 } 1206 catch (InterruptedException ie) {} 1207 1208 m_buildInProgress = false; 1209 1210 } 1211 1212 1220 public static String arrayToString(String [] array) 1221 { 1222 StringBuffer sb = new StringBuffer (); 1223 1224 for (int I = 0; I < array.length; I++) 1225 sb.append(array[I] + " "); 1226 1227 return (sb.toString()); 1228 } 1229 1230 1236 public void addSearchPath(String path) 1237 { 1238 addSearchPaths(".*", new String [] {path}); 1239 } 1240 1241 1247 public void setVerbose(boolean verbose) 1248 { 1249 m_verbose = verbose; 1250 } 1251 1252 1260 public void addSearchPath(String pattern, String path) 1261 { 1262 addSearchPaths(pattern, new String [] {path}); 1263 } 1264 1265 1271 public void addSearchPaths(String [] paths) 1272 { 1273 addSearchPaths(".*", paths); 1274 } 1275 1276 1284 public void addSearchPaths(String pattern, String [] paths) 1285 { 1286 for (int I = 0; I < paths.length; I++) 1287 m_searchPaths.add(new SearchPath(pattern, paths[I])); 1288 } 1289 1290 1298 public File locateFile(String file) 1299 { 1300 Iterator it = m_searchPaths.iterator(); 1301 SearchPath sp; 1302 String path; 1303 File ret = null; 1304 File f; 1305 1306 f = new File(m_workingDir, file); 1307 if (f.exists()) 1308 ret = f; 1309 else 1310 { 1311 while (it.hasNext()) 1312 { 1313 sp = (SearchPath)it.next(); 1314 1315 if (sp.matches(file)) 1316 { 1317 path = sp.getPath(); 1318 f = new File(new File(m_workingDir, path), file); 1319 if (f.exists()) 1320 { 1321 ret = f; 1322 break; 1323 } 1324 } 1325 } 1326 } 1327 return (ret); 1328 } 1329 1330 1334 String getPath(File file) 1335 { 1336 String ret; 1337 1338 ret = file.getPath(); 1339 1340 if (m_workingDir != null) 1341 { 1342 if (ret.startsWith(m_workingDir.getPath())) 1343 ret = ret.substring(m_workingDir.getPath().length() +1); 1344 } 1345 1346 return (ret); 1347 } 1348 1359 public static String fixPath(String path) 1360 { 1361 String slash = System.getProperty("file.separator"); 1362 1363 if (slash.equals("/")) 1364 path = path.replace('\\', '/'); 1365 else 1366 path = path.replace('/', '\\'); 1367 1368 return (path); 1369 } 1370 1371 1382 public static String [] fixPath(String [] paths) 1383 { 1384 String [] newPaths = new String [paths.length]; 1385 1386 for (int I = 0; I < paths.length; I++) 1387 { 1388 newPaths[I] = fixPath(paths[I]); 1389 } 1390 1391 return (newPaths); 1392 } 1393 1394 1400 public void setDefaultTarget(String target) 1401 { 1402 if (m_primaryTarget == null) 1403 m_primaryTarget = target; 1404 } 1405 1406 1412 public int getThreadCount() 1413 { 1414 return (m_threadCount); 1415 } 1416 1417 1423 public void setThreadCount(int threadCount) 1424 { 1425 m_threadCount = threadCount; 1426 } 1427 1428 1435 public void setProperty(String name, String value) 1436 { 1437 m_modifiedEnv = true; 1438 m_properties.setProperty(name, value); 1439 } 1440 1441 1452 public String getProperty(String name, String def) 1453 { 1454 String value = getProperty(name); 1455 1456 if (value == null) 1457 return (def); 1458 else 1459 return (value); 1460 1461 } 1462 1463 1473 public String getProperty(String name) 1474 { 1475 String value = m_properties.getProperty(name); 1476 1477 if (value == null) 1478 value = m_properties.getProperty(name.replace('.', '_')); 1479 1480 return (value); 1481 } 1482 1483 1487 public Properties getProperties() 1488 { 1489 return (m_properties); 1490 } 1491 1501 public void exec(String cmd, String logFile) 1502 throws CPMakeException 1503 { 1504 exec(null, cmd, false, logFile); 1505 } 1506 1507 1516 public void exec(String cmd) 1517 throws CPMakeException 1518 { 1519 exec(null, cmd, false, null); 1520 } 1521 1522 1533 public void exec(String cmd, boolean exitOnError, String logFile) 1534 throws CPMakeException 1535 { 1536 exec(null, cmd, exitOnError, logFile); 1537 } 1538 1539 1549 public void exec(String cmd, boolean exitOnError) 1550 throws CPMakeException 1551 { 1552 exec(null, cmd, exitOnError, null); 1553 } 1554 1555 1568 public void exec(String cwd, String cmd, boolean exitOnError) 1569 throws CPMakeException 1570 { 1571 exec(cwd, cmd, exitOnError, null); 1572 } 1573 1587 public void exec(String cwd, String cmd, boolean exitOnError, String logFile) 1588 throws CPMakeException 1589 { 1590 Process proc; 1591 BufferedReader br; 1592 String line; 1593 File cwdf = null; 1594 StreamPipe stderr, stdout; 1595 boolean multiThreaded = false; 1596 1597 if ((m_activeThreadCnt - m_waitingThreadCnt) > 1) 1598 multiThreaded = true; 1599 1600 if (cwd != null) 1601 { 1602 cwdf = new File(m_workingDir, cwd); 1603 } 1605 else 1606 cwdf = m_workingDir; 1607 1608 if (m_verbose) 1609 { 1610 if (cwd != null) 1611 System.out.print(cwdf.getPath()+" "); 1612 System.out.println(cmd+"\n"); 1613 } 1614 1615 try 1616 { 1617 proc = Runtime.getRuntime().exec(cmd, getEnvArr(), cwdf); 1618 1619 m_inputWatcher.addProcess(proc); 1620 1621 if (logFile == null) 1622 { 1623 stdout = new StreamPipe(proc.getInputStream(), System.out, multiThreaded); 1624 stderr = new StreamPipe(proc.getErrorStream(), System.out, multiThreaded); 1625 } 1627 else 1628 { 1629 stdout = new StreamPipe(proc.getInputStream(), System.out, new File(m_workingDir, logFile), multiThreaded); 1630 stderr = new StreamPipe(proc.getErrorStream(), System.out, new File(m_workingDir, logFile), multiThreaded); 1631 } 1632 1633 stdout.waitForClose(); 1634 stderr.waitForClose(); 1635 1636 if (proc.waitFor() != 0) 1637 { 1638 m_inputWatcher.removeProcess(proc); 1639 throw new CPMakeException("", proc.exitValue()); 1640 } 1641 m_inputWatcher.removeProcess(proc); 1642 } 1643 catch (IOException ioe) 1644 { 1645 ioe.printStackTrace(); 1646 System.exit(-1); 1647 } 1648 catch (InterruptedException ie) 1649 { 1650 ie.printStackTrace(); 1651 System.exit(-1); 1652 } 1653 1654 } 1655 1656 private Vector getFileList(File dir, Pattern pattern, boolean recurse, boolean filePath) 1658 { 1659 String [] list = dir.list(); 1660 Vector retList = new Vector(); 1661 File f; 1662 1663 if (list != null) 1664 for (int I = 0; I < list.length; I ++) 1665 { 1666 if (list[I].equals(".") || list[I].equals("..")) 1667 continue; 1668 1669 f = new File(dir, list[I]); 1670 if (recurse && f.isDirectory()) 1671 { 1672 retList.addAll(getFileList(f, pattern, recurse, filePath)); 1673 continue; 1674 } 1675 1676 if (pattern.matcher(list[I]).matches()) 1677 { 1678 if (filePath) 1679 retList.add(f.getPath()); 1680 else 1681 retList.add(list[I]); 1682 } 1683 } 1684 1685 return (retList); 1686 } 1687 1691 public String [] createFileList(String rootDirectory, String regexFilePattern) 1692 { 1693 return (createFileList(rootDirectory, regexFilePattern, 0)); 1694 } 1695 1699 public String [] createFileList(String rootDirectory, String regexFilePattern, 1700 boolean recurse, boolean filePath) 1701 { 1702 int flags = 0; 1703 if (recurse) 1704 flags |= RECURSE; 1705 1706 if (filePath) 1707 flags |= INCLUDE_PATH; 1708 1709 return (createFileList(rootDirectory, regexFilePattern, flags)); 1710 } 1711 1721 public String [] createFileList(String rootDirectory, String regexFilePattern, 1722 int flags) 1723 { 1724 File root = new File(m_workingDir, rootDirectory); 1725 Pattern pattern = Pattern.compile(regexFilePattern); 1726 String [] strList; 1727 1728 Vector fileList = getFileList(root, pattern, ((flags & RECURSE)>0), ((flags & INCLUDE_PATH)>0)); 1729 if (fileList.size() > 0) 1730 strList = (String [])fileList.toArray(new String [0]); 1731 else 1732 strList = new String [0]; 1733 1734 if ((m_workingDir != null) && ((flags & INCLUDE_PATH)>0)) 1735 { 1736 int workdirSz = m_workingDir.getPath().length(); 1737 for (int I = 0; I < strList.length; I ++) 1738 strList[I] = strList[I].substring(workdirSz+1); 1739 } 1740 1741 if (((flags & INCLUDE_PATH)>0) && ((flags & RELATIVE_PATH)>0)) 1743 { 1744 int rootSz = rootDirectory.length(); 1745 for (int I = 0; I < strList.length; I ++) 1746 { 1747 strList[I] = strList[I].substring(rootSz+1); } 1749 } 1750 1751 return (strList); 1752 } 1753 1754 1758 public void deltree(File directory) 1759 { 1760 if (!directory.exists()) 1761 return; 1762 File[] list = directory.listFiles(); 1763 1764 if (list.length > 0) 1765 { 1766 for (int I = 0; I < list.length; I++) 1767 { 1768 if (list[I].isDirectory()) 1769 deltree(list[I]); 1770 1771 list[I].delete(); 1772 } 1773 } 1774 1775 directory.delete(); 1776 } 1777 1778 1782 public void deltree(String directory) 1783 { 1784 File f = new File(directory); 1785 1786 if (f.isAbsolute()) 1787 deltree(f); 1788 else 1789 deltree(new File(m_workingDir, directory)); 1790 } 1791 1792 1797 public void delete(String file) 1798 { 1799 File f = new File(m_workingDir, file); 1800 f.delete(); 1801 } 1802 1803 1812 public void copyIfNewer(String sourceDir, String filePattern, String dest) 1813 { 1814 String [] files = createFileList(sourceDir, filePattern); 1815 1816 if (files.length > 0) 1817 { 1818 for (int I = 0; I < files.length; I++) 1819 copyIfNewer(sourceDir+"/"+files[I], dest); 1820 } 1821 } 1822 1823 1830 public void copyIfNewer(String source, String dest) 1831 { 1832 File destf = new File(m_workingDir, dest); 1833 File sourcef = new File(m_workingDir, source); 1834 1835 if (destf.isDirectory()) 1836 destf = new File(destf, sourcef.getName()); 1837 1838 if (sourcef.lastModified() > destf.lastModified()) 1839 copy(source, dest); 1840 } 1841 1842 1851 public void copy(String sourceDir, String filePattern, String dest) 1852 { 1853 String [] files = createFileList(sourceDir, filePattern); 1854 1855 if (files.length > 0) 1856 { 1857 for (int I = 0; I < files.length; I++) 1858 copy(sourceDir+"/"+files[I], dest); 1859 } 1860 } 1861 1866 public void copy(String source, String dest) 1867 { 1868 File destf = new File(m_workingDir, dest); 1869 File sourcef = new File(m_workingDir, source); 1870 BufferedInputStream in; 1871 BufferedOutputStream out; 1872 byte[] buff = new byte[32*1024]; 1873 int len; 1874 1875 if (sourcef.isDirectory()) 1876 return; 1877 1878 if (m_verbose) 1879 System.out.println("Copying "+source+" to "+dest); 1880 1881 if (destf.isDirectory()) 1882 destf = new File(destf, sourcef.getName()); 1883 1884 try 1885 { 1886 in = new BufferedInputStream(new FileInputStream(sourcef)); 1887 out = new BufferedOutputStream(new FileOutputStream(destf)); 1888 while ((len = in.read(buff)) > 0) 1889 out.write(buff, 0, len); 1890 1891 in.close(); 1892 out.close(); 1893 destf.setLastModified(sourcef.lastModified()); 1894 } 1895 catch (FileNotFoundException fnfe) 1896 { 1897 fnfe.printStackTrace(); 1898 System.exit(-1); 1899 } 1900 catch (IOException ioe) 1901 { 1902 ioe.printStackTrace(); 1903 System.exit(-1); 1904 } 1905 } 1906 1907 1918 public void processMakeDependencyFiles(String [] files, boolean create, 1919 boolean soft) 1920 throws CPMakeException 1921 { 1922 for (int I = 0; I < files.length; I ++) 1923 processMakeDependencyFile(files[I], create, soft); 1924 } 1925 1936 public void processMakeDependencyFile(String file, boolean create, 1937 boolean soft) 1938 throws CPMakeException 1939 { 1940 File f = new File(m_workingDir, file); 1941 BufferedReader br; 1942 String line; 1943 String [] splitLine; 1944 String [] targets; 1945 Vector dependencies; 1946 boolean continued = false; 1947 1948 if ((!f.exists())&&(create)) 1949 buildTarget(file, false); 1950 1951 if (f.exists()) 1952 { 1953 try 1954 { 1955 br = new BufferedReader(new FileReader(f)); 1956 1957 while ((line = br.readLine()) != null) 1958 { 1959 line = line.trim(); 1960 if (line.charAt(0) == '#') continue; 1962 1963 if (line.length() == 0) 1964 continue; 1965 1966 dependencies = new Vector(); 1967 splitLine = line.split(": "); 1968 1969 if (splitLine.length == 1) continue; 1971 1972 targets = splitLine[0].trim().split(" "); 1973 line = splitLine[1].trim(); 1974 if (line.charAt(line.length() - 1) == '\\') 1975 { 1976 continued = true; 1977 line = line.substring(0, (line.length()-1)).trim(); } 1979 1980 loadVector(dependencies, line.split(" ")); 1981 while(continued) 1982 { 1983 line = br.readLine(); 1984 line = line.trim(); 1985 if (line.charAt(line.length() - 1) == '\\') 1986 { 1987 continued = true; 1988 line = line.substring(0, (line.length()-1)).trim(); } 1990 else 1991 continued = false; 1992 1993 loadVector(dependencies, line.split(" ")); 1994 } 1995 1996 if (soft) 1997 { 1998 String [] temp = (String [])dependencies.toArray(new String [0]); 1999 dependencies = new Vector(); 2000 for (int I = 0; I < temp.length; I++) 2001 { 2002 if ((new File(m_workingDir, temp[I])).exists()) 2003 dependencies.add(temp[I]); 2004 } 2005 } 2006 2007 for (int I = 0; I < targets.length; I++) 2008 { 2009 createExplicitDependency(targets[I].replace('\\', '/'), (String [])dependencies.toArray(new String [0])); 2010 } 2011 } 2012 br.close(); 2013 } 2014 catch (Exception e) 2015 { 2016 } 2017 } 2018 2019 } 2020 2021 2025 public void clearMakeRules() 2026 { 2027 m_rules.clear(); 2028 m_dependencies.clear(); 2029 } 2030 2031 2038 public void include(String fileName) 2039 throws CPMakeException 2040 { 2041 File f = new File(m_workingDir, fileName); 2042 2043 buildTarget(fileName, false); 2045 try 2046 { 2047 m_interpreter.source(fileName); 2048 } 2049 catch (Exception e) {} } 2051 2052 2063 public static String [] substitute(String srcPattern, String destPattern, String [] srcList) 2064 { 2065 String [] dest = new String [srcList.length]; 2066 2067 for (int I = 0; I < srcList.length; I++) 2068 { 2069 dest[I] = srcList[I].replaceAll(srcPattern, destPattern); 2070 } 2071 2072 return (dest); 2073 } 2074 2075 2081 public void mkdir(String directory) 2082 { 2083 File f = new File(m_workingDir, directory); 2084 f.mkdirs(); 2085 } 2086 2087 2094 public String fullPath(String relPath) 2095 { 2096 File f = new File(m_workingDir, relPath); 2097 return(f.getAbsolutePath()); 2098 } 2099 2100 2106 public static void throwException(String msg) 2107 throws CPMakeException 2108 { 2109 throw new CPMakeException(msg, -1); 2110 } 2111 2112 private boolean isInCleanDir(String target) 2114 { 2115 Iterator it = m_autoCleanDirs.iterator(); 2116 String dir; 2117 2118 while (it.hasNext()) 2120 { 2121 dir = (String )it.next(); 2122 2123 if (target.startsWith(dir)) 2124 return (true); 2125 } 2126 2127 return (false); 2128 } 2129 2130 private void getTargets(Set targets, Set phonies, String target, Rule rule) 2132 throws CPMakeException 2133 { 2134 String [] prereqs; 2135 Rule pRule; 2136 boolean addSuccess; 2137 2138 prereqs = getPrerequisites(target, rule, false); 2139 for (int I = 0; I < prereqs.length; I++) 2140 { 2141 pRule = getRule(prereqs[I]); 2142 if (pRule != null) 2143 { 2144 if (pRule instanceof PhonyRule) 2145 addSuccess = phonies.add(prereqs[I]); 2146 else 2147 addSuccess = targets.add(prereqs[I]); 2148 2149 if (addSuccess) 2150 getTargets(targets, phonies, prereqs[I], pRule); 2151 } 2152 } 2153 } 2154 2155 2163 public void autoClean() 2164 throws CPMakeException 2165 { 2166 Vector delFiles = new Vector(); 2167 Iterator it; 2168 Set targets = new HashSet(); 2169 Set phonies = new HashSet(); 2170 Rule rule; 2171 String target; 2172 File file; 2173 2174 it = m_rules.iterator(); 2175 while (it.hasNext()) 2176 { 2177 rule = (Rule)it.next(); 2178 target = null; 2179 2180 if (rule instanceof PhonyRule) 2181 { 2182 target = ((PhonyRule)rule).getTarget(); 2183 phonies.add(target); 2184 } 2185 else if (rule instanceof ExplicitRule) 2186 { 2187 target = ((ExplicitRule)rule).getTarget(); 2188 targets.add(target); 2189 } 2190 2191 if (target != null) 2192 { 2193 getTargets(targets, phonies, target, rule); 2194 target = null; 2195 } 2196 } 2197 2198 it = targets.iterator(); 2199 while (it.hasNext()) 2200 { 2201 target = (String )it.next(); 2202 if (!isInCleanDir(fullPath(target))) 2204 delFiles.add(target); 2205 } 2206 2207 it = delFiles.iterator(); 2208 while (it.hasNext()) 2209 { 2210 target = (String )it.next(); 2211 file = new File(m_workingDir, target); 2213 if (file.exists()) 2214 { 2215 System.out.println("Removing "+target); 2216 file.delete(); 2217 } 2218 } 2219 2220 it = m_autoCleanDirs.iterator(); 2221 while (it.hasNext()) 2222 { 2223 target = (String )it.next(); 2224 file = new File(target); 2226 if (file.exists()) 2227 { 2228 System.out.println("Cleaning "+target); 2229 deltree(target); 2230 } 2231 } 2232 2233 } 2234 2235 2240 public static String [] combine(String [] arr1, String [] arr2) 2241 { 2242 String [] ret = new String [arr1.length + arr2.length]; 2243 2244 System.arraycopy(arr1, 0, ret, 0, arr1.length); 2245 System.arraycopy(arr2, 0, ret, arr1.length, arr2.length); 2246 2247 return (ret); 2248 } 2249 2250 2256 public File getWorkingDirectory() 2257 { 2258 return (m_workingDir); 2259 } 2260 2261 2267 public void setObject(String name, Object obj) 2268 { 2269 m_scriptObjects.put(name, obj); 2270 } 2271 2272 2275 private static final Class [] parameters = new Class [] {URL.class}; 2276 public void addClassPath(String path) 2277 throws CPMakeException 2278 { 2279 URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader(); 2280 Class sysclass = URLClassLoader.class; 2281 2282 try 2283 { 2284 Method method = sysclass.getDeclaredMethod("addURL",parameters); 2285 method.setAccessible(true); 2286 method.invoke(sysloader,new Object []{ new File(path).toURL() }); 2287 } 2288 catch (Throwable t) 2289 { 2290 t.printStackTrace(); 2291 throw new CPMakeException("Error, could not add URL to system classloader", -1); 2292 } 2293 } 2294 } 2295 2296 | Popular Tags |