Commit Graph

2324 Commits

Author SHA1 Message Date
Ethan Atkins e481ddb1fc
Merge branch 'develop' into watch-alias 2019-05-28 21:06:31 -07:00
Ethan Atkins f7dd228808 Allow aliases to be used in continuous builds
@japgolly reported in #4695 that aliased commands don't work in watch
anymore. This was because we were extracting the task from the raw
command rather than the aliased command. Since the alias wasn't a valid
key, we weren't able to parse the scoped key. The fix is to find the
aliased value and try that if we fail to parse the original command.

Fixes #4695
2019-05-28 16:49:23 -07:00
Guillaume Martres 2aab767962 Replace usages of deprecated ScalaInstance#libraryJar 2019-05-29 00:10:47 +02:00
eugene yokota aefd0969b1
Merge pull request #4732 from smarter/fix-updatesbtclass
updateSbtClassifiers: use the correct scalaOrganization
2019-05-28 17:52:12 -04:00
Ethan Atkins 5d08d82f3a Use libraryJars rather than libraryJar in ClassLoaders
Dotty uses multiple library jars. It also simplifies the code to use the
libraryJars method.
2019-05-28 11:22:34 -07:00
Guillaume Martres 7a84808f74 updateSbtClassifiers: use the correct scalaOrganization 2019-05-28 19:58:05 +02:00
Ethan Atkins df51281d90 Remove dead test 2019-05-28 10:39:08 -07:00
Ethan Atkins 7b870d647a Add missing header 2019-05-28 10:36:44 -07:00
Ethan Atkins d78d8d650c Don't automatically die on OOM: metaspace
In an interactive session, it's possible for task evaluation to trigger
an OOM: Metaspace but for sbt to continue working after that failure.
Moreover, the metaspace oom can be caused by using a dependency
classloader layer. If the user changes the layering strategy, they may
be able to re-run their command successfully.
2019-05-28 09:53:36 -07:00
Ethan Atkins 92992a8243 Use file stamps for resource loader
Instead of caching based on the classpath of the resources, we should
instead cache based on the actual resource files. This commit achieves
that by adding the classpathFiles key which just transforms the
attributed classpath to a Seq[Path]. This implicitly generates the
outputFileStamps key for classpathFiles which we can use to read the
stamps (the file stamp entries for the classpath should get filled by
the compile task so this shouldn't actually cause any additional io).
2019-05-28 09:53:36 -07:00
Ethan Atkins b6cdd60cf8 Simplify layering strategies
The ShareRuntimeDependenciesLayerWithTestDependencies strategy doesn't
really work with resources, so it makes sense to get rid of it. Without
the share layer, there is no point in having separate
RuntimeDependencies and TestDependencies layers so I consolidated them
to Dependencies.

If we really care about binary/source compatibility for the 1.3.0-RCx
series, I can restore the traits and objects and set them private[sbt].
I think it was kind of a bug that they existed at all given the issue
with resources so it makes sense to just remove them.
2019-05-28 09:53:36 -07:00
Ethan Atkins 468334f142 Don't use anonymous URLClassLoaders
This makes debugging a bit easier in the eclipse memory analyzer tool
since we get a more specific classloader type than URLClassLoader and by
giving the class a meaningful name, we can tell from where it
originated.
2019-05-28 09:53:35 -07:00
Ethan Atkins af9f665649 Use new ClassLoaderCache for layered classloaders
This commit removes the ClassLoaderCache that I'd added for the purpose
of caching layered classloaders. Instead, we will use the state's global
ClassLoaderCache. This is better both because it centralizes the
classloader caching and because the new ClassLoaderCache will evict
unused classloaders when the jvm is under memory pressure.

I also add a new layer for the resources that goes between the scala
library layer and the dependency layer. This should help in cases where
users depend on libraries that require access to resources, e.g.
logback.xml.
2019-05-28 09:53:35 -07:00
Ethan Atkins a128ddf4a6 Route all ScalaInstance creations through the cache
It was possible to make new classloaders for the scala library and other
jars with each new scala instance. To avoid this, I audited all of the
places within sbt where we make a ScalaInstance and ensure that we
instantiate them in such a way that the classloaders are retrieved
through the state's ClassLoaderCache.

After this change, I found from a heap dump that it was possible to run
test in a project that uses scala 2.12.8 and have only ONE classloader
for the scala library present in the heap dump. With older versions,
there were would be up to 3 or 4 in most heap dumps.
2019-05-28 09:53:35 -07:00
Ethan Atkins 03bf539ce9 Add new ClassLoaderCache implementation
This commit adds a new ClassLoaderCache that builds on the
ClassLoaderCache that is present in zinc (and can be used to build an
instance of the zinc ClassLoaderCache to preserve compatibility). It
differs from the zinc classloader cache that it does not use direct
SoftReferences to classloaders. Instead, we create a wrapper loader
that can't load any classes and just delegates to its parent. This
allows us to add a thread that reaps the soft reference to the wrapper
loader. Crucially, we add a custom SoftReference class that has a strong
reference to the underlying classloader. This allows us to call close on
the strong reference.

The one issue with this approach is that we can't
rescue the jvm from crashing with an OOM: metaspace because the jvm
doesn't give us a chance to close and dereference the underlying
classloaders before it crashes. It WILL collect classloaders under
normal memory pressure, just not metaspace pressure. To fix this, I
check if the MaxMetaspaceSize is set via an MxBean and, if it is, we
fill the cache with regular soft references. We are going to change the
bash script to not set -XX:MaxMetaspaceSize by default so most builds
should probably end up correctly closing the classloaders after this
change. But we should break existing builds that set MaxMetaspaceSize
but don't crash.

As part of this commit, I audited all of the places where we were
instantiating ClassLoaderCache instances and instead pass in the
state's ClassLoaderCache instance. This reduces the total number of
classloaders created.
2019-05-28 09:53:35 -07:00
Ethan Atkins 20f6d22439 Fix memory leak
Using a lazy val causes the log manager to hold onto a reference to the
state. These would accumulate with each task evaluation. I found that
that in the beanpuree project, that if I ran compile 10 times in a row,
the heap usage was 40mb lower after this change.
2019-05-28 09:53:35 -07:00
Ethan Atkins f8d729cd3b Don't set fileOutputs at the compile config level
This was problematic because it had no dependency on the compile task
which meant that any other task in the config would pick up those
fileOutputs which did not make sense. I noticed this because
(resources / outputFileStamps).value would include class files.
2019-05-28 09:53:35 -07:00
Ethan Atkins df628d4f87 Improve legacy launcher
To minimize classloading and consistency between sbt instances launched
with the latest launcher compared to old launchers, I overhauled code
that replaces the app configuration and meta build classloader at
startup. The goals of this change for legacy launchers were:

1) Do not ever load the scala-library.jar from the app provider class loader.
2) Close the class loaders that are below the topLoader in the class
   loading hierarcy

For the new launcher, we simply want to avoid modifying the loader at
all.

I added the SbtParserInit class so that it was more straightforward to
preload the global instance using reflection. We now use reflection to
instantiate an SbtParserInit instance for both the legacy and new
launcher cases to simplify the logic.

After this change, the legacy loader still uses somewhat more metaspace
than the new loader, but the difference seems to be O(10MB), which
should only impact projects that were close their MaxMetaspaceSize to
begin with.

I verified using javap that none of the code in this class uses the
scala standard library which should help metaspace since we don't load
much of the scala standard library until we enter xMainImpl.run.
2019-05-28 09:53:35 -07:00
Ethan Atkins 22d5fbad13 Move external hooks definition
I verified manually that ExternalHooks were still applied by default but
that I could set the incOptions in the Test and Compile configs so that
they weren't used.

Fixes #4624
2019-05-26 19:15:55 -07:00
Eugene Yokota 5936bd1ff2 Revert Defaults.collectFiles
Fixes #4681
Ref #4649
2019-05-25 14:10:14 -04:00
Eugene Yokota 0ff97e4561 scalaCompilerBridgeDependencyResolution
Fixes #4712

This adds a specialized DependencyResolution instance called `scalaCompilerBridgeDependencyResolution` to download the compiler bridge. It has its own list of resolvers set by `scalaCompilerBridgeResolvers`. For backward compatibility, it will append `externalResolvers.value` as well.
2019-05-24 01:02:44 -04:00
eugene yokota ecce47e5b7
Merge pull request #4703 from eed3si9n/wip/scalatest
Fixes layer 4 missing scala-reflect
2019-05-20 14:26:42 -04:00
Eugene Yokota 9d3b626567 Fix ScalaTest issue with ScalaLibrary classloader
Ref #4689
Ref #4671
2019-05-17 14:24:55 -04:00
Ethan Atkins 5a9f5a69d5 Fix warnings
These lines added new warnings that slipped through the cracks.
2019-05-15 17:27:07 -07:00
eugene yokota 15b4befa9c
Merge pull request #4679 from eatkins/rt-jar
Don't ever invalidate rt.jar
2019-05-14 22:13:45 -04:00
Ethan Atkins a820bb5623 Sort the supershell tasks by task name
This should make the output less jumpy.
2019-05-14 17:27:17 -07:00
Ethan Atkins 564aa7262b Fix TaskProgress
Supershell was not reliably working and I tracked it down to
TaskProgress not actually publishing updates during task execution. This
seemed to happen because the background task was only run once when the
task started up. Once that task exited, no further task reports would be
published. The fix is to start a new thread every time we enter
EvaluateTask. I verified manually that it did not seem to leak threads
because EvaluateTask always calls shutdown, which calls
afterAllCompleted, which stops the progress thread.

I also decreased the default report period to 100ms. I can't imagine
that this will have a big effect on performance. It can be tuned with
the sbt.supershell.sleep parameter.
2019-05-14 17:27:16 -07:00
Ethan Atkins 0d9be6dd4a Don't ever invalidate rt.jar
There are issues when using jdk > 8 where the rt.jar file can be
invalidated by ExternalHooks. This causes spurious rebuilds. I think
it's fair to assume that rt.jar never changes. If a dependency is named
rt.jar, then invalidation may not work correctly but I think that this
is the more important case to handle.

I verified that before this change, it was impossible to run
akka-actor/compile twice in a row using adopt jdk 11 and, after this
change, re-compilation worked as expected.
2019-05-14 16:53:09 -07:00
Ethan Atkins e5b54a59ea Manage shutdown hooks
I discovered that some registered shutdown hooks would crash due to
67df72ab01 because they would try to load
classes from the closed classloader. To fix this, I add a internal
shutdown hooks mechanism that can be managed by sbt. Any unevaluated
shutdown hooks will be run when the sbt main method exits. This means
that they will be run when the user calls reboot. I think that is
reasonable.
2019-05-13 17:38:56 -07:00
eugene yokota 7e5b9c521e
Merge pull request #4675 from eatkins/startup
Startup
2019-05-13 20:10:05 -04:00
eugene yokota 84bee1e440
Merge pull request #4671 from eed3si9n/wip/scalalibrary
change ClassLoaderLayeringStrategy.ScalaInstance to ScalaLibrary
2019-05-13 17:49:47 -04:00
Ethan Atkins 54412d8c59 Improve ScalaMetaBuildClassLoader construction
I realized that all of the data structures that I needed to isolate the
classpath are contained in the AppProvider interface so there was no
need to use structural reflection on the top class loader.
2019-05-13 14:40:22 -07:00
Ethan Atkins 418e7e09fd Shave O(500ms) off of sbt startup
It turns out that it can take roughly one second to instantiate a
scala.nsc.tools.Global instance for the first time. When sbt is starting
up, it also takes nearly 2 seconds to initialize logging. We can speed
up the boot time by doing these two things concurrently. On my machine,
I saw on average a 500ms decrease in startup time after this change.
2019-05-13 14:39:39 -07:00
Eugene Yokota 5c85c04e0d don't include si.allJars into the test classpath
allJars contains unwanted Scala modules.
Having this in prevents the flat classloader from working correctly.

Ref #4609
2019-05-12 23:51:17 -04:00
Eugene Yokota b00c675a19 change ClassLoaderLayeringStrategy.ScalaInstance to ScalaLibrary
Fixes #4609

ScalaInstance contains unwanted Scala modules such as scala-xml and scala-parser-combinators.
2019-05-12 23:36:12 -04:00
Eugene Yokota d8c9eb90c6 exclude inter-project resolvers when resolving the compiler bridge
Fixes #4669
2019-05-12 23:03:07 -04:00
Ethan Atkins b96be5343b Support char buffered stdin on windows in continuous
I finally realized that the trick is that for non cygwin windows, the
available method on the jline wrapped input stream always returns zero.
Unlike on posix, however, the read method is interruptible which means
that we can just spin up a background thread that polls from the input
stream and writes it into a buffer.

I verified that it was no longer necessary to hit <enter> after 'r' to
rerun the continuous command on my windows vm after this change.
2019-05-11 22:01:49 -07:00
Ethan Atkins 8f54ecd536 Check meta build sources before task evaluation
This commit finally fixes #241 by adding support for sbt to either
print a warning or automatically reload the project if the metabuild
sources have changed. To facilitate this, I introduce a new key,
metaBuildSourceOption which has three options:
1) IgnoreSourceChanges
2) WarnOnSourceChanges
3) ReloadOnSourceChanges

When the former is set, sbt will not check if the meta build sources
have changed. Otherwise, sbt will use the buildStructure / fileInputs to
get the ChangedFiles for the metabuild. If there are any changes, it
will either warn or reload the build depending on the value of
metaBuildSourceOption.

The mechanism for diffing the files is that I add a step to EvaluateTask
where, if the project has been loaded and
metaBuildSourceOption != IgnoreSourceChanges, we evaluate the needReload
task. If we need a reload, we return an error that indicates that a
Reload is necessary. When that error is detected, the MainLoop will
prepend "reload" to the pending commands for the state. Otherwise we
just print a warning and continue.

I benchmarked the overhead of this and it wasn't too bad. I generally
saw it taking 5-20ms to perform the check. Since this is only done once
per task evaluation run, I don't think it's a big deal. When
IgnoreSourceChanges is set, there is O(10us) overhead. If performance
does become a problem, we could add a global watch service and skip the
needReload evaluation if no files have been modified.

I removed the watchTrackMetaBuild key and made it so that the continuous
builds only track the meta build when
metaBuildSourceOption == ReloadOnSourceChanges
2019-05-11 22:01:49 -07:00
Ethan Atkins 4007810adb Add watchPersistFileStamps key
The persistentFileStampCache does seem to work pretty well but in case
users encounter issues, I add a boolean flag that allows the user to
turn this behavior off and always re-stamp every source file in every
task evaluation run.
2019-05-11 22:01:48 -07:00
Ethan Atkins ec09e73437 Improve cache invalidation strategy
Previously the persistent attribute map was only reset when the file
event monitor detected a change. This made it possible for the cache to
be inconsistent with the state of the file system*. To fix this, I add an
observer on the file tree repository used by the continuous build that
invalidates the cache entry for any path for which it detects a change.
Invalidating the cache does not stamp the file. That only happens either
when a task asks for the stamp for that file or when the file event
monitor reports an event and we must check if the file was updated or
not.

After this change, touching a source file will not trigger a build
unless the contents of the file actually changes.

I added a test that touches one source file in a project and updates the
content of the other. If the source file that is only ever touched ever
triggers a build, then the test fails.

* This could lead to under-compilation because ExternalHooks would not
detect that the file had been updated.
2019-05-11 22:01:48 -07:00
Ethan Atkins 3d965799f3 Fix trigger bug
I got the if condition wrong which was setting the fileInputs to have a
LastModified stamp.
2019-05-11 21:34:02 -07:00
Ethan Atkins 8a456aef8a Always inject input tasks
I had tried to be cute and only inject certain tasks if they're actually
used, but that made it so that dynamic tasks may not have be able to use
them.
2019-05-11 21:34:02 -07:00
Ethan Atkins 40dc3ff7b3 Move json formatters
Organizationally this was sloppy with the FileStamp implementation
classes split by a bunch of json formatters.
2019-05-11 21:34:02 -07:00
Ethan Atkins f60d4060dd Fix toString for Update 2019-05-11 21:34:02 -07:00
Ethan Atkins b6ad077a72 Update io
The new io verion removes the PathFinder <-> Glob implicit translations.
It also has a number of small bug fixes related to directory listing via
FileTreeView.
2019-05-11 21:34:02 -07:00
Ethan Atkins 2ab8fed8fd Deprecation cleanup
The main project emits a number of deprecation warnings. I've isolated
the deprecation warnings related to Watch to the DeprecatedContinuous
file. I fixed the deprecation warnings where it was straightforward to
do so. After this change, there are three non-watch related changes
emitted:

1) Defaults.scala:3760 uses the deprecated InputTask.apply. This seems
   fixable but I'm not in a hurry
2) oldLoadFailed and oldLastGrep are used by Main. I think this could
   just be fixed by removing the deprecation warnings and setting them
   private[sbt] since they will still be available in the shell.
2019-05-11 21:34:02 -07:00
Ethan Atkins b15b638632 Remove unused private[sbt] key
This slipped through by mistake.
2019-05-11 21:34:02 -07:00
Ethan Atkins f9eb631b13 Filter scala-library more safely
I previously tried to fix https://github.com/sbt/sbt/issues/4608 in
fc715cab44 by finding the instance of
xsbt.boot.BootFilteredLoader in the classloader heirarchy. This was a
risky approach since it made a lot of assumptions about the classloaders
used to invoke xMain.run. Since the point is to filter out the scala
standard library jar, I reworked things to just find all the parents of
the scala provider loader and then walk the graph from the root
classloader until it finds the classloader that contains the scala
library. If no such classloader exists, it ends up returning the parent
of the scala provider library.

I also renamed the libraryLoader parameter to scalaProviderLoader since
that is what is actually passedin. It is actually the libraryLoader that
we want to exclude.
2019-05-11 19:45:25 -07:00
eugene yokota cf932c8a13
Merge pull request #4666 from eed3si9n/wip/coursierlog
silence coursier log when supershell is off
2019-05-11 19:39:21 -04:00
Eugene Yokota b18f3e8710 Reduce the test noise by making id more realistic
Fixes #3893

This fixes the flaky ParserSpec by making the id generation more realistic ASCII identifiers.
2019-05-11 03:55:34 -04:00