diff options
Diffstat (limited to 'stage2')
-rw-r--r-- | stage2/BasicBuild.scala | 7 | ||||
-rw-r--r-- | stage2/Lib.scala | 5 | ||||
-rw-r--r-- | stage2/plugins/Frege.scala | 136 |
3 files changed, 142 insertions, 6 deletions
diff --git a/stage2/BasicBuild.scala b/stage2/BasicBuild.scala index ef5411a..750b0bc 100644 --- a/stage2/BasicBuild.scala +++ b/stage2/BasicBuild.scala @@ -84,10 +84,13 @@ trait BaseBuild extends BuildInterface with DependencyImplementation with Trigge def compileStatusFile: File = compileTarget ++ ".last-success" /** Source directories and files. Defaults to .scala and .java files in src/ and top-level. */ - def sources: Seq[File] = Seq(defaultSourceDirectory) ++ projectDirectory.listFiles.toVector.filter(lib.sourceFileFilter) + def sources: Seq[File] = Seq(defaultSourceDirectory) ++ projectDirectory.listFiles.toVector.filter(sourceFileFilter) + + /** Which file endings to consider being source files. */ + def sourceFileFilter(file: File): Boolean = file.toString.endsWith(".scala") || file.toString.endsWith(".java") /** Absolute path names for all individual files found in sources directly or contained in directories. */ - final def sourceFiles: Seq[File] = lib.sourceFiles(sources) + final def sourceFiles: Seq[File] = lib.sourceFiles(sources, sourceFileFilter) protected def logEmptySourceDirectories(): Unit = { val nonExisting = diff --git a/stage2/Lib.scala b/stage2/Lib.scala index a76e281..45803b4 100644 --- a/stage2/Lib.scala +++ b/stage2/Lib.scala @@ -266,10 +266,7 @@ final class Lib(val logger: Logger) extends Stage1Lib(logger) with Scaffold{ def dirname(path: File): File = new File(realpath(path).string.stripSuffix("/").split("/").dropRight(1).mkString("/")) def nameAndContents(file: File) = basename(file) -> readAllBytes(file.toPath) - /** Which file endings to consider being source files. */ - def sourceFileFilter(file: File): Boolean = file.toString.endsWith(".scala") || file.toString.endsWith(".java") - - def sourceFiles( sources: Seq[File], sourceFileFilter: File => Boolean = sourceFileFilter ): Seq[File] = { + def sourceFiles( sources: Seq[File], sourceFileFilter: File => Boolean ): Seq[File] = { for { base <- sources.filter(_.exists).map(lib.realpath) file <- lib.listFilesRecursive(base) if file.isFile && sourceFileFilter(file) diff --git a/stage2/plugins/Frege.scala b/stage2/plugins/Frege.scala new file mode 100644 index 0000000..88e1f59 --- /dev/null +++ b/stage2/plugins/Frege.scala @@ -0,0 +1,136 @@ +package cbt +import java.io.File +import java.net.URL +import java.nio.file.Files +import java.nio.file.attribute.FileTime + +trait Frege extends BaseBuild{ + def fregeVersion: String = "3.24.100.1" + def classifier: Option[String] = Some("jdk8") + def fregeTarget: String = "1.8" + def enableMakeMode = true + def enableOptimisation = true + def fregeDependencies: Seq[String] = dependencies.map{ _.classpath.string} + def inline = true + + private def fregeOptions: Seq[String] = { + val opts : Seq[(String, Boolean)] = Seq(("-make", enableMakeMode), ("-O", enableOptimisation), ("-inline", inline) ) + opts.filter(_._2).map(_._1) + } + override def scalaTarget: File = target ++ s"/frege-$fregeVersion" + + private lazy val fregeLib = new FregeLib( + logger, context.cbtHasChanged, context.paths.mavenCache, + context.classLoaderCache, fregeVersion = fregeVersion, classifier = classifier, + fregeDependencies = fregeDependencies, fregeTarget = fregeTarget + ) + + override def sourceFileFilter(file: File): Boolean = file.toString.endsWith(".fr") || file.toString.endsWith(".java") + + private object compileCache extends Cache[Option[File]] + override def compile: Option[File] = compileCache{ + fregeLib.compile( + needsUpdate || context.parentBuild.map(_.needsUpdate).getOrElse(false), + sourceFiles, compileTarget, compileStatusFile, compileClasspath, + fregeOptions + ) + } + + override def dependencies = Resolver(mavenCentral).bind( + MavenDependency("org.frege-lang","frege",fregeVersion, Classifier(classifier)) + ) + +} + +class FregeLib( + logger: Logger, + cbtHasChanged: Boolean, + mavenCache: File, + classLoaderCache: ClassLoaderCache, + fregeVersion: String, + classifier: Option[String], + fregeDependencies: Seq[String], + fregeTarget: String +){ + val lib = new Lib(logger) + import lib._ + + private def Resolver(urls: URL*) = MavenResolver(cbtHasChanged, mavenCache, urls: _*) + private lazy val fregeDependency = Resolver(mavenCentral).bindOne( + MavenDependency("org.frege-lang","frege",fregeVersion, Classifier(classifier)) + ) + + def compile( + needsRecompile: Boolean, + files: Seq[File], + compileTarget: File, + statusFile: File, + classpath: ClassPath, + fregeOptions: Seq[String] + ): Option[File] = { + + if(classpath.files.isEmpty) + throw new Exception("Trying to compile with empty classpath. Source files: " ++ files.toString) + + if( files.isEmpty ){ + None + }else{ + if( needsRecompile ){ + val start = System.currentTimeMillis + + val _class = "frege.compiler.Main" + val dualArgs = + Seq( + "-target", fregeTarget, + "-d", compileTarget.toString, + "-fp", (fregeDependency.classpath.strings ++ fregeDependencies).mkString(":") + ) + val singleArgs = fregeOptions + val code = + try{ + System.err.println("Compiling with Frege to " ++ compileTarget.toString) + compileTarget.mkdirs + redirectOutToErr{ + lib.runMain( + _class, + dualArgs ++ singleArgs ++ files.map(_.toString), + fregeDependency.classLoader(classLoaderCache) + ) + } + } catch { + case e: Exception => + System.err.println(red("Frege crashed. To reproduce run:")) + System.out.println(s""" +java -cp \\ +${fregeDependency.classpath.strings.mkString(":\\\n")} \\ +\\ +${_class} \\ +\\ +${dualArgs.grouped(2).map(_.mkString(" ")).mkString(" \\\n")} \\ +\\ +${singleArgs.mkString(" \\\n")} \\ +\\ +-bootclasspath \\ +${fregeDependency.classpath.strings.mkString(":\\\n")} \\ +-classpath \\ +${classpath.strings.mkString(":\\\n")} \\ +\\ +${files.sorted.mkString(" \\\n")} +""" + ) + ExitCode.Failure + } + + if(code == ExitCode.Success){ + // write version and when last compilation started so we can trigger + // recompile if cbt version changed or newer source files are seen + write(statusFile, "")//cbtVersion.getBytes) + Files.setLastModifiedTime(statusFile.toPath, FileTime.fromMillis(start) ) + } else { + System.exit(code.integer) // FIXME: let's find a better solution for error handling. Maybe a monad after all. + } + } + Some( compileTarget ) + } + } +} |