src/Pure/System/build.scala
changeset 48509 4854ced3e9d7
parent 48508 5a59e4c03957
child 48511 37999ee01156
equal deleted inserted replaced
48508:5a59e4c03957 48509:4854ced3e9d7
    23   {
    23   {
    24     /* Info */
    24     /* Info */
    25 
    25 
    26     sealed case class Info(
    26     sealed case class Info(
    27       base_name: String,
    27       base_name: String,
       
    28       groups: List[String],
    28       dir: Path,
    29       dir: Path,
    29       parent: Option[String],
    30       parent: Option[String],
    30       parent_base_name: Option[String],
    31       parent_base_name: Option[String],
    31       description: String,
    32       description: String,
    32       options: Options,
    33       options: Options,
    63                   cycle.map(c => quote(c.toString)).mkString(" via "))))
    64                   cycle.map(c => quote(c.toString)).mkString(" via "))))
    64           })
    65           })
    65 
    66 
    66       def - (name: String): Queue = new Queue(graph.del_node(name))
    67       def - (name: String): Queue = new Queue(graph.del_node(name))
    67 
    68 
    68       def required(names: List[String]): Queue =
    69       def required(groups: List[String], names: List[String]): Queue =
    69         new Queue(graph.restrict(graph.all_preds(names).toSet))
    70       {
       
    71         val selected_group = groups.toSet
       
    72         val selected_name = names.toSet
       
    73         val selected =
       
    74           graph.keys.filter(name =>
       
    75             selected_name(name) || apply(name).groups.exists(selected_group)).toList
       
    76         new Queue(graph.restrict(graph.all_preds(selected).toSet))
       
    77       }
    70 
    78 
    71       def dequeue(skip: String => Boolean): Option[(String, Info)] =
    79       def dequeue(skip: String => Boolean): Option[(String, Info)] =
    72       {
    80       {
    73         val it = graph.entries.dropWhile(
    81         val it = graph.entries.dropWhile(
    74           { case (name, (_, (deps, _))) => !deps.isEmpty || skip(name) })
    82           { case (name, (_, (deps, _))) => !deps.isEmpty || skip(name) })
    85   /* parsing */
    93   /* parsing */
    86 
    94 
    87   private case class Session_Entry(
    95   private case class Session_Entry(
    88     name: String,
    96     name: String,
    89     this_name: Boolean,
    97     this_name: Boolean,
       
    98     groups: List[String],
    90     path: Option[String],
    99     path: Option[String],
    91     parent: Option[String],
   100     parent: Option[String],
    92     description: String,
   101     description: String,
    93     options: List[Options.Spec],
   102     options: List[Options.Spec],
    94     theories: List[(List[Options.Spec], List[String])],
   103     theories: List[(List[Options.Spec], List[String])],
   119         keyword(THEORIES) ~! ((options | success(Nil)) ~ rep1(theory_name)) ^^
   128         keyword(THEORIES) ~! ((options | success(Nil)) ~ rep1(theory_name)) ^^
   120           { case _ ~ (x ~ y) => (x, y) }
   129           { case _ ~ (x ~ y) => (x, y) }
   121 
   130 
   122       ((keyword(SESSION) ~! session_name) ^^ { case _ ~ x => x }) ~
   131       ((keyword(SESSION) ~! session_name) ^^ { case _ ~ x => x }) ~
   123         (keyword("!") ^^^ true | success(false)) ~
   132         (keyword("!") ^^^ true | success(false)) ~
       
   133         (keyword("(") ~! (rep1(name) <~ keyword(")")) ^^ { case _ ~ x => x } | success(Nil)) ~
   124         (opt(keyword(IN) ~! string ^^ { case _ ~ x => x })) ~
   134         (opt(keyword(IN) ~! string ^^ { case _ ~ x => x })) ~
   125         (keyword("=") ~> opt(session_name <~ keyword("+"))) ~
   135         (keyword("=") ~> opt(session_name <~ keyword("+"))) ~
   126         (keyword(DESCRIPTION) ~! text ^^ { case _ ~ x => x } | success("")) ~
   136         (keyword(DESCRIPTION) ~! text ^^ { case _ ~ x => x } | success("")) ~
   127         (keyword(OPTIONS) ~! options ^^ { case _ ~ x => x } | success(Nil)) ~
   137         (keyword(OPTIONS) ~! options ^^ { case _ ~ x => x } | success(Nil)) ~
   128         rep(theories) ~
   138         rep(theories) ~
   129         (keyword(FILES) ~! rep1(path) ^^ { case _ ~ x => x } | success(Nil)) ^^
   139         (keyword(FILES) ~! rep1(path) ^^ { case _ ~ x => x } | success(Nil)) ^^
   130           { case a ~ b ~ c ~ d ~ e ~ f ~ g ~ h => Session_Entry(a, b, c, d, e, f, g, h) }
   140           { case a ~ b ~ c ~ d ~ e ~ f ~ g ~ h ~ i => Session_Entry(a, b, c, d, e, f, g, h, i) }
   131     }
   141     }
   132 
   142 
   133     def parse_entries(root: JFile): List[Session_Entry] =
   143     def parse_entries(root: JFile): List[Session_Entry] =
   134     {
   144     {
   135       val toks = syntax.scan(File.read(root))
   145       val toks = syntax.scan(File.read(root))
   184             (session_options ++ opts, thys.map(Path.explode(_))) })
   194             (session_options ++ opts, thys.map(Path.explode(_))) })
   185         val files = entry.files.map(Path.explode(_))
   195         val files = entry.files.map(Path.explode(_))
   186         val digest = SHA1.digest((full_name, entry.parent, entry.options, entry.theories).toString)
   196         val digest = SHA1.digest((full_name, entry.parent, entry.options, entry.theories).toString)
   187 
   197 
   188         val info =
   198         val info =
   189           Session.Info(entry.name, dir + path, entry.parent, parent_base_name,
   199           Session.Info(entry.name, entry.groups, dir + path, entry.parent, parent_base_name,
   190             entry.description, session_options, theories, files, digest)
   200             entry.description, session_options, theories, files, digest)
   191 
   201 
   192         queue1 + (full_name, info)
   202         queue1 + (full_name, info)
   193       }
   203       }
   194       catch {
   204       catch {
   222         case ERROR(msg) =>
   232         case ERROR(msg) =>
   223           error(msg + "\nThe error(s) above occurred in session catalog " + quote(catalog.toString))
   233           error(msg + "\nThe error(s) above occurred in session catalog " + quote(catalog.toString))
   224       })
   234       })
   225   }
   235   }
   226 
   236 
   227   def find_sessions(options: Options, all_sessions: Boolean, sessions: List[String],
   237   def find_sessions(options: Options, more_dirs: List[Path],
   228     more_dirs: List[Path]): Session.Queue =
   238     all_sessions: Boolean, session_groups: List[String], sessions: List[String]): Session.Queue =
   229   {
   239   {
   230     var queue = Session.Queue.empty
   240     var queue = Session.Queue.empty
   231 
   241 
   232     for (dir <- Isabelle_System.components()) {
   242     for (dir <- Isabelle_System.components()) {
   233       queue = sessions_dir(options, false, dir, queue)
   243       queue = sessions_dir(options, false, dir, queue)
   242     sessions.filter(name => !queue.isDefinedAt(name)) match {
   252     sessions.filter(name => !queue.isDefinedAt(name)) match {
   243       case Nil =>
   253       case Nil =>
   244       case bad => error("Undefined session(s): " + commas_quote(bad))
   254       case bad => error("Undefined session(s): " + commas_quote(bad))
   245     }
   255     }
   246 
   256 
   247     if (all_sessions) queue else queue.required(sessions)
   257     if (all_sessions) queue else queue.required(session_groups, sessions)
   248   }
   258   }
   249 
   259 
   250 
   260 
   251 
   261 
   252   /** build **/
   262   /** build **/
   417   }
   427   }
   418 
   428 
   419 
   429 
   420   /* build */
   430   /* build */
   421 
   431 
   422   def build(all_sessions: Boolean, build_images: Boolean, max_jobs: Int,
   432   def build(
   423     no_build: Boolean, system_mode: Boolean, timing: Boolean, verbose: Boolean,
   433     all_sessions: Boolean = false,
   424     more_dirs: List[Path], more_options: List[String], sessions: List[String]): Int =
   434     build_images: Boolean = false,
   425   {
   435     more_dirs: List[Path] = Nil,
   426     val options = (Options.init() /: more_options)(_.define_simple(_))
   436     session_groups: List[String] = Nil,
   427     val queue = find_sessions(options, all_sessions, sessions, more_dirs)
   437     max_jobs: Int = 1,
       
   438     no_build: Boolean = false,
       
   439     build_options: List[String] = Nil,
       
   440     system_mode: Boolean = false,
       
   441     timing: Boolean = false,
       
   442     verbose: Boolean = false,
       
   443     sessions: List[String] = Nil): Int =
       
   444   {
       
   445     val options = (Options.init() /: build_options)(_.define_simple(_))
       
   446     val queue = find_sessions(options, more_dirs, all_sessions, session_groups, sessions)
   428     val deps = dependencies(verbose, queue)
   447     val deps = dependencies(verbose, queue)
   429 
   448 
   430     def make_stamp(name: String): String =
   449     def make_stamp(name: String): String =
   431       sources_stamp(queue(name).digest :: deps.sources(name))
   450       sources_stamp(queue(name).digest :: deps.sources(name))
   432 
   451 
   532           Properties.Value.Int(max_jobs) ::
   551           Properties.Value.Int(max_jobs) ::
   533           Properties.Value.Boolean(no_build) ::
   552           Properties.Value.Boolean(no_build) ::
   534           Properties.Value.Boolean(system_mode) ::
   553           Properties.Value.Boolean(system_mode) ::
   535           Properties.Value.Boolean(timing) ::
   554           Properties.Value.Boolean(timing) ::
   536           Properties.Value.Boolean(verbose) ::
   555           Properties.Value.Boolean(verbose) ::
   537           Command_Line.Chunks(more_dirs, options, sessions) =>
   556           Command_Line.Chunks(more_dirs, session_groups, build_options, sessions) =>
   538             build(all_sessions, build_images, max_jobs, no_build, system_mode, timing,
   557             build(all_sessions, build_images, more_dirs.map(Path.explode), session_groups,
   539               verbose, more_dirs.map(Path.explode), options, sessions)
   558               max_jobs, no_build, build_options, system_mode, timing, verbose, sessions)
   540         case _ => error("Bad arguments:\n" + cat_lines(args))
   559         case _ => error("Bad arguments:\n" + cat_lines(args))
   541       }
   560       }
   542     }
   561     }
   543   }
   562   }
   544 }
   563 }