Skip to content

Commit

Permalink
Subsume platform cross building
Browse files Browse the repository at this point in the history
Problem
In sbt 1, platform cross building is implemented using in the user-land
using `%%%` operator, which clevery handles both Scala cross building
and appending platform suffix like sjs1.
However, in general symbolic `%%%` is confusing, and hard to explain.

Solution
In sbt 2, we should subsume the idea of platform cross building,
so `%%` can act as the current `%%%` operator.
This adds a new field called `platformOpt` to `ModuleID`, which
by default will be set to `None`.
`ScalaModuleInfo` will also add a new field called `platform`,
which can be set to `None`, `Some(sjs1)` etc.
As part of module transformation (like adding `_2.13`), the library
management engine can transform `ModuleID` to `sjs1` etc.
`("com.github.scopt" %% "scopt" % "4.1.0").platform(jvm)` will
explicitly use the JVM version of dependency (equivalent to today's `%%`).
  • Loading branch information
eed3si9n committed Mar 12, 2023
1 parent f0c54a9 commit 47ef80e
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,24 @@ final class ModuleID private (
val exclusions: Vector[sbt.librarymanagement.InclExclRule],
val extraAttributes: Map[String, String],
val crossVersion: sbt.librarymanagement.CrossVersion,
val branchName: Option[String]) extends sbt.librarymanagement.ModuleIDExtra with Serializable {
val branchName: Option[String],
val platformOpt: Option[String]) extends sbt.librarymanagement.ModuleIDExtra with Serializable {

private def this(organization: String, name: String, revision: String) = this(organization, name, revision, None, false, true, false, Vector.empty, Vector.empty, Vector.empty, Map.empty, sbt.librarymanagement.Disabled(), None)
private def this(organization: String, name: String, revision: String) = this(organization, name, revision, None, false, true, false, Vector.empty, Vector.empty, Vector.empty, Map.empty, sbt.librarymanagement.Disabled(), None, None)
private def this(organization: String, name: String, revision: String, configurations: Option[String], isChanging: Boolean, isTransitive: Boolean, isForce: Boolean, explicitArtifacts: Vector[sbt.librarymanagement.Artifact], inclusions: Vector[sbt.librarymanagement.InclExclRule], exclusions: Vector[sbt.librarymanagement.InclExclRule], extraAttributes: Map[String, String], crossVersion: sbt.librarymanagement.CrossVersion, branchName: Option[String]) = this(organization, name, revision, configurations, isChanging, isTransitive, isForce, explicitArtifacts, inclusions, exclusions, extraAttributes, crossVersion, branchName, None)

override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
case x: ModuleID => (this.organization == x.organization) && (this.name == x.name) && (this.revision == x.revision) && (this.configurations == x.configurations) && (this.isChanging == x.isChanging) && (this.isTransitive == x.isTransitive) && (this.isForce == x.isForce) && (this.explicitArtifacts == x.explicitArtifacts) && (this.inclusions == x.inclusions) && (this.exclusions == x.exclusions) && (this.extraAttributes == x.extraAttributes) && (this.crossVersion == x.crossVersion) && (this.branchName == x.branchName)
case x: ModuleID => (this.organization == x.organization) && (this.name == x.name) && (this.revision == x.revision) && (this.configurations == x.configurations) && (this.isChanging == x.isChanging) && (this.isTransitive == x.isTransitive) && (this.isForce == x.isForce) && (this.explicitArtifacts == x.explicitArtifacts) && (this.inclusions == x.inclusions) && (this.exclusions == x.exclusions) && (this.extraAttributes == x.extraAttributes) && (this.crossVersion == x.crossVersion) && (this.branchName == x.branchName) && (this.platformOpt == x.platformOpt)
case _ => false
})
override def hashCode: Int = {
37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.librarymanagement.ModuleID".##) + organization.##) + name.##) + revision.##) + configurations.##) + isChanging.##) + isTransitive.##) + isForce.##) + explicitArtifacts.##) + inclusions.##) + exclusions.##) + extraAttributes.##) + crossVersion.##) + branchName.##)
37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.librarymanagement.ModuleID".##) + organization.##) + name.##) + revision.##) + configurations.##) + isChanging.##) + isTransitive.##) + isForce.##) + explicitArtifacts.##) + inclusions.##) + exclusions.##) + extraAttributes.##) + crossVersion.##) + branchName.##) + platformOpt.##)
}
override def toString: String = {
this.toStringImpl
}
private[this] def copy(organization: String = organization, name: String = name, revision: String = revision, configurations: Option[String] = configurations, isChanging: Boolean = isChanging, isTransitive: Boolean = isTransitive, isForce: Boolean = isForce, explicitArtifacts: Vector[sbt.librarymanagement.Artifact] = explicitArtifacts, inclusions: Vector[sbt.librarymanagement.InclExclRule] = inclusions, exclusions: Vector[sbt.librarymanagement.InclExclRule] = exclusions, extraAttributes: Map[String, String] = extraAttributes, crossVersion: sbt.librarymanagement.CrossVersion = crossVersion, branchName: Option[String] = branchName): ModuleID = {
new ModuleID(organization, name, revision, configurations, isChanging, isTransitive, isForce, explicitArtifacts, inclusions, exclusions, extraAttributes, crossVersion, branchName)
private[this] def copy(organization: String = organization, name: String = name, revision: String = revision, configurations: Option[String] = configurations, isChanging: Boolean = isChanging, isTransitive: Boolean = isTransitive, isForce: Boolean = isForce, explicitArtifacts: Vector[sbt.librarymanagement.Artifact] = explicitArtifacts, inclusions: Vector[sbt.librarymanagement.InclExclRule] = inclusions, exclusions: Vector[sbt.librarymanagement.InclExclRule] = exclusions, extraAttributes: Map[String, String] = extraAttributes, crossVersion: sbt.librarymanagement.CrossVersion = crossVersion, branchName: Option[String] = branchName, platformOpt: Option[String] = platformOpt): ModuleID = {
new ModuleID(organization, name, revision, configurations, isChanging, isTransitive, isForce, explicitArtifacts, inclusions, exclusions, extraAttributes, crossVersion, branchName, platformOpt)
}
def withOrganization(organization: String): ModuleID = {
copy(organization = organization)
Expand Down Expand Up @@ -73,9 +75,13 @@ final class ModuleID private (
def withBranchName(branchName: Option[String]): ModuleID = {
copy(branchName = branchName)
}
def withPlatformOpt(platformOpt: Option[String]): ModuleID = {
copy(platformOpt = platformOpt)
}
}
object ModuleID extends sbt.librarymanagement.ModuleIDFunctions {

def apply(organization: String, name: String, revision: String): ModuleID = new ModuleID(organization, name, revision)
def apply(organization: String, name: String, revision: String, configurations: Option[String], isChanging: Boolean, isTransitive: Boolean, isForce: Boolean, explicitArtifacts: Vector[sbt.librarymanagement.Artifact], inclusions: Vector[sbt.librarymanagement.InclExclRule], exclusions: Vector[sbt.librarymanagement.InclExclRule], extraAttributes: Map[String, String], crossVersion: sbt.librarymanagement.CrossVersion, branchName: Option[String]): ModuleID = new ModuleID(organization, name, revision, configurations, isChanging, isTransitive, isForce, explicitArtifacts, inclusions, exclusions, extraAttributes, crossVersion, branchName)
def apply(organization: String, name: String, revision: String, configurations: Option[String], isChanging: Boolean, isTransitive: Boolean, isForce: Boolean, explicitArtifacts: Vector[sbt.librarymanagement.Artifact], inclusions: Vector[sbt.librarymanagement.InclExclRule], exclusions: Vector[sbt.librarymanagement.InclExclRule], extraAttributes: Map[String, String], crossVersion: sbt.librarymanagement.CrossVersion, branchName: Option[String], platformOpt: Option[String]): ModuleID = new ModuleID(organization, name, revision, configurations, isChanging, isTransitive, isForce, explicitArtifacts, inclusions, exclusions, extraAttributes, crossVersion, branchName, platformOpt)
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ implicit lazy val ModuleIDFormat: JsonFormat[sbt.librarymanagement.ModuleID] = n
val extraAttributes = unbuilder.readField[Map[String, String]]("extraAttributes")
val crossVersion = unbuilder.readField[sbt.librarymanagement.CrossVersion]("crossVersion")
val branchName = unbuilder.readField[Option[String]]("branchName")
val platformOpt = unbuilder.readField[Option[String]]("platformOpt")
unbuilder.endObject()
sbt.librarymanagement.ModuleID(organization, name, revision, configurations, isChanging, isTransitive, isForce, explicitArtifacts, inclusions, exclusions, extraAttributes, crossVersion, branchName)
sbt.librarymanagement.ModuleID(organization, name, revision, configurations, isChanging, isTransitive, isForce, explicitArtifacts, inclusions, exclusions, extraAttributes, crossVersion, branchName, platformOpt)
case None =>
deserializationError("Expected JsObject but found None")
}
Expand All @@ -45,6 +46,7 @@ implicit lazy val ModuleIDFormat: JsonFormat[sbt.librarymanagement.ModuleID] = n
builder.addField("extraAttributes", obj.extraAttributes)
builder.addField("crossVersion", obj.crossVersion)
builder.addField("branchName", obj.branchName)
builder.addField("platformOpt", obj.platformOpt)
builder.endObject()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,24 @@ final class ScalaModuleInfo private (
val filterImplicit: Boolean,
val overrideScalaVersion: Boolean,
val scalaOrganization: String,
val scalaArtifacts: scala.Vector[String]) extends Serializable {
val scalaArtifacts: scala.Vector[String],
val platform: Option[String]) extends Serializable {

private def this(scalaFullVersion: String, scalaBinaryVersion: String, configurations: Vector[sbt.librarymanagement.Configuration], checkExplicit: Boolean, filterImplicit: Boolean, overrideScalaVersion: Boolean) = this(scalaFullVersion, scalaBinaryVersion, configurations, checkExplicit, filterImplicit, overrideScalaVersion, sbt.librarymanagement.ScalaArtifacts.Organization, sbt.librarymanagement.ScalaArtifacts.Artifacts)
private def this(scalaFullVersion: String, scalaBinaryVersion: String, configurations: Vector[sbt.librarymanagement.Configuration], checkExplicit: Boolean, filterImplicit: Boolean, overrideScalaVersion: Boolean) = this(scalaFullVersion, scalaBinaryVersion, configurations, checkExplicit, filterImplicit, overrideScalaVersion, sbt.librarymanagement.ScalaArtifacts.Organization, sbt.librarymanagement.ScalaArtifacts.Artifacts, None)
private def this(scalaFullVersion: String, scalaBinaryVersion: String, configurations: Vector[sbt.librarymanagement.Configuration], checkExplicit: Boolean, filterImplicit: Boolean, overrideScalaVersion: Boolean, scalaOrganization: String, scalaArtifacts: scala.Vector[String]) = this(scalaFullVersion, scalaBinaryVersion, configurations, checkExplicit, filterImplicit, overrideScalaVersion, scalaOrganization, scalaArtifacts, None)

override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
case x: ScalaModuleInfo => (this.scalaFullVersion == x.scalaFullVersion) && (this.scalaBinaryVersion == x.scalaBinaryVersion) && (this.configurations == x.configurations) && (this.checkExplicit == x.checkExplicit) && (this.filterImplicit == x.filterImplicit) && (this.overrideScalaVersion == x.overrideScalaVersion) && (this.scalaOrganization == x.scalaOrganization) && (this.scalaArtifacts == x.scalaArtifacts)
case x: ScalaModuleInfo => (this.scalaFullVersion == x.scalaFullVersion) && (this.scalaBinaryVersion == x.scalaBinaryVersion) && (this.configurations == x.configurations) && (this.checkExplicit == x.checkExplicit) && (this.filterImplicit == x.filterImplicit) && (this.overrideScalaVersion == x.overrideScalaVersion) && (this.scalaOrganization == x.scalaOrganization) && (this.scalaArtifacts == x.scalaArtifacts) && (this.platform == x.platform)
case _ => false
})
override def hashCode: Int = {
37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.librarymanagement.ScalaModuleInfo".##) + scalaFullVersion.##) + scalaBinaryVersion.##) + configurations.##) + checkExplicit.##) + filterImplicit.##) + overrideScalaVersion.##) + scalaOrganization.##) + scalaArtifacts.##)
37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.librarymanagement.ScalaModuleInfo".##) + scalaFullVersion.##) + scalaBinaryVersion.##) + configurations.##) + checkExplicit.##) + filterImplicit.##) + overrideScalaVersion.##) + scalaOrganization.##) + scalaArtifacts.##) + platform.##)
}
override def toString: String = {
"ScalaModuleInfo(" + scalaFullVersion + ", " + scalaBinaryVersion + ", " + configurations + ", " + checkExplicit + ", " + filterImplicit + ", " + overrideScalaVersion + ", " + scalaOrganization + ", " + scalaArtifacts + ")"
"ScalaModuleInfo(" + scalaFullVersion + ", " + scalaBinaryVersion + ", " + configurations + ", " + checkExplicit + ", " + filterImplicit + ", " + overrideScalaVersion + ", " + scalaOrganization + ", " + scalaArtifacts + ", " + platform + ")"
}
private[this] def copy(scalaFullVersion: String = scalaFullVersion, scalaBinaryVersion: String = scalaBinaryVersion, configurations: Vector[sbt.librarymanagement.Configuration] = configurations, checkExplicit: Boolean = checkExplicit, filterImplicit: Boolean = filterImplicit, overrideScalaVersion: Boolean = overrideScalaVersion, scalaOrganization: String = scalaOrganization, scalaArtifacts: scala.Vector[String] = scalaArtifacts): ScalaModuleInfo = {
new ScalaModuleInfo(scalaFullVersion, scalaBinaryVersion, configurations, checkExplicit, filterImplicit, overrideScalaVersion, scalaOrganization, scalaArtifacts)
private[this] def copy(scalaFullVersion: String = scalaFullVersion, scalaBinaryVersion: String = scalaBinaryVersion, configurations: Vector[sbt.librarymanagement.Configuration] = configurations, checkExplicit: Boolean = checkExplicit, filterImplicit: Boolean = filterImplicit, overrideScalaVersion: Boolean = overrideScalaVersion, scalaOrganization: String = scalaOrganization, scalaArtifacts: scala.Vector[String] = scalaArtifacts, platform: Option[String] = platform): ScalaModuleInfo = {
new ScalaModuleInfo(scalaFullVersion, scalaBinaryVersion, configurations, checkExplicit, filterImplicit, overrideScalaVersion, scalaOrganization, scalaArtifacts, platform)
}
def withScalaFullVersion(scalaFullVersion: String): ScalaModuleInfo = {
copy(scalaFullVersion = scalaFullVersion)
Expand All @@ -53,9 +55,13 @@ final class ScalaModuleInfo private (
def withScalaArtifacts(scalaArtifacts: scala.Vector[String]): ScalaModuleInfo = {
copy(scalaArtifacts = scalaArtifacts)
}
def withPlatform(platform: Option[String]): ScalaModuleInfo = {
copy(platform = platform)
}
}
object ScalaModuleInfo {

def apply(scalaFullVersion: String, scalaBinaryVersion: String, configurations: Vector[sbt.librarymanagement.Configuration], checkExplicit: Boolean, filterImplicit: Boolean, overrideScalaVersion: Boolean): ScalaModuleInfo = new ScalaModuleInfo(scalaFullVersion, scalaBinaryVersion, configurations, checkExplicit, filterImplicit, overrideScalaVersion)
def apply(scalaFullVersion: String, scalaBinaryVersion: String, configurations: Vector[sbt.librarymanagement.Configuration], checkExplicit: Boolean, filterImplicit: Boolean, overrideScalaVersion: Boolean, scalaOrganization: String, scalaArtifacts: scala.Vector[String]): ScalaModuleInfo = new ScalaModuleInfo(scalaFullVersion, scalaBinaryVersion, configurations, checkExplicit, filterImplicit, overrideScalaVersion, scalaOrganization, scalaArtifacts)
def apply(scalaFullVersion: String, scalaBinaryVersion: String, configurations: Vector[sbt.librarymanagement.Configuration], checkExplicit: Boolean, filterImplicit: Boolean, overrideScalaVersion: Boolean, scalaOrganization: String, scalaArtifacts: scala.Vector[String], platform: Option[String]): ScalaModuleInfo = new ScalaModuleInfo(scalaFullVersion, scalaBinaryVersion, configurations, checkExplicit, filterImplicit, overrideScalaVersion, scalaOrganization, scalaArtifacts, platform)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ implicit lazy val ScalaModuleInfoFormat: JsonFormat[sbt.librarymanagement.ScalaM
val overrideScalaVersion = unbuilder.readField[Boolean]("overrideScalaVersion")
val scalaOrganization = unbuilder.readField[String]("scalaOrganization")
val scalaArtifacts = unbuilder.readField[scala.Vector[String]]("scalaArtifacts")
val platform = unbuilder.readField[Option[String]]("platform")
unbuilder.endObject()
sbt.librarymanagement.ScalaModuleInfo(scalaFullVersion, scalaBinaryVersion, configurations, checkExplicit, filterImplicit, overrideScalaVersion, scalaOrganization, scalaArtifacts)
sbt.librarymanagement.ScalaModuleInfo(scalaFullVersion, scalaBinaryVersion, configurations, checkExplicit, filterImplicit, overrideScalaVersion, scalaOrganization, scalaArtifacts, platform)
case None =>
deserializationError("Expected JsObject but found None")
}
Expand All @@ -35,6 +36,7 @@ implicit lazy val ScalaModuleInfoFormat: JsonFormat[sbt.librarymanagement.ScalaM
builder.addField("overrideScalaVersion", obj.overrideScalaVersion)
builder.addField("scalaOrganization", obj.scalaOrganization)
builder.addField("scalaArtifacts", obj.scalaArtifacts)
builder.addField("platform", obj.platform)
builder.endObject()
}
}
Expand Down
11 changes: 9 additions & 2 deletions core/src/main/contraband/librarymanagement.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,13 @@
{ "name": "filterImplicit", "type": "boolean" },
{ "name": "overrideScalaVersion", "type": "boolean" },
{ "name": "scalaOrganization", "type": "String", "default": "sbt.librarymanagement.ScalaArtifacts.Organization", "since": "0.0.1" },
{ "name": "scalaArtifacts", "type": "scala.Vector[String]", "default": "sbt.librarymanagement.ScalaArtifacts.Artifacts", "since": "0.0.1" }
{ "name": "scalaArtifacts", "type": "scala.Vector[String]", "default": "sbt.librarymanagement.ScalaArtifacts.Artifacts", "since": "0.0.1" },
{
"name": "platform",
"type": "Option[String]",
"default": "None",
"since": "2.0.0"
}
]
},
{
Expand Down Expand Up @@ -332,7 +338,8 @@
{ "name": "exclusions", "type": "sbt.librarymanagement.InclExclRule*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "extraAttributes", "type": "Map[String, String]", "default": "Map.empty", "since": "0.0.1" },
{ "name": "crossVersion", "type": "sbt.librarymanagement.CrossVersion", "default": "sbt.librarymanagement.Disabled()", "since": "0.0.1" },
{ "name": "branchName", "type": "Option[String]", "default": "None", "since": "0.0.1" }
{ "name": "branchName", "type": "Option[String]", "default": "None", "since": "0.0.1" },
{ "name": "platformOpt", "type": "Option[String]", "default": "None", "since": "2.0.0" }
],
"toString": [
"this.toStringImpl"
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/scala/sbt/librarymanagement/ModuleIDExtra.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ private[librarymanagement] abstract class ModuleIDExtra {
def withExtraAttributes(extraAttributes: Map[String, String]): ModuleID
def withCrossVersion(crossVersion: CrossVersion): ModuleID
def withBranchName(branchName: Option[String]): ModuleID
def withPlatformOpt(platformOpt: Option[String]): ModuleID

protected def toStringImpl: String =
s"""$organization:$name:$revision""" +
Expand Down Expand Up @@ -205,6 +206,8 @@ private[librarymanagement] abstract class ModuleIDExtra {
def branch(branchName: String): ModuleID = withBranchName(Some(branchName))

def branch(branchName: Option[String]): ModuleID = withBranchName(branchName)

def platform(platform: String): ModuleID = withPlatformOpt(Some(platform))
}

private[librarymanagement] abstract class ModuleIDFunctions {
Expand Down
7 changes: 7 additions & 0 deletions core/src/main/scala/sbt/librarymanagement/Platform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package sbt.librarymanagement

object Platform:
val sjs1: String = "sjs1"
val jvm: String = "jvm"
val native0_4: String = "native0.4"
end Platform
Loading

0 comments on commit 47ef80e

Please sign in to comment.