src/Pure/Tools/build.scala
changeset 51399 6ac3c29a300e
parent 51397 03b586ee5930
child 51402 b05cd411d3d3
equal deleted inserted replaced
51398:c3d02b3518c2 51399:6ac3c29a300e
   495       if (is_pure(name)) Options.encode(info.options)
   495       if (is_pure(name)) Options.encode(info.options)
   496       else
   496       else
   497         {
   497         {
   498           import XML.Encode._
   498           import XML.Encode._
   499               pair(list(properties), pair(bool, pair(Options.encode, pair(bool, pair(Path.encode,
   499               pair(list(properties), pair(bool, pair(Options.encode, pair(bool, pair(Path.encode,
   500                 pair(string, pair(string, list(pair(Options.encode, list(Path.encode))))))))))(
   500                 pair(string, pair(string, pair(string,
       
   501                   list(pair(Options.encode, list(Path.encode)))))))))))(
   501               (command_timings, (do_output, (info.options, (verbose, (browser_info,
   502               (command_timings, (do_output, (info.options, (verbose, (browser_info,
   502                 (parent, (name, info.theories))))))))
   503                 (parent, (info.chapter, (name, info.theories)))))))))
   503         }))
   504         }))
   504 
   505 
   505     private val env =
   506     private val env =
   506       Map("INPUT" -> parent, "TARGET" -> name, "OUTPUT" -> Isabelle_System.standard_path(output),
   507       Map("INPUT" -> parent, "TARGET" -> name, "OUTPUT" -> Isabelle_System.standard_path(output),
   507         (if (is_pure(name)) "ISABELLE_PROCESS_OPTIONS" else "ARGS_FILE") ->
   508         (if (is_pure(name)) "ISABELLE_PROCESS_OPTIONS" else "ARGS_FILE") ->
   593   private val LOG = Path.explode("log")
   594   private val LOG = Path.explode("log")
   594   private def log(name: String): Path = LOG + Path.basic(name)
   595   private def log(name: String): Path = LOG + Path.basic(name)
   595   private def log_gz(name: String): Path = log(name).ext("gz")
   596   private def log_gz(name: String): Path = log(name).ext("gz")
   596 
   597 
   597   private val SESSION_NAME = "\fSession.name = "
   598   private val SESSION_NAME = "\fSession.name = "
   598   private val SESSION_PARENT_PATH = "\fSession.parent_path = "
       
   599 
   599 
   600 
   600 
   601   sealed case class Log_Info(
   601   sealed case class Log_Info(
   602     name: String,
   602     name: String,
   603     stats: List[Properties.T],
   603     stats: List[Properties.T],
   752         if (!files.forall(p => p.file.delete)) progress.echo(name + " FAILED to delete")
   752         if (!files.forall(p => p.file.delete)) progress.echo(name + " FAILED to delete")
   753       }
   753       }
   754     }
   754     }
   755 
   755 
   756     // scheduler loop
   756     // scheduler loop
   757     case class Result(current: Boolean, parent_path: Option[String], heap: String, rc: Int)
   757     case class Result(current: Boolean, heap: String, rc: Int)
   758 
   758 
   759     def sleep(): Unit = Thread.sleep(500)
   759     def sleep(): Unit = Thread.sleep(500)
   760 
   760 
   761     @tailrec def loop(
   761     @tailrec def loop(
   762       pending: Queue,
   762       pending: Queue,
   773             //{{{ finish job
   773             //{{{ finish job
   774 
   774 
   775             val res = job.join
   775             val res = job.join
   776             progress.echo(res.err)
   776             progress.echo(res.err)
   777 
   777 
   778             val (parent_path, heap) =
   778             val heap =
   779               if (res.rc == 0) {
   779               if (res.rc == 0) {
   780                 (output_dir + log(name)).file.delete
   780                 (output_dir + log(name)).file.delete
   781 
   781 
   782                 val sources = make_stamp(name)
   782                 val sources = make_stamp(name)
   783                 val heap = heap_stamp(job.output_path)
   783                 val heap = heap_stamp(job.output_path)
   784                 File.write_gzip(output_dir + log_gz(name),
   784                 File.write_gzip(output_dir + log_gz(name),
   785                   sources + "\n" + parent_heap + "\n" + heap + "\n" + res.out)
   785                   sources + "\n" + parent_heap + "\n" + heap + "\n" + res.out)
   786 
   786 
   787                 val parent_path =
   787                 heap
   788                   if (job.info.options.bool("browser_info"))
       
   789                     res.out_lines.find(_.startsWith(SESSION_PARENT_PATH))
       
   790                       .map(_.substring(SESSION_PARENT_PATH.length))
       
   791                   else None
       
   792 
       
   793                 (parent_path, heap)
       
   794               }
   788               }
   795               else {
   789               else {
   796                 (output_dir + Path.basic(name)).file.delete
   790                 (output_dir + Path.basic(name)).file.delete
   797                 (output_dir + log_gz(name)).file.delete
   791                 (output_dir + log_gz(name)).file.delete
   798 
   792 
   803                   val lines = res.out_lines.filterNot(_.startsWith("\f"))
   797                   val lines = res.out_lines.filterNot(_.startsWith("\f"))
   804                   val tail = lines.drop(lines.length - 20 max 0)
   798                   val tail = lines.drop(lines.length - 20 max 0)
   805                   progress.echo("\n" + cat_lines(tail))
   799                   progress.echo("\n" + cat_lines(tail))
   806                 }
   800                 }
   807 
   801 
   808                 (None, no_heap)
   802                 no_heap
   809               }
   803               }
   810             loop(pending - name, running - name,
   804             loop(pending - name, running - name,
   811               results + (name -> Result(false, parent_path, heap, res.rc)))
   805               results + (name -> Result(false, heap, res.rc)))
   812             //}}}
   806             //}}}
   813           case None if (running.size < (max_jobs max 1)) =>
   807           case None if (running.size < (max_jobs max 1)) =>
   814             //{{{ check/start next job
   808             //{{{ check/start next job
   815             pending.dequeue(running.isDefinedAt(_)) match {
   809             pending.dequeue(running.isDefinedAt(_)) match {
   816               case Some((name, info)) =>
   810               case Some((name, info)) =>
   817                 val parent_result =
   811                 val parent_result =
   818                   info.parent match {
   812                   info.parent match {
   819                     case None => Result(true, None, no_heap, 0)
   813                     case None => Result(true, no_heap, 0)
   820                     case Some(parent) => results(parent)
   814                     case Some(parent) => results(parent)
   821                   }
   815                   }
   822                 val output = output_dir + Path.basic(name)
   816                 val output = output_dir + Path.basic(name)
   823                 val do_output = build_heap || queue.is_inner(name)
   817                 val do_output = build_heap || queue.is_inner(name)
   824 
   818 
   837                   }
   831                   }
   838                 }
   832                 }
   839                 val all_current = current && parent_result.current
   833                 val all_current = current && parent_result.current
   840 
   834 
   841                 if (all_current)
   835                 if (all_current)
   842                   loop(pending - name, running, results + (name -> Result(true, None, heap, 0)))
   836                   loop(pending - name, running, results + (name -> Result(true, heap, 0)))
   843                 else if (no_build) {
   837                 else if (no_build) {
   844                   if (verbose) progress.echo("Skipping " + name + " ...")
   838                   if (verbose) progress.echo("Skipping " + name + " ...")
   845                   loop(pending - name, running, results + (name -> Result(false, None, heap, 1)))
   839                   loop(pending - name, running, results + (name -> Result(false, heap, 1)))
   846                 }
   840                 }
   847                 else if (parent_result.rc == 0 && !progress.stopped) {
   841                 else if (parent_result.rc == 0 && !progress.stopped) {
   848                   progress.echo((if (do_output) "Building " else "Running ") + name + " ...")
   842                   progress.echo((if (do_output) "Building " else "Running ") + name + " ...")
   849                   val job =
   843                   val job =
   850                     new Job(progress, name, info, output, do_output, verbose, browser_info,
   844                     new Job(progress, name, info, output, do_output, verbose, browser_info,
   851                       queue.command_timings(name))
   845                       queue.command_timings(name))
   852                   loop(pending, running + (name -> (parent_result.heap, job)), results)
   846                   loop(pending, running + (name -> (parent_result.heap, job)), results)
   853                 }
   847                 }
   854                 else {
   848                 else {
   855                   progress.echo(name + " CANCELLED")
   849                   progress.echo(name + " CANCELLED")
   856                   loop(pending - name, running, results + (name -> Result(false, None, heap, 1)))
   850                   loop(pending - name, running, results + (name -> Result(false, heap, 1)))
   857                 }
   851                 }
   858               case None => sleep(); loop(pending, running, results)
   852               case None => sleep(); loop(pending, running, results)
   859             }
   853             }
   860             ///}}}
   854             ///}}}
   861           case None => sleep(); loop(pending, running, results)
   855           case None => sleep(); loop(pending, running, results)
   872         Map.empty[String, Result]
   866         Map.empty[String, Result]
   873       }
   867       }
   874       else loop(queue, Map.empty, Map.empty)
   868       else loop(queue, Map.empty, Map.empty)
   875 
   869 
   876     val session_entries =
   870     val session_entries =
   877       (for ((name, res) <- results.iterator if res.parent_path.isDefined)
   871       (for ((name, res) <- results.iterator)
   878         yield (res.parent_path.get, name)).toList.groupBy(_._1).map(
   872         yield (full_tree(name).chapter, name)).toList.groupBy(_._1).map(
   879           { case (p, es) => (p, es.map(_._2).sorted) })
   873           { case (chapter, es) => (chapter, es.map(_._2).sorted) })
   880     for ((p, names) <- session_entries)
   874     for ((chapter, names) <- session_entries)
   881       Present.update_index(browser_info + Path.explode(p), names)
   875       Present.update_chapter_index(browser_info, chapter, names)
   882 
   876 
   883     val rc = (0 /: results)({ case (rc1, (_, res)) => rc1 max res.rc })
   877     val rc = (0 /: results)({ case (rc1, (_, res)) => rc1 max res.rc })
   884     if (rc != 0 && (verbose || !no_build)) {
   878     if (rc != 0 && (verbose || !no_build)) {
   885       val unfinished =
   879       val unfinished =
   886         (for ((name, res) <- results.iterator if res.rc != 0) yield name).toList
   880         (for ((name, res) <- results.iterator if res.rc != 0) yield name).toList