@@ -61,6 +61,7 @@ val partestDep = withoutScalaLang("org.scala-lang.modules" %% "scala-partest" %
61
61
val partestInterfaceDep = withoutScalaLang(" org.scala-lang.modules" %% " scala-partest-interface" % " 0.5.0" )
62
62
val junitDep = " junit" % " junit" % " 4.11"
63
63
val junitIntefaceDep = " com.novocode" % " junit-interface" % " 0.11" % " test"
64
+ val asmDep = " org.scala-lang.modules" % " scala-asm" % versionProps(" scala-asm.version" )
64
65
val jlineDep = " jline" % " jline" % versionProps(" jline.version" )
65
66
val antDep = " org.apache.ant" % " ant" % " 1.9.4"
66
67
val scalacheckDep = withoutScalaLang(" org.scalacheck" %% " scalacheck" % " 1.11.4" )
@@ -169,17 +170,22 @@ lazy val compiler = configureAsSubproject(project)
169
170
.settings(generatePropertiesFileSettings : _* )
170
171
.settings(
171
172
name := " scala-compiler" ,
172
- libraryDependencies += antDep,
173
+ libraryDependencies ++= Seq ( antDep, asmDep) ,
173
174
// this a way to make sure that classes from interactive and scaladoc projects
174
175
// end up in compiler jar (that's what Ant build does)
175
176
// we need to use LocalProject references (with strings) to deal with mutual recursion
176
177
mappings in Compile in packageBin :=
177
178
(mappings in Compile in packageBin).value ++
179
+ dependencyClasses(
180
+ (externalDependencyClasspath in Compile ).value,
181
+ modules = Set (asmDep),
182
+ keep = " *.class" || " scala-asm.properties" ,
183
+ streams.value.cacheDirectory) ++
178
184
(mappings in Compile in packageBin in LocalProject (" interactive" )).value ++
179
185
(mappings in Compile in packageBin in LocalProject (" scaladoc" )).value ++
180
186
(mappings in Compile in packageBin in LocalProject (" repl" )).value,
181
187
includeFilter in unmanagedResources in Compile := compilerIncludes)
182
- .dependsOn(library, reflect, asm )
188
+ .dependsOn(library, reflect)
183
189
184
190
lazy val interactive = configureAsSubproject(project)
185
191
.settings(disableDocsAndPublishingTasks : _* )
@@ -209,8 +215,6 @@ lazy val actors = configureAsSubproject(project)
209
215
210
216
lazy val forkjoin = configureAsForkOfJavaProject(project)
211
217
212
- lazy val asm = configureAsForkOfJavaProject(project)
213
-
214
218
lazy val partestExtras = configureAsSubproject(Project (" partest-extras" , file(" ." ) / " src" / " partest-extras" ))
215
219
.dependsOn(repl)
216
220
.settings(clearSourceAndResourceDirectories : _* )
@@ -231,9 +235,9 @@ lazy val junit = project.in(file("test") / "junit")
231
235
)
232
236
233
237
lazy val partestJavaAgent = (project in file(" ." ) / " src" / " partest-javaagent" ).
234
- dependsOn(asm).
235
238
settings(commonSettings : _* ).
236
239
settings(
240
+ libraryDependencies += asmDep,
237
241
doc := file(" !!! NO DOCS !!!" ),
238
242
publishLocal := {},
239
243
publish := {},
@@ -249,13 +253,13 @@ lazy val partestJavaAgent = (project in file(".") / "src" / "partest-javaagent")
249
253
)
250
254
251
255
lazy val test = project.
252
- dependsOn(compiler, interactive, actors, repl, scalap, partestExtras, partestJavaAgent, asm, scaladoc).
256
+ dependsOn(compiler, interactive, actors, repl, scalap, partestExtras, partestJavaAgent, scaladoc).
253
257
configs(IntegrationTest ).
254
258
settings(disableDocsAndPublishingTasks : _* ).
255
259
settings(commonSettings : _* ).
256
260
settings(Defaults .itSettings: _* ).
257
261
settings(
258
- libraryDependencies ++= Seq (partestDep, scalaXmlDep, partestInterfaceDep, scalacheckDep),
262
+ libraryDependencies ++= Seq (asmDep, partestDep, scalaXmlDep, partestInterfaceDep, scalacheckDep),
259
263
unmanagedBase in Test := baseDirectory.value / " files" / " lib" ,
260
264
unmanagedJars in Test <+= (unmanagedBase) (j => Attributed .blank(j)) map(identity),
261
265
// no main sources
@@ -279,7 +283,7 @@ lazy val test = project.
279
283
)
280
284
281
285
lazy val root = (project in file(" ." )).
282
- aggregate(library, forkjoin, reflect, compiler, asm, interactive, repl,
286
+ aggregate(library, forkjoin, reflect, compiler, interactive, repl,
283
287
scaladoc, scalap, actors, partestExtras, junit).settings(
284
288
sources in Compile := Seq .empty,
285
289
onLoadMessage := """ |*** Welcome to the sbt build definition for Scala! ***
@@ -310,7 +314,7 @@ def configureAsSubproject(project: Project): Project = {
310
314
311
315
/**
312
316
* Configuration for subprojects that are forks of some Java projects
313
- * we depend on. At the moment there are just two: asm and forkjoin.
317
+ * we depend on. At the moment there's just forkjoin.
314
318
*
315
319
* We do not publish artifacts for those projects but we package their
316
320
* binaries in a jar of other project (compiler or library).
@@ -382,6 +386,50 @@ lazy val generateVersionPropertiesFileImpl: Def.Initialize[Task[File]] = Def.tas
382
386
propFile
383
387
}
384
388
389
+ /**
390
+ * Extract selected dependencies to the `cacheDirectory` and return a mapping for the content.
391
+ * Heavily inspired by sbt-assembly (https://github.com/sbt/sbt-assembly/blob/0.13.0/src/main/scala/sbtassembly/Assembly.scala#L157)
392
+ */
393
+ def dependencyClasses (dependencies : Classpath , modules : Set [ModuleID ], keep : FileFilter , cacheDirectory : File ): Seq [(File , String )] = {
394
+ val dependencyFiles : Seq [File ] = dependencies.map(_.data).toSeq
395
+ val toInclude = dependencyFiles.filter(f => {
396
+ val p = f.getCanonicalPath
397
+ modules.exists(m => {
398
+ // works for both .m2 (org/scala-lang/modules/scala-asm/5.0.3-scala-3/scala-asm-5.0.3-scala-3.jar)
399
+ // and .ivy2 (org.scala-lang.modules/scala-asm/5.0.3-scala-3/bundles/scala-asm.jar)
400
+ val nameParts = m.organization.split('.' ).toSet + m.name + m.revision
401
+ nameParts.forall(p.contains)
402
+ })
403
+ })
404
+ assert(toInclude.forall(sbt.classpath.ClasspathUtilities .isArchive), s " Expected JAR files as dependencies: $toInclude" )
405
+
406
+ val tempDir = cacheDirectory / " unpackedDependencies"
407
+
408
+ def sha1name (f : File ): String = bytesToSha1String(f.getCanonicalPath.getBytes(" UTF-8" ))
409
+ def sha1content (f : File ): String = bytesToSha1String(IO .readBytes(f))
410
+ def bytesToSha1String (bytes : Array [Byte ]): String = {
411
+ val sha1 = java.security.MessageDigest .getInstance(" SHA-1" )
412
+ val hash = sha1.digest(bytes)
413
+ hash map {" %02x" .format(_)} mkString
414
+ }
415
+
416
+ val jarDirs : Seq [File ] = for (jar <- toInclude) yield {
417
+ val jarName = jar.getName
418
+ val hash = sha1name(jar) + " _" + sha1content(jar)
419
+ val jarNamePath = tempDir / (hash + " .jarName" )
420
+ val dest = tempDir / hash
421
+ if (! jarNamePath.exists || IO .read(jarNamePath) != jar.getCanonicalPath) {
422
+ IO .delete(dest)
423
+ dest.mkdir()
424
+ IO .unzip(jar, dest)
425
+ IO .write(jarNamePath, jar.getCanonicalPath, IO .utf8, append = false )
426
+ }
427
+ dest
428
+ }
429
+
430
+ jarDirs.flatMap(dir => dir ** keep --- dir pair relativeTo(dir))
431
+ }
432
+
385
433
// Defining these settings is somewhat redundant as we also redefine settings that depend on them.
386
434
// However, IntelliJ's project import works better when these are set correctly.
387
435
def clearSourceAndResourceDirectories = Seq (Compile , Test ).flatMap(config => inConfig(config)(Seq (
0 commit comments