From afac251f282844975c08ec748181406ff6d67993 Mon Sep 17 00:00:00 2001 From: Anatolii Kmetiuk Date: Wed, 22 Apr 2026 11:58:34 +0900 Subject: [PATCH] [2.x] fix: Include platform suffix in Artifact.artifactName (#9118) --- .../sbt/librarymanagement/ArtifactExtra.scala | 10 ++++- .../sbt/librarymanagement/ArtifactTest.scala | 41 +++++++++++++++++++ .../lmcoursier/FromSbtPlatformSpec.scala | 17 ++++++++ main/src/main/scala/sbt/Defaults.scala | 1 + .../platform-artifact-name/build.sbt | 16 ++++++++ .../platform-artifact-name/test | 1 + 6 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 lm-core/src/test/scala/sbt/librarymanagement/ArtifactTest.scala create mode 100644 sbt-app/src/sbt-test/dependency-management/platform-artifact-name/build.sbt create mode 100644 sbt-app/src/sbt-test/dependency-management/platform-artifact-name/test diff --git a/lm-core/src/main/scala/sbt/librarymanagement/ArtifactExtra.scala b/lm-core/src/main/scala/sbt/librarymanagement/ArtifactExtra.scala index 938a164d6..c96da0fa4 100644 --- a/lm-core/src/main/scala/sbt/librarymanagement/ArtifactExtra.scala +++ b/lm-core/src/main/scala/sbt/librarymanagement/ArtifactExtra.scala @@ -104,7 +104,15 @@ private[librarymanagement] abstract class ArtifactFunctions { import artifact.* val classifierStr = classifier match { case None => ""; case Some(c) => "-" + c } val cross = CrossVersion(module.crossVersion, scalaVersion.full, scalaVersion.binary) - val base = CrossVersion.applyCross(artifact.name, cross) + val withPlatform = module.crossVersion match { + case _: Disabled => artifact.name + case _ => + module.platformOpt match { + case Some(p) if p.nonEmpty && p != Platform.jvm => s"${artifact.name}_$p" + case _ => artifact.name + } + } + val base = CrossVersion.applyCross(withPlatform, cross) base + "-" + module.revision + classifierStr + "." + artifact.extension } diff --git a/lm-core/src/test/scala/sbt/librarymanagement/ArtifactTest.scala b/lm-core/src/test/scala/sbt/librarymanagement/ArtifactTest.scala new file mode 100644 index 000000000..04bc1115f --- /dev/null +++ b/lm-core/src/test/scala/sbt/librarymanagement/ArtifactTest.scala @@ -0,0 +1,41 @@ +package sbt.librarymanagement + +import sbt.internal.librarymanagement.UnitSpec + +class ArtifactTest extends UnitSpec { + + "Artifact.artifactName" should "include the platform suffix before the Scala suffix" in { + val m = ModuleID("com.example", "root-178", "0.1.0-SNAPSHOT") + .cross(CrossVersion.binary) + .platform("native0.5") + val a = Artifact("root-178", "pom", "pom") + val sv = ScalaVersion("3.8.3", "3") + Artifact.artifactName(sv, m, a) shouldBe "root-178_native0.5_3-0.1.0-SNAPSHOT.pom" + } + + it should "omit the platform suffix for jvm" in { + val m = ModuleID("com.example", "foo", "1.0.0") + .cross(CrossVersion.binary) + .platform(Platform.jvm) + val a = Artifact("foo", "jar", "jar") + Artifact.artifactName(ScalaVersion("3.8.3", "3"), m, a) shouldBe "foo_3-1.0.0.jar" + } + + it should "omit platform and cross suffix when crossVersion is disabled" in { + val m = ModuleID("com.example", "foo", "1.0.0").platform("native0.5") + val a = Artifact("foo", "jar", "jar") + Artifact.artifactName(ScalaVersion("3.8.3", "3"), m, a) shouldBe "foo-1.0.0.jar" + } + + it should "produce a filename whose base matches the Maven coordinate (#9117)" in { + val m = ModuleID("com.indoorvivants", "sniper", "0.0.9-SNAPSHOT") + .cross(CrossVersion.binary) + .platform("native0.5") + val a = Artifact("sniper", "pom", "pom") + val sv = ScalaVersion("3.8.3", "3") + + val expectedMavenArtifactId = "sniper_native0.5_3" + Artifact.artifactName(sv, m, a) shouldBe + s"$expectedMavenArtifactId-0.0.9-SNAPSHOT.pom" + } +} diff --git a/lm-coursier/src/test/scala/lmcoursier/FromSbtPlatformSpec.scala b/lm-coursier/src/test/scala/lmcoursier/FromSbtPlatformSpec.scala index 1e9de19c4..f957a8770 100644 --- a/lm-coursier/src/test/scala/lmcoursier/FromSbtPlatformSpec.scala +++ b/lm-coursier/src/test/scala/lmcoursier/FromSbtPlatformSpec.scala @@ -107,4 +107,21 @@ final class FromSbtPlatformSpec extends AnyPropSpec with Matchers { // Should just have cross-version suffix, no platform module.name.value shouldBe "qux_2.13" } + + property("issue #9117: project with native0.5 publishes as _native0.5_3") { + val projectID = ModuleID("com.indoorvivants", "sniper", "0.0.9-SNAPSHOT") + .withCrossVersion(Binary()) + .platform("native0.5") + + val (module, version) = FromSbt.moduleVersion( + projectID, + scalaVersion = "3.8.3", + scalaBinaryVersion = "3", + optionalCrossVer = false, + projectPlatform = Some("native0.5") + ) + + module.name.value shouldBe "sniper_native0.5_3" + version shouldBe "0.0.9-SNAPSHOT" + } } diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 47585bc45..888d42cdb 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -3589,6 +3589,7 @@ object Classpaths { val p0 = ModuleID(organization.value, moduleName.value, version.value) .cross((projectID / crossVersion).value) .artifacts(artifacts.value*) + .withPlatformOpt(platform.?.value) val p1 = apiURL.value match case Some(u) => p0.extra(SbtPomExtraProperties.POM_API_KEY -> u.toURL().toExternalForm) case _ => p0 diff --git a/sbt-app/src/sbt-test/dependency-management/platform-artifact-name/build.sbt b/sbt-app/src/sbt-test/dependency-management/platform-artifact-name/build.sbt new file mode 100644 index 000000000..4f5547891 --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/platform-artifact-name/build.sbt @@ -0,0 +1,16 @@ +ThisBuild / organization := "com.example" +name := "testproj" +version := "0.1.0-SNAPSHOT" +scalaVersion := "3.8.3" + +platform := "native0.5" +crossVersion := CrossVersion.binary + +lazy val checkPomName = taskKey[Unit]("check POM artifact path includes native0.5_3") + +checkPomName := { + val converter = fileConverter.value + val p = (makePom / artifactPath).value + val s = converter.toPath(p).toString + assert(s.contains("native0.5_3"), s"expected native0.5_3 in POM path, got: $s") +} diff --git a/sbt-app/src/sbt-test/dependency-management/platform-artifact-name/test b/sbt-app/src/sbt-test/dependency-management/platform-artifact-name/test new file mode 100644 index 000000000..de28d123a --- /dev/null +++ b/sbt-app/src/sbt-test/dependency-management/platform-artifact-name/test @@ -0,0 +1 @@ +> checkPomName