**Problem**
sbt currently does not support JDK 25 Main class. JDK 25 supports:
1. non-public main method
2. doesn't need Array[String] arg
3. doesn't have to be a static method
**Solution**
This updates Zinc, which supports new Main class detection.
In addition, this implements in-process run emulation support.
**Problem**
There are a few places where javaHome or java path is set,
using java.home system property. The problem is that it points to JRE,
not JDK, so it would break on Java compilation etc.
**Solution**
If the path ends with jre, go up one directory.
**Problem**
The sbtn response handling code is relatively stragightforward,
but it's a bit messy.
**Solution**
This cleans it up a bit, similar to the style used by Unfiltered
back then (not sure how Unfiltered plans are written nowadays) by
expressing each event handling as a partial function, and composing them
together using `orElse`.
**Problem**
We changed the content of Chrome tracing file incorrectly
and renamed tid to tname.
**Solution**
1. This renames tname back to to tid.
2. To retain the fix to avoid Thread#getId, this calls
either the JDK 8 way or the JDK 19 way reflectively.
Fixes https://github.com/sbt/sbt/issues/6102https://github.com/sbt/sbt/pull/6026 changed the implementation of remote cache to NOT use dependency resolution (Coursier), and directly use Ivy resolver for efficiency. This was good, but when I made the change, I've changed the cache directory to be `crossTarget.value / "remote-cache"`. This was ok for local testing purpose, but not great for real usage since we don't want the cache to be wiped out either in the CI machines or on a local laptop.
This adds a new Global key called `localCacheDirectory`. Similar to Coursier cache, this is meant to be shared across all builds running on a machine. Also similar to Coursier cache this will try to follow the operating system specifc caching directory.
### localCacheDirectory location
- Environment variable: `SBT_LOCAL_CACHE`
- System property: `sbt.global.localcache`
- Windows: %LOCALAPPDATA%\sbt\v1
- macOS: $HOME/Library/Caches/sbt/v1
- Linux: $HOME/.cache/sbt/v1
The sbt project load made a number of relatively inefficient
transformations of scala collecitons. I went through and found the slow
parts during project loading and made my best attempt at fixing them.
The most significant changes I made were in places using IMap. An IMap
is more or less a wrapper around an immutable Map. It can be much faster
to construct an IMap by creating a java mutable hashmap, wrapping it a
scala Map that delegates to the underlying java hashmap (with a copy on
write if the map is modified) and constructing the IMap from the wrapped
map. It was also in many cases to parallelize some transformations
wherever the order didn't matter.
After applying all of these changes, I found that loading the sbt
project took generally between 8.5 and 9 seconds on my laptop. With
1.3.13, it hovered around 11.5 seconds. I saw a similar speedup in zinc.
The biggest specific improvement was that generating the compiled map
dropped from between 3.5-4 seconds to pretty consistently being around
1.5 seconds.
The continuous command recompiles the setting graph into a CompiledMap
data structure so that it can determine which files it needs to
transitively monitor during watch. Generating the CompiledMap can be
very slow for large projects (5 seconds or so on my computer in the sbt
project) and this startup cost is paid every time the user enters a
watch with `~`. To avoid this, we can cache the compile map that is
generated during the initial settings evaluation.
The only real drawback I can see is that the compiled map is guaranteed
to remain in memory so long as the BuildStructure instance that holds it
is alive. Given the performance benefit, this seems like a worthwhile
tradeoff.
This implements Selective functor for `Either[A, B]` "task" (`Initialize[Task[Either[A, B]]]`).
The selective functor allows an encoding of if-expression:
```
def ifS[A](
x: Def.Initialize[Task[Boolean]]
)(t: Def.Initialize[Task[A]])(e: Def.Initialize[Task[A]]): Def.Initialize[Task[A]]
```
The benefit of this approach is that task dependencies are still visible to inspect command.
To demonstrate [-Yno-lub](http://eed3si9n.com/stricter-scala-with-ynolub), this shows the code changes that removes lubing (Not all subprojects are done).
After I made the changes, I switched the Scala back to normal 2.12.10.
During akka startup, addLocal was caused twice and prior to this change,
it took roughly 200ms per call on my computer. After this change, it
took about 100ms.
I was seeing a number of compiler warnings about the type parameter
Scope:
Settings.scala:55:12: type parameter Scope defined in trait Init shadows class Scope defined in package util. You may want to rename your type parameter, or possibly remove it.
I'm not sure why I wasn't seeing these before, but the fix is simple.
While the AnyLeft and AnyRight types are necessary to make the extension
class work, I don't want to leak the AnyLeft or AnyRight traits into the
public api. It wasn't neceessary to annotate `some`, but it's good
practice to annotate anything public anyway.