-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.sc
282 lines (243 loc) · 10.1 KB
/
build.sc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
import mill._, scalalib._, publish._, scalajslib._, scalanativelib._
import $ivy.`com.github.lolgab::mill-mima::0.1.0`
import $ivy.`de.tototec::de.tobiasroeser.mill.vcs.version::0.4.0`
import de.tobiasroeser.mill.vcs.version.VcsVersion
import com.github.lolgab.mill.mima.{CheckDirection, ProblemFilter, Mima}
import com.github.lolgab.mill.mima.worker.MimaBuildInfo
import com.github.lolgab.mill.mima.IncompatibleSignatureProblem
import com.github.lolgab.mill.mima.worker
import com.github.lolgab.mill.mima.worker.MimaWorkerExternalModule
import scala.util.chaining._
val scala212 = "2.12.18"
val scala213 = "2.13.12"
val scala3 = "3.3.1"
val scalaVersions = Seq(scala212, scala213, scala3)
object unroll extends Cross[UnrollModule](scalaVersions)
trait UnrollModule extends Cross.Module[String]{
trait InnerScalaModule extends CrossScalaModule {
def crossValue = UnrollModule.this.crossValue
override def artifactNameParts: T[Seq[String]] = millModuleSegments.parts.patch(1, Nil, 1)
}
trait InnerScalaJsModule extends InnerScalaModule with ScalaJSModule{
def scalaJSVersion = "1.13.1"
}
trait InnerScalaNativeModule extends InnerScalaModule with ScalaNativeModule{
def scalaNativeVersion = "0.4.14"
}
trait InnerPublishModule extends InnerScalaModule with PublishModule{
def publishVersion = VcsVersion.vcsState().format()
def pomSettings = PomSettings(
description = "Main method argument parser for Scala",
organization = "com.lihaoyi",
url = "https://github.com/com-lihaoyi/unroll",
licenses = Seq(License.MIT),
versionControl = VersionControl.github("com-lihaoyi", "unroll"),
developers = Seq(Developer("lihaoyi", "Li Haoyi", "https://github.com/lihaoyi"))
)
}
object annotation extends InnerPublishModule
object plugin extends InnerPublishModule{
def moduleDeps = Seq(annotation)
def ivyDeps = T{
if (scalaVersion().startsWith("2.")) Agg(ivy"org.scala-lang:scala-compiler:${scalaVersion()}")
else Agg(ivy"org.scala-lang:scala3-compiler_3:${scalaVersion()}")
}
}
object testutils extends InnerScalaModule
val testcases = Seq(
"classMethod",
"objectMethod",
"traitMethod",
"genericMethod",
"curriedMethod",
"methodWithImplicit",
"primaryConstructor",
"secondaryConstructor",
"caseclass",
"secondParameterList",
"abstractTraitMethod",
"abstractClassMethod"
)
object tests extends Cross[Tests](testcases)
trait Tests extends Cross.Module[String]{
override def millSourcePath = super.millSourcePath / crossValue
trait DownstreamModule extends Module{
def jvm: InnerScalaModule
def js: InnerScalaJsModule
def native: InnerScalaNativeModule
}
trait CrossPlatformModule extends Module{
def mimaPrevious = Seq.empty[CrossPlatformModule]
def moduleDeps: Seq[CrossPlatformModule] = Nil
object downstream extends DownstreamModule{
object jvm extends InnerScalaModule with Unrolled {
def run(args: Task[Args] = T.task(Args())) = T.command{/*donothing*/}
def moduleDeps = Seq(CrossPlatformModule.this.jvm)
}
object js extends InnerScalaJsModule with Unrolled {
def run(args: Task[Args] = T.task(Args())) = T.command{/*donothing*/}
def moduleDeps = Seq(CrossPlatformModule.this.js)
}
object native extends InnerScalaNativeModule with Unrolled {
def run(args: Task[Args] = T.task(Args())) = T.command{/*donothing*/}
def moduleDeps = Seq(CrossPlatformModule.this.native)
}
}
trait Unrolled extends InnerScalaModule with PlatformScalaModule{
def moduleDeps: Seq[JavaModule] = Seq(annotation)
def run(args: Task[Args] = T.task(Args())) = T.command{/*donothing*/}
def mimaPreviousArtifacts = T{
if (Tests.this.crossValue == "caseclass" && scalaVersion().startsWith("2.")) Nil
else T.traverse(mimaPrevious)(_.jvm.jar)()
}
def scalacPluginClasspath = T{ Agg(plugin.jar()) }
// override def scalaCompilerClasspath = T{
// super.scalaCompilerClasspath().filter(!_.toString().contains("scala3-compiler")) ++
// Agg(PathRef(os.Path("/Users/lihaoyi/.ivy2/local/org.scala-lang/scala3-compiler_3/3.3.2-RC3-bin-SNAPSHOT/jars/scala3-compiler_3.jar")))
// }
def scalacOptions = T{
Seq(
s"-Xplugin:${plugin.jar().path}",
"-Xplugin-require:unroll",
//"-Xprint:all",
//"-Ydebug-error",
//"-Ydebug-type-error",
//"-Ydebug-trace"
//"-Xprint:typer",
//"-Xprint:unroll",
//"-Xprint:patmat",
//"-Xprint:superaccessors"
)
}
trait UnrolledTestModule extends ScalaModule {
def sources = super.sources() ++ testutils.sources()
def moduleDeps = Seq(Unrolled.this)
def mainClass = Some("unroll.UnrollTestMain")
def testFramework = T{ "" } // stub
}
}
object jvm extends InnerScalaModule with Unrolled with LocalMimaModule{
def moduleDeps = super.moduleDeps ++ CrossPlatformModule.this.moduleDeps.map(_.jvm.asInstanceOf[Unrolled])
object test extends ScalaTests with UnrolledTestModule{
def moduleDeps = Seq(jvm, downstream.jvm)
}
}
object js extends InnerScalaJsModule with Unrolled with LocalMimaModule{
def moduleDeps = super.moduleDeps ++ CrossPlatformModule.this.moduleDeps.map(_.js.asInstanceOf[Unrolled])
object test extends ScalaJSTests with UnrolledTestModule{
def moduleDeps = Seq(js, downstream.js)
}
}
object native extends InnerScalaNativeModule with Unrolled with LocalMimaModule{
def moduleDeps = super.moduleDeps ++ CrossPlatformModule.this.moduleDeps.map(_.native.asInstanceOf[Unrolled])
object test extends ScalaNativeTests with UnrolledTestModule{
def moduleDeps = Seq(native, downstream.native)
}
}
}
// Different versions of Unrolled.scala
object v1 extends CrossPlatformModule{
def mimaPrevious = Seq()
}
object v2 extends CrossPlatformModule {
def mimaPrevious = Seq(v1)
}
object v3 extends CrossPlatformModule {
def mimaPrevious = Seq(v1, v2)
}
// proxy modules used to make sure old versions of UnrolledTestMain.scala can
// successfully call newer versions of the Unrolled.scala
val items =
if (!crossValue.startsWith("abstract")) Seq("v3v2", "v3v1", "v2v1")
else Seq("v3v2", "v3v1", "v2v1", "v2v1v2", "v3v1v3", "v3v1v2", "v3v2v3")
object cross extends Cross[ComparativeModule](items)
trait ComparativeModule extends Cross.Module[String]{
def lookup(x: String): CrossPlatformModule = x match {
case "1" => v1
case "2" => v2
case "3" => v3
}
val (upstream, downstream, test) = crossValue match{
case s"v${a}v${b}v${c}" => (lookup(a), lookup(b), lookup(c))
case s"v${a}v${b}" => (lookup(a), lookup(a), lookup(b))
}
trait ComparativePlatformScalaModule extends PlatformScalaModule{
def sources = super.sources() ++ testutils.sources()
def mainClass = Some("unroll.UnrollTestMain")
}
object jvm extends InnerScalaModule with ComparativePlatformScalaModule{
def runClasspath =
super.runClasspath() ++
Seq(test.jvm.test.compile().classes, upstream.jvm.compile().classes, downstream.downstream.jvm.compile().classes)
}
object js extends InnerScalaJsModule with ComparativePlatformScalaModule{
def runClasspath =
super.runClasspath() ++
Seq(test.js.test.compile().classes, upstream.js.compile().classes, downstream.downstream.js.compile().classes)
}
object native extends InnerScalaNativeModule with ComparativePlatformScalaModule{
def runClasspath =
super.runClasspath() ++
Seq(test.native.test.compile().classes, upstream.native.compile().classes, downstream.downstream.native.compile().classes)
}
}
}
}
// Fork of the Mima trait from `mill-mima`, to allow us to run MIMA against
// two compilation outputs for testing purposes.
trait LocalMimaModule extends ScalaModule{
def mimaWorkerClasspath: T[Agg[PathRef]] = T {
Lib
.resolveDependencies(
repositoriesTask(),
Agg(
ivy"com.github.lolgab:mill-mima-worker-impl_2.13:${MimaBuildInfo.publishVersion}"
.exclude("com.github.lolgab" -> "mill-mima-worker-api_2.13")
).map(Lib.depToBoundDep(_, mill.main.BuildInfo.scalaVersion)),
ctx = Some(T.log)
)
}
def mimaWorker2: Task[worker.api.MimaWorkerApi] = T.task {
val cp = mimaWorkerClasspath()
MimaWorkerExternalModule.mimaWorker().impl(cp)
}
def mimaCurrentArtifact: T[PathRef] = jar()
def mimaPreviousArtifacts: T[Seq[PathRef]]
def mimaReportBinaryIssues(): Command[Unit] = T.command {
val logDebug: java.util.function.Consumer[String] = T.log.debug(_)
val logError: java.util.function.Consumer[String] = T.log.error(_)
val logPrintln: java.util.function.Consumer[String] =
T.log.outputStream.println(_)
val runClasspathIO =
runClasspath().view.map(_.path).filter(os.exists).map(_.toIO).toArray
val current = mimaCurrentArtifact().path.pipe {
case p if os.exists(p) => p
case _ => (T.dest / "emptyClasses").tap(os.makeDir)
}.toIO
val previous = mimaPreviousArtifacts().iterator.map {
case artifact =>
new worker.api.Artifact(artifact.path.toString, artifact.path.toIO)
}.toArray
val checkDirection = worker.api.CheckDirection.Backward
val errorOpt: java.util.Optional[String] = mimaWorker2().reportBinaryIssues(
scalaVersion() match{
case s"2.$x.$y" => s"2.$x"
case s"3.$x.$y" => s"3"
},
logDebug,
logError,
logPrintln,
checkDirection,
runClasspathIO,
previous,
current,
Array(),
new java.util.HashMap(),
new java.util.HashMap(),
Array(),
"dev"
)
if (errorOpt.isPresent()) mill.api.Result.Failure(errorOpt.get())
else mill.api.Result.Success(())
}
}