|
| 1 | +package build |
| 2 | + |
| 3 | +import mill._ |
| 4 | +import mill.scalalib._ |
| 5 | +import mill.scalalib.scalafmt._ |
| 6 | + |
| 7 | +import $packages._ |
| 8 | +import build._ |
| 9 | + |
| 10 | +object v extends Module { |
| 11 | + |
| 12 | + val javaVersion = { |
| 13 | + val rawVersion = sys.props("java.specification.version") |
| 14 | + // Older versions of Java started with 1., e.g. 1.8 == 8 |
| 15 | + rawVersion.stripPrefix("1.").toInt |
| 16 | + } |
| 17 | + |
| 18 | + val firtoolVersion = { |
| 19 | + val j = _root_.upickle.default.read[Map[String, String]](os.read(millSourcePath / os.up / "etc" / "circt.json")) |
| 20 | + j("version").stripPrefix("firtool-") |
| 21 | + } |
| 22 | + // Java 21 only works with 2.13.11+, but Project Panama uses Java 21 |
| 23 | + // Only publish plugin for 2.13.11+ when using Java > 11, but still |
| 24 | + // publish all versions when Java version <= 11. |
| 25 | + val pluginScalaCrossVersions = { |
| 26 | + val latest213 = 15 |
| 27 | + val java21Min213 = 11 |
| 28 | + val minVersion = if (javaVersion > 11) java21Min213 else 0 |
| 29 | + val versions = minVersion to latest213 |
| 30 | + val versionSeq = versions.map(v => s"2.13.$v").toSeq |
| 31 | + versionSeq ++ Seq("3.3.4") |
| 32 | + } |
| 33 | + |
| 34 | + val scalaCrossVersions = Seq( |
| 35 | + "2.13.15", |
| 36 | + "3.3.4" |
| 37 | + ) |
| 38 | + |
| 39 | + def isScala3(ver: String): Boolean = ver.startsWith("3.") |
| 40 | + |
| 41 | + def buildUnits(): Seq[ScalaModule] = { |
| 42 | + scalaCrossVersions.flatMap { ver => |
| 43 | + Seq(chisel(ver), stdlib.cross(ver), unipublish) |
| 44 | + } ++ scalaCrossVersions.filterNot(isScala3(_)).flatMap { ver2 => |
| 45 | + Seq( |
| 46 | + chisel(ver2).test, |
| 47 | + firrtl.cross(ver2).test, |
| 48 | + svsim.cross(ver2).test, |
| 49 | + `integration-tests`.cross(ver2).test, |
| 50 | + lit.utility.cross(ver2), |
| 51 | + panamaconverter.cross(ver2), |
| 52 | + panamalib.cross(ver2), |
| 53 | + panamaom.cross(ver2) |
| 54 | + ) |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + val scalaVersion = scalaCrossVersions.head |
| 59 | + val jmhVersion = "1.37" |
| 60 | + val osLib = ivy"com.lihaoyi::os-lib:0.10.0" |
| 61 | + val upickle = ivy"com.lihaoyi::upickle:3.3.1" |
| 62 | + val firtoolResolver = ivy"org.chipsalliance::firtool-resolver:2.0.0" |
| 63 | + val scalatest = ivy"org.scalatest::scalatest:3.2.19" |
| 64 | + val scalacheck = ivy"org.scalatestplus::scalacheck-1-18:3.2.19.0" |
| 65 | + val json4s = ivy"org.json4s::json4s-native:4.0.7" |
| 66 | + val dataclass = ivy"io.github.alexarchambault::data-class:0.2.6" |
| 67 | + val commonText = ivy"org.apache.commons:commons-text:1.12.0" |
| 68 | + val scopt = ivy"com.github.scopt::scopt:4.1.0" |
| 69 | + |
| 70 | + def scalaReflect(scalaVersion: String) = ivy"org.scala-lang:scala-reflect:$scalaVersion" |
| 71 | + def scalaCompiler(scalaVersion: String) = ivy"org.scala-lang:scala-compiler:$scalaVersion" |
| 72 | + def scalaLibrary(scalaVersion: String) = ivy"org.scala-lang:scala-library:$scalaVersion" |
| 73 | + |
| 74 | + def circt(version: String, os: String, platform: String) = |
| 75 | + s"https://github.com/llvm/circt/releases/download/firtool-${version}/circt-full-shared-${os}-${platform}.tar.gz" |
| 76 | + |
| 77 | + val scala2WarnConf = Seq( |
| 78 | + "msg=APIs in chisel3.internal:s", |
| 79 | + "msg=Importing from firrtl:s", |
| 80 | + "msg=migration to the MLIR:s", |
| 81 | + "msg=method hasDefiniteSize in trait IterableOnceOps is deprecated:s", // replacement `knownSize` is not in 2.12 |
| 82 | + "msg=object JavaConverters in package collection is deprecated:s", |
| 83 | + "msg=undefined in comment for method cf in class PrintableHelper:s", |
| 84 | + // This is deprecated for external users but not internal use |
| 85 | + "cat=deprecation&origin=firrtl\\.options\\.internal\\.WriteableCircuitAnnotation:s", |
| 86 | + "cat=deprecation&origin=chisel3\\.util\\.experimental\\.BoringUtils.*:s", |
| 87 | + "cat=deprecation&origin=chisel3\\.experimental\\.IntrinsicModule:s", |
| 88 | + "cat=deprecation&origin=chisel3\\.ltl.*:s", |
| 89 | + // Deprecated for external users, will eventually be removed. |
| 90 | + "cat=deprecation&msg=Looking up Modules is deprecated:s", |
| 91 | + // Only for testing of deprecated APIs |
| 92 | + "cat=deprecation&msg=Use of @instantiable on user-defined types is deprecated:s" |
| 93 | + ) |
| 94 | + |
| 95 | + // ScalacOptions |
| 96 | + val scala2CommonOptions = Seq( |
| 97 | + "-deprecation", |
| 98 | + "-feature", |
| 99 | + "-unchecked", |
| 100 | + "-Werror", |
| 101 | + "-Ymacro-annotations", |
| 102 | + "-explaintypes", |
| 103 | + "-Xcheckinit", |
| 104 | + "-Xlint:infer-any", |
| 105 | + "-Xlint:missing-interpolator", |
| 106 | + "-language:reflectiveCalls", |
| 107 | + s"-Wconf:${scala2WarnConf.mkString(",")}" |
| 108 | + ) |
| 109 | +} |
| 110 | + |
| 111 | +def compileAll() = Task.Command { |
| 112 | + Task.traverse(v.buildUnits())(_.compile)() |
| 113 | +} |
| 114 | + |
| 115 | +trait HasScala2MacroAnno extends CrossModuleBase { |
| 116 | + override def scalacOptions = Task { |
| 117 | + if (!v.isScala3(crossScalaVersion)) { |
| 118 | + super.scalacOptions() ++ Agg("-Ymacro-annotations") |
| 119 | + } else super.scalacOptions() |
| 120 | + } |
| 121 | +} |
| 122 | + |
| 123 | +trait HasScala2Plugin extends CrossModuleBase { |
| 124 | + import build_.plugin.Plugin |
| 125 | + def pluginModule: Plugin |
| 126 | + |
| 127 | + override def scalacOptions = Task { |
| 128 | + if (!v.isScala3(crossScalaVersion)) { |
| 129 | + super.scalacOptions() ++ Agg(s"-Xplugin:${pluginModule.jar().path}") |
| 130 | + } else super.scalacOptions() |
| 131 | + } |
| 132 | + |
| 133 | + override def scalacPluginClasspath = Task { |
| 134 | + if (!v.isScala3(crossScalaVersion)) { |
| 135 | + super.scalacPluginClasspath() ++ Agg(pluginModule.jar()) |
| 136 | + } else super.scalacPluginClasspath() |
| 137 | + } |
| 138 | +} |
| 139 | + |
| 140 | +trait HasJextractGeneratedSources extends JavaModule { |
| 141 | + |
| 142 | + def jextractBinary: T[os.Path] |
| 143 | + |
| 144 | + def includePaths: T[Seq[PathRef]] |
| 145 | + |
| 146 | + def libraryPaths: T[Seq[PathRef]] |
| 147 | + |
| 148 | + def header: T[PathRef] |
| 149 | + |
| 150 | + def includeFunctions: T[Seq[String]] |
| 151 | + |
| 152 | + def includeConstants: T[Seq[String]] |
| 153 | + |
| 154 | + def includeStructs: T[Seq[String]] |
| 155 | + |
| 156 | + def includeTypedefs: T[Seq[String]] |
| 157 | + |
| 158 | + def includeUnions: T[Seq[String]] |
| 159 | + |
| 160 | + def includeVars: T[Seq[String]] |
| 161 | + |
| 162 | + def linkLibraries: T[Seq[String]] |
| 163 | + |
| 164 | + def target: T[String] |
| 165 | + |
| 166 | + def headerClassName: T[String] |
| 167 | + |
| 168 | + def dumpAllIncludes = Task { |
| 169 | + val f = os.temp() |
| 170 | + os.proc( |
| 171 | + Seq(jextractBinary().toString, header().path.toString) |
| 172 | + ++ includePaths().flatMap(p => Seq("-I", p.path.toString)) |
| 173 | + ++ Seq("--dump-includes", f.toString) |
| 174 | + ).call() |
| 175 | + os.read.lines(f).filter(s => s.nonEmpty && !s.startsWith("#")) |
| 176 | + } |
| 177 | + |
| 178 | + override def generatedSources: T[Seq[PathRef]] = Task { |
| 179 | + super.generatedSources() ++ { |
| 180 | + // @formatter:off |
| 181 | + os.proc( |
| 182 | + Seq(jextractBinary().toString, header().path.toString) |
| 183 | + ++ includePaths().flatMap(p => Seq("-I", p.path.toString)) |
| 184 | + ++ Seq( |
| 185 | + "-t", target(), |
| 186 | + "--header-class-name", headerClassName(), |
| 187 | + "--source", |
| 188 | + "--output", Task.dest.toString |
| 189 | + ) ++ includeFunctions().flatMap(f => Seq("--include-function", f)) ++ |
| 190 | + includeConstants().flatMap(f => Seq("--include-constant", f)) ++ |
| 191 | + includeStructs().flatMap(f => Seq("--include-struct", f)) ++ |
| 192 | + includeTypedefs().flatMap(f => Seq("--include-typedef", f)) ++ |
| 193 | + includeUnions().flatMap(f => Seq("--include-union", f)) ++ |
| 194 | + includeVars().flatMap(f => Seq("--include-var", f)) ++ |
| 195 | + linkLibraries().flatMap(l => Seq("-l", l)) |
| 196 | + ).call(Task.dest) |
| 197 | + // @formatter:on |
| 198 | + Seq(PathRef(Task.dest)) |
| 199 | + } |
| 200 | + } |
| 201 | + |
| 202 | + override def javacOptions = Task(super.javacOptions() ++ Seq("--enable-preview", "--release", "21")) |
| 203 | +} |
| 204 | + |
| 205 | +trait HasCIRCTPanamaBindingModule extends JavaModule { |
| 206 | + import build_.circtpanamabinding.CIRCTPanamaBinding |
| 207 | + def circtPanamaBindingModule: CIRCTPanamaBinding |
| 208 | + |
| 209 | + override def moduleDeps = super.moduleDeps ++ Some(circtPanamaBindingModule) |
| 210 | + // |
| 211 | + override def javacOptions = Task(super.javacOptions() ++ Seq("--enable-preview", "--release", "21")) |
| 212 | + |
| 213 | + override def forkArgs: T[Seq[String]] = Task( |
| 214 | + super.forkArgs() ++ Seq("--enable-native-access=ALL-UNNAMED", "--enable-preview") |
| 215 | + ++ circtPanamaBindingModule |
| 216 | + .libraryPaths() |
| 217 | + .map(p => s"-Djava.library.path=${p.path}") |
| 218 | + ) |
| 219 | +} |
| 220 | + |
| 221 | +trait HasPanamaLibModule extends ScalaModule with HasCIRCTPanamaBindingModule { |
| 222 | + import build_.panamalib.PanamaLib |
| 223 | + def panamaLibModule: PanamaLib |
| 224 | + |
| 225 | + def circtPanamaBindingModule = panamaLibModule.circtPanamaBindingModule |
| 226 | + |
| 227 | + override def moduleDeps = super.moduleDeps ++ Some(panamaLibModule) |
| 228 | +} |
| 229 | + |
| 230 | +trait HasPanamaOMModule extends ScalaModule with HasCIRCTPanamaBindingModule { |
| 231 | + import build_.panamaom.PanamaOM |
| 232 | + def panamaOMModule: PanamaOM |
| 233 | + |
| 234 | + def circtPanamaBindingModule = panamaOMModule.circtPanamaBindingModule |
| 235 | + |
| 236 | + override def moduleDeps = super.moduleDeps ++ Some(panamaOMModule) |
| 237 | +} |
| 238 | + |
| 239 | +trait HasPanamaConverterModule extends ScalaModule with HasCIRCTPanamaBindingModule { |
| 240 | + import build_.panamaconverter.PanamaConverter |
| 241 | + def panamaConverterModule: PanamaConverter |
| 242 | + |
| 243 | + def circtPanamaBindingModule = panamaConverterModule.circtPanamaBindingModule |
| 244 | + |
| 245 | + override def moduleDeps = super.moduleDeps ++ Some(panamaConverterModule) |
| 246 | +} |
| 247 | + |
| 248 | +// TODO: move chisel src to subfolder once we have dropped sbt flow |
| 249 | +object chisel extends Cross[Chisel](v.scalaCrossVersions) |
| 250 | + |
| 251 | +trait Chisel extends CrossSbtModule with HasScala2MacroAnno with HasScala2Plugin with ScalafmtModule { |
| 252 | + override def millSourcePath = super.millSourcePath / os.up |
| 253 | + def svsimModule = svsim.cross(crossScalaVersion) |
| 254 | + def coreModule = core.cross(crossScalaVersion) |
| 255 | + def pluginModule = plugin.cross() |
| 256 | + |
| 257 | + override def scalacOptions = Task { |
| 258 | + if (v.isScala3(crossScalaVersion)) { |
| 259 | + Seq.empty[String] |
| 260 | + } else { |
| 261 | + super.scalacOptions() ++ v.scala2CommonOptions |
| 262 | + } |
| 263 | + } |
| 264 | + |
| 265 | + override def moduleDeps = super.moduleDeps ++ Seq(coreModule, svsimModule) |
| 266 | + |
| 267 | + object test extends SbtTests with TestModule.ScalaTest with ScalafmtModule { |
| 268 | + def ivyDeps = Agg(v.scalatest, v.scalacheck) |
| 269 | + |
| 270 | + // TODO: enable sandbox and run tests in parallel |
| 271 | + override def testSandboxWorkingDir = false |
| 272 | + |
| 273 | + // Suppress Scala 3 behavior requiring explicit types on implicit definitions |
| 274 | + // Note this must come before the -Wconf is warningSuppression |
| 275 | + override def scalacOptions = Task { super.scalacOptions() :+ "-Wconf:cat=other-implicit-type:s" } |
| 276 | + } |
| 277 | +} |
| 278 | + |
| 279 | +object unipublish extends release.Unipublish |
0 commit comments