summaryrefslogtreecommitdiff
path: root/build.sc
diff options
context:
space:
mode:
authoredwardcwang2019-03-20 10:06:18 -0700
committerGitHub2019-03-20 10:06:18 -0700
commit1894319c712628c22ccbc9c174505f9c1c186b69 (patch)
treec1bf81a63178ac019754d021f07eb81e0feb26f1 /build.sc
parent2c449c5d6e23dcbb60e8c64cab6b6f4ba6ae313f (diff)
Mill support for Chisel3 (#1035)
Co-Authored-By: Jack Koenig <jack.koenig3@gmail.com> Co-Authored-By: Jim Lawson <ucbjrl@berkeley.edu>
Diffstat (limited to 'build.sc')
-rw-r--r--build.sc235
1 files changed, 235 insertions, 0 deletions
diff --git a/build.sc b/build.sc
new file mode 100644
index 00000000..f080c522
--- /dev/null
+++ b/build.sc
@@ -0,0 +1,235 @@
+import ammonite.ops._
+import ammonite.ops.ImplicitWd._
+import mill._
+import mill.scalalib._
+import mill.scalalib.publish._
+import mill.eval.{Evaluator, Result}
+import mill.define.Task
+import mill.modules.Jvm._
+
+import $file.CommonBuild
+
+/** Utility types for changing a dependency between Ivy and Module (source) */
+sealed trait IvyOrModuleDep
+case class IvyDep(dep: Dep) extends IvyOrModuleDep
+case class ModuleDep(dep: PublishModule) extends IvyOrModuleDep
+
+object chiselCompileOptions {
+ def scalacOptions = Seq(
+ "-deprecation",
+ "-explaintypes",
+ "-feature",
+ "-language:reflectiveCalls",
+ "-unchecked",
+ "-Xcheckinit",
+ "-Xlint:infer-any"
+/* "-Xlint:missing-interpolator" // this causes a:
+//[error] .../chisel3/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala:605:48: recursive value outer needs type
+//[error] val outer = clazz.getDeclaredField("$outer").get(this)
+//[error] ^
+//[error] one error found
+ */
+ )
+}
+
+val crossVersions = Seq("2.12.6", "2.11.12")
+
+// Provide a managed dependency on X if -DXVersion="" is supplied on the command line.
+val defaultVersions = Map("firrtl" -> "1.2-SNAPSHOT")
+
+def getVersion(dep: String, org: String = "edu.berkeley.cs") = {
+ val version = sys.env.getOrElse(dep + "Version", defaultVersions(dep))
+ ivy"$org::$dep:$version"
+}
+
+// Define the common chisel module.
+trait CommonChiselModule extends SbtModule {
+ // Normally defined in CrossSbtModule, our submodules don't have it by default
+ def crossScalaVersion: String
+ // This build uses an ivy dependency but allows overriding with a module (source) dependency
+ def firrtlDep: IvyOrModuleDep
+ override def scalacOptions = chiselCompileOptions.scalacOptions ++ CommonBuild.scalacOptionsVersion(crossScalaVersion)
+ override def javacOptions = CommonBuild.javacOptionsVersion(crossScalaVersion)
+ val macroPlugins = Agg(ivy"org.scalamacros:::paradise:2.1.0")
+ def scalacPluginIvyDeps = macroPlugins
+ def compileIvyDeps = macroPlugins
+ def chiselDeps = firrtlDep match {
+ case IvyDep(dep) => Agg(dep)
+ case ModuleDep(_) => Agg()
+ }
+ override def ivyDeps = T { chiselDeps }
+}
+
+trait PublishChiselModule extends CommonChiselModule with PublishModule {
+ override def artifactName = "chisel3"
+ def publishVersion = "3.2-SNAPSHOT"
+
+ def pomSettings = PomSettings(
+ description = artifactName(),
+ organization = "edu.berkeley.cs",
+ url = "https://chisel.eecs.berkeley.edu",
+ licenses = Seq(License.`BSD-3-Clause`),
+ versionControl = VersionControl.github("freechipsproject", "chisel3"),
+ developers = Seq(
+ Developer("jackbackrack", "Jonathan Bachrach", "https://eecs.berkeley.edu/~jrb/")
+ )
+ )
+}
+
+// Make this available to external tools.
+object chisel3 extends Cross[ChiselTopModule](crossVersions: _*) {
+ def defaultVersion(ev: Evaluator) = T.command{
+ println(crossVersions.head)
+ }
+
+ def compile = T{
+ chisel3(crossVersions.head).compile()
+ }
+
+ def jar = T{
+ chisel3(crossVersions.head).jar()
+ }
+
+ def test = T{
+ chisel3(crossVersions.head).test.test()
+ }
+
+ def publishLocal = T{
+ chisel3(crossVersions.head).publishLocal()
+ }
+
+ def docJar = T{
+ chisel3(crossVersions.head).docJar()
+ }
+}
+
+class ChiselTopModule(val crossScalaVersion: String) extends AbstractChiselModule {
+ // This build uses an ivy dependency but allows overriding with a module (source) dependency
+ def firrtlDep: IvyOrModuleDep = IvyDep(getVersion("firrtl"))
+}
+
+trait AbstractChiselModule extends PublishChiselModule with CommonBuild.BuildInfo with CrossSbtModule { top =>
+
+ // If would be nice if we didn't need to do this, but PublishModule may only be dependent on
+ // other PublishModules.
+ trait UnpublishedChiselModule extends PublishChiselModule
+
+
+ object coreMacros extends UnpublishedChiselModule {
+ def crossScalaVersion = top.crossScalaVersion
+ def scalaVersion = crossScalaVersion
+ def firrtlDep: IvyOrModuleDep = top.firrtlDep
+ }
+
+ object chiselFrontend extends UnpublishedChiselModule {
+ def crossScalaVersion = top.crossScalaVersion
+ def scalaVersion = crossScalaVersion
+ def moduleDeps = Seq(coreMacros) ++ (firrtlDep match {
+ case ModuleDep(dep) => Seq(dep)
+ case IvyDep(_) => Seq()
+ })
+ def firrtlDep: IvyOrModuleDep = top.firrtlDep
+ }
+
+ override def moduleDeps = Seq(coreMacros, chiselFrontend)
+
+ // This submodule is unrooted - its source directory is in the top level directory.
+ override def millSourcePath = super.millSourcePath / ammonite.ops.up
+
+ // In order to preserve our "all-in-one" policy for published jars,
+ // we define allModuleSources() to include transitive sources, and define
+ // allModuleClasspath() to include transitive classes.
+ def transitiveSources = T {
+ Task.traverse(moduleDeps)(m =>
+ T.task{m.allSources()}
+ )().flatten
+ }
+
+ def allModuleSources = T {
+ allSources() ++ transitiveSources()
+ }
+
+ def transitiveResources = T {
+ Task.traverse(moduleDeps)(m =>
+ T.task{m.resources()}
+ )().flatten
+ }
+
+ def allModuleResources = T {
+ resources() ++ transitiveResources()
+ }
+
+ // We package all classes in a singe jar.
+ def allModuleClasspath = T {
+ localClasspath() ++ transitiveLocalClasspath()
+ }
+
+ // Override publishXmlDeps so we don't include dependencies on our sub-modules.
+ override def publishXmlDeps = T.task {
+ val ivyPomDeps = ivyDeps().map(resolvePublishDependency().apply(_))
+ ivyPomDeps
+ }
+
+ // We need to copy (and override) the `jar` and `docJar` targets so we can build
+ // single jars implementing our "all-in-one" policy.
+ override def jar = T {
+ createJar(
+ allModuleClasspath().map(_.path).filter(exists),
+ mainClass()
+ )
+ }
+
+
+ override def docJar = T {
+ val outDir = T.ctx().dest
+
+ val javadocDir = outDir / 'javadoc
+ mkdir(javadocDir)
+
+ val files = for{
+ ref <- allModuleSources()
+ if exists(ref.path)
+ p <- (if (ref.path.isDir) ls.rec(ref.path) else Seq(ref.path))
+ if (p.isFile && ((p.ext == "scala") || (p.ext == "java")))
+ } yield p.toNIO.toString
+
+ val pluginOptions = scalacPluginClasspath().map(pluginPathRef => s"-Xplugin:${pluginPathRef.path}")
+ val options = Seq("-d", javadocDir.toNIO.toString, "-usejavacp") ++ pluginOptions ++ scalacOptions()
+
+ if (files.nonEmpty) runSubprocess(
+ "scala.tools.nsc.ScalaDoc",
+ scalaCompilerClasspath().map(_.path) ++ compileClasspath().filter(_.path.ext != "pom").map(_.path),
+ mainArgs = (files ++ options).toSeq
+ )
+
+ createJar(Agg(javadocDir), None)(outDir)
+ }
+
+ def sourceJar = T {
+ createJar((allModuleSources() ++ allModuleResources()).map(_.path).filter(exists), None)
+ }
+
+ override def ivyDeps = Agg(
+ ivy"com.github.scopt::scopt:3.6.0"
+ ) ++ chiselDeps
+
+ object test extends Tests {
+ override def ivyDeps = Agg(
+ ivy"org.scalatest::scalatest:3.0.1",
+ ivy"org.scalacheck::scalacheck:1.13.4"
+ )
+ def testFrameworks = Seq("org.scalatest.tools.Framework")
+ }
+
+ // This is required for building a library, but not for a `run` target.
+ // In the latter case, mill will determine this on its own.
+ def mainClass = Some("chisel3.Driver")
+
+ override def buildInfoMembers = T {
+ Map[String, String](
+ "buildInfoPackage" -> artifactName(),
+ "version" -> publishVersion(),
+ "scalaVersion" -> scalaVersion()
+ )
+ }
+}