Skip to content

Commit e82b0a9

Browse files
szeigerretronym
authored andcommitted
Publish usable Scala distributions to Ivy repositories
- sbt requires a `default` configuration in the Scala distribution but doesn’t publish such a configuration to Ivy repositories by default. This is not a problem when publishing to a Maven repository because Maven doesn’t use the concept of configurations and Ivy creates a standard set (including `default`) when resolving artifacts from Maven repositories, but it prevents the use of any Scala distribution published with `publishLocal`. The underlying issue is that sbt requires `default` instead of `default(compile)`. We work around this limitation by publishing a dummy `default` configuration. - sbt has hardcoded dependencies on the `scala-library` artifact of type `jar`. In the tradition of `sbt-osgi` we used type `bundle` when publishing via Ivy but this makes the artifacts unusable from sbt. We now publish the OSGi bundles directly as type `jar` (which is compatible with how they appear in Ivy after resolving from a Maven repository). - We have to be more aggressive about not publishing certain subprojects, otherwise `ivy.xml` files could still be published even when using `publishArtifacts := false`. - `removePomDependencies` now also modifies `ivy.xml` in addition to the Maven POM so that bogus dependencies do not leak into the Ivy descriptors. Fixes scala/scala-dev#130
1 parent 1b1bc81 commit e82b0a9

File tree

2 files changed

+48
-22
lines changed

2 files changed

+48
-22
lines changed

build.sbt

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ lazy val publishSettings : Seq[Setting[_]] = Seq(
8484
val mappings = artifacts.toSeq.map { case (a, f) =>
8585
val typeSuffix = a.`type` match {
8686
case "pom" => "-pom.xml"
87-
case "bundle" | "jar" => ".jar"
87+
case "jar" => ".jar"
8888
case "doc" => "-docs.jar"
8989
case tpe => s"-$tpe.${a.extension}"
9090
}
@@ -99,6 +99,7 @@ lazy val publishSettings : Seq[Setting[_]] = Seq(
9999
if (file.exists) List(Credentials(file))
100100
else Nil
101101
},
102+
ivyConfigurations += Configuration("default", "Default", true, List(Configurations.Runtime), true),
102103
publishMavenStyle := true
103104
)
104105

@@ -236,8 +237,8 @@ def fixPom(extra: (String, scala.xml.Node)*): Setting[_] = {
236237
) ++ extra) }
237238
}
238239

239-
/** Remove unwanted dependencies from the POM. */
240-
def removePomDependencies(deps: (String, String)*): Setting[_] = {
240+
/** Remove unwanted dependencies from the POM and ivy.xml. */
241+
def removePomDependencies(deps: (String, String)*): Seq[Setting[_]] = Seq(
241242
pomPostProcess := { n =>
242243
val n2 = pomPostProcess.value.apply(n)
243244
import scala.xml._
@@ -252,14 +253,40 @@ def removePomDependencies(deps: (String, String)*): Setting[_] = {
252253
case n => Seq(n)
253254
}
254255
})).transform(Seq(n2)).head
256+
},
257+
deliverLocal := {
258+
import scala.xml._
259+
import scala.xml.transform._
260+
val f = deliverLocal.value
261+
val e = (new RuleTransformer(new RewriteRule {
262+
override def transform(node: Node) = node match {
263+
case e: Elem if e.label == "dependency" && {
264+
val org = e.attribute("org").getOrElse("").toString
265+
val name = e.attribute("name").getOrElse("").toString
266+
deps.exists { case (g, a) =>
267+
org == g && (name == a || name == (a + "_" + scalaBinaryVersion.value))
268+
}
269+
} => Seq.empty
270+
case n => Seq(n)
271+
}
272+
})).transform(Seq(XML.loadFile(f))).head
273+
XML.save(f.getAbsolutePath, e)
274+
f
255275
}
256-
}
276+
)
257277

258278
val disableDocs = Seq[Setting[_]](
259279
sources in (Compile, doc) := Seq.empty,
260280
publishArtifact in (Compile, packageDoc) := false
261281
)
262282

283+
val disablePublishing = Seq[Setting[_]](
284+
publishArtifact := false,
285+
// The above is enough for Maven repos but it doesn't prevent publishing of ivy.xml files
286+
publish := {},
287+
publishLocal := {}
288+
)
289+
263290
lazy val setJarLocation: Setting[_] =
264291
artifactPath in packageBin in Compile := {
265292
// two lines below are copied over from sbt's sources:
@@ -397,43 +424,44 @@ lazy val compiler = configureAsSubproject(project)
397424
"/project/description" -> <description>Compiler for the Scala Programming Language</description>,
398425
"/project/packaging" -> <packaging>jar</packaging>
399426
),
400-
apiURL := None,
401-
removePomDependencies(
402-
("org.apache.ant", "ant"),
403-
("org.scala-lang.modules", "scala-asm")
404-
)
427+
apiURL := None
405428
)
429+
.settings(removePomDependencies(
430+
("org.apache.ant", "ant"),
431+
("org.scala-lang.modules", "scala-asm")
432+
): _*)
406433
.dependsOn(library, reflect)
407434

408435
lazy val interactive = configureAsSubproject(project)
409436
.settings(disableDocs: _*)
437+
.settings(disablePublishing: _*)
410438
.settings(
411439
name := "scala-compiler-interactive",
412-
description := "Scala Interactive Compiler",
413-
publishArtifact := false
440+
description := "Scala Interactive Compiler"
414441
)
415442
.dependsOn(compiler)
416443

417444
lazy val repl = configureAsSubproject(project)
418445
.settings(disableDocs: _*)
446+
.settings(disablePublishing: _*)
419447
.settings(
420448
connectInput in run := true,
421-
publishArtifact := false,
422449
run <<= (run in Compile).partialInput(" -usejavacp") // Automatically add this so that `repl/run` works without additional arguments.
423450
)
424451
.dependsOn(compiler, interactive)
425452

426453
lazy val replJline = configureAsSubproject(Project("repl-jline", file(".") / "src" / "repl-jline"))
427454
.settings(disableDocs: _*)
455+
.settings(disablePublishing: _*)
428456
.settings(
429457
libraryDependencies += jlineDep,
430-
name := "scala-repl-jline",
431-
publishArtifact := false
458+
name := "scala-repl-jline"
432459
)
433460
.dependsOn(repl)
434461

435462
lazy val replJlineEmbedded = Project("repl-jline-embedded", file(".") / "target" / "repl-jline-embedded-src-dummy")
436463
.settings(scalaSubprojectSettings: _*)
464+
.settings(disablePublishing: _*)
437465
.settings(
438466
name := "scala-repl-jline-embedded",
439467
// There is nothing to compile for this project. Instead we use the compile task to create
@@ -464,18 +492,17 @@ lazy val replJlineEmbedded = Project("repl-jline-embedded", file(".") / "target"
464492
val outdir = (classDirectory in Compile).value
465493
JarJar(inputs, outdir, config)
466494
}),
467-
publishArtifact := false,
468495
connectInput in run := true
469496
)
470497
.dependsOn(replJline)
471498

472499
lazy val scaladoc = configureAsSubproject(project)
473500
.settings(disableDocs: _*)
501+
.settings(disablePublishing: _*)
474502
.settings(
475503
name := "scala-compiler-doc",
476504
description := "Scala Documentation Generator",
477505
libraryDependencies ++= Seq(scalaXmlDep, scalaParserCombinatorsDep, partestDep),
478-
publishArtifact := false,
479506
includeFilter in unmanagedResources in Compile := "*.html" | "*.css" | "*.gif" | "*.png" | "*.js" | "*.txt"
480507
)
481508
.dependsOn(compiler)
@@ -497,10 +524,10 @@ lazy val partestExtras = configureAsSubproject(Project("partest-extras", file(".
497524
.dependsOn(replJlineEmbedded)
498525
.settings(clearSourceAndResourceDirectories: _*)
499526
.settings(disableDocs: _*)
527+
.settings(disablePublishing: _*)
500528
.settings(
501529
name := "scala-partest-extras",
502530
description := "Scala Compiler Testing Tool (compiler-specific extras)",
503-
publishArtifact := false,
504531
libraryDependencies += partestDep,
505532
unmanagedSourceDirectories in Compile := List(baseDirectory.value)
506533
)
@@ -510,8 +537,8 @@ lazy val junit = project.in(file("test") / "junit")
510537
.settings(clearSourceAndResourceDirectories: _*)
511538
.settings(commonSettings: _*)
512539
.settings(disableDocs: _*)
540+
.settings(disablePublishing: _*)
513541
.settings(
514-
publishArtifact := false,
515542
fork in Test := true,
516543
libraryDependencies ++= Seq(junitDep, junitIntefaceDep),
517544
testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v"),
@@ -543,9 +570,9 @@ lazy val test = project
543570
.configs(IntegrationTest)
544571
.settings(commonSettings: _*)
545572
.settings(disableDocs: _*)
573+
.settings(disablePublishing: _*)
546574
.settings(Defaults.itSettings: _*)
547575
.settings(
548-
publishArtifact := false,
549576
libraryDependencies ++= Seq(asmDep, partestDep, scalaXmlDep, scalacheckDep),
550577
unmanagedBase in IntegrationTest := baseDirectory.value / "files" / "lib",
551578
unmanagedJars in IntegrationTest <+= (unmanagedBase) (j => Attributed.blank(j)) map(identity),
@@ -572,8 +599,8 @@ lazy val test = project
572599

573600
lazy val manual = configureAsSubproject(project)
574601
.settings(disableDocs: _*)
602+
.settings(disablePublishing: _*)
575603
.settings(
576-
publishArtifact := false,
577604
libraryDependencies ++= Seq(scalaXmlDep, antDep),
578605
classDirectory in Compile := (target in Compile).value / "classes"
579606
)
@@ -643,9 +670,9 @@ lazy val scalaDist = Project("scala-dist", file(".") / "target" / "scala-dist-di
643670

644671
lazy val root = (project in file("."))
645672
.settings(disableDocs: _*)
673+
.settings(disablePublishing: _*)
646674
.settings(generateBuildCharacterFileSettings: _*)
647675
.settings(
648-
publishArtifact := false,
649676
publish := {},
650677
publishLocal := {},
651678
commands ++= ScriptCommands.all,

project/Osgi.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ object Osgi {
4040
},
4141
packagedArtifact in (Compile, packageBin) <<= (artifact in (Compile, packageBin), bundle).identityMap,
4242
// Also create OSGi source bundles:
43-
artifact in (Compile, packageBin) ~= (_.copy(`type` = "bundle")),
4443
packageOptions in (Compile, packageSrc) += Package.ManifestAttributes(
4544
"Bundle-Name" -> (description.value + " Sources"),
4645
"Bundle-SymbolicName" -> (bundleSymbolicName.value + ".source"),

0 commit comments

Comments
 (0)