diff --git a/.github/workflows/dependency-graph.yml b/.github/workflows/dependency-graph.yml index 8e5f9dc7a..de558d3bb 100644 --- a/.github/workflows/dependency-graph.yml +++ b/.github/workflows/dependency-graph.yml @@ -13,4 +13,4 @@ jobs: runs-on: ubuntu-latest # or windows-latest, or macOS-latest steps: - uses: actions/checkout@v4 - - uses: scalacenter/sbt-dependency-submission@v2 + - uses: scalacenter/sbt-dependency-submission@v3 diff --git a/DEVELOPING.md b/DEVELOPING.md index 8616765d3..beff0e099 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -18,6 +18,12 @@ The `develop` branch represents sbt 2.x, the next major sbt series. Next minor branch is where new features should be added as long as it is binary compatible with sbt 1.x. The `stable` branch represents the current stable sbt release. Only bug fixes are back-ported to the stable branch. +### Note on supported JDK version for the SBT build + +The SBT build itself currently doesn't support any JDK beyond version 17. You will run into deprecation warnings (which would become build errors due to build configuration) if you use any later JDK version to build SBT. + +If you're using Metals as IDE, also check the `Java Version` setting. The default at the time of writing this is `17`, but this may change in the future, or you may have set it to a later version yourself. (Be aware that Metals may download a JDK in the background if you haven't switch to a local JDK matching the version before changing this setting. Also, this setting is currently only available as a `User` setting, so you can't set it for a single workspace. Don't forget to switch back if you need to for other projects). + ### Instruction to build just sbt Sbt has a number of sub-modules. If the change you are making is just contained in sbt/sbt (not one of the sub-modules), diff --git a/main/src/main/scala/sbt/internal/InternalDependencies.scala b/main/src/main/scala/sbt/internal/InternalDependencies.scala index 31ee6be94..b52b84790 100644 --- a/main/src/main/scala/sbt/internal/InternalDependencies.scala +++ b/main/src/main/scala/sbt/internal/InternalDependencies.scala @@ -13,7 +13,9 @@ import sbt.Keys._ private[sbt] object InternalDependencies { def configurations: Def.Initialize[Seq[(ProjectRef, Set[String])]] = Def.setting { - val allConfigs = Classpaths.allConfigs(configuration.value).map(_.name).toSet + val configMap = internalConfigurationMap.value + val config = configMap(configuration.value) + val allConfigs = Classpaths.allConfigs(config).map(_.name).toSet val ref = thisProjectRef.value val projectDependencies = buildDependencies.value.classpath.get(ref).toSeq.flatten val applicableConfigs = allConfigs + "*" diff --git a/main/src/main/scala/sbt/internal/LibraryManagement.scala b/main/src/main/scala/sbt/internal/LibraryManagement.scala index 4feb7dd3e..21d454f56 100644 --- a/main/src/main/scala/sbt/internal/LibraryManagement.scala +++ b/main/src/main/scala/sbt/internal/LibraryManagement.scala @@ -168,7 +168,7 @@ private[sbt] object LibraryManagement { val extraInputHash = module.extraInputHash val settings = module.moduleSettings val outStore = cacheStoreFactory.make("output") - val handler = if (skip && !force) skipResolve(outStore) else doResolve(outStore) + val handler = if (skip && !force) skipResolve(outStore)(_) else doResolve(outStore) // Remove clock for caching purpose val withoutClock = updateConfig.withLogicalClock(LogicalClock.unknown) handler((extraInputHash, settings, withoutClock)) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index d12246e87..6d1e2486a 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -23,7 +23,7 @@ object Dependencies { private val libraryManagementCore = "org.scala-sbt" %% "librarymanagement-core" % lmVersion private val libraryManagementIvy = "org.scala-sbt" %% "librarymanagement-ivy" % lmVersion - val launcherVersion = "1.4.2" + val launcherVersion = "1.4.3" val launcherInterface = "org.scala-sbt" % "launcher-interface" % launcherVersion val rawLauncher = "org.scala-sbt" % "launcher" % launcherVersion val testInterface = "org.scala-sbt" % "test-interface" % "1.0" @@ -146,6 +146,6 @@ object Dependencies { val hedgehog = "qa.hedgehog" %% "hedgehog-sbt" % "0.7.0" val disruptor = "com.lmax" % "disruptor" % "3.4.2" - val kindProjector = ("org.typelevel" % "kind-projector" % "0.13.2").cross(CrossVersion.full) + val kindProjector = ("org.typelevel" % "kind-projector" % "0.13.3").cross(CrossVersion.full) val zeroAllocationHashing = "net.openhft" % "zero-allocation-hashing" % "0.10.1" } diff --git a/project/build.properties b/project/build.properties index e8a1e246e..081fdbbc7 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.7 +sbt.version=1.10.0 diff --git a/project/plugins.sbt b/project/plugins.sbt index 7078f1435..f9d8f987f 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,7 +2,7 @@ ThisBuild / useCoursier := false scalacOptions ++= Seq("-feature", "-language:postfixOps", "-Ywarn-unused:_,-imports") -addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.0.0") +addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.5.3") diff --git a/sbt b/sbt index e4123a72e..0d4e7e4fb 100755 --- a/sbt +++ b/sbt @@ -1,7 +1,7 @@ #!/usr/bin/env bash set +e -declare builtin_sbt_version="1.10.0" +declare builtin_sbt_version="1.10.1" declare -a residual_args declare -a java_args declare -a scalac_args @@ -89,6 +89,14 @@ cygwinpath() { fi } +# Trim leading and trailing spaces from a string. +# Echos the new trimmed string. +trimString() { + local inputStr="$*" + local modStr="${inputStr#"${inputStr%%[![:space:]]*}"}" + modStr="${modStr%"${modStr##*[![:space:]]}"}" + echo "$modStr" +} declare -r sbt_bin_dir="$(dirname "$(realpathish "$0")")" declare -r sbt_home="$(dirname "$sbt_bin_dir")" @@ -710,6 +718,9 @@ loadConfigFile() { } loadPropFile() { + # trim key and value so as to be more forgiving with spaces around the '=': + k=$(trimString $k) + v=$(trimString $v) while IFS='=' read -r k v; do if [[ "$k" == "sbt.version" ]]; then build_props_sbt_version="$v" diff --git a/sbt-app/src/sbt-test/actions/doc-scala3/m3/src/main/scala/foo/A.scala b/sbt-app/src/sbt-test/actions/doc-scala3/a/src/main/scala/foo/A.scala similarity index 100% rename from sbt-app/src/sbt-test/actions/doc-scala3/m3/src/main/scala/foo/A.scala rename to sbt-app/src/sbt-test/actions/doc-scala3/a/src/main/scala/foo/A.scala diff --git a/sbt-app/src/sbt-test/actions/doc-scala3/build.sbt b/sbt-app/src/sbt-test/actions/doc-scala3/build.sbt index 583a736e0..daa934878 100644 --- a/sbt-app/src/sbt-test/actions/doc-scala3/build.sbt +++ b/sbt-app/src/sbt-test/actions/doc-scala3/build.sbt @@ -1,11 +1,9 @@ -lazy val m3 = (project in file("m3")) - .settings( - scalaVersion := "3.0.0-M3", - resolvers += Resolver.JCenterRepository - ) - lazy val rc1 = (project in file("rc1")) .settings( scalaVersion := "3.0.0-RC1" ) +lazy val a = project + .settings( + scalaVersion := "3.4.2", + ) diff --git a/sbt-app/src/sbt-test/actions/doc-scala3/test b/sbt-app/src/sbt-test/actions/doc-scala3/test index b0a167b0c..60d542401 100644 --- a/sbt-app/src/sbt-test/actions/doc-scala3/test +++ b/sbt-app/src/sbt-test/actions/doc-scala3/test @@ -6,10 +6,10 @@ $ exists target/out/jvm/scala-3.0.0-RC1/rc1/api/api/index.html $ exists target/out/jvm/scala-3.0.0-RC1/rc1/api/api/foo/A$.html $ exists target/out/jvm/scala-3.0.0-RC1/rc1/api/api/foo.html -> m3 / doc +> a / doc # there shouldn't be two api/ directories # see https://github.com/lampepfl/dotty/issues/11412 -$ exists target/out/jvm/scala-3.0.0-M3/m3/api/index.html -$ exists target/out/jvm/scala-3.0.0-M3/m3/api/api/foo/A$.html -$ exists target/out/jvm/scala-3.0.0-M3/m3/api/api/foo.html +$ exists target/out/jvm/scala-3.4.2/a/api/index.html +$ exists target/out/jvm/scala-3.4.2/a/api/foo/A$.html +$ exists target/out/jvm/scala-3.4.2/a/api/foo.html diff --git a/sbt-app/src/sbt-test/dependency-management/force-update-period/test b/sbt-app/src/sbt-test/dependency-management/force-update-period/disabled similarity index 100% rename from sbt-app/src/sbt-test/dependency-management/force-update-period/test rename to sbt-app/src/sbt-test/dependency-management/force-update-period/disabled diff --git a/sbt-app/src/sbt-test/project1/internal-dependency-configurations/build.sbt b/sbt-app/src/sbt-test/project1/internal-dependency-configurations/build.sbt index 06a8556dd..f65b34710 100644 --- a/sbt-app/src/sbt-test/project1/internal-dependency-configurations/build.sbt +++ b/sbt-app/src/sbt-test/project1/internal-dependency-configurations/build.sbt @@ -23,31 +23,31 @@ def getConfigs(key: SettingKey[Seq[(ProjectRef, Set[String])]]): val checkA = taskKey[Unit]("Verify that project a's internal dependencies are as expected") checkA := { val compileDeps = getConfigs(a / Compile / internalDependencyConfigurations).value - assert(compileDeps == Map("a" -> Set("compile"))) + assert(compileDeps == Map("a" -> Set("compile", "optional", "provided", "compile-internal"))) val testDeps = getConfigs(a / Test / internalDependencyConfigurations).value - assert(testDeps == Map("a" -> Set("compile", "runtime", "test"))) + assert(testDeps == Map("a" -> Set("compile", "optional", "provided", "runtime", "test", "test-internal")), testDeps.mkString(", ")) } val checkB = taskKey[Unit]("Verify that project b's internal dependencies are as expected") checkB := { val compileDeps = getConfigs(b / Compile / internalDependencyConfigurations).value - assert(compileDeps == Map("b" -> Set("compile"), "a" -> Set("compile"))) + assert(compileDeps == Map("b" -> Set("compile", "optional", "provided", "compile-internal"), "a" -> Set("compile"))) val testDeps = getConfigs(b / Test / internalDependencyConfigurations).value - assert(testDeps == Map("b" -> Set("compile", "runtime", "test"), "a" -> Set("compile"))) + assert(testDeps == Map("b" -> Set("compile", "optional", "provided", "runtime", "test", "test-internal"), "a" -> Set("compile"))) } val checkC = taskKey[Unit]("Verify that project c's internal dependencies are as expected") checkC := { val compileDeps = getConfigs(c / Compile / internalDependencyConfigurations).value - assert(compileDeps == Map("c" -> Set("compile"))) + assert(compileDeps == Map("c" -> Set("compile", "optional", "provided", "compile-internal"))) val testDeps = getConfigs(c / Test / internalDependencyConfigurations).value - assert(testDeps == Map("c" -> Set("compile", "runtime", "test"))) + assert(testDeps == Map("c" -> Set("compile", "optional", "provided", "runtime", "test", "test-internal"))) } val checkD = taskKey[Unit]("Verify that project d's internal dependencies are as expected") checkD := { val compileDeps = getConfigs(d / Compile / internalDependencyConfigurations).value - assert(compileDeps == Map("d" -> Set("compile"), "c" -> Set("compile"))) + assert(compileDeps == Map("d" -> Set("compile", "optional", "provided", "compile-internal"), "c" -> Set("compile"))) val testDeps = getConfigs(d / Test / internalDependencyConfigurations).value - assert(testDeps == Map("d" -> Set("compile", "runtime", "test"), "c" -> Set("compile", "test"))) + assert(testDeps == Map("d" -> Set("compile", "optional", "provided", "runtime", "test", "test-internal"), "c" -> Set("compile", "test"))) } diff --git a/server-test/src/server-test/buildserver/build.sbt b/server-test/src/server-test/buildserver/build.sbt index 838a60d02..1a9a400d6 100644 --- a/server-test/src/server-test/buildserver/build.sbt +++ b/server-test/src/server-test/buildserver/build.sbt @@ -13,7 +13,7 @@ lazy val runAndTest = project.in(file("run-and-test")) Test / javaOptions := Vector("Xmx512M"), Test / envVars := Map("KEY_TEST" -> "VALUE_TEST"), ) - .dependsOn(util) + .dependsOn(util % Optional) lazy val reportError = project.in(file("report-error")) diff --git a/server-test/src/test/scala/testpkg/BuildServerTest.scala b/server-test/src/test/scala/testpkg/BuildServerTest.scala index b112ecf18..43aa5106f 100644 --- a/server-test/src/test/scala/testpkg/BuildServerTest.scala +++ b/server-test/src/test/scala/testpkg/BuildServerTest.scala @@ -45,8 +45,12 @@ class BuildServerTest extends AbstractServerTest { ) assertProcessing("workspace/buildTargets") val result = svr.waitFor[WorkspaceBuildTargetsResult](10.seconds) - val utilTarget = result.targets.find(_.displayName.contains("util")).get + val utilTargetIdentifier = BuildTargetIdentifier(buildTargetUri("util", "Compile")) + val utilTarget = result.targets.find(_.id == utilTargetIdentifier).get assert(utilTarget.id.uri.toString.endsWith("#util/Compile")) + val runAndTestTarget = result.targets.find(_.displayName.contains("runAndTest")).get + // runAndTest should declare the dependency to util even if optional + assert(runAndTestTarget.dependencies.contains(utilTargetIdentifier)) val buildServerBuildTarget = result.targets.find(_.displayName.contains("buildserver-build")).get assert(buildServerBuildTarget.id.uri.toString.endsWith("#buildserver-build")) @@ -246,14 +250,21 @@ class BuildServerTest extends AbstractServerTest { } test("buildTarget/scalacOptions, buildTarget/javacOptions") { - val buildTarget = buildTargetUri("util", "Compile") - val badBuildTarget = buildTargetUri("badBuildTarget", "Compile") + val buildTargets = Seq( + buildTargetUri("util", "Compile"), + buildTargetUri("badBuildTarget", "Compile"), + ) - val id1 = scalacOptions(Seq(buildTarget, badBuildTarget)) + val id1 = scalacOptions(buildTargets) assertMessage(s""""id":"$id1"""", "scala-library-2.13.11.jar")() - val id2 = javacOptions(Seq(buildTarget, badBuildTarget)) + val id2 = javacOptions(buildTargets) assertMessage(s""""id":"$id2"""", "scala-library-2.13.11.jar")() + + val id3 = scalacOptions(Seq(buildTargetUri("runAndTest", "Compile"))) + assertMessage(s""""id":"$id3"""", "target/out/jvm/scala-2.13.11/runandtest/classes")(debug = + true + ) } test("buildTarget/cleanCache") { @@ -593,7 +604,7 @@ class BuildServerTest extends AbstractServerTest { private def assertProcessing(method: String, debug: Boolean = false): Unit = assertMessage("build/logMessage", s""""message":"Processing $method"""")(debug = debug) - def assertMessage( + inline def assertMessage( parts: String* )(duration: FiniteDuration = 10.seconds, debug: Boolean = false, message: String = ""): Unit = { def assertion =