// --------------------------------------------------------------------------- private void printDependencies() throws TablesawException { m_printedDependencies = new HashSet<String>(); try { PrintWriter pw = new PrintWriter(new FileWriter("dependency.txt")); pw.println("Targets marked with a * have already been printed"); // Create a reduced set of stuff to print Set<String> ruleNames = new HashSet<String>(); for (String name : m_nameRuleMap.keySet()) ruleNames.add(name); for (String name : m_nameRuleMap.keySet()) { Rule rule = m_nameRuleMap.get(name); for (String dep : rule.getDependNames()) ruleNames.remove(dep); for (Rule dep : rule.getDependRules()) { if (dep.getName() != null) ruleNames.remove(dep.getName()); } } for (String name : ruleNames) { if (!name.startsWith(NAMED_RULE_PREFIX)) printDependencies(name, pw, 0); } pw.close(); } catch (IOException ioe) { throw new TablesawException("Cannot write to file dependency.txt", -1); } }
// --------------------------------------------------------------------------- public void addRule(Rule rule) { Debug.print("AddRule() " + rule.getName() + " " + rule); // do not get the rule name as it may not be set yet // rules are added often in the constructor when other values // have not been set yet. // todo: Get a list of provides and consumes annotations m_ruleList.add(rule); Class ruleClass = rule.getClass(); DependencyAnnotations da = m_classAnnotations.get(ruleClass); if (da == null) m_classAnnotations.put(ruleClass, createDependencyAnnotations(ruleClass)); }
// --------------------------------------------------------------------------- private void printDependencies(String target, PrintWriter pw, int spacing) throws TablesawException { Rule tr = findTargetRule(target); String[] pre; for (int I = 0; I < spacing; I++) pw.print("\t"); List<String> targetList = new ArrayList<String>(); if (tr != null) { for (String name : tr.getDependNames()) { targetList.add(name); } for (Rule r : tr.getDependRules()) { if ((r.getName() != null) && (!r.getName().startsWith(NAMED_RULE_PREFIX))) { targetList.add(r.getName()); } else { for (String t : r.getTargets()) { targetList.add(t); } } } } if (!m_printedDependencies.add(target) && (targetList.size() != 0)) { pw.println(target + "*"); return; } pw.println(target); for (String t : targetList) printDependencies(t, pw, spacing + 1); }
// --------------------------------------------------------------------------- private void addRule(String key, Rule rule) throws TablesawException { Debug.print("Adding rule for " + key); Rule old = m_targetRuleMap.put(key, rule); if ((old != null) && (!rule.getOverride()) && (!(old instanceof Overridable))) throw new TablesawException( "Duplicate rules for " + key + " rule1: " + old + " rule2: " + rule, 1); }
/** * This fills in the m_targetRuleMap. The keys are the names of the rules and the targets they * produce */ private void resolveRules() throws TablesawException { for (Rule rule : m_ruleList) { // Add rule by name if it has one String name = rule.getName(); if (name != null) { Debug.print("Adding rule name: " + name); Rule namedRule = m_nameRuleMap.get(name); if (namedRule == null) { m_nameRuleMap.put(name, rule); } /*else if (namedRule instanceof CompoundNameRule) { ((CompoundNameRule)namedRule).addDepends(rule); }*/ else if ((namedRule instanceof Overridable) || (rule.getOverride())) { m_nameRuleMap.put(name, rule); } else { throw new TablesawException( "Multiple rules exist for '" + name + "'. Call Rule.override() if you wish to override an existing rule."); /*System.out.println("GGGGGGGGGGGGGGGGGGGAAAAAAAAAAAAAHHHHHHHHHHH"); CompoundNameRule cnr = new CompoundNameRule(name); cnr.addDepends(namedRule); cnr.addDepends(rule); m_nameRuleMap.put(name, cnr);*/ } } // Add rule by each target it declares Iterable<String> targets = rule.getTargets(); for (String t : targets) { Debug.print("Add target " + t); addRule(t, rule); } } m_resolved = true; }
/** Method to process the build queue, can be called by more than one thread */ public void processBuildQueue() throws TablesawException { BuildAction ba; Rule rule; String target; synchronized (m_threadList) { m_threadList.add(Thread.currentThread()); } try { doloop: do { synchronized (this) { try { ba = (BuildAction) m_buildQueue.removeLast(); } catch (NoSuchElementException nsee) { break doloop; // ba = new BuildAction(m_fileManager, null); } if (m_printDebug) Debug.print("Processing: " + ba); if (m_makeException != null) break doloop; ba.waitForDependencies(); if (m_makeException != null) break doloop; } rule = ba.getTargetRule(); MakeAction action = rule.getMakeAction(); // target = ba.getTarget(); if (action != null) { action.doMakeAction(rule); rule.verify(); } Debug.print("COMPLETE - " + ba); ba.complete(); // Complete the BuildAction } while (m_makeException == null); } catch (Exception e) { TablesawException cpe; if (e instanceof TablesawException) cpe = (TablesawException) e; else cpe = new TablesawException(e); synchronized (this) { m_makeException = cpe; for (Thread t : m_threadList) t.interrupt(); } throw cpe; } // This causes worker threads to die off and the exception to // pass to the main thread if (m_makeException != null) throw m_makeException; }
// --------------------------------------------------------------------------- private BuildAction addToBuildQueue(String target, boolean primaryTarget, int insertPosition) throws TablesawException { // The target was already checked and does not need to be built if (m_noBuildCache.contains(target)) return (null); Debug.print("addToBuildQueue(" + target + ", " + primaryTarget + ", " + insertPosition + ")"); Debug.indent(); Rule trule = findTargetRule(target); CachedFile targetFile = null; BuildAction[] buildDep = null; BuildAction targetBA = null; BuildAction depBA = null; BuildAction ret = null; if (trule == null) { targetFile = m_fileManager.locateFile(target); // TODO: Add the rule that required this target to the error message if (targetFile == null) throw new TablesawException("Unable to locate rule for '" + target + "'"); if (m_sourceFiles != null) m_sourceFiles.add( new File( targetFile.getPath())); // Doing this because locateFile will return a CachedFile // TODO: check file against cache file stamps and if changed return dummy rule Debug.print("Cache lookup for " + targetFile.getPath()); // Add file to cache for next run m_newModificationCache.put(targetFile.getPath(), targetFile.lastModified()); Long cacheModTime = m_modificationCache.get(targetFile.getPath()); if (cacheModTime != null) { Debug.print("Cache hit " + cacheModTime + ":" + targetFile.lastModified()); if (cacheModTime != targetFile.lastModified()) { Debug.print("returning obj for " + targetFile); Debug.popIndent(); targetBA = new BuildAction( m_fileManager, new ModifiedFileRule(targetFile.getPath()), m_classAnnotations); m_buildQueue.add(insertPosition, targetBA); return (targetBA); } } else Debug.print("Cache miss"); // System.out.println("File "+targetFile); m_noBuildCache.add(target); Debug.print("Target " + target + " is a file with no rule"); Debug.popIndent(); return (null); } if ((m_sourceFiles != null) && (trule instanceof SourceFileSet)) { m_sourceFiles.addAll(((SourceFileSet) trule).getSourceFiles()); } long targetTime = 0; boolean tExists = true; boolean tDir = false; boolean tPhony = true; boolean rebuild = false; targetBA = new BuildAction(m_fileManager, trule, m_classAnnotations); int index; if (m_buildQueueCache.containsKey(targetBA)) { // Get the build action from the queue targetBA = m_buildQueueCache.get(targetBA); Debug.print("target: " + trule + " already in build queue."); // Target has already been added to build queue Debug.popIndent(); return (targetBA); } File f; trule.preBuild(m_depCache, m_modificationCache); // NOTE: need to add in dependencies that are individually declared // NOTE: getPrerequisites is also where dependency parsing happens to include C headers and // other java classes // String[] prereqs = getPrerequisites(trule, true); List<String> prereqs = new ArrayList<String>(); for (String dn : trule.getDependNames()) { Debug.print("adding depend name " + dn); prereqs.add(dn); } for (Rule r : trule.getDependRules()) { Debug.print("adding depend rule " + r); if (r.getName() == null) { // Generate name for rule String genRuleName = NAMED_RULE_PREFIX + (m_ruleNameCounter++); r.setName(genRuleName); m_nameRuleMap.put(genRuleName, r); } prereqs.add(r.getName()); } Debug.print("rule dependents " + prereqs.size()); if (prereqs.size() > 0) { ListIterator<String> it = prereqs.listIterator(); while (it.hasNext()) { String prereq = it.next(); if (prereq.equals(target)) throw new TablesawException("Target " + target + " depends on itself"); /* //See if the prereq is the name of a rule first Rule nameRule = m_nameRuleMap.get(prereq); //Add the new rule targets to the prereqs list // TODO: some kind of check so we dont add the same named rule again and again. if (nameRule != null) { Iterable<String> ruleTargets = nameRule.getTargets(); boolean hasTargets = false; for (String t : ruleTargets) { hasTargets = true; it.add(t); it.previous(); } if (hasTargets) continue; } */ // Add dependencies to build queue first. // f = m_fileManager.getFile(prereq); if ((depBA = addToBuildQueue(prereq, false, insertPosition)) != null) { targetBA.addDependency(depBA); // trule.addNewerDepend(prereq); if (depBA.isBinding()) { Debug.print("Rebuild: " + trule + " because rebuild of " + depBA.getTargetRule()); rebuild = true; } } } } if (!rebuild) { rebuild = trule.needToRun(); Debug.print("Rule needToRun() returned " + rebuild); } // TODO: change this to get depends from above and check if no depends if ((!rebuild) && (primaryTarget && (!trule .getTargets() .iterator() .hasNext()))) { // If target is the primary target and it has no targets Debug.print("Adding primary target: " + trule + " to build queue."); rebuild = true; } if (rebuild) { // Add target to build queue m_buildQueue.add(insertPosition, targetBA); m_buildQueueCache.put(targetBA, targetBA); Debug.print("Adding " + targetBA + " to build queue at pos " + insertPosition); // System.out.println("Adding "+targetBA+" to build queue at pos "+insertPosition); ret = targetBA; } // Add target to cache if it does not need to be built // This is to speed up incremental builds if (ret == null) m_noBuildCache.add(target); Debug.popIndent(); return (ret); }