| author | wenzelm | 
| Fri, 07 Dec 2012 16:33:17 +0100 | |
| changeset 50423 | 027d405951c8 | 
| parent 50414 | e17a1f179bb0 | 
| child 50566 | b43c4f660320 | 
| permissions | -rw-r--r-- | 
| 48276 | 1 | /* Title: Pure/System/build.scala | 
| 2 | Author: Makarius | |
| 50367 | 3 | Options: :folding=explicit:collapseFolds=1: | 
| 48276 | 4 | |
| 5 | Build and manage Isabelle sessions. | |
| 6 | */ | |
| 7 | ||
| 8 | package isabelle | |
| 9 | ||
| 10 | ||
| 48661 | 11 | import java.util.{Timer, TimerTask}
 | 
| 48548 | 12 | import java.io.{BufferedInputStream, FileInputStream,
 | 
| 48494 | 13 | BufferedReader, InputStreamReader, IOException} | 
| 14 | import java.util.zip.GZIPInputStream | |
| 48335 | 15 | |
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 16 | import scala.collection.SortedSet | 
| 48340 
6f4fc030882a
allow explicit specification of additional session directories;
 wenzelm parents: 
48339diff
changeset | 17 | import scala.annotation.tailrec | 
| 48337 
9c7f8e5805b4
cumulate semantic Session_Info, based on syntactic Session_Entry;
 wenzelm parents: 
48336diff
changeset | 18 | |
| 48335 | 19 | |
| 48276 | 20 | object Build | 
| 21 | {
 | |
| 50366 | 22 | /** progress context **/ | 
| 23 | ||
| 50367 | 24 |   class Progress {
 | 
| 25 |     def echo(msg: String) {}
 | |
| 26 | def stopped: Boolean = false | |
| 50366 | 27 | } | 
| 28 | ||
| 50367 | 29 | object Ignore_Progress extends Progress | 
| 50366 | 30 | |
| 31 |   object Console_Progress extends Progress {
 | |
| 32 |     override def echo(msg: String) { java.lang.System.out.println(msg) }
 | |
| 33 | } | |
| 34 | ||
| 35 | ||
| 36 | ||
| 48337 
9c7f8e5805b4
cumulate semantic Session_Info, based on syntactic Session_Entry;
 wenzelm parents: 
48336diff
changeset | 37 | /** session information **/ | 
| 48334 | 38 | |
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 39 | // external version | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 40 | sealed case class Session_Entry( | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 41 | pos: Position.T, | 
| 48738 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 42 | name: String, | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 43 | groups: List[String], | 
| 48738 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 44 | path: String, | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 45 | parent: Option[String], | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 46 | description: String, | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 47 | options: List[Options.Spec], | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 48 | theories: List[(List[Options.Spec], List[String])], | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 49 | files: List[String]) | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 50 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 51 | // internal version | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 52 | sealed case class Session_Info( | 
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 53 | select: Boolean, | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 54 | pos: Position.T, | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 55 | groups: List[String], | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 56 | dir: Path, | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 57 | parent: Option[String], | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 58 | description: String, | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 59 | options: Options, | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 60 | theories: List[(Options, List[Path])], | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 61 | files: List[Path], | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 62 | entry_digest: SHA1.Digest) | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 63 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 64 | def is_pure(name: String): Boolean = name == "RAW" || name == "Pure" | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 65 | |
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 66 | def session_info(options: Options, select: Boolean, dir: Path, entry: Session_Entry) | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 67 | : (String, Session_Info) = | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 68 |     try {
 | 
| 48738 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 69 | val name = entry.name | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 70 | |
| 48738 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 71 |       if (name == "") error("Bad session name")
 | 
| 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 72 |       if (is_pure(name) && entry.parent.isDefined) error("Illegal parent session")
 | 
| 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 73 |       if (!is_pure(name) && !entry.parent.isDefined) error("Missing parent session")
 | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 74 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 75 | val session_options = options ++ entry.options | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 76 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 77 | val theories = | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 78 |         entry.theories.map({ case (opts, thys) =>
 | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 79 | (session_options ++ opts, thys.map(Path.explode(_))) }) | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 80 | val files = entry.files.map(Path.explode(_)) | 
| 48738 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 81 | val entry_digest = SHA1.digest((name, entry.parent, entry.options, entry.theories).toString) | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 82 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 83 | val info = | 
| 48738 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 84 | Session_Info(select, entry.pos, entry.groups, dir + Path.explode(entry.path), | 
| 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 85 | entry.parent, entry.description, session_options, theories, files, entry_digest) | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 86 | |
| 48738 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 87 | (name, info) | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 88 | } | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 89 |     catch {
 | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 90 | case ERROR(msg) => | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 91 | error(msg + "\nThe error(s) above occurred in session entry " + | 
| 48992 | 92 | quote(entry.name) + Position.here(entry.pos)) | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 93 | } | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 94 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 95 | |
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 96 | /* session tree */ | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 97 | |
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 98 | object Session_Tree | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 99 |   {
 | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 100 | def apply(infos: Seq[(String, Session_Info)]): Session_Tree = | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 101 |     {
 | 
| 48680 | 102 | val graph1 = | 
| 103 |         (Graph.string[Session_Info] /: infos) {
 | |
| 48684 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 104 | case (graph, (name, info)) => | 
| 48680 | 105 | if (graph.defined(name)) | 
| 48992 | 106 |               error("Duplicate session " + quote(name) + Position.here(info.pos))
 | 
| 48680 | 107 | else graph.new_node(name, info) | 
| 108 | } | |
| 109 | val graph2 = | |
| 110 |         (graph1 /: graph1.entries) {
 | |
| 111 | case (graph, (name, (info, _))) => | |
| 112 |             info.parent match {
 | |
| 113 | case None => graph | |
| 114 | case Some(parent) => | |
| 115 | if (!graph.defined(parent)) | |
| 116 |                   error("Bad parent session " + quote(parent) + " for " +
 | |
| 48992 | 117 | quote(name) + Position.here(info.pos)) | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 118 | |
| 48680 | 119 |                 try { graph.add_edge_acyclic(parent, name) }
 | 
| 120 |                 catch {
 | |
| 121 | case exn: Graph.Cycles[_] => | |
| 122 | error(cat_lines(exn.cycles.map(cycle => | |
| 123 | "Cyclic session dependency of " + | |
| 124 |                         cycle.map(c => quote(c.toString)).mkString(" via "))) +
 | |
| 48992 | 125 | Position.here(info.pos)) | 
| 48680 | 126 | } | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 127 | } | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 128 | } | 
| 48680 | 129 | new Session_Tree(graph2) | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 130 | } | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 131 | } | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 132 | |
| 48680 | 133 | final class Session_Tree private(val graph: Graph[String, Session_Info]) | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 134 | extends PartialFunction[String, Session_Info] | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 135 |   {
 | 
| 48680 | 136 | def apply(name: String): Session_Info = graph.get_node(name) | 
| 137 | def isDefinedAt(name: String): Boolean = graph.defined(name) | |
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 138 | |
| 49131 | 139 | def selection(requirements: Boolean, all_sessions: Boolean, | 
| 140 | session_groups: List[String], sessions: List[String]): (List[String], Session_Tree) = | |
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 141 |     {
 | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 142 | val bad_sessions = sessions.filterNot(isDefinedAt(_)) | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 143 |       if (!bad_sessions.isEmpty) error("Undefined session(s): " + commas_quote(bad_sessions))
 | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 144 | |
| 49131 | 145 | val pre_selected = | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 146 |       {
 | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 147 | if (all_sessions) graph.keys.toList | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 148 |         else {
 | 
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 149 | val select_group = session_groups.toSet | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 150 | val select = sessions.toSet | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 151 |           (for {
 | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 152 | (name, (info, _)) <- graph.entries | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 153 | if info.select || select(name) || apply(name).groups.exists(select_group) | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 154 | } yield name).toList | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 155 | } | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 156 | } | 
| 49131 | 157 | val selected = | 
| 158 | if (requirements) (graph.all_preds(pre_selected).toSet -- pre_selected).toList | |
| 159 | else pre_selected | |
| 160 | ||
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 161 | val tree1 = new Session_Tree(graph.restrict(graph.all_preds(selected).toSet)) | 
| 49131 | 162 | (selected, tree1) | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 163 | } | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 164 | |
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 165 | def topological_order: List[(String, Session_Info)] = | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 166 | graph.topological_order.map(name => (name, apply(name))) | 
| 48794 | 167 | |
| 168 |     override def toString: String = graph.entries.map(_._1).toList.sorted.mkString(",")
 | |
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 169 | } | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 170 | |
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 171 | |
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 172 | /* parser */ | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 173 | |
| 48713 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48710diff
changeset | 174 | private val SESSION = "session" | 
| 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48710diff
changeset | 175 | private val IN = "in" | 
| 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48710diff
changeset | 176 | private val DESCRIPTION = "description" | 
| 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48710diff
changeset | 177 | private val OPTIONS = "options" | 
| 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48710diff
changeset | 178 | private val THEORIES = "theories" | 
| 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48710diff
changeset | 179 | private val FILES = "files" | 
| 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48710diff
changeset | 180 | |
| 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48710diff
changeset | 181 | lazy val root_syntax = | 
| 48738 
f8c1a5b9488f
simplified session specifications: names are taken verbatim and current directory is default;
 wenzelm parents: 
48737diff
changeset | 182 |     Outer_Syntax.init() + "(" + ")" + "+" + "," + "=" + "[" + "]" +
 | 
| 48718 | 183 | (SESSION, Keyword.THY_DECL) + IN + DESCRIPTION + OPTIONS + THEORIES + FILES | 
| 48713 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48710diff
changeset | 184 | |
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 185 | private object Parser extends Parse.Parser | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 186 |   {
 | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 187 | def session_entry(pos: Position.T): Parser[Session_Entry] = | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 188 |     {
 | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 189 |       val session_name = atom("session name", _.is_name)
 | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 190 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 191 | val option = | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 192 |         name ~ opt(keyword("=") ~! name ^^ { case _ ~ x => x }) ^^ { case x ~ y => (x, y) }
 | 
| 48862 | 193 |       val options = keyword("[") ~> rep1sep(option, keyword(",")) <~ keyword("]")
 | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 194 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 195 | val theories = | 
| 48739 | 196 | keyword(THEORIES) ~! ((options | success(Nil)) ~ rep(theory_name)) ^^ | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 197 |           { case _ ~ (x ~ y) => (x, y) }
 | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 198 | |
| 48912 | 199 | command(SESSION) ~! | 
| 200 | (session_name ~ | |
| 201 |           ((keyword("(") ~! (rep1(name) <~ keyword(")")) ^^ { case _ ~ x => x }) | success(Nil)) ~
 | |
| 202 |           ((keyword(IN) ~! path ^^ { case _ ~ x => x }) | success(".")) ~
 | |
| 203 |           (keyword("=") ~!
 | |
| 204 |             (opt(session_name ~! keyword("+") ^^ { case x ~ _ => x }) ~
 | |
| 205 |               ((keyword(DESCRIPTION) ~! text ^^ { case _ ~ x => x }) | success("")) ~
 | |
| 206 |               ((keyword(OPTIONS) ~! options ^^ { case _ ~ x => x }) | success(Nil)) ~
 | |
| 48916 | 207 | rep1(theories) ~ | 
| 48912 | 208 |               ((keyword(FILES) ~! rep1(path) ^^ { case _ ~ x => x }) | success(Nil))))) ^^
 | 
| 209 |         { case _ ~ (a ~ b ~ c ~ (_ ~ (d ~ e ~ f ~ g ~ h))) =>
 | |
| 210 | Session_Entry(pos, a, b, c, d, e, f, g, h) } | |
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 211 | } | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 212 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 213 | def parse_entries(root: Path): List[Session_Entry] = | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 214 |     {
 | 
| 48713 
de26cf3191a3
more token markers, based on actual outer syntax;
 wenzelm parents: 
48710diff
changeset | 215 | val toks = root_syntax.scan(File.read(root)) | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 216 |       parse_all(rep(session_entry(root.position)), Token.reader(toks, root.implode)) match {
 | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 217 | case Success(result, _) => result | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 218 | case bad => error(bad.toString) | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 219 | } | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 220 | } | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 221 | } | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 222 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 223 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 224 | /* find sessions within certain directories */ | 
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 225 | |
| 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 226 |   private val ROOT = Path.explode("ROOT")
 | 
| 48684 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 227 |   private val ROOTS = Path.explode("ROOTS")
 | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 228 | |
| 48684 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 229 | private def is_session_dir(dir: Path): Boolean = | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 230 | (dir + ROOT).is_file || (dir + ROOTS).is_file | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 231 | |
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 232 | private def check_session_dir(dir: Path): Path = | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 233 | if (is_session_dir(dir)) dir | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 234 |     else error("Bad session root directory: " + dir.toString)
 | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 235 | |
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 236 | def find_sessions(options: Options, more_dirs: List[(Boolean, Path)]): Session_Tree = | 
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 237 |   {
 | 
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 238 | def find_dir(select: Boolean, dir: Path): List[(String, Session_Info)] = | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 239 | find_root(select, dir) ::: find_roots(select, dir) | 
| 48684 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 240 | |
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 241 | def find_root(select: Boolean, dir: Path): List[(String, Session_Info)] = | 
| 48684 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 242 |     {
 | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 243 | val root = dir + ROOT | 
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 244 | if (root.is_file) Parser.parse_entries(root).map(session_info(options, select, dir, _)) | 
| 48684 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 245 | else Nil | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 246 | } | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 247 | |
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 248 | def find_roots(select: Boolean, dir: Path): List[(String, Session_Info)] = | 
| 48684 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 249 |     {
 | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 250 | val roots = dir + ROOTS | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 251 |       if (roots.is_file) {
 | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 252 |         for {
 | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 253 | line <- split_lines(File.read(roots)) | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 254 |           if !(line == "" || line.startsWith("#"))
 | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 255 | dir1 = | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 256 |             try { check_session_dir(dir + Path.explode(line)) }
 | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 257 |             catch {
 | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 258 | case ERROR(msg) => | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 259 | error(msg + "\nThe error(s) above occurred in session catalog " + roots.toString) | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 260 | } | 
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 261 | info <- find_dir(select, dir1) | 
| 48684 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 262 | } yield info | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 263 | } | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 264 | else Nil | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 265 | } | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 266 | |
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 267 | val default_dirs = Isabelle_System.components().filter(is_session_dir(_)).map((false, _)) | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 268 | |
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 269 |     more_dirs foreach { case (_, dir) => check_session_dir(dir) }
 | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 270 | |
| 48684 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 271 | Session_Tree( | 
| 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 272 |       for {
 | 
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 273 | (select, dir) <- default_dirs ::: more_dirs | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 274 | info <- find_dir(select, dir) | 
| 48684 
9170e10c651e
re-introduced ROOTS catalog files (cf. 47330b712f8f) which help to organize AFP or make -d options persistent;
 wenzelm parents: 
48680diff
changeset | 275 | } yield info) | 
| 48349 
a78e5d399599
support Session.Queue with ordering and dependencies;
 wenzelm parents: 
48347diff
changeset | 276 | } | 
| 48334 | 277 | |
| 48337 
9c7f8e5805b4
cumulate semantic Session_Info, based on syntactic Session_Entry;
 wenzelm parents: 
48336diff
changeset | 278 | |
| 48424 | 279 | |
| 280 | /** build **/ | |
| 281 | ||
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 282 | /* queue */ | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 283 | |
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 284 | object Queue | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 285 |   {
 | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 286 | def apply(tree: Session_Tree): Queue = | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 287 |     {
 | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 288 | val graph = tree.graph | 
| 48678 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 289 | |
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 290 | def outdegree(name: String): Int = graph.imm_succs(name).size | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 291 |       def timeout(name: String): Double = tree(name).options.real("timeout")
 | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 292 | |
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 293 | object Ordering extends scala.math.Ordering[String] | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 294 |       {
 | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 295 | def compare(name1: String, name2: String): Int = | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 296 |           outdegree(name2) compare outdegree(name1) match {
 | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 297 | case 0 => | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 298 |               timeout(name2) compare timeout(name1) match {
 | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 299 | case 0 => name1 compare name2 | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 300 | case ord => ord | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 301 | } | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 302 | case ord => ord | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 303 | } | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 304 | } | 
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 305 | |
| 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 306 | new Queue(graph, SortedSet(graph.keys.toList: _*)(Ordering)) | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 307 | } | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 308 | } | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 309 | |
| 48680 | 310 | final class Queue private(graph: Graph[String, Session_Info], order: SortedSet[String]) | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 311 |   {
 | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 312 | def is_inner(name: String): Boolean = !graph.is_maximal(name) | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 313 | |
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 314 | def is_empty: Boolean = graph.is_empty | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 315 | |
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 316 | def - (name: String): Queue = new Queue(graph.del_node(name), order - name) | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 317 | |
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 318 | def dequeue(skip: String => Boolean): Option[(String, Session_Info)] = | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 319 |     {
 | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 320 | val it = order.iterator.dropWhile(name => skip(name) || !graph.is_minimal(name)) | 
| 48680 | 321 |       if (it.hasNext) { val name = it.next; Some((name, graph.get_node(name))) }
 | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 322 | else None | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 323 | } | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 324 | } | 
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 325 | |
| 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 326 | |
| 48710 
5b51ccdc8623
prefer static Build.session_content for loaded theories -- discontinued incremental protocol;
 wenzelm parents: 
48708diff
changeset | 327 | /* source dependencies and static content */ | 
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 328 | |
| 48710 
5b51ccdc8623
prefer static Build.session_content for loaded theories -- discontinued incremental protocol;
 wenzelm parents: 
48708diff
changeset | 329 | sealed case class Session_Content( | 
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 330 | loaded_theories: Set[String], | 
| 48660 
730ca503e955
static outer syntax based on session specifications;
 wenzelm parents: 
48650diff
changeset | 331 | syntax: Outer_Syntax, | 
| 48794 | 332 | sources: List[(Path, SHA1.Digest)], | 
| 333 | errors: List[String]) | |
| 334 |   {
 | |
| 335 | def check_errors: Session_Content = | |
| 336 |     {
 | |
| 337 | if (errors.isEmpty) this | |
| 338 | else error(cat_lines(errors)) | |
| 339 | } | |
| 340 | } | |
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 341 | |
| 48710 
5b51ccdc8623
prefer static Build.session_content for loaded theories -- discontinued incremental protocol;
 wenzelm parents: 
48708diff
changeset | 342 | sealed case class Deps(deps: Map[String, Session_Content]) | 
| 48423 
0ccf143a2a69
maintain set of source digests, including relevant parts of session entry;
 wenzelm parents: 
48422diff
changeset | 343 |   {
 | 
| 48583 | 344 | def is_empty: Boolean = deps.isEmpty | 
| 48710 
5b51ccdc8623
prefer static Build.session_content for loaded theories -- discontinued incremental protocol;
 wenzelm parents: 
48708diff
changeset | 345 | def apply(name: String): Session_Content = deps(name) | 
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 346 | def sources(name: String): List[SHA1.Digest] = deps(name).sources.map(_._2) | 
| 48423 
0ccf143a2a69
maintain set of source digests, including relevant parts of session entry;
 wenzelm parents: 
48422diff
changeset | 347 | } | 
| 
0ccf143a2a69
maintain set of source digests, including relevant parts of session entry;
 wenzelm parents: 
48422diff
changeset | 348 | |
| 50366 | 349 | def dependencies(progress: Build.Progress, inlined_files: Boolean, | 
| 350 | verbose: Boolean, list_files: Boolean, tree: Session_Tree): Deps = | |
| 48710 
5b51ccdc8623
prefer static Build.session_content for loaded theories -- discontinued incremental protocol;
 wenzelm parents: 
48708diff
changeset | 351 | Deps((Map.empty[String, Session_Content] /: tree.topological_order)( | 
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 352 |       { case (deps, (name, info)) =>
 | 
| 48794 | 353 | val (preloaded, parent_syntax, parent_errors) = | 
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 354 |             info.parent match {
 | 
| 48870 
4accee106f0f
clarified initialization of Thy_Load, Thy_Info, Session;
 wenzelm parents: 
48867diff
changeset | 355 | case None => | 
| 
4accee106f0f
clarified initialization of Thy_Load, Thy_Info, Session;
 wenzelm parents: 
48867diff
changeset | 356 | (Set.empty[String], Outer_Syntax.init_pure(), Nil) | 
| 48794 | 357 | case Some(parent_name) => | 
| 358 | val parent = deps(parent_name) | |
| 359 | (parent.loaded_theories, parent.syntax, parent.errors) | |
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 360 | } | 
| 48870 
4accee106f0f
clarified initialization of Thy_Load, Thy_Info, Session;
 wenzelm parents: 
48867diff
changeset | 361 | val thy_info = new Thy_Info(new Thy_Load(preloaded, parent_syntax)) | 
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 362 | |
| 48903 | 363 |           if (verbose || list_files) {
 | 
| 48583 | 364 | val groups = | 
| 365 | if (info.groups.isEmpty) "" | |
| 366 |               else info.groups.mkString(" (", " ", ")")
 | |
| 50366 | 367 |             progress.echo("Session " + name + groups)
 | 
| 48583 | 368 | } | 
| 48478 | 369 | |
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 370 | val thy_deps = | 
| 49098 
673e0ed547af
bypass slow check for inlined files, where it is not really required;
 wenzelm parents: 
48992diff
changeset | 371 | thy_info.dependencies(inlined_files, | 
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 372 | info.theories.map(_._2).flatten. | 
| 50204 
daeb1674fb91
tuned signature -- avoid intrusion of module Path in generic PIDE concepts;
 wenzelm parents: 
50203diff
changeset | 373 | map(thy => Thy_Load.external_node(info.dir + Thy_Load.thy_path(thy)))) | 
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 374 | |
| 48872 | 375 | val loaded_theories = thy_deps.loaded_theories | 
| 48883 | 376 | val syntax = thy_deps.make_syntax | 
| 48660 
730ca503e955
static outer syntax based on session specifications;
 wenzelm parents: 
48650diff
changeset | 377 | |
| 48423 
0ccf143a2a69
maintain set of source digests, including relevant parts of session entry;
 wenzelm parents: 
48422diff
changeset | 378 | val all_files = | 
| 50414 
e17a1f179bb0
explore theory_body_files via future, for improved performance;
 wenzelm parents: 
50404diff
changeset | 379 |             (thy_deps.deps.map({ case dep =>
 | 
| 
e17a1f179bb0
explore theory_body_files via future, for improved performance;
 wenzelm parents: 
50404diff
changeset | 380 | val thy = Path.explode(dep.name.node) | 
| 
e17a1f179bb0
explore theory_body_files via future, for improved performance;
 wenzelm parents: 
50404diff
changeset | 381 | val uses = dep.join_header.uses.map(p => | 
| 
e17a1f179bb0
explore theory_body_files via future, for improved performance;
 wenzelm parents: 
50404diff
changeset | 382 | Path.explode(dep.name.dir) + Path.explode(p._1)) | 
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 383 | thy :: uses | 
| 48904 | 384 | }).flatten ::: info.files.map(file => info.dir + file)).map(_.expand) | 
| 48903 | 385 | |
| 386 | if (list_files) | |
| 50366 | 387 |             progress.echo(cat_lines(all_files.map(_.implode).sorted.map("  " + _)))
 | 
| 48903 | 388 | |
| 48485 | 389 | val sources = | 
| 49696 | 390 |             try { all_files.map(p => (p, SHA1.digest(p.file))) }
 | 
| 48485 | 391 |             catch {
 | 
| 392 | case ERROR(msg) => | |
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 393 | error(msg + "\nThe error(s) above occurred in session " + | 
| 48992 | 394 | quote(name) + Position.here(info.pos)) | 
| 48485 | 395 | } | 
| 50414 
e17a1f179bb0
explore theory_body_files via future, for improved performance;
 wenzelm parents: 
50404diff
changeset | 396 | val errors = parent_errors ::: thy_deps.deps.map(dep => dep.join_header.errors).flatten | 
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 397 | |
| 48794 | 398 | deps + (name -> Session_Content(loaded_theories, syntax, sources, errors)) | 
| 48423 
0ccf143a2a69
maintain set of source digests, including relevant parts of session entry;
 wenzelm parents: 
48422diff
changeset | 399 | })) | 
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 400 | |
| 49098 
673e0ed547af
bypass slow check for inlined files, where it is not really required;
 wenzelm parents: 
48992diff
changeset | 401 | def session_content(inlined_files: Boolean, dirs: List[Path], session: String): Session_Content = | 
| 48710 
5b51ccdc8623
prefer static Build.session_content for loaded theories -- discontinued incremental protocol;
 wenzelm parents: 
48708diff
changeset | 402 |   {
 | 
| 50404 
898cac1dad5e
avoid startup within GUI thread -- it is only required later for dialog;
 wenzelm parents: 
50367diff
changeset | 403 | val options = Options.init() | 
| 48791 | 404 | val (_, tree) = | 
| 49131 | 405 | find_sessions(options, dirs.map((false, _))).selection(false, false, Nil, List(session)) | 
| 50366 | 406 | dependencies(Build.Ignore_Progress, inlined_files, false, false, tree)(session) | 
| 48710 
5b51ccdc8623
prefer static Build.session_content for loaded theories -- discontinued incremental protocol;
 wenzelm parents: 
48708diff
changeset | 407 | } | 
| 
5b51ccdc8623
prefer static Build.session_content for loaded theories -- discontinued incremental protocol;
 wenzelm parents: 
48708diff
changeset | 408 | |
| 48794 | 409 | def outer_syntax(session: String): Outer_Syntax = | 
| 49098 
673e0ed547af
bypass slow check for inlined files, where it is not really required;
 wenzelm parents: 
48992diff
changeset | 410 | session_content(false, Nil, session).check_errors.syntax | 
| 48710 
5b51ccdc8623
prefer static Build.session_content for loaded theories -- discontinued incremental protocol;
 wenzelm parents: 
48708diff
changeset | 411 | |
| 48422 
9613780a805b
determine source dependencies, relatively to preloaded theories;
 wenzelm parents: 
48421diff
changeset | 412 | |
| 48424 | 413 | /* jobs */ | 
| 48341 | 414 | |
| 48675 
10f5303f86e5
clarified Session_Entry vs. Session_Info with related parsing operations;
 wenzelm parents: 
48674diff
changeset | 415 | private class Job(name: String, info: Session_Info, output: Path, do_output: Boolean, | 
| 48674 | 416 | verbose: Boolean, browser_info: Path) | 
| 48418 | 417 |   {
 | 
| 48467 
a4318c36a829
more precise propagation of options: build, session, theories;
 wenzelm parents: 
48462diff
changeset | 418 | // global browser info dir | 
| 48674 | 419 |     if (info.options.bool("browser_info") && !(browser_info + Path.explode("index.html")).is_file)
 | 
| 48467 
a4318c36a829
more precise propagation of options: build, session, theories;
 wenzelm parents: 
48462diff
changeset | 420 |     {
 | 
| 
a4318c36a829
more precise propagation of options: build, session, theories;
 wenzelm parents: 
48462diff
changeset | 421 | browser_info.file.mkdirs() | 
| 
a4318c36a829
more precise propagation of options: build, session, theories;
 wenzelm parents: 
48462diff
changeset | 422 |       File.copy(Path.explode("~~/lib/logo/isabelle.gif"),
 | 
| 
a4318c36a829
more precise propagation of options: build, session, theories;
 wenzelm parents: 
48462diff
changeset | 423 |         browser_info + Path.explode("isabelle.gif"))
 | 
| 
a4318c36a829
more precise propagation of options: build, session, theories;
 wenzelm parents: 
48462diff
changeset | 424 |       File.write(browser_info + Path.explode("index.html"),
 | 
| 
a4318c36a829
more precise propagation of options: build, session, theories;
 wenzelm parents: 
48462diff
changeset | 425 |         File.read(Path.explode("~~/lib/html/library_index_header.template")) +
 | 
| 48724 | 426 |         File.read(Path.explode("~~/lib/html/library_index_content.template")) +
 | 
| 48467 
a4318c36a829
more precise propagation of options: build, session, theories;
 wenzelm parents: 
48462diff
changeset | 427 |         File.read(Path.explode("~~/lib/html/library_index_footer.template")))
 | 
| 
a4318c36a829
more precise propagation of options: build, session, theories;
 wenzelm parents: 
48462diff
changeset | 428 | } | 
| 
a4318c36a829
more precise propagation of options: build, session, theories;
 wenzelm parents: 
48462diff
changeset | 429 | |
| 48674 | 430 | def output_path: Option[Path] = if (do_output) Some(output) else None | 
| 431 | ||
| 432 |     private val parent = info.parent.getOrElse("")
 | |
| 48418 | 433 | |
| 48698 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 434 |     private val args_file = File.tmp_file("args")
 | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 435 | File.write(args_file, YXML.string_of_body( | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 436 | if (is_pure(name)) Options.encode(info.options) | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 437 | else | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 438 |         {
 | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 439 | import XML.Encode._ | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 440 | pair(bool, pair(Options.encode, pair(bool, pair(Path.encode, pair(string, | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 441 | pair(string, list(pair(Options.encode, list(Path.encode)))))))))( | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 442 | (do_output, (info.options, (verbose, (browser_info, (parent, | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 443 | (name, info.theories))))))) | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 444 | })) | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 445 | |
| 48674 | 446 | private val env = | 
| 48698 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 447 |       Map("INPUT" -> parent, "TARGET" -> name, "OUTPUT" -> Isabelle_System.standard_path(output),
 | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 448 | (if (is_pure(name)) "ISABELLE_PROCESS_OPTIONS" else "ARGS_FILE") -> | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 449 | Isabelle_System.posix_path(args_file.getPath)) | 
| 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 450 | |
| 48674 | 451 | private val script = | 
| 48511 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 452 |       if (is_pure(name)) {
 | 
| 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 453 | if (do_output) "./build " + name + " \"$OUTPUT\"" | 
| 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 454 | else """ rm -f "$OUTPUT"; ./build """ + name | 
| 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 455 | } | 
| 48418 | 456 |       else {
 | 
| 457 | """ | |
| 458 | . "$ISABELLE_HOME/lib/scripts/timestart.bash" | |
| 459 | """ + | |
| 48511 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 460 | (if (do_output) | 
| 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 461 | """ | 
| 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 462 | "$ISABELLE_PROCESS" -e "Build.build \"$ARGS_FILE\";" -q -w "$INPUT" "$OUTPUT" | 
| 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 463 | """ | 
| 48418 | 464 | else | 
| 48511 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 465 | """ | 
| 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 466 | rm -f "$OUTPUT"; "$ISABELLE_PROCESS" -e "Build.build \"$ARGS_FILE\";" -r -q "$INPUT" | 
| 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 467 | """) + | 
| 48418 | 468 | """ | 
| 469 | RC="$?" | |
| 470 | ||
| 471 | . "$ISABELLE_HOME/lib/scripts/timestop.bash" | |
| 472 | ||
| 473 | if [ "$RC" -eq 0 ]; then | |
| 474 | echo "Finished $TARGET ($TIMES_REPORT)" >&2 | |
| 475 | fi | |
| 476 | ||
| 477 | exit "$RC" | |
| 478 | """ | |
| 479 | } | |
| 48674 | 480 | |
| 481 | private val (thread, result) = | |
| 48698 
2585042b1a30
pass Isabelle/Scala system options into ML process of Isar tty or build jobs;
 wenzelm parents: 
48684diff
changeset | 482 |       Simple_Thread.future("build") { Isabelle_System.bash_env(info.dir.file, env, script) }
 | 
| 48674 | 483 | |
| 484 | def terminate: Unit = thread.interrupt | |
| 485 | def is_finished: Boolean = result.is_finished | |
| 486 | ||
| 487 | @volatile private var timeout = false | |
| 50207 | 488 |     private val time = info.options.seconds("timeout")
 | 
| 48674 | 489 | private val timer: Option[Timer] = | 
| 490 |       if (time.seconds > 0.0) {
 | |
| 491 |         val t = new Timer("build", true)
 | |
| 492 |         t.schedule(new TimerTask { def run = { terminate; timeout = true } }, time.ms)
 | |
| 493 | Some(t) | |
| 494 | } | |
| 495 | else None | |
| 496 | ||
| 497 |     def join: (String, String, Int) = {
 | |
| 498 | val (out, err, rc) = result.join | |
| 499 | args_file.delete | |
| 500 | timer.map(_.cancel()) | |
| 501 | ||
| 502 | val err1 = | |
| 503 | if (rc == 130) | |
| 504 |           (if (err.isEmpty || err.endsWith("\n")) err else err + "\n") +
 | |
| 505 | (if (timeout) "*** Timeout\n" else "*** Interrupt\n") | |
| 506 | else err | |
| 507 | (out, err1, rc) | |
| 508 | } | |
| 48364 | 509 | } | 
| 510 | ||
| 48424 | 511 | |
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 512 | /* log files and corresponding heaps */ | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 513 | |
| 48505 | 514 |   private val LOG = Path.explode("log")
 | 
| 515 | private def log(name: String): Path = LOG + Path.basic(name) | |
| 516 |   private def log_gz(name: String): Path = log(name).ext("gz")
 | |
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 517 | |
| 48505 | 518 | private def sources_stamp(digests: List[SHA1.Digest]): String = | 
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 519 |     digests.map(_.toString).sorted.mkString("sources: ", " ", "")
 | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 520 | |
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 521 | private val no_heap: String = "heap: -" | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 522 | |
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 523 | private def heap_stamp(heap: Option[Path]): String = | 
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 524 |   {
 | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 525 | "heap: " + | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 526 |       (heap match {
 | 
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 527 | case Some(path) => | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 528 | val file = path.file | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 529 | if (file.isFile) file.length.toString + " " + file.lastModified.toString | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 530 | else "-" | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 531 | case None => "-" | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 532 | }) | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 533 | } | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 534 | |
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 535 | private def read_stamps(path: Path): Option[(String, String, String)] = | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 536 |     if (path.is_file) {
 | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 537 | val stream = new GZIPInputStream (new BufferedInputStream(new FileInputStream(path.file))) | 
| 50203 | 538 | val reader = new BufferedReader(new InputStreamReader(stream, UTF8.charset)) | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 539 | val (s, h1, h2) = | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 540 |         try { (reader.readLine, reader.readLine, reader.readLine) }
 | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 541 |         finally { reader.close }
 | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 542 |       if (s != null && s.startsWith("sources: ") &&
 | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 543 |           h1 != null && h1.startsWith("heap: ") &&
 | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 544 |           h2 != null && h2.startsWith("heap: ")) Some((s, h1, h2))
 | 
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 545 | else None | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 546 | } | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 547 | else None | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 548 | |
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 549 | |
| 48425 | 550 | /* build */ | 
| 48424 | 551 | |
| 48509 | 552 | def build( | 
| 50366 | 553 | progress: Build.Progress, | 
| 50404 
898cac1dad5e
avoid startup within GUI thread -- it is only required later for dialog;
 wenzelm parents: 
50367diff
changeset | 554 | options: Options, | 
| 49131 | 555 | requirements: Boolean = false, | 
| 48509 | 556 | all_sessions: Boolean = false, | 
| 48511 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 557 | build_heap: Boolean = false, | 
| 48595 | 558 | clean_build: Boolean = false, | 
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 559 | more_dirs: List[(Boolean, Path)] = Nil, | 
| 48509 | 560 | session_groups: List[String] = Nil, | 
| 561 | max_jobs: Int = 1, | |
| 48903 | 562 | list_files: Boolean = false, | 
| 48509 | 563 | no_build: Boolean = false, | 
| 564 | system_mode: Boolean = false, | |
| 565 | verbose: Boolean = false, | |
| 566 | sessions: List[String] = Nil): Int = | |
| 48341 | 567 |   {
 | 
| 49131 | 568 | val full_tree = find_sessions(options, more_dirs) | 
| 569 | val (selected, selected_tree) = | |
| 570 | full_tree.selection(requirements, all_sessions, session_groups, sessions) | |
| 571 | ||
| 50366 | 572 | val deps = dependencies(progress, true, verbose, list_files, selected_tree) | 
| 49131 | 573 | val queue = Queue(selected_tree) | 
| 48368 | 574 | |
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 575 | def make_stamp(name: String): String = | 
| 49131 | 576 | sources_stamp(selected_tree(name).entry_digest :: deps.sources(name)) | 
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 577 | |
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 578 | val (input_dirs, output_dir, browser_info) = | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 579 |       if (system_mode) {
 | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 580 |         val output_dir = Path.explode("~~/heaps/$ML_IDENTIFIER")
 | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 581 |         (List(output_dir), output_dir, Path.explode("~~/browser_info"))
 | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 582 | } | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 583 |       else {
 | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 584 |         val output_dir = Path.explode("$ISABELLE_OUTPUT")
 | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 585 | (output_dir :: Isabelle_System.find_logics_dirs(), output_dir, | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 586 |          Path.explode("$ISABELLE_BROWSER_INFO"))
 | 
| 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 587 | } | 
| 48363 | 588 | |
| 48373 | 589 | // prepare log dir | 
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 590 | (output_dir + LOG).file.mkdirs() | 
| 48373 | 591 | |
| 48595 | 592 | // optional cleanup | 
| 593 |     if (clean_build) {
 | |
| 49131 | 594 |       for (name <- full_tree.graph.all_succs(selected)) {
 | 
| 48595 | 595 | val files = | 
| 596 | List(Path.basic(name), log(name), log_gz(name)).map(output_dir + _).filter(_.is_file) | |
| 50366 | 597 |         if (!files.isEmpty) progress.echo("Cleaning " + name + " ...")
 | 
| 598 | if (!files.forall(p => p.file.delete)) progress.echo(name + " FAILED to delete") | |
| 48595 | 599 | } | 
| 600 | } | |
| 601 | ||
| 48425 | 602 | // scheduler loop | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 603 | case class Result(current: Boolean, heap: String, rc: Int) | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 604 | |
| 50366 | 605 | def sleep(): Unit = Thread.sleep(500) | 
| 606 | ||
| 48425 | 607 | @tailrec def loop( | 
| 48676 
3ef82491cdd6
clarified Session_Tree (with proper integrity check) vs. Queue (with provision for alternative ordering);
 wenzelm parents: 
48675diff
changeset | 608 | pending: Queue, | 
| 48674 | 609 | running: Map[String, (String, Job)], | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 610 | results: Map[String, Result]): Map[String, Result] = | 
| 48425 | 611 |     {
 | 
| 612 | if (pending.is_empty) results | |
| 50367 | 613 |       else if (progress.stopped) {
 | 
| 614 | for ((_, (_, job)) <- running) job.terminate | |
| 615 | sleep(); loop(pending, running, results) | |
| 616 | } | |
| 48547 | 617 | else | 
| 48674 | 618 |         running.find({ case (_, (_, job)) => job.is_finished }) match {
 | 
| 619 | case Some((name, (parent_heap, job))) => | |
| 50367 | 620 |             //{{{ finish job
 | 
| 48424 | 621 | |
| 48547 | 622 | val (out, err, rc) = job.join | 
| 50366 | 623 | progress.echo(Library.trim_line(err)) | 
| 48373 | 624 | |
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 625 | val heap = | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 626 |               if (rc == 0) {
 | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 627 | (output_dir + log(name)).file.delete | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 628 | |
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 629 | val sources = make_stamp(name) | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 630 | val heap = heap_stamp(job.output_path) | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 631 | File.write_gzip(output_dir + log_gz(name), | 
| 48674 | 632 | sources + "\n" + parent_heap + "\n" + heap + "\n" + out) | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 633 | |
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 634 | heap | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 635 | } | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 636 |               else {
 | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 637 | (output_dir + Path.basic(name)).file.delete | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 638 | (output_dir + log_gz(name)).file.delete | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 639 | |
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 640 | File.write(output_dir + log(name), out) | 
| 50366 | 641 | progress.echo(name + " FAILED") | 
| 48661 | 642 |                 if (rc != 130) {
 | 
| 50366 | 643 |                   progress.echo("(see also " + (output_dir + log(name)).file.toString + ")")
 | 
| 48661 | 644 | val lines = split_lines(out) | 
| 645 | val tail = lines.drop(lines.length - 20 max 0) | |
| 50366 | 646 |                   progress.echo("\n" + cat_lines(tail))
 | 
| 48661 | 647 | } | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 648 | |
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 649 | no_heap | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 650 | } | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 651 | loop(pending - name, running - name, results + (name -> Result(false, heap, rc))) | 
| 50367 | 652 | //}}} | 
| 48547 | 653 | case None if (running.size < (max_jobs max 1)) => | 
| 50367 | 654 |             //{{{ check/start next job
 | 
| 48547 | 655 |             pending.dequeue(running.isDefinedAt(_)) match {
 | 
| 656 | case Some((name, info)) => | |
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 657 | val parent_result = | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 658 |                   info.parent match {
 | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 659 | case None => Result(true, no_heap, 0) | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 660 | case Some(parent) => results(parent) | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 661 | } | 
| 48547 | 662 | val output = output_dir + Path.basic(name) | 
| 663 | val do_output = build_heap || queue.is_inner(name) | |
| 664 | ||
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 665 | val (current, heap) = | 
| 48547 | 666 |                 {
 | 
| 48548 | 667 |                   input_dirs.find(dir => (dir + log_gz(name)).is_file) match {
 | 
| 48547 | 668 | case Some(dir) => | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 669 |                       read_stamps(dir + log_gz(name)) match {
 | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 670 | case Some((s, h1, h2)) => | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 671 | val heap = heap_stamp(Some(dir + Path.basic(name))) | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 672 | (s == make_stamp(name) && h1 == parent_result.heap && h2 == heap && | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 673 | !(do_output && heap == no_heap), heap) | 
| 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 674 | case None => (false, no_heap) | 
| 48547 | 675 | } | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 676 | case None => (false, no_heap) | 
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 677 | } | 
| 48547 | 678 | } | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 679 | val all_current = current && parent_result.current | 
| 48528 
784c6f63d79c
proper all_current, which regards parent status as well;
 wenzelm parents: 
48511diff
changeset | 680 | |
| 48547 | 681 | if (all_current) | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 682 | loop(pending - name, running, results + (name -> Result(true, heap, 0))) | 
| 48678 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 683 |                 else if (no_build) {
 | 
| 50366 | 684 |                   if (verbose) progress.echo("Skipping " + name + " ...")
 | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 685 | loop(pending - name, running, results + (name -> Result(false, heap, 1))) | 
| 48678 
ff27af15530c
queue ordering by descending outdegree and timeout;
 wenzelm parents: 
48676diff
changeset | 686 | } | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 687 |                 else if (parent_result.rc == 0) {
 | 
| 50366 | 688 | progress.echo((if (do_output) "Building " else "Running ") + name + " ...") | 
| 48674 | 689 | val job = new Job(name, info, output, do_output, verbose, browser_info) | 
| 690 | loop(pending, running + (name -> (parent_result.heap, job)), results) | |
| 48547 | 691 | } | 
| 692 |                 else {
 | |
| 50366 | 693 | progress.echo(name + " CANCELLED") | 
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 694 | loop(pending - name, running, results + (name -> Result(false, heap, 1))) | 
| 48547 | 695 | } | 
| 696 | case None => sleep(); loop(pending, running, results) | |
| 48425 | 697 | } | 
| 50367 | 698 | ///}}} | 
| 48425 | 699 | case None => sleep(); loop(pending, running, results) | 
| 48373 | 700 | } | 
| 48425 | 701 | } | 
| 702 | ||
| 48583 | 703 | val results = | 
| 704 |       if (deps.is_empty) {
 | |
| 50366 | 705 |         progress.echo("### Nothing to build")
 | 
| 48583 | 706 | Map.empty | 
| 707 | } | |
| 708 | else loop(queue, Map.empty, Map.empty) | |
| 709 | ||
| 48639 
675988e64bf9
store parent heap stamp as well -- needs to be propagated through the build hierarchy;
 wenzelm parents: 
48626diff
changeset | 710 |     val rc = (0 /: results)({ case (rc1, (_, res)) => rc1 max res.rc })
 | 
| 48504 
21dfd6c04482
actually check source vs. target stamps, based on information from log files;
 wenzelm parents: 
48494diff
changeset | 711 |     if (rc != 0 && (verbose || !no_build)) {
 | 
| 48552 | 712 | val unfinished = | 
| 49951 | 713 | (for ((name, res) <- results.iterator if res.rc != 0) yield name).toList | 
| 714 | .sorted(scala.math.Ordering.String) // FIXME scala-2.10.0-RC1 | |
| 50366 | 715 |       progress.echo("Unfinished session(s): " + commas(unfinished))
 | 
| 48473 | 716 | } | 
| 717 | rc | |
| 48341 | 718 | } | 
| 719 | ||
| 720 | ||
| 48346 
e2382bede914
more general support for Isabelle/Scala command line tools;
 wenzelm parents: 
48344diff
changeset | 721 | /* command line entry point */ | 
| 48341 | 722 | |
| 723 | def main(args: Array[String]) | |
| 724 |   {
 | |
| 48346 
e2382bede914
more general support for Isabelle/Scala command line tools;
 wenzelm parents: 
48344diff
changeset | 725 |     Command_Line.tool {
 | 
| 
e2382bede914
more general support for Isabelle/Scala command line tools;
 wenzelm parents: 
48344diff
changeset | 726 |       args.toList match {
 | 
| 
e2382bede914
more general support for Isabelle/Scala command line tools;
 wenzelm parents: 
48344diff
changeset | 727 | case | 
| 49131 | 728 | Properties.Value.Boolean(requirements) :: | 
| 48346 
e2382bede914
more general support for Isabelle/Scala command line tools;
 wenzelm parents: 
48344diff
changeset | 729 | Properties.Value.Boolean(all_sessions) :: | 
| 48511 
37999ee01156
remove old output heaps, to ensure that result is valid wrt. check_stamps;
 wenzelm parents: 
48509diff
changeset | 730 | Properties.Value.Boolean(build_heap) :: | 
| 48595 | 731 | Properties.Value.Boolean(clean_build) :: | 
| 48425 | 732 | Properties.Value.Int(max_jobs) :: | 
| 48903 | 733 | Properties.Value.Boolean(list_files) :: | 
| 48469 | 734 | Properties.Value.Boolean(no_build) :: | 
| 48447 
ef600ce4559c
added system build mode: produce output in ISABELLE_HOME;
 wenzelm parents: 
48425diff
changeset | 735 | Properties.Value.Boolean(system_mode) :: | 
| 48425 | 736 | Properties.Value.Boolean(verbose) :: | 
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 737 | Command_Line.Chunks(select_dirs, include_dirs, session_groups, build_options, sessions) => | 
| 50404 
898cac1dad5e
avoid startup within GUI thread -- it is only required later for dialog;
 wenzelm parents: 
50367diff
changeset | 738 | val options = (Options.init() /: build_options)(_ + _) | 
| 48737 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 739 | val dirs = | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 740 | select_dirs.map(d => (true, Path.explode(d))) ::: | 
| 
f3bbb9ca57d6
added build option -D: include session directory and select its sessions;
 wenzelm parents: 
48724diff
changeset | 741 | include_dirs.map(d => (false, Path.explode(d))) | 
| 50404 
898cac1dad5e
avoid startup within GUI thread -- it is only required later for dialog;
 wenzelm parents: 
50367diff
changeset | 742 | build(Build.Console_Progress, options, requirements, all_sessions, build_heap, | 
| 
898cac1dad5e
avoid startup within GUI thread -- it is only required later for dialog;
 wenzelm parents: 
50367diff
changeset | 743 | clean_build, dirs, session_groups, max_jobs, list_files, no_build, system_mode, | 
| 50366 | 744 | verbose, sessions) | 
| 48346 
e2382bede914
more general support for Isabelle/Scala command line tools;
 wenzelm parents: 
48344diff
changeset | 745 |         case _ => error("Bad arguments:\n" + cat_lines(args))
 | 
| 48341 | 746 | } | 
| 48346 
e2382bede914
more general support for Isabelle/Scala command line tools;
 wenzelm parents: 
48344diff
changeset | 747 | } | 
| 48341 | 748 | } | 
| 48276 | 749 | } | 
| 750 |