diff --git a/src/docs/export.md b/src/docs/export.md index b5d108caea7..e46640e81bd 100644 --- a/src/docs/export.md +++ b/src/docs/export.md @@ -107,6 +107,15 @@ The following is an abbreviated export file from a command in the pants repo: }, "default_interpreter": "CPython-2.7.10" }, + "scala_platform": { + "scala_version": "2.12", + "compiler_classpath": [ + "/Users/dmcclanahan/tools/pants-v4/.pants.d/bootstrap/bootstrap-jvm-tools/a0ebe8e0b001/ivy/jars/org.scala-lang/scala-compiler/jars/scala-compiler-2.12.8.jar", + "/Users/dmcclanahan/tools/pants-v4/.pants.d/bootstrap/bootstrap-jvm-tools/a0ebe8e0b001/ivy/jars/org.scala-lang/scala-library/jars/scala-library-2.12.8.jar", + "/Users/dmcclanahan/tools/pants-v4/.pants.d/bootstrap/bootstrap-jvm-tools/a0ebe8e0b001/ivy/jars/org.scala-lang/scala-reflect/jars/scala-reflect-2.12.8.jar", + "/Users/dmcclanahan/tools/pants-v4/.pants.d/bootstrap/bootstrap-jvm-tools/a0ebe8e0b001/ivy/jars/org.scala-lang.modules/scala-xml_2.12/jars/scala-xml_2.12-1.0.6.jar" + ] + }, "targets": { "examples/tests/java/org/pantsbuild/example/usethrift:usethrift": { "is_code_gen": false, @@ -168,6 +177,10 @@ The following is an abbreviated export file from a command in the pants repo: # Export Format Changes +## 1.0.11 + +The 'scala_platform' field is added to the top-level keys, containing the 'scala_version' string (without patch version, e.g. "2.12") and the 'compiler_classpath' jars (a list of absolute paths to jar files). + ## 1.0.10 Coursier is added to be an option for the resolve path which ignores the confs for library sources and javadoc yet. diff --git a/src/python/pants/backend/project_info/tasks/export.py b/src/python/pants/backend/project_info/tasks/export.py index 5ece83c146b..812e37547e6 100644 --- a/src/python/pants/backend/project_info/tasks/export.py +++ b/src/python/pants/backend/project_info/tasks/export.py @@ -9,6 +9,7 @@ from pants.backend.jvm.subsystems.jvm_platform import JvmPlatform from pants.backend.jvm.subsystems.resolve_subsystem import JvmResolveSubsystem +from pants.backend.jvm.subsystems.scala_platform import ScalaPlatform from pants.backend.jvm.targets.jar_library import JarLibrary from pants.backend.jvm.targets.junit_tests import JUnitTests from pants.backend.jvm.targets.jvm_app import JvmApp @@ -55,12 +56,12 @@ class ExportTask(ResolveRequirementsTaskBase, IvyTaskMixin, CoursierMixin): # # Note format changes in src/docs/export.md and update the Changelog section. # - DEFAULT_EXPORT_VERSION = '1.0.10' + DEFAULT_EXPORT_VERSION = '1.0.11' @classmethod def subsystem_dependencies(cls): return super().subsystem_dependencies() + ( - DistributionLocator, JvmPlatform, PythonInterpreterCache + DistributionLocator, JvmPlatform, PythonInterpreterCache, ScalaPlatform ) class SourceRootTypes: @@ -282,6 +283,15 @@ def iter_transitive_jars(jar_lib): for target in targets: process_target(target) + scala_platform = ScalaPlatform.global_instance() + scala_platform_map = { + 'scala_version': scala_platform.version, + 'compiler_classpath': [ + cp_entry.path + for cp_entry in scala_platform.compiler_classpath_entries(self.context.products) + ], + } + jvm_platforms_map = { 'default_platform' : JvmPlatform.global_instance().default_platform.name, 'platforms': { @@ -296,6 +306,7 @@ def iter_transitive_jars(jar_lib): 'version': self.DEFAULT_EXPORT_VERSION, 'targets': targets_map, 'jvm_platforms': jvm_platforms_map, + 'scala_platform': scala_platform_map, # `jvm_distributions` are static distribution settings from config, # `preferred_jvm_distributions` are distributions that pants actually uses for the # given platform setting. diff --git a/tests/python/pants_test/backend/project_info/tasks/resolve_jars_test_mixin.py b/tests/python/pants_test/backend/project_info/tasks/resolve_jars_test_mixin.py index 4c6871330ef..87a975d18f9 100644 --- a/tests/python/pants_test/backend/project_info/tasks/resolve_jars_test_mixin.py +++ b/tests/python/pants_test/backend/project_info/tasks/resolve_jars_test_mixin.py @@ -76,10 +76,9 @@ def _test_jar_lib_with_url(self, load_all): targets = ['{0}:{1}'.format(os.path.join(source_dir, 'src'), name) for name in spec_names] - with temporary_dir() as ivy_temp_dir: - extra_args = ['--ivy-cache-dir={}'.format(ivy_temp_dir)] - self.evaluate_subtask(targets, workdir, load_all, extra_args=extra_args, - expected_jars=['org.pantsbuild:synthetic-test-jar:1.2.3']) + self.evaluate_subtask(targets, workdir, load_all, + extra_args=[], + expected_jars=['org.pantsbuild:synthetic-test-jar:1.2.3']) def test_jar_lib_with_url_resolve_default(self): self._test_jar_lib_with_url(False) diff --git a/tests/python/pants_test/backend/project_info/tasks/test_export.py b/tests/python/pants_test/backend/project_info/tasks/test_export.py index 547275ccd1e..5b219177807 100644 --- a/tests/python/pants_test/backend/project_info/tasks/test_export.py +++ b/tests/python/pants_test/backend/project_info/tasks/test_export.py @@ -20,6 +20,7 @@ from pants.backend.jvm.targets.jvm_binary import JvmBinary from pants.backend.jvm.targets.jvm_target import JvmTarget from pants.backend.jvm.targets.scala_library import ScalaLibrary +from pants.backend.jvm.tasks.bootstrap_jvm_tools import BootstrapJvmTools from pants.backend.jvm.tasks.classpath_products import ClasspathProducts from pants.backend.project_info.tasks.export import Export from pants.backend.python.register import build_file_aliases as register_python @@ -45,6 +46,9 @@ def task_type(cls): def alias_groups(cls): return register_core().merge(register_jvm()).merge(register_python()) + # Version of the scala compiler and libraries used for this test. + _scala_toolchain_version = '2.10.5' + def setUp(self): super().setUp() @@ -56,10 +60,85 @@ def setUp(self): } init_subsystems([JUnit, ScalaPlatform, ScoveragePlatform], scala_options) + self.make_target( + ':jar-tool', + JarLibrary, + jars=[JarDependency('org.pantsbuild', 'jar-tool', '0.0.10')] + ) + + # NB: `test_has_python_requirements` will attempt to inject every possible scala compiler target + # spec, for versions 2.10, 2.11, 2.12, and custom, and will error out if they are not + # available. This isn't a problem when running pants on the command line, but in unit testing + # there's probably some task or subsystem that needs to be initialized to avoid this. + for empty_target in ['scalac', 'scala-repl', 'scala-library', 'scala-reflect', 'scalastyle']: + for unused_scala_version in ['2_10', '2_11']: + self.make_target( + f':{empty_target}_{unused_scala_version}', + Target, + ) + self.make_target( + ':scalac-plugin-dep', + Target, + ) + + self.make_target( + ':jarjar', + JarLibrary, + jars=[JarDependency(org='org.pantsbuild', name='jarjar', rev='1.7.2')] + ) + self.make_target( ':scala-library', JarLibrary, - jars=[JarDependency('org.scala-lang', 'scala-library', '2.10.5')] + jars=[JarDependency('org.scala-lang', 'scala-library', self._scala_toolchain_version)] + ) + + self.make_target( + ':scalac', + JarLibrary, + jars=[JarDependency('org.scala-lang', 'scala-compiler', self._scala_toolchain_version)] + ) + + self.make_target( + ':scalac_2_12', + JarLibrary, + jars=[JarDependency('org.scala-lang', 'scala-compiler', '2.12.8')] + ) + self.make_target( + ':scala-library_2_12', + JarLibrary, + jars=[JarDependency('org.scala-lang', 'scala-library', '2.12.8')] + ) + self.make_target( + ':scala-reflect_2_12', + JarLibrary, + jars=[JarDependency('org.scala-lang', 'scala-reflect', '2.12.8')] + ) + self.make_target( + ':scala-repl_2_12', + JarLibrary, + jars=[JarDependency('org.scala-lang', 'scala-repl', '2.12.8')] + ) + self.make_target( + ':scalastyle_2_12', + Target, + ) + self.make_target( + ':scalastyle', + Target, + ) + + + self.make_target( + ':scala-reflect', + JarLibrary, + jars=[JarDependency('org.scala-lang', 'scala-reflect', self._scala_toolchain_version)] + ) + + self.make_target( + ':scala-repl', + JarLibrary, + jars=[JarDependency('org.scala-lang', 'scala-repl', self._scala_toolchain_version)] ) self.make_target( @@ -181,17 +260,20 @@ def setUp(self): self.add_to_build_file('src/python/has_reqs/BUILD', textwrap.dedent(""" python_library(name="has_reqs", sources=globs("*.py"), dependencies=[':six']) - + python_requirement_library( name='six', requirements=[ python_requirement('six==1.9.0') ] - ) + ) """)) def execute_export(self, *specs, **options_overrides): options = { + ScalaPlatform.options_scope: { + 'version': 'custom' + }, JvmResolveSubsystem.options_scope: { 'resolver': 'ivy' }, @@ -204,10 +286,14 @@ def execute_export(self, *specs, **options_overrides): } options.update(options_overrides) + BootstrapJvmTools.options_scope = 'bootstrap-jvm-tools' context = self.context(options=options, target_roots=[self.target(spec) for spec in specs], - for_subsystems=[JvmPlatform]) + for_subsystems=[JvmPlatform], + for_task_types=[BootstrapJvmTools]) context.products.safe_create_data('compile_classpath', init_func=ClasspathProducts.init_func(self.pants_workdir)) + bootstrap_task = BootstrapJvmTools(context, self.pants_workdir) + bootstrap_task.execute() task = self.create_task(context) return list(task.console_output(list(task.context.targets()), context.products.get_data('compile_classpath'))) @@ -249,7 +335,27 @@ def test_without_dependencies(self): def test_version(self): result = self.execute_export_json('project_info:first') # If you have to update this test, make sure export.md is updated with changelog notes - self.assertEqual('1.0.10', result['version']) + self.assertEqual('1.0.11', result['version']) + + def test_scala_platform_custom(self): + result = self.execute_export_json('project_info:first') + scala_platform = result['scala_platform'] + scala_version = scala_platform['scala_version'] + self.assertEqual(scala_version, 'custom') + scala_jars = scala_platform['compiler_classpath'] + self.assertTrue(any(self._scala_toolchain_version in jar_path for jar_path in scala_jars)) + + def test_scala_platform_standard(self): + result = self.execute_export_json('project_info:first', **{ + ScalaPlatform.options_scope: { + 'version': '2.12' + } + }) + scala_platform = result['scala_platform'] + scala_version = scala_platform['scala_version'] + self.assertEqual(scala_version, '2.12') + scala_jars = scala_platform['compiler_classpath'] + self.assertTrue(any('2.12' in jar_path for jar_path in scala_jars)) def test_sources(self): self.set_options(sources=True)