aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Vogt <oss.nsp@cvogt.org>2017-06-14 12:21:40 -0400
committerChristopher Vogt <oss.nsp@cvogt.org>2017-06-14 12:21:40 -0400
commite3262d4e4f8b83cac6f1b2a0558af3e30073ec2a (patch)
tree293f6094560094ff5580ba62e4a2d07e02e86a7d
parent66c3d62ebb08eb0054ade9b98dc7a477976117b7 (diff)
parent3df15ef7c9c5a48516c06cf7b598acf298d8b8c0 (diff)
downloadcbt-e3262d4e4f8b83cac6f1b2a0558af3e30073ec2a.tar.gz
cbt-e3262d4e4f8b83cac6f1b2a0558af3e30073ec2a.tar.bz2
cbt-e3262d4e4f8b83cac6f1b2a0558af3e30073ec2a.zip
Merge remote-tracking branch 'origin/master' into kind-projector-plugin
-rwxr-xr-xcbt2
-rw-r--r--examples/export-build-information/Main.scala6
-rw-r--r--examples/export-build-information/build/build.scala3
-rw-r--r--examples/export-build-information/build/build/build.scala9
-rw-r--r--examples/new-style-macros-example/Hello.scala6
-rw-r--r--examples/new-style-macros-example/build/build.scala19
-rw-r--r--examples/new-style-macros-example/macros/Main.scala25
-rw-r--r--stage2/BasicBuild.scala2
-rw-r--r--stage2/plugins/ExportBuildInformation.scala170
-rw-r--r--stage2/plugins/NewStyleMacros.scala29
-rw-r--r--stage2/plugins/OldStyleMacros.scala (renamed from stage2/plugins/ScalaParadise.scala)6
-rw-r--r--test/test.scala17
12 files changed, 287 insertions, 7 deletions
diff --git a/cbt b/cbt
index e4511ec..bc369de 100755
--- a/cbt
+++ b/cbt
@@ -141,7 +141,7 @@ if [ ! "$DEBUG" == "" ]; then
shift
fi
-JAVA_OPTS_CBT=($DEBUG -Xmx1536m -Xss10M -XX:MaxJavaStackTraceDepth=-1 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xverify:none)
+JAVA_OPTS_CBT=($DEBUG -Xmx1536m -Xss10M "-XX:MaxJavaStackTraceDepth=-1" -XX:+TieredCompilation "-XX:TieredStopAtLevel=1" -Xverify:none)
# ng on osx, install via brew install nailgun
# ng-nailgun on unbuntu, install via apt-get install nailgun
diff --git a/examples/export-build-information/Main.scala b/examples/export-build-information/Main.scala
new file mode 100644
index 0000000..586aa1d
--- /dev/null
+++ b/examples/export-build-information/Main.scala
@@ -0,0 +1,6 @@
+package export_build_information
+object Main{
+ def main( args: Array[String] ): Unit = {
+ println( Console.GREEN ++ "Hello World" ++ Console.RESET )
+ }
+}
diff --git a/examples/export-build-information/build/build.scala b/examples/export-build-information/build/build.scala
new file mode 100644
index 0000000..23b3f2d
--- /dev/null
+++ b/examples/export-build-information/build/build.scala
@@ -0,0 +1,3 @@
+import cbt._
+
+class Build(val context: Context) extends BaseBuild
diff --git a/examples/export-build-information/build/build/build.scala b/examples/export-build-information/build/build/build.scala
new file mode 100644
index 0000000..c7d5d82
--- /dev/null
+++ b/examples/export-build-information/build/build/build.scala
@@ -0,0 +1,9 @@
+import cbt._
+
+class Build(val context: Context) extends BuildBuild {
+ override def dependencies =
+ super.dependencies ++
+ Resolver(mavenCentral, sonatypeReleases).bind(
+ ScalaDependency( "org.scala-lang.modules", "scala-xml", "1.0.6" )
+ )
+}
diff --git a/examples/new-style-macros-example/Hello.scala b/examples/new-style-macros-example/Hello.scala
new file mode 100644
index 0000000..7e04dcb
--- /dev/null
+++ b/examples/new-style-macros-example/Hello.scala
@@ -0,0 +1,6 @@
+package macroparadise_example
+import macros._
+
+@Main object Hello{
+ println("hello, world!")
+}
diff --git a/examples/new-style-macros-example/build/build.scala b/examples/new-style-macros-example/build/build.scala
new file mode 100644
index 0000000..2054aba
--- /dev/null
+++ b/examples/new-style-macros-example/build/build.scala
@@ -0,0 +1,19 @@
+package macroparadise_example_build
+import cbt._
+
+trait SharedSettings extends NewStyleMacros{
+ override def defaultScalaVersion = "2.12.2"
+}
+
+class Build(val context: Context) extends SharedSettings{
+ override def dependencies =
+ super.dependencies :+
+ new MacroBuild( context.copy( workingDirectory = projectDirectory / "macros" ) )
+}
+
+class MacroBuild(val context: Context) extends SharedSettings{
+ override def dependencies =
+ super.dependencies :+
+ Resolver( mavenCentral ).bindOne( ScalaDependency( "org.scalameta", "scalameta", "1.8.0" ) )
+}
+
diff --git a/examples/new-style-macros-example/macros/Main.scala b/examples/new-style-macros-example/macros/Main.scala
new file mode 100644
index 0000000..ecdce34
--- /dev/null
+++ b/examples/new-style-macros-example/macros/Main.scala
@@ -0,0 +1,25 @@
+package macroparadise_example.macros
+
+import scala.meta._
+import scala.collection.immutable.Seq
+
+class Main extends scala.annotation.StaticAnnotation {
+ inline def apply(defn: Any): Any = meta {
+ defn match {
+ case q"object $name { ..$stats }" =>
+ MainMacroImpl.expand(name, stats)
+ case _ =>
+ abort("@main must annotate an object.")
+ }
+ }
+}
+
+// This is an example how we can refactor the macro implementation into a utility
+// function which can be used for unit testing, see MainUnitTest.
+object MainMacroImpl {
+ def expand(name: Term.Name, stats: Seq[Stat]): Defn.Object = {
+ val main = q"def main(args: Array[String]): Unit = { ..$stats }"
+ q"object $name { $main }"
+ }
+}
+
diff --git a/stage2/BasicBuild.scala b/stage2/BasicBuild.scala
index 05e3c41..0bdbad7 100644
--- a/stage2/BasicBuild.scala
+++ b/stage2/BasicBuild.scala
@@ -5,7 +5,7 @@ import java.net._
import java.nio.file._
class BasicBuild(final val context: Context) extends BaseBuild
-trait BaseBuild extends BuildInterface with DependencyImplementation with SbtDependencyDsl{
+trait BaseBuild extends BuildInterface with DependencyImplementation with SbtDependencyDsl with ExportBuildInformation{
override def equals(other: Any) = {
other match {
case b: BaseBuild => projectDirectory === b.projectDirectory
diff --git a/stage2/plugins/ExportBuildInformation.scala b/stage2/plugins/ExportBuildInformation.scala
new file mode 100644
index 0000000..0d33d75
--- /dev/null
+++ b/stage2/plugins/ExportBuildInformation.scala
@@ -0,0 +1,170 @@
+package cbt
+
+import cbt._
+import scala.xml._
+import java.io._
+
+trait ExportBuildInformation { self: BaseBuild =>
+ lazy val printer = new scala.xml.PrettyPrinter(200, 2)
+
+ def buildInfoXml =
+ printer.format(BuildInformationSerializer.serialize(BuildInformation.Project(self)))
+}
+
+object BuildInformation {
+ case class Project(
+ name: String,
+ root: File,
+ rootModule: Module,
+ modules: Seq[Module],
+ libraries: Seq[Library]
+ )
+
+ case class Module(
+ name: String,
+ root: File,
+ sources: Seq[File],
+ target: File,
+ mavenDependencies: Seq[MavenDependency],
+ moduleDependencies: Seq[ModuleDependency],
+ classpaths: Seq[ClassPathItem],
+ parentBuild: Option[String]
+ )
+
+ case class Library( name: String, jars: Seq[File] )
+
+ case class MavenDependency( name: String )
+
+ case class ModuleDependency( name: String )
+
+ case class ClassPathItem( path: File )
+
+ object Project {
+ def apply(build: BaseBuild) =
+ new BuildInformationExporter(build).exportBuildInformation
+
+ private class BuildInformationExporter(rootBuild: BaseBuild) {
+ def exportBuildInformation(): Project = {
+ val rootModule = exportModule(rootBuild)
+ val modules = (rootBuild +: rootBuild.transitiveDependencies)
+ .collect { case d: BaseBuild => d +: collectParentBuilds(d)}
+ .flatten
+ .map(exportModule)
+ .distinct
+ val libraries = rootBuild.transitiveDependencies
+ .collect { case d: BoundMavenDependency => exportLibrary(d)}
+ .distinct
+
+ Project(
+ rootModule.name,
+ rootModule.root,
+ rootModule,
+ modules,
+ libraries
+ )
+ }
+
+ private def exportLibrary(mavenDependency: BoundMavenDependency) =
+ Library(fomatMavenDependency(mavenDependency.mavenDependency), mavenDependency.exportedJars)
+
+ private def collectParentBuilds(build: BaseBuild): Seq[BaseBuild] =
+ build.context.parentBuild
+ .map(_.asInstanceOf[BaseBuild])
+ .map(b => b +: collectParentBuilds(b))
+ .toSeq
+ .flatten
+
+ private def exportModule(build: BaseBuild): Module = {
+ val moduleDependencies = build.dependencies
+ .collect { case d: BaseBuild => ModuleDependency(moduleName(d)) }
+ val mavenDependencies = build.dependencies
+ .collect { case d: BoundMavenDependency => MavenDependency(fomatMavenDependency(d.mavenDependency))}
+ val classpaths = build.dependencyClasspath.files
+ .filter(_.isFile)
+ .map(t => ClassPathItem(t))
+ val sources = {
+ val s = build.sources
+ .filter(s => s.exists && s.isDirectory)
+ if (s.isEmpty)
+ Seq(build.projectDirectory)
+ else
+ s
+ }
+ Module(
+ name = moduleName(build),
+ root = build.projectDirectory,
+ sources = sources,
+ target = build.target,
+ mavenDependencies = mavenDependencies,
+ moduleDependencies = moduleDependencies,
+ classpaths = classpaths,
+ parentBuild = build.context.parentBuild.map(b => moduleName(b.asInstanceOf[BaseBuild]))
+ )
+ }
+
+ private def fomatMavenDependency(dependency: cbt.MavenDependency) =
+ s"${dependency.groupId}:${dependency.artifactId}:${dependency.version}"
+
+ private def moduleName(build: BaseBuild) =
+ if (rootBuild.projectDirectory == build.projectDirectory)
+ rootBuild.projectDirectory.getName
+ else
+ build.projectDirectory.getPath
+ .drop(rootBuild.projectDirectory.getPath.length)
+ .stripPrefix("/")
+ .replace("/", "-")
+ }
+ }
+}
+
+object BuildInformationSerializer {
+ def serialize(project: BuildInformation.Project): Node =
+ <project>
+ <name>{project.name}</name>
+ <root>{project.root.toString}</root>
+ <rootModule>{project.rootModule.name}</rootModule>
+ <modules>
+ {project.modules.map(serialize)}
+ </modules>
+ <libraries>
+ {project.libraries.map(serialize)}
+ </libraries>
+ </project>
+
+ private def serialize(module: BuildInformation.Module): Node =
+ <module>
+ <name>{module.name}</name>
+ <root>{module.root}</root>
+ <target>{module.target}</target>
+ <sources>
+ {module.sources.map(s => <source>{s}</source>)}
+ </sources>
+ <mavenDependencies>
+ {module.mavenDependencies.map(serialize)}
+ </mavenDependencies>
+ <moduleDependencies>
+ {module.moduleDependencies.map(serialize)}
+ </moduleDependencies>
+ <classpaths>
+ {module.classpaths.map(serialize)}
+ </classpaths>
+ {module.parentBuild.map(p => <parentBuild>{p}</parentBuild>).getOrElse(NodeSeq.Empty)}
+ </module>
+
+ private def serialize(mavenDependency: BuildInformation.MavenDependency): Node =
+ <mavenDependency>{mavenDependency.name}</mavenDependency>
+
+ private def serialize(library: BuildInformation.Library): Node =
+ <library>
+ <name>{library.name}</name>
+ <jars>
+ {library.jars.map(j => <jar>{j}</jar>)}
+ </jars>
+ </library>
+
+ private def serialize(moduleDependency: BuildInformation.ModuleDependency): Node =
+ <moduleDependency>{moduleDependency.name}</moduleDependency>
+
+ private def serialize(targetLibrary: BuildInformation.ClassPathItem): Node =
+ <classpathItem>{targetLibrary.path.toString}</classpathItem>
+}
diff --git a/stage2/plugins/NewStyleMacros.scala b/stage2/plugins/NewStyleMacros.scala
new file mode 100644
index 0000000..42b3287
--- /dev/null
+++ b/stage2/plugins/NewStyleMacros.scala
@@ -0,0 +1,29 @@
+package cbt
+import java.io.File
+
+trait NewStyleMacros extends BaseBuild{
+ def newStyleMacrosVersion = "3.0.0-M9"
+
+ override def scalacOptions = super.scalacOptions ++ NewStyleMacros.scalacOptions(
+ NewStyleMacros.dependencies( scalaVersion, newStyleMacrosVersion, context.cbtLastModified, context.paths.mavenCache ).jar
+ )
+}
+
+object NewStyleMacros{
+ def dependencies(
+ scalaVersion: String, newStyleMacrosVersion: String, cbtLastModified: Long, mavenCache: java.io.File
+ )(
+ implicit logger: Logger, transientCache: java.util.Map[AnyRef,AnyRef], classLoaderCache: ClassLoaderCache
+ ) =
+ MavenResolver( cbtLastModified, mavenCache, mavenCentral ).bindOne(
+ MavenDependency( "org.scalameta", "paradise_"+scalaVersion, newStyleMacrosVersion )
+ )
+
+ def scalacOptions( jarPath: File ) =
+ Seq(
+ "-Xplugin:" ++ jarPath.string,
+ "-Yrangepos",
+ "-Xplugin-require:macroparadise"
+ )
+}
+
diff --git a/stage2/plugins/ScalaParadise.scala b/stage2/plugins/OldStyleMacros.scala
index 28ee934..42719ea 100644
--- a/stage2/plugins/ScalaParadise.scala
+++ b/stage2/plugins/OldStyleMacros.scala
@@ -1,10 +1,10 @@
package cbt
-trait ScalaParadise extends BaseBuild{
- def scalaParadiseVersion = "2.1.0"
+trait OldStyleMacros extends BaseBuild{
+ def oldStyleMacrosVersion = "2.1.0"
private def scalaParadiseDependency =
Resolver( mavenCentral ).bindOne(
- "org.scalamacros" % ("paradise_" ++ scalaVersion) % scalaParadiseVersion
+ "org.scalamacros" % ("paradise_" ++ scalaVersion) % oldStyleMacrosVersion
)
override def dependencies = (
diff --git a/test/test.scala b/test/test.scala
index 81a164f..55ce205 100644
--- a/test/test.scala
+++ b/test/test.scala
@@ -35,8 +35,15 @@ object Main{
val p = pb.start
val out = new java.io.InputStreamReader(p.getInputStream)
val errors = Iterator.continually(out.read).takeWhile(_ != -1).map(_.toChar).mkString
- if( p.waitFor != 0 ){
- throw new Exception("Linting error in ./cbt bash launcher script:\n" + errors)
+ p.waitFor() match {
+ case 0 =>
+ ()
+
+ case 127 => // bash exit code: not found
+ System.err.println( "Shellcheck not found. Your build may fail during ci-build" )
+
+ case _ =>
+ throw new Exception( "Linting error in ./cbt bash launcher script:\n" + errors )
}
} else System.err.println( "Skipping shellcheck" )
@@ -422,6 +429,12 @@ object Main{
}
{
+ val res = runCbt("../examples/new-style-macros-example", Seq("run"))
+ assert(res.exit0)
+ assert(res.out.contains("hello, world!"), res.out)
+ }
+
+ {
val res = runCbt("../examples/resources-example", Seq("run"))
assert(res.exit0)
assert(res.out.contains("via parent.parent: false 0"), res.out)