/** 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); }