diff options
author | Christopher Vogt <oss.nsp@cvogt.org> | 2017-06-14 12:21:40 -0400 |
---|---|---|
committer | Christopher Vogt <oss.nsp@cvogt.org> | 2017-06-14 12:21:40 -0400 |
commit | e3262d4e4f8b83cac6f1b2a0558af3e30073ec2a (patch) | |
tree | 293f6094560094ff5580ba62e4a2d07e02e86a7d | |
parent | 66c3d62ebb08eb0054ade9b98dc7a477976117b7 (diff) | |
parent | 3df15ef7c9c5a48516c06cf7b598acf298d8b8c0 (diff) | |
download | cbt-e3262d4e4f8b83cac6f1b2a0558af3e30073ec2a.tar.gz cbt-e3262d4e4f8b83cac6f1b2a0558af3e30073ec2a.tar.bz2 cbt-e3262d4e4f8b83cac6f1b2a0558af3e30073ec2a.zip |
Merge remote-tracking branch 'origin/master' into kind-projector-plugin
-rwxr-xr-x | cbt | 2 | ||||
-rw-r--r-- | examples/export-build-information/Main.scala | 6 | ||||
-rw-r--r-- | examples/export-build-information/build/build.scala | 3 | ||||
-rw-r--r-- | examples/export-build-information/build/build/build.scala | 9 | ||||
-rw-r--r-- | examples/new-style-macros-example/Hello.scala | 6 | ||||
-rw-r--r-- | examples/new-style-macros-example/build/build.scala | 19 | ||||
-rw-r--r-- | examples/new-style-macros-example/macros/Main.scala | 25 | ||||
-rw-r--r-- | stage2/BasicBuild.scala | 2 | ||||
-rw-r--r-- | stage2/plugins/ExportBuildInformation.scala | 170 | ||||
-rw-r--r-- | stage2/plugins/NewStyleMacros.scala | 29 | ||||
-rw-r--r-- | stage2/plugins/OldStyleMacros.scala (renamed from stage2/plugins/ScalaParadise.scala) | 6 | ||||
-rw-r--r-- | test/test.scala | 17 |
12 files changed, 287 insertions, 7 deletions
@@ -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) |