Change the behavior when a cached task's output type contains
java.io.File: instead of silently skipping the cache, throw a
compile-time error with a message recommending xsbti.VirtualFileRef,
xsbti.HashedVirtualFileRef, or xsbti.VirtualFile, and linking to the
caching documentation.
Internal sbt tasks that return File types are wrapped with
Def.uncached to opt out of caching.
Fixes https://github.com/sbt/sbt/issues/8762
Generated-by: GitHub Copilot (Claude)
* [2.x] fix: Reject java.io.File as cached task output type
Use @transient on File-returning keys in Keys.scala instead of
wrapping tasks with Def.uncached in Defaults.scala. This ensures
build users who rewire these tasks also get caching skipped
automatically.
- Add @transient to 19 File-returning taskKey definitions in Keys.scala
- Revert Def.uncached wrappers from Defaults.scala
- Error at compile time when File is used as cached task output type
- Update error message to recommend @transient and link to docs
- Update scripted tests to use @transient approach
Fixes#8762
Generated-by: GitHub Copilot (Claude Opus 4.6)
**Problem**
`scalaOrganization` was ignored during compiler bridge resolution because `ZincLmUtil.getDefaultBridgeModule` hard-coded `ScalaArtifacts.Organization` (`org.scala-lang`).
**Solution**
Add a `scalaOrganization` parameter to `ZincLmUtil` methods, and passing `scalaOrganization` value to those methods.
Generated-by: Claude Opus 4.6
When `semanticdbEnabled := true` is set on Scala 2.x projects, the
`doc` task fails because `${CSR_CACHE}` placeholders in scalacOptions
(specifically the `-Xplugin:` path for the semanticdb compiler plugin)
are not resolved before being passed to Scaladoc.
This fix resolves virtual file references (containing $) in
scalacOptions before passing them to the Scaladoc bridge, matching
what zinc's MixedAnalyzingCompiler already does for compilation
(see sbt/zinc#1545).
Fixessbt/sbt#8740
Generated-by: GitHub Copilot (Claude Opus 4.6)
Allow settings to delegate when the user specifies an explicit scope
(config or task axis), so that e.g. Compile/console/fork resolves
when console/fork is defined in a delegated scope. Tasks continue to
not delegate (getDirect only) so non-existent scopes like Compile/update
still fail as in 2.0.0.
**Problem**
Adopting Scala 3.8 on sbt 2.x has created confusing errors with scala-library mismatch,
popping up as undefined summon.
**Solution**
Removing the Provided scope seems to work.
**Problem**
When the user runs testOnly with an explicit suite name (e.g. testOnly com.example.MySuite),
ScalaTest suites annotated with @DoNotDiscover were not run because sbt always passed
explicitlySpecified=false to the test framework.
**Solution**
In Tests.processOptions, when the user has specified test filters (orderedFilters.nonEmpty),
mark the filtered tests as explicitlySpecified=true with SuiteSelector so frameworks
can run @DoNotDiscover suites when explicitly requested.
- this should also work for global plugins once they are fixed in sbt 2.x
- add `missingOk` support in classifier resolution to enable failure-tolerant artifact retrieval
**Problem**
ScalaTest's `AsyncFunSuite` invokes the test framework's event handler **asynchronously**. sbt's `TestFramework` was collecting events in a **`ListBuffer`**, which is not thread-safe. With multiple suites (e.g. `IgnoreBugTestA` and `IgnoreBugTestB`), concurrent `handle()` calls could corrupt the buffer, so events from the second suite were lost or merged incorrectly and the summary showed wrong suite/test counts.
**Solution**
Replaced the event buffer in `sbt.TestFramework`'s `EventHandler` with a **thread-safe** collection: **`CopyOnWriteArrayList`** (from `java.util.concurrent`). Event handling now uses:
- `CopyOnWriteArrayList[Event]` for `results`
- `results.add(e)` in the handler
- `results.asScala.toList` when building `TestEvent` / `SuiteResult` (via `scala.jdk.CollectionConverters._`)
This preserves ordering and ensures all suites' events are reported correctly when using async styles like `AsyncFunSuite` with `test`/`ignore`.
When usePipelining is enabled and compilation has errors, CancellationException
was being thrown and showing confusing stack traces to users. This fix catches
the exception in ConcurrentRestrictions.take() and converts it to Incomplete,
which is properly handled by the task execution framework without showing stack
traces.
- Added CancellationException import
- Wrapped jservice.take().get() in try-catch
- Convert CancellationException to Incomplete to prevent stack traces
- Added scripted test to verify the fix
Fixes#7973
Build-level references (ThisBuild, BuildRef) should not participate
in aggregation. Only project-level references should aggregate.
Previously, when querying `ThisBuild/version`, the aggregation logic
would resolve ThisBuild to a BuildRef, then convert it to the root
project's ProjectRef, causing it to incorrectly use the root project's
aggregate definitions.
The fix uses pattern matching to distinguish BuildReference from other
reference types, returning None (no aggregation) for build-level scopes.
Fixessbt/sbt#5349
**Problem**
Setting `Global / autoStartServer := false` in global.sbt triggers a
spurious lintUnused warning, even though the setting is correctly used
by sbt's server startup logic.
**Solution**
Add `autoStartServer` to the `excludeLintKeys` set in LintUnused.scala,
similar to other server-related settings like `serverConnectionType` and
`serverIdleTimeout`. This prevents the warning while maintaining the
functionality of the setting.
Commit 92b0564dc (fix for #8632) changed `csrSameVersions` so that Scala 2.13+ only aligned `scala-library` and `scala3-library`. This removed `scala-compiler` and `scala-reflect` from version
unification, so transitive dependencies pulling in an older `scala-compiler` (e.g. 2.13.15 via `refined_2.13`) were no longer evicted to match `scalaVersion` (e.g. 2.13.18).
**Problem**
The configuration name translation in logging was incorrect. When a
configuration like MultiJvm (id="MultiJvm", name="multi-jvm") was
displayed, it showed "Multi-jvm" instead of "MultiJvm" because the
display logic was guessing the identifier by capitalizing the ivy
config name.
**Solution**
This fix:
- Adds configNameToIdent reverse mapping in ConfigIndex to look up
the correct Configuration.id from the ivy config name
- Adds toConfigIdent method in KeyIndex trait for display lookup
- Updates Scope.display to accept a config name lookup function
- Updates showLoadingKey and showContextKey to use the index lookup
Fixes#5211
Generated-by: Claude
**Problem**
When platform is set, it incorrectly adds the platform suffix to implicit Scala library dependencies even though they explicitly set platform to jvm. This causes resolution errors.
**Solution**
Modified addPlatformSuffix to prioritize explicit platform settings on dependencies. If a dependency has an explicit platform, use that instead of the project platform. The project platform should only apply to dependencies without an explicit platform.
Fixes#8665
Generated-by: Claude Sonnet 4.5
When an AutoPlugin adds a project at the build root via extraProjects,
avoid creating a second root from the build definition so both do not
share the same target directory. Treat extraProjects root as 'root
already defined' and exclude the build-defined root from initialProjects
when both would be at the same base.
- Add ivylessPublishMavenToFile and ivylessPublishMavenToUrl for Maven layout
- Handle MavenCache and MavenRepo in ivylessPublishTask (file + HTTP)
- Add credentialFor for realm+host credential matching per Publishing docs
- Consume HTTP response body on success to avoid connection leak
- Add scripted tests: ivyless-publish-maven, ivyless-publish-maven-http
When using the aggregated key parser, a key is now valid if it exists in `data` for that scope **or** it's an aggregate key and every key it aggregates to exists in `data`. So `(root, scripted)` is accepted when the root aggregates a project that defines `scripted`, and running `scripted` at root runs it on that project as before.
Implements ivyless publish task as part of #7639 (drop Ivy dependency).
Fixes#8639.
- Add ivylessPublish for URLRepository: HTTP PUT with optional Basic auth,
same layout as ivyless publishLocal (artifacts + ivy.xml + checksums).
- Add ivylessPublishToFile for FileRepository: write to local path for
testing without HTTP server.
- Add ivylessPublishTask: when useIvy is false, use ivyless path for
URLRepository or FileRepository; otherwise use Ivy.
- Wire publish in Defaults to LibraryManagement.ivylessPublishTask
(tagged Publish, Network).
- Add scripted test dependency-management/ivyless-publish using
Resolver.file to verify ivyless publish produces identical layout.
Credentials supported via allCredentials (Basic auth for PUT).
When a project depended on another project that was built with a different Scala binary version (e.g. 2.12 vs 2.13), compilation could fail with "not found: value X" because resolution was asking for the wrong artifact.
This change updates how we build the `ModuleID` for inter-project dependencies in `projectDependenciesTask`: we now request the dependency’s Scala binary version (e.g. `bar_2.12`) instead of the current project’s, so the resolver can find the right artifact. We keep existing behavior for `Disabled` and `Constant` cross-version, and add a small safeguard in the default case when the dependency’s Scala version differs from the current project’s.
**Consuming BOMs**
- You can declare a BOM with `.pomOnly()` and versionless deps with `"*"`:
- `libraryDependencies += ("com.fasterxml.jackson" % "jackson-bom" % "2.21.0").pomOnly()`
- `libraryDependencies += "com.fasterxml.jackson.core" % "jackson-core" % "*"`
- BOMs are passed to Coursier via `Resolve.addBom()`; version `"*"` is resolved from the BOM.
**makePom**
- POM-only dependencies are emitted under `<dependencyManagement><dependencies>...</dependencies></dependencyManagement>` with `<type>pom</type>` and `<scope>import</scope>`.
- Dependencies with version `"*"` are emitted without a `<version>` element so Maven uses the BOM-managed version.
**Ivy / publishLocal emulation**
- When publishing to Ivy (e.g. `publishLocal`), BOM-resolved versions (deps that had `"*"`) are written into the published `ivy.xml` as forced dependencies (`force="true"`), so consumers that depend on this module get those versions.
Resolving ThisProject to ProjectRef(uri, p.id) created a self-reference
in the aggregate (and dependency) list. BuildUtil.checkCycles runs
topological sort on this relation and throws Cyclic when it sees the
self-loop.
Treat ThisProject as no-op: resolve to Vector.empty so the build loads
without error. aggregate(ThisProject) / dependsOn(ThisProject) is
effectively a no-op (self is already included).
Fixes#3616 - Scope's resolveProjectBuild and resolveProjectRef
mishandle ThisProject.
Previously, using ThisProject in aggregate() or dependsOn() would
cause a runtime error: 'Cannot resolve ThisProject w/o the current
project'.
This change adds proper handling for ThisProject in Load.scala:
- In checkAll: Skip validation for ThisProject (refers to self)
- In resolveProjects: Resolve ThisProject to ProjectRef(uri, p.id)
Problem
When a user defines an alias with a name that matches an existing task or setting key (e.g., `alias c = compile` when a custom task `c` exists), the alias silently wins and shadows the task.
Solution
Detect conflicts at alias creation time and fail with an error message:
```
Alias 'c' conflicts with a task or setting key of the same name. Use a different alias name to avoid ambiguity.
```
Fixes#8627
- Use ${OUT} placeholder and remove StringVirtualFile1 special-case handling
- Make dirZipExt check generic (use vf instead of svf: StringVirtualFile1)
- Let syncBlobs handle StringVirtualFile1 transparently via fileConverter.toPath()
Fixes#8631
**Changes:**
- Add `useIvy` setting key (defaults to `true`)
- Add `ivylessPublishLocalImpl` helper that publishes without Ivy
- Modify `publishLocal` to use ivyless publisher when `useIvy := false`
- Generate ivy.xml via `lmcoursier.IvyXml`
- Generate MD5/SHA-1 checksums for all files
- Add scripted test `dependency-management/ivyless-publish-local`
## Problem
We enforce same-version policy for scala-reflect in Scala 2.13.
However due to sandwich dependency, the graph can bump
scala-library to 3.8.1, which is missing scala-reflect counterpart.
## Solution
Drop the same-version policy.
**Problem**
When `autoAPIMappings := true` is set on a Scala 3 project, running `sbt doc` emits warnings:
```
[warn] bad option '-doc-external-doc:/modules/java.base#https://docs.oracle.com/...
```
This happens because Scala 3's scaladoc doesn't recognize Scala 2's `-doc-external-doc` option.
Fixes#6652
**Solution**
- Added `Opts.doc.externalAPIScala3` that generates the Scala 3 format: `-external-mappings:regex::[scaladoc3|javadoc]::url`
- Modified `Defaults.scala` to use the appropriate method based on Scala version
- Added heuristics to detect javadoc vs scaladoc based on file/URL patterns
**What it does**
When you run `dependencyLock`, sbt generates a `deps.lock` file that captures your resolved dependencies. This file can be checked into version control to ensure reproducible builds across different machines and CI environments.
**New tasks**
- **`dependencyLock`** - Generates the lock file from the current resolution
- **`dependencyLockCheck`** - Validates the lock file is up-to-date (fails build if stale)
**How it works**
The lock file stores a hash of your declared dependencies and resolvers. When dependencies change, the hash changes, and `dependencyLockCheck` will fail until you regenerate the lock file.
If no lock file exists, `dependencyLockCheck` passes silently - this allows gradual adoption.
Add support for `"3-latest.candidate"` to automatically resolve to the latest Scala 3 RC from Maven Central.
```scala
scalaVersion := "3-latest.candidate"
```
Ref https://github.com/sbt/sbt/discussions/8590
This PR adds a scripted test to prevent regression of issue #6175, where `MethodHandle.invokeExact` failed to compile on JDK 15+ when using `-release 11`.
Changes:
- Added `sbt-app/src/sbt-test/java/method-handle-release/` scripted test
- Test uses Scala 2.13.16 with `-release:11` to reproduce the original issue scenario
- Verifies that polymorphic signature methods compile correctly under cross-version targeting
**Problem**
Currently the shell delegates request tasks even when a non-existent
task like Compile / update is requested.
**Solution**
This removes the delegation, if the input key is scoped, so it will fail.
We will, however, continue to delegate on the subproject axis,
since it's useful to use Global or ThisBuild scoping.
**Problem**
When binary compatibility eviction errors occur, users cannot run
`dependencyTree` to debug the dependency conflict because it fails
with the same eviction error.
**Solution**
Set `evictionErrorLevel` and `assumedEvictionErrorLevel` to `Level.Warn`
for the `dependencyTreeIgnoreMissingUpdate` task, allowing the dependency
tree to be displayed even when eviction errors are present.
Fixes#7255
Fixes#7489
When using nested task scopes like otherTask / testTask, the
inputFileChanges macro was returning the wrong scope. It checked
if the scope already had a task axis and returned it as-is, but
this meant it would use otherTask's scope instead of testTask's.
The fix always sets the task axis to the key being queried,
ensuring fileInputs settings are found at the correct scope.
**Problem**
When a val definition in build.sbt changes and the user runs `reload`, sbt crashes with `NoClassDefFoundError: $Wrap<hash>$`.
```
java.lang.NoClassDefFoundError: $Wrape8743d4f36$
at $Wrap0b8ea34d40$.$anonfun$1(build.sbt:1)
```
The workaround was to delete `project/target` directory.
**Solution**
The root cause was that imports were not included in the hash calculation when evaluating build.sbt expressions. When a val definition changes:
1. Its `$Wrap` module gets a new hash
2. Settings that reference the val get new imports pointing to the new module
3. But if the setting expression didn't change, its hash was the same
4. The old cached class was loaded with bytecode referencing the old module
Fix: Include imports in the hash calculation in `Eval.evalCommon`. Also re-enable `cleanEvalClasses` in `Load.scala` which was disabled pending this fix.
Filters out empty versions during parser construction to prevent RuntimeException when creating token parsers. Includes comprehensive test coverage for edge cases.
DependencyTreePlugin is an AutoPlugin with trigger = AllRequirements,
so it loads automatically in scripted tests without requiring explicit
plugin configuration.
* Add JSON output support to dependencyLicenseInfo
- Add LicenseInfo rendering object with text and JSON output
- Add dependencyLicenseInfo input task key
- Implement dependencyLicenseInfo task with JSON format support
- Supports --out option for file output
- Auto-detects JSON format from .json file extension
- Follows same pattern as dependencyTree task
Resolves#7771