Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Hermetic zinc compile] Memoize scalac classpath snapshots #6491

Merged
merged 7 commits into from Sep 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 26 additions & 10 deletions src/python/pants/backend/jvm/subsystems/scala_platform.py
Expand Up @@ -9,10 +9,15 @@
from pants.backend.jvm.subsystems.jvm_tool_mixin import JvmToolMixin
from pants.backend.jvm.subsystems.zinc_language_mixin import ZincLanguageMixin
from pants.backend.jvm.targets.jar_library import JarLibrary
from pants.backend.jvm.tasks.classpath_entry import ClasspathEntry
from pants.base.build_environment import get_buildroot
from pants.build_graph.address import Address
from pants.build_graph.injectables_mixin import InjectablesMixin
from pants.engine.fs import PathGlobs, PathGlobsAndRoot
from pants.java.jar.jar_dependency import JarDependency
from pants.subsystem.subsystem import Subsystem
from pants.util.dirutil import fast_relpath
from pants.util.memo import memoized_method


# full_version - the full scala version to use.
Expand Down Expand Up @@ -132,17 +137,28 @@ def register_custom_tool(key):
register_custom_tool('scala-repl')
register_custom_tool('scalastyle')

def _tool_classpath(self, tool, products):
def _tool_classpath(self, tool, products, scheduler):
"""Return the proper classpath based on products and scala version."""
return self.tool_classpath_from_products(products,
self.versioned_tool_name(tool, self.version),
scope=self.options_scope)

def compiler_classpath(self, products):
return self._tool_classpath('scalac', products)

def style_classpath(self, products):
return self._tool_classpath('scalastyle', products)
classpath = self.tool_classpath_from_products(products,
self.versioned_tool_name(tool, self.version),
scope=self.options_scope)
classpath = tuple(fast_relpath(c, get_buildroot()) for c in classpath)

return self._memoized_scalac_classpath(classpath, scheduler)

@memoized_method
def _memoized_scalac_classpath(self, scala_path, scheduler):
snapshots = scheduler.capture_snapshots(tuple(PathGlobsAndRoot(PathGlobs([path]), get_buildroot()) for path in scala_path))
return [ClasspathEntry(path, snapshot) for path, snapshot in list(zip(scala_path, snapshots))]

def compiler_classpath_entries(self, products, scheduler):
"""Returns classpath entries for the scalac tool."""
return self._tool_classpath('scalac', products, scheduler)

def style_classpath(self, products, scheduler):
"""Returns classpath as paths for scalastyle."""
classpath_entries = self._tool_classpath('scalastyle', products, scheduler)
return [classpath_entry.path for classpath_entry in classpath_entries]

@property
def version(self):
Expand Down
26 changes: 12 additions & 14 deletions src/python/pants/backend/jvm/tasks/jvm_compile/zinc/zinc_compile.py
Expand Up @@ -30,7 +30,7 @@
from pants.base.exceptions import TaskError
from pants.base.hash_utils import hash_file
from pants.base.workunit import WorkUnitLabel
from pants.engine.fs import DirectoryToMaterialize, PathGlobs, PathGlobsAndRoot
from pants.engine.fs import DirectoryToMaterialize
from pants.engine.isolated_process import ExecuteProcessRequest
from pants.java.distribution.distribution import DistributionLocator
from pants.util.contextutil import open_zip
Expand Down Expand Up @@ -261,8 +261,10 @@ def javac_classpath(self):
# the JDK it was invoked with.
return Java.global_javac_classpath(self.context.products)

def scalac_classpath(self):
return ScalaPlatform.global_instance().compiler_classpath(self.context.products)
def scalac_classpath_entries(self):
"""Returns classpath entries for the scalac classpath."""
return ScalaPlatform.global_instance().compiler_classpath_entries(
self.context.products, self.context._scheduler)

def write_extra_resources(self, compile_context):
"""Override write_extra_resources to produce plugin and annotation processor files."""
Expand Down Expand Up @@ -299,16 +301,18 @@ def relative_to_exec_root(path):
# TODO: Support workdirs not nested under buildroot by path-rewriting.
return fast_relpath(path, get_buildroot())

scala_path = self.scalac_classpath()
classes_dir = ctx.classes_dir
analysis_cache = ctx.analysis_file

scala_path = tuple(relative_to_exec_root(c) for c in scala_path)
analysis_cache = relative_to_exec_root(analysis_cache)
classes_dir = relative_to_exec_root(classes_dir)
# TODO: Have these produced correctly, rather than having to relativize them here
relative_classpath = tuple(relative_to_exec_root(c) for c in absolute_classpath)

# list of classpath entries
scalac_classpath_entries = self.scalac_classpath_entries()
scala_path = [classpath_entry.path for classpath_entry in scalac_classpath_entries]

zinc_args = []
zinc_args.extend([
'-log-level', self.get_options().level,
Expand Down Expand Up @@ -411,15 +415,9 @@ def relative_to_exec_root(path):
"execution".format(dep)
)

if scala_path:
# TODO: ScalaPlatform._tool_classpath should capture this and memoize it.
# See https://github.com/pantsbuild/pants/issues/6435
snapshots.append(
self.context._scheduler.capture_snapshots((PathGlobsAndRoot(
PathGlobs(scala_path),
get_buildroot(),
),))[0]
)
snapshots.extend(
classpath_entry.directory_digest for classpath_entry in scalac_classpath_entries
)

merged_input_digest = self.context._scheduler.merge_directories(
tuple(s.directory_digest for s in (snapshots)) + directory_digests
Expand Down
3 changes: 2 additions & 1 deletion src/python/pants/backend/jvm/tasks/scaladoc_gen.py
Expand Up @@ -48,7 +48,8 @@ def create_scaladoc_command(self, classpath, gendir, *targets):
return None

scala_platform = ScalaPlatform.global_instance()
tool_classpath = scala_platform.compiler_classpath(self.context.products)
tool_classpath = [cp_entry.path for cp_entry in scala_platform.compiler_classpath_entries(
self.context.products, self.context._scheduler)]

args = ['-usejavacp',
'-classpath', ':'.join(classpath),
Expand Down
2 changes: 1 addition & 1 deletion src/python/pants/backend/jvm/tasks/scalastyle.py
Expand Up @@ -145,7 +145,7 @@ def call(srcs):
def to_java_boolean(x):
return str(x).lower()

cp = ScalaPlatform.global_instance().style_classpath(self.context.products)
cp = ScalaPlatform.global_instance().style_classpath(self.context.products, self.context._scheduler)
scalastyle_args = [
'-c', scalastyle_config,
'-v', to_java_boolean(scalastyle_verbose),
Expand Down