From dd8a148eef1f82f9ef4e3f90741ea500e149bb4e Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Thu, 12 Dec 2019 14:33:02 +0000 Subject: [PATCH 01/17] Add test to check that we are outputting targets between roots --- .../backend/project_info/tasks/test_export_dep_as_jar.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py index cf072c0b783..999deeb7871 100644 --- a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py +++ b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py @@ -539,3 +539,10 @@ def test_export_sources_if_flag_passed(self): sorted(self.jvm_target_with_sources.sources_relative_to_source_root()), sorted(sources_jar_of_dep.namelist()) ) + + def test_includes_targets_between_roots(self): + result = self.execute_export_json('project_info:scala_with_source_dep', 'project_info:jar_lib') + self.assertIn( + 'project_info:jvm_target', + result['targets'].keys() + ) From e25b9fcd9c102cd848964149f402d26e1fd67a56 Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Thu, 12 Dec 2019 14:34:35 +0000 Subject: [PATCH 02/17] Extract target map assignment from graph_info initialization --- .../pants/backend/project_info/tasks/export_dep_as_jar.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index d587006abcb..36a04fc45a7 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -207,7 +207,7 @@ def iter_transitive_jars(jar_lib): return info - def initialize_graph_info(self, targets_map): + def initialize_graph_info(self): scala_platform = ScalaPlatform.global_instance() scala_platform_map = { 'scala_version': scala_platform.version, @@ -229,7 +229,7 @@ def initialize_graph_info(self, targets_map): graph_info = { 'version': DEFAULT_EXPORT_VERSION, - 'targets': targets_map, + 'targets': {}, 'jvm_platforms': jvm_platforms_map, 'scala_platform': scala_platform_map, # `jvm_distributions` are static distribution settings from config, @@ -280,7 +280,8 @@ def generate_targets_map(self, all_targets, runtime_classpath): if isinstance(dep, Resources): resource_target_map[dep] = target - graph_info = self.initialize_graph_info(targets_map) + graph_info = self.initialize_graph_info() + graph_info['targets'] = targets_map graph_info['libraries'] = self._resolve_jars_info(all_targets, runtime_classpath) # Using resolved path in preparation for VCFS. From bbf55363734464871a166e80e199f6f11105d057 Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Fri, 13 Dec 2019 15:42:53 +0000 Subject: [PATCH 03/17] Add first experiments --- .../project_info/tasks/export_dep_as_jar.py | 92 +++++++++++++------ 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index 36a04fc45a7..7116f2945d8 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -8,6 +8,7 @@ from twitter.common.collections import OrderedSet +from pants.backend.jvm.subsystems.dependency_context import DependencyContext from pants.backend.jvm.subsystems.jvm_platform import JvmPlatform from pants.backend.jvm.subsystems.scala_platform import ScalaPlatform from pants.backend.jvm.targets.jar_library import JarLibrary @@ -33,6 +34,10 @@ class ExportDepAsJar(ConsoleTask): jvm dependencies instead of sources. """ + @classmethod + def subsystem_dependencies(cls): + return super().subsystem_dependencies() + (DependencyContext,) + @classmethod def register_options(cls, register): super().register_options(register) @@ -252,7 +257,35 @@ def initialize_graph_info(self): return graph_info - def generate_targets_map(self, all_targets, runtime_classpath): + def _get_all_targets(self, targets): + additional_java_targets = [] + for t in targets: + if isinstance(t, ScalaLibrary): + additional_java_targets.extend(t.java_sources) + targets.extend(additional_java_targets) + return targets + + def _get_targets_to_print(self, all_targets, target_roots_set): + def target_is_between_roots(t): + transitive_dependencies = set( + DependencyContext.global_instance().dependencies_respecting_strict_deps(t) if hasattr(t, 'strict_deps') else \ + DependencyContext.global_instance().all_dependencies(t) + ) + return len(transitive_dependencies.intersection(target_roots_set)) > 0 + + def target_is_a_resource(t): + return isinstance(t, Resources) + + printable_targets = [] + for target in all_targets: + print(f"BL: COnsidering target {target}, with target_root_set {target_roots_set}. is_a_resource {target_is_a_resource(target)}, is_between_roots {target_is_between_roots(target)}") + if (target in target_roots_set) or \ + target_is_between_roots(target) or \ + target_is_a_resource(target): + printable_targets.append(target) + return printable_targets + + def generate_targets_map(self, targets, runtime_classpath): """Generates a dictionary containing all pertinent information about the target graph. The return dictionary is suitable for serialization by json.dumps. @@ -260,60 +293,59 @@ def generate_targets_map(self, all_targets, runtime_classpath): :param classpath_products: Optional classpath_products. If not provided when the --libraries option is `True`, this task will perform its own jar resolution. """ + target_roots_set = set(self.context.target_roots) + + all_targets = self._get_all_targets(targets) + libraries_map = self._resolve_jars_info(all_targets, runtime_classpath) targets_map = {} resource_target_map = {} - target_roots_set = set(self.context.target_roots) + # Using resolved path in preparation for VCFS. + resource_jar_root = os.path.realpath(self.versioned_workdir) - additional_java_targets = [] for t in all_targets: - if isinstance(t, ScalaLibrary): - additional_java_targets.extend(t.java_sources) - - all_targets.extend(additional_java_targets) - - for target in all_targets: - info = self._process_target(target, target_roots_set, resource_target_map, runtime_classpath) - targets_map[target.address.spec] = info - - for dep in target.dependencies: + for dep in t.dependencies: if isinstance(dep, Resources): - resource_target_map[dep] = target + resource_target_map[dep] = t - graph_info = self.initialize_graph_info() - graph_info['targets'] = targets_map - graph_info['libraries'] = self._resolve_jars_info(all_targets, runtime_classpath) - - # Using resolved path in preparation for VCFS. - resource_jar_root = os.path.realpath(self.versioned_workdir) for t in all_targets: target_type = ExportDepAsJar._get_target_type(t, resource_target_map) - # If it is a target root or it is already a jar_library target, then no-op. - if t in target_roots_set or targets_map[t.address.spec]['pants_target_type'] == 'jar_library': - continue - - targets_map[t.address.spec]['pants_target_type'] = 'jar_library' - targets_map[t.address.spec]['libraries'] = [t.id] - if target_type == SourceRootTypes.RESOURCE or target_type == SourceRootTypes.TEST_RESOURCE: # yic assumed that the cost to fingerprint the target may not be that lower than # just zipping up the resources anyway. jarred_resources = ExportDepAsJar._zip_sources(t, resource_jar_root) - graph_info['libraries'][t.id]['default'] = jarred_resources.name + libraries_map[t.id]['default'] = jarred_resources.name else: jar_products = runtime_classpath.get_for_target(t) for conf, jar_entry in jar_products: # TODO(yic): check --compile-rsc-use-classpath-jars is enabled. # If not, zip up the classes/ dir here. if 'z.jar' in jar_entry: - graph_info['libraries'][t.id][conf] = jar_entry + libraries_map[t.id][conf] = jar_entry if self.get_options().sources: # NB: We create the jar in the same place as we create the resources # (as opposed to where we store the z.jar), because the path to the z.jar depends # on tasks outside of this one. # In addition to that, we may not want to depend on z.jar existing to export source jars. jarred_sources = ExportDepAsJar._zip_sources(t, resource_jar_root, suffix='-sources.jar') - graph_info['libraries'][t.id]['sources'] = jarred_sources.name + libraries_map[t.id]['sources'] = jarred_sources.name + + printable_targets = self._get_targets_to_print(all_targets, target_roots_set) + for target in printable_targets: + + info = self._process_target(target, target_roots_set, resource_target_map, runtime_classpath) + targets_map[target.address.spec] = info + + # If it is a target root or it is already a jar_library target, then no-op. + if target in target_roots_set or targets_map[t.address.spec]['pants_target_type'] == 'jar_library': + continue + + targets_map[t.address.spec]['pants_target_type'] = 'jar_library' + targets_map[t.address.spec]['libraries'] = [t.id] + + graph_info = self.initialize_graph_info() + graph_info['targets'] = targets_map + graph_info['libraries'] = libraries_map return graph_info From 4f1d89afce8b171bfadd77029b664192499bfe39 Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Mon, 16 Dec 2019 11:56:57 +0000 Subject: [PATCH 04/17] Simplify the calculation for printable targets --- .../project_info/tasks/export_dep_as_jar.py | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index 7116f2945d8..2c8e8731d76 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -265,25 +265,10 @@ def _get_all_targets(self, targets): targets.extend(additional_java_targets) return targets - def _get_targets_to_print(self, all_targets, target_roots_set): - def target_is_between_roots(t): - transitive_dependencies = set( - DependencyContext.global_instance().dependencies_respecting_strict_deps(t) if hasattr(t, 'strict_deps') else \ - DependencyContext.global_instance().all_dependencies(t) - ) - return len(transitive_dependencies.intersection(target_roots_set)) > 0 - - def target_is_a_resource(t): - return isinstance(t, Resources) - - printable_targets = [] - for target in all_targets: - print(f"BL: COnsidering target {target}, with target_root_set {target_roots_set}. is_a_resource {target_is_a_resource(target)}, is_between_roots {target_is_between_roots(target)}") - if (target in target_roots_set) or \ - target_is_between_roots(target) or \ - target_is_a_resource(target): - printable_targets.append(target) - return printable_targets + def _get_targets_to_make_into_modules(self, target_roots_set): + target_root_addresses = [t.address for t in target_roots_set] + dependees_of_target_roots = self.context.build_graph.transitive_dependees_of_addresses(target_root_addresses) + return dependees_of_target_roots def generate_targets_map(self, targets, runtime_classpath): """Generates a dictionary containing all pertinent information about the target graph. @@ -330,18 +315,19 @@ def generate_targets_map(self, targets, runtime_classpath): jarred_sources = ExportDepAsJar._zip_sources(t, resource_jar_root, suffix='-sources.jar') libraries_map[t.id]['sources'] = jarred_sources.name - printable_targets = self._get_targets_to_print(all_targets, target_roots_set) - for target in printable_targets: + modulizable_targets = self._get_targets_to_make_into_modules(target_roots_set) + print(f"BL: Printable targets: {modulizable_targets}") + for target in modulizable_targets: info = self._process_target(target, target_roots_set, resource_target_map, runtime_classpath) targets_map[target.address.spec] = info # If it is a target root or it is already a jar_library target, then no-op. - if target in target_roots_set or targets_map[t.address.spec]['pants_target_type'] == 'jar_library': + if target in target_roots_set or targets_map[target.address.spec]['pants_target_type'] == 'jar_library': continue - targets_map[t.address.spec]['pants_target_type'] = 'jar_library' - targets_map[t.address.spec]['libraries'] = [t.id] + targets_map[target.address.spec]['pants_target_type'] = 'jar_library' + targets_map[target.address.spec]['libraries'] = [t.id] graph_info = self.initialize_graph_info() graph_info['targets'] = targets_map From 2a184b888b7fe81da9c556d773aaaa548c0af584 Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Mon, 16 Dec 2019 12:01:51 +0000 Subject: [PATCH 05/17] Add transitive dependencies as libraries to modulizable targets --- .../project_info/tasks/export_dep_as_jar.py | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index 2c8e8731d76..a6d41742c5d 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -145,7 +145,7 @@ def _zip_sources(target, location, suffix='.jar'): zip_file.write(os.path.join(get_buildroot(), src_from_build_root), src_from_source_root) return f - def _process_target(self, current_target, target_roots_set, resource_target_map, runtime_classpath): + def _process_target(self, current_target, target_roots_set, modulizable_target_set, resource_target_map, runtime_classpath): """ :type current_target:pants.build_graph.target.Target """ @@ -184,12 +184,13 @@ def iter_transitive_jars(jar_lib): if isinstance(current_target, JarLibrary): target_libraries = OrderedSet(iter_transitive_jars(current_target)) for dep in current_target.dependencies: - info['targets'].append(dep.address.spec) - if isinstance(dep, JarLibrary): - for jar in dep.jar_dependencies: - target_libraries.add(M2Coordinate(jar.org, jar.name, jar.rev)) - # Add all the jars pulled in by this jar_library - target_libraries.update(iter_transitive_jars(dep)) + if dep in modulizable_target_set: + info['targets'].append(dep.address.spec) + if isinstance(dep, JarLibrary): + for jar in dep.jar_dependencies: + target_libraries.add(M2Coordinate(jar.org, jar.name, jar.rev)) + # Add all the jars pulled in by this jar_library + target_libraries.update(iter_transitive_jars(dep)) if isinstance(current_target, ScalaLibrary): for dep in current_target.java_sources: @@ -204,6 +205,13 @@ def iter_transitive_jars(jar_lib): if runtime_classpath: info['libraries'].extend(self._jar_id(lib) for lib in target_libraries) + def _transitive_deps(t): + return set( + DependencyContext.global_instance().dependencies_respecting_strict_deps(t) if hasattr(t, 'strict_deps') else \ + DependencyContext.global_instance().all_dependencies(t) + ) + info['libraries'].extend([dep.id for dep in _transitive_deps(current_target)]) + if current_target in target_roots_set: info['roots'] = [{ 'source_root': os.path.realpath(source_root_package_prefix[0]), @@ -319,7 +327,7 @@ def generate_targets_map(self, targets, runtime_classpath): print(f"BL: Printable targets: {modulizable_targets}") for target in modulizable_targets: - info = self._process_target(target, target_roots_set, resource_target_map, runtime_classpath) + info = self._process_target(target, target_roots_set, modulizable_targets, resource_target_map, runtime_classpath) targets_map[target.address.spec] = info # If it is a target root or it is already a jar_library target, then no-op. From 07568bc3b7b557125b84b24790a189a6bef89ae6 Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Mon, 16 Dec 2019 13:49:16 +0000 Subject: [PATCH 06/17] Don't include the target itself in its own libraries --- .../pants/backend/project_info/tasks/export_dep_as_jar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index a6d41742c5d..8b5e27435ed 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -209,7 +209,7 @@ def _transitive_deps(t): return set( DependencyContext.global_instance().dependencies_respecting_strict_deps(t) if hasattr(t, 'strict_deps') else \ DependencyContext.global_instance().all_dependencies(t) - ) + ).difference({t}) # The transitive deps include the target itself, which we don't want info['libraries'].extend([dep.id for dep in _transitive_deps(current_target)]) if current_target in target_roots_set: From 401840ec93e7cddd526883f7ac044466670e182d Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Mon, 16 Dec 2019 14:02:16 +0000 Subject: [PATCH 07/17] Add JarLibraries of dependencies to targets even when the dep is not modulizable --- .../backend/project_info/tasks/export_dep_as_jar.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index 8b5e27435ed..2c143c49c18 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -184,13 +184,13 @@ def iter_transitive_jars(jar_lib): if isinstance(current_target, JarLibrary): target_libraries = OrderedSet(iter_transitive_jars(current_target)) for dep in current_target.dependencies: + if isinstance(dep, JarLibrary): + for jar in dep.jar_dependencies: + target_libraries.add(M2Coordinate(jar.org, jar.name, jar.rev)) + # Add all the jars pulled in by this jar_library + target_libraries.update(iter_transitive_jars(dep)) if dep in modulizable_target_set: info['targets'].append(dep.address.spec) - if isinstance(dep, JarLibrary): - for jar in dep.jar_dependencies: - target_libraries.add(M2Coordinate(jar.org, jar.name, jar.rev)) - # Add all the jars pulled in by this jar_library - target_libraries.update(iter_transitive_jars(dep)) if isinstance(current_target, ScalaLibrary): for dep in current_target.java_sources: From 85d988c4258f51d60ba68b114cc5eaaec3ed158f Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Mon, 16 Dec 2019 14:35:44 +0000 Subject: [PATCH 08/17] Modify tests to accomodate for the new structure --- .../tasks/test_export_dep_as_jar.py | 51 ++++++++++--------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py index 999deeb7871..211e15c023a 100644 --- a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py +++ b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py @@ -332,15 +332,13 @@ def test_with_dependencies(self): result = self.execute_export_json('project_info:third') self.assertEqual( - sorted([ - '//:scala-library', - 'java/project_info:java_lib', - 'project_info:jar_lib' - ]), + sorted(['java/project_info:java_lib']), sorted(result['targets']['project_info:third']['targets']) ) self.assertEqual(sorted(['org.scala-lang:scala-library:2.10.5', - 'org.apache:apache-jar:12.12.2012']), + 'org.apache:apache-jar:12.12.2012', + '.scala-library', + 'project_info.jar_lib']), sorted(result['targets']['project_info:third']['libraries'])) self.assertEqual(1, len(result['targets']['project_info:third']['roots'])) @@ -353,21 +351,27 @@ def test_with_dependencies(self): def test_jvm_app(self): result = self.execute_export_json('project_info:jvm_app') - self.assertEqual(['org.apache:apache-jar:12.12.2012'], - result['targets']['project_info:jvm_app']['libraries']) + self.assertEqual(sorted(['org.apache:apache-jar:12.12.2012', 'project_info.jar_lib']), + sorted(result['targets']['project_info:jvm_app']['libraries'])) def test_jvm_target(self): self.maxDiff = None result = self.execute_export_json('project_info:jvm_target') jvm_target = result['targets']['project_info:jvm_target'] + jvm_target['libraries'] = sorted(jvm_target['libraries']) expected_jvm_target = { 'excludes': [], 'globs': {'globs': ['project_info/this/is/a/source/Foo.scala', 'project_info/this/is/a/source/Bar.scala']}, - 'libraries': ['org.apache:apache-jar:12.12.2012', 'org.scala-lang:scala-library:2.10.5'], + 'libraries': sorted([ + 'org.apache:apache-jar:12.12.2012', + 'org.scala-lang:scala-library:2.10.5', + 'project_info.jar_lib', + '.scala-library', + ]), 'id': 'project_info.jvm_target', # 'is_code_gen': False, - 'targets': ['project_info:jar_lib', '//:scala-library'], + 'targets': [], 'is_synthetic': False, 'is_target_root': True, 'roots': [ @@ -388,22 +392,25 @@ def test_java_test(self): result = self.execute_export_json('project_info:java_test') self.assertEqual('TEST', result['targets']['project_info:java_test']['target_type']) # Note that the junit dep gets auto-injected via the JUnit subsystem. - self.assertEqual(['org.apache:apache-jar:12.12.2012', - 'junit:junit:{}'.format(JUnit.LIBRARY_REV)], - result['targets']['project_info:java_test']['libraries']) - self.assertEqual('TEST_RESOURCE', - result['targets']['project_info:test_resource']['target_type']) + self.assertEqual(sorted([ + 'org.apache:apache-jar:12.12.2012', + 'junit:junit:{}'.format(JUnit.LIBRARY_REV), + 'project_info.jar_lib', + 'project_info.test_resource', + '.junit_library', + ]), + sorted(result['targets']['project_info:java_test']['libraries'])) def test_jvm_binary(self): result = self.execute_export_json('project_info:jvm_binary') - self.assertEqual(['org.apache:apache-jar:12.12.2012'], - result['targets']['project_info:jvm_binary']['libraries']) + self.assertEqual(sorted(['org.apache:apache-jar:12.12.2012', 'project_info.jar_lib']), + sorted(result['targets']['project_info:jvm_binary']['libraries'])) def test_top_dependency(self): result = self.execute_export_json('project_info:top_dependency') - self.assertEqual([], result['targets']['project_info:top_dependency']['libraries']) - self.assertEqual(['project_info:jvm_binary'], - result['targets']['project_info:top_dependency']['targets']) + self.assertEqual(sorted(['project_info.jvm_binary', 'project_info.jar_lib']), + sorted(result['targets']['project_info:top_dependency']['libraries'])) + self.assertEqual([], result['targets']['project_info:top_dependency']['targets']) def test_format_flag(self): self.set_options(formatted=False) @@ -415,9 +422,7 @@ def test_target_types_with_resource_as_deps(self): result = self.execute_export_json('project_info:target_type') self.assertEqual('SOURCE', result['targets']['project_info:target_type']['target_type']) - self.assertEqual('RESOURCE', result['targets']['project_info:resource']['target_type']) - self.assertEqual([], result['targets']['project_info:resource']['roots']) - self.assertEqual(['project_info.resource'], result['targets']['project_info:resource']['libraries']) + self.assertIn('project_info.resource', result['targets']['project_info:target_type']['libraries']) self.assertTrue(result['libraries']['project_info.resource']['default'].endswith('.jar')) def test_target_types_with_resource_as_root(self): From 92a54e2e7d854bea3b50b1f25359e2834ab42586 Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Wed, 18 Dec 2019 12:20:56 +0000 Subject: [PATCH 09/17] Not create libraries for modulizable targets --- .../project_info/tasks/export_dep_as_jar.py | 61 ++++++++++--------- .../tasks/test_export_dep_as_jar.py | 19 ++++++ 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index 2c143c49c18..a147e256f90 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -209,7 +209,7 @@ def _transitive_deps(t): return set( DependencyContext.global_instance().dependencies_respecting_strict_deps(t) if hasattr(t, 'strict_deps') else \ DependencyContext.global_instance().all_dependencies(t) - ).difference({t}) # The transitive deps include the target itself, which we don't want + ).difference(modulizable_target_set) # Modulizable targets won't generate libraries info['libraries'].extend([dep.id for dep in _transitive_deps(current_target)]) if current_target in target_roots_set: @@ -271,13 +271,39 @@ def _get_all_targets(self, targets): if isinstance(t, ScalaLibrary): additional_java_targets.extend(t.java_sources) targets.extend(additional_java_targets) - return targets + return set(targets) def _get_targets_to_make_into_modules(self, target_roots_set): target_root_addresses = [t.address for t in target_roots_set] dependees_of_target_roots = self.context.build_graph.transitive_dependees_of_addresses(target_root_addresses) return dependees_of_target_roots + def _make_libraries_entry(self, target, resource_target_map, runtime_classpath): + # Using resolved path in preparation for VCFS. + resource_jar_root = os.path.realpath(self.versioned_workdir) + library_entry = {} + target_type = ExportDepAsJar._get_target_type(target, resource_target_map) + if target_type == SourceRootTypes.RESOURCE or target_type == SourceRootTypes.TEST_RESOURCE: + # yic assumed that the cost to fingerprint the target may not be that lower than + # just zipping up the resources anyway. + jarred_resources = ExportDepAsJar._zip_sources(target, resource_jar_root) + library_entry['default'] = jarred_resources.name + else: + jar_products = runtime_classpath.get_for_target(target) + for conf, jar_entry in jar_products: + # TODO(yic): check --compile-rsc-use-classpath-jars is enabled. + # If not, zip up the classes/ dir here. + if 'z.jar' in jar_entry: + library_entry[conf] = jar_entry + if self.get_options().sources: + # NB: We create the jar in the same place as we create the resources + # (as opposed to where we store the z.jar), because the path to the z.jar depends + # on tasks outside of this one. + # In addition to that, we may not want to depend on z.jar existing to export source jars. + jarred_sources = ExportDepAsJar._zip_sources(target, resource_jar_root, suffix='-sources.jar') + library_entry['sources'] = jarred_sources.name + return library_entry + def generate_targets_map(self, targets, runtime_classpath): """Generates a dictionary containing all pertinent information about the target graph. @@ -293,40 +319,19 @@ def generate_targets_map(self, targets, runtime_classpath): targets_map = {} resource_target_map = {} - # Using resolved path in preparation for VCFS. - resource_jar_root = os.path.realpath(self.versioned_workdir) for t in all_targets: for dep in t.dependencies: if isinstance(dep, Resources): resource_target_map[dep] = t - for t in all_targets: - target_type = ExportDepAsJar._get_target_type(t, resource_target_map) - if target_type == SourceRootTypes.RESOURCE or target_type == SourceRootTypes.TEST_RESOURCE: - # yic assumed that the cost to fingerprint the target may not be that lower than - # just zipping up the resources anyway. - jarred_resources = ExportDepAsJar._zip_sources(t, resource_jar_root) - libraries_map[t.id]['default'] = jarred_resources.name - else: - jar_products = runtime_classpath.get_for_target(t) - for conf, jar_entry in jar_products: - # TODO(yic): check --compile-rsc-use-classpath-jars is enabled. - # If not, zip up the classes/ dir here. - if 'z.jar' in jar_entry: - libraries_map[t.id][conf] = jar_entry - if self.get_options().sources: - # NB: We create the jar in the same place as we create the resources - # (as opposed to where we store the z.jar), because the path to the z.jar depends - # on tasks outside of this one. - # In addition to that, we may not want to depend on z.jar existing to export source jars. - jarred_sources = ExportDepAsJar._zip_sources(t, resource_jar_root, suffix='-sources.jar') - libraries_map[t.id]['sources'] = jarred_sources.name - modulizable_targets = self._get_targets_to_make_into_modules(target_roots_set) - print(f"BL: Printable targets: {modulizable_targets}") - for target in modulizable_targets: + non_modulizable_targets = all_targets.difference(modulizable_targets) + + for t in non_modulizable_targets: + libraries_map[t.id] = self._make_libraries_entry(t, resource_target_map, runtime_classpath) + for target in modulizable_targets: info = self._process_target(target, target_roots_set, modulizable_targets, resource_target_map, runtime_classpath) targets_map[target.address.spec] = info diff --git a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py index 211e15c023a..8fd8bfe2db1 100644 --- a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py +++ b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py @@ -551,3 +551,22 @@ def test_includes_targets_between_roots(self): 'project_info:jvm_target', result['targets'].keys() ) + + def test_target_roots_dont_generate_libs(self): + result = self.execute_export_json('project_info:scala_with_source_dep', 'project_info:jvm_target') + self.assertNotIn( + 'project_info.scala_with_source_dep', + result['targets']['project_info:scala_with_source_dep']['libraries'] + ) + self.assertNotIn( + 'project_info.jvm_target', + result['targets']['project_info:scala_with_source_dep']['libraries'] + ) + self.assertNotIn( + 'project_info.scala_with_source_dep', + result['libraries'].keys() + ) + self.assertNotIn( + 'project_info.jvm_target', + result['libraries'].keys() + ) From 7bb0f0b575f914ecfb1166b34298a115f7efe066 Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Wed, 18 Dec 2019 15:18:14 +0000 Subject: [PATCH 10/17] Only include libraries in one of the applicable modulizable targets --- .../project_info/tasks/export_dep_as_jar.py | 17 ++++--- .../tasks/test_export_dep_as_jar.py | 46 +++++++++++++++++++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index a147e256f90..97d853615b6 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -205,12 +205,17 @@ def iter_transitive_jars(jar_lib): if runtime_classpath: info['libraries'].extend(self._jar_id(lib) for lib in target_libraries) - def _transitive_deps(t): - return set( - DependencyContext.global_instance().dependencies_respecting_strict_deps(t) if hasattr(t, 'strict_deps') else \ - DependencyContext.global_instance().all_dependencies(t) - ).difference(modulizable_target_set) # Modulizable targets won't generate libraries - info['libraries'].extend([dep.id for dep in _transitive_deps(current_target)]) + def _libraries_to_include(t): + libraries_to_include = set([]) + self.context.build_graph.walk_transitive_dependency_graph( + [direct_dep.address for direct_dep in t.dependencies], + # NB: Dependency graph between modulizable targets is represented with modules, + # so we don't need to expand those branches of the tree. + predicate=lambda dep: dep not in modulizable_target_set, + work=lambda dep: libraries_to_include.add(dep.id), + ) + return libraries_to_include + info['libraries'].extend(_libraries_to_include(current_target)) if current_target in target_roots_set: info['roots'] = [{ diff --git a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py index 8fd8bfe2db1..fe4e6257b4a 100644 --- a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py +++ b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py @@ -247,6 +247,17 @@ def setUp(self): sources=[] ) + # A build graph where a -(depends on)-> b -> ... -> e + self.linear_build_graph = {} + last_target = None + for letter in reversed(['a', 'b', 'c', 'd', 'e']): + last_target = self.make_target( + f'project_info:{letter}', + target_type=ScalaLibrary, + dependencies=[] if last_target is None else [last_target] + ) + self.linear_build_graph[letter] = last_target + def create_runtime_classpath_for_targets(self, target): def path_to_zjar_with_workdir(address: Address): return os.path.join(self.pants_workdir, address.path_safe_spec, "z.jar") @@ -570,3 +581,38 @@ def test_target_roots_dont_generate_libs(self): 'project_info.jvm_target', result['libraries'].keys() ) + + def test_transitive_libs_only_added_if_dependency_is_not_modulizable(self): + a_spec = self.linear_build_graph['a'].address.spec + b_spec = self.linear_build_graph['b'].address.spec + result_a = self.execute_export_json(a_spec) + self.assertEquals( + sorted([ + 'project_info.b', + 'project_info.c', + 'project_info.d', + 'project_info.e', + 'org.scala-lang:scala-library:2.10.5', + '.scala-library', + ]), + sorted(result_a['targets'][a_spec]['libraries']) + ) + result_ab = self.execute_export_json(a_spec, b_spec) + self.assertEquals( + sorted(['org.scala-lang:scala-library:2.10.5', '.scala-library']), + sorted(result_ab['targets'][a_spec]['libraries']) + ) + self.assertIn( + b_spec, + result_ab['targets'][a_spec]['targets'] + ) + self.assertEquals( + sorted([ + 'project_info.c', + 'project_info.d', + 'project_info.e', + 'org.scala-lang:scala-library:2.10.5', + '.scala-library', + ]), + sorted(result_ab['targets'][b_spec]['libraries']) + ) From a7d9926c28df5fcbb7ae96c79f5ae8f72f4978bf Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Thu, 19 Dec 2019 14:54:39 +0000 Subject: [PATCH 11/17] Pull in jar dependencies for dependency libraries --- .../project_info/tasks/export_dep_as_jar.py | 23 ++++++++---- .../tasks/test_export_dep_as_jar.py | 37 +++++++++++++------ 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index 97d853615b6..32366dba492 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -184,11 +184,6 @@ def iter_transitive_jars(jar_lib): if isinstance(current_target, JarLibrary): target_libraries = OrderedSet(iter_transitive_jars(current_target)) for dep in current_target.dependencies: - if isinstance(dep, JarLibrary): - for jar in dep.jar_dependencies: - target_libraries.add(M2Coordinate(jar.org, jar.name, jar.rev)) - # Add all the jars pulled in by this jar_library - target_libraries.update(iter_transitive_jars(dep)) if dep in modulizable_target_set: info['targets'].append(dep.address.spec) @@ -205,17 +200,29 @@ def iter_transitive_jars(jar_lib): if runtime_classpath: info['libraries'].extend(self._jar_id(lib) for lib in target_libraries) - def _libraries_to_include(t): + def _full_library_set_for_dep(dep): + """ + Get the full library set for a dependency, including jar dependencies and jars of the library itself. + """ + libraries = {dep.id} + if isinstance(dep, JarLibrary): + for jar in dep.jar_dependencies: + libraries.add(self._jar_id(M2Coordinate(jar.org, jar.name, jar.rev))) + # Add all the jars pulled in by this jar_library + libraries.update(iter_transitive_jars(dep)) + return libraries + + def _libraries_to_include_from_dependencies(t): libraries_to_include = set([]) self.context.build_graph.walk_transitive_dependency_graph( [direct_dep.address for direct_dep in t.dependencies], # NB: Dependency graph between modulizable targets is represented with modules, # so we don't need to expand those branches of the tree. predicate=lambda dep: dep not in modulizable_target_set, - work=lambda dep: libraries_to_include.add(dep.id), + work=lambda dep: libraries_to_include.update(_full_library_set_for_dep(dep)), ) return libraries_to_include - info['libraries'].extend(_libraries_to_include(current_target)) + info['libraries'].extend(_libraries_to_include_from_dependencies(current_target)) if current_target in target_roots_set: info['roots'] = [{ diff --git a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py index fe4e6257b4a..706bd241f7d 100644 --- a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py +++ b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py @@ -244,19 +244,24 @@ def setUp(self): 'project_info:scala_with_source_dep', target_type=ScalaLibrary, dependencies=[self.jvm_target_with_sources], - sources=[] - ) + sources=[], + ) + + def _make_linear_graph(names, **additional_target_args): + # A build graph where a -(depends on)-> b -> ... -> e + graph = {} + last_target = None + for name in reversed(names): + last_target = self.make_target( + f'project_info:{name}', + target_type=ScalaLibrary, + dependencies=[] if last_target is None else [last_target], + **additional_target_args, + ) + graph[name] = last_target + return graph - # A build graph where a -(depends on)-> b -> ... -> e - self.linear_build_graph = {} - last_target = None - for letter in reversed(['a', 'b', 'c', 'd', 'e']): - last_target = self.make_target( - f'project_info:{letter}', - target_type=ScalaLibrary, - dependencies=[] if last_target is None else [last_target] - ) - self.linear_build_graph[letter] = last_target + self.linear_build_graph = _make_linear_graph(['a', 'b', 'c', 'd', 'e']) def create_runtime_classpath_for_targets(self, target): def path_to_zjar_with_workdir(address: Address): @@ -616,3 +621,11 @@ def test_transitive_libs_only_added_if_dependency_is_not_modulizable(self): ]), sorted(result_ab['targets'][b_spec]['libraries']) ) + + def test_imports_3rdparty_jars_from_transitive_dependencies(self): + spec = self.scala_with_source_dep.address.spec + result = self.execute_export_json(spec) + self.assertIn( + 'org.apache:apache-jar:12.12.2012', + result['targets'][spec]['libraries'] + ) From 9f87adea5abf285ad9197b32c09baa2fe7e0b54f Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Thu, 19 Dec 2019 16:20:36 +0000 Subject: [PATCH 12/17] Don't add JarLibrary targets to libraries, only the jars --- .../project_info/tasks/export_dep_as_jar.py | 76 +++++++++---------- .../tasks/test_export_dep_as_jar.py | 20 ++--- 2 files changed, 44 insertions(+), 52 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index 32366dba492..445f0ecfba7 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -6,8 +6,6 @@ import zipfile from collections import defaultdict -from twitter.common.collections import OrderedSet - from pants.backend.jvm.subsystems.dependency_context import DependencyContext from pants.backend.jvm.subsystems.jvm_platform import JvmPlatform from pants.backend.jvm.subsystems.scala_platform import ScalaPlatform @@ -145,6 +143,17 @@ def _zip_sources(target, location, suffix='.jar'): zip_file.write(os.path.join(get_buildroot(), src_from_build_root), src_from_source_root) return f + def _dependencies_to_include_in_libraries(self, t, modulizable_target_set): + dependencies_to_include = set([]) + self.context.build_graph.walk_transitive_dependency_graph( + [direct_dep.address for direct_dep in t.dependencies], + # NB: Dependency graph between modulizable targets is represented with modules, + # so we don't need to expand those branches of the dep graph. + predicate=lambda dep: dep not in modulizable_target_set, + work=lambda dep: dependencies_to_include.add(dep), + ) + return dependencies_to_include + def _process_target(self, current_target, target_roots_set, modulizable_target_set, resource_target_map, runtime_classpath): """ :type current_target:pants.build_graph.target.Target @@ -180,9 +189,33 @@ def iter_transitive_jars(jar_lib): # libraries dict and here we just want the key into that dict (see `_jar_id`). yield M2Coordinate(org=coordinate.org, name=coordinate.name, rev=coordinate.rev) - target_libraries = OrderedSet() - if isinstance(current_target, JarLibrary): - target_libraries = OrderedSet(iter_transitive_jars(current_target)) + def _full_library_set_for_target(target): + """ + Get the full library set for a target, including jar dependencies and jars of the library itself. + """ + libraries = set([]) + if isinstance(target, JarLibrary): + jars = set([]) + for jar in target.jar_dependencies: + jars.add(M2Coordinate(jar.org, jar.name, jar.rev)) + # Add all the jars pulled in by this jar_library + jars.update(iter_transitive_jars(target)) + libraries = [self._jar_id(jar) for jar in jars] + else: + libraries.add(target.id) + return libraries + + libraries_for_target = set([self._jar_id(jar) for jar in iter_transitive_jars(current_target)]) + for dep in self._dependencies_to_include_in_libraries(current_target, modulizable_target_set): + libraries_for_target.update(_full_library_set_for_target(dep)) + info['libraries'].extend(libraries_for_target) + + if current_target in target_roots_set: + info['roots'] = [{ + 'source_root': os.path.realpath(source_root_package_prefix[0]), + 'package_prefix': source_root_package_prefix[1] + } for source_root_package_prefix in self._source_roots_for_target(current_target)] + for dep in current_target.dependencies: if dep in modulizable_target_set: info['targets'].append(dep.address.spec) @@ -197,39 +230,6 @@ def iter_transitive_jars(jar_lib): if hasattr(current_target, 'test_platform'): info['test_platform'] = current_target.test_platform.name - if runtime_classpath: - info['libraries'].extend(self._jar_id(lib) for lib in target_libraries) - - def _full_library_set_for_dep(dep): - """ - Get the full library set for a dependency, including jar dependencies and jars of the library itself. - """ - libraries = {dep.id} - if isinstance(dep, JarLibrary): - for jar in dep.jar_dependencies: - libraries.add(self._jar_id(M2Coordinate(jar.org, jar.name, jar.rev))) - # Add all the jars pulled in by this jar_library - libraries.update(iter_transitive_jars(dep)) - return libraries - - def _libraries_to_include_from_dependencies(t): - libraries_to_include = set([]) - self.context.build_graph.walk_transitive_dependency_graph( - [direct_dep.address for direct_dep in t.dependencies], - # NB: Dependency graph between modulizable targets is represented with modules, - # so we don't need to expand those branches of the tree. - predicate=lambda dep: dep not in modulizable_target_set, - work=lambda dep: libraries_to_include.update(_full_library_set_for_dep(dep)), - ) - return libraries_to_include - info['libraries'].extend(_libraries_to_include_from_dependencies(current_target)) - - if current_target in target_roots_set: - info['roots'] = [{ - 'source_root': os.path.realpath(source_root_package_prefix[0]), - 'package_prefix': source_root_package_prefix[1] - } for source_root_package_prefix in self._source_roots_for_target(current_target)] - return info def initialize_graph_info(self): diff --git a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py index 706bd241f7d..41d56fd841d 100644 --- a/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py +++ b/tests/python/pants_test/backend/project_info/tasks/test_export_dep_as_jar.py @@ -352,9 +352,7 @@ def test_with_dependencies(self): sorted(result['targets']['project_info:third']['targets']) ) self.assertEqual(sorted(['org.scala-lang:scala-library:2.10.5', - 'org.apache:apache-jar:12.12.2012', - '.scala-library', - 'project_info.jar_lib']), + 'org.apache:apache-jar:12.12.2012']), sorted(result['targets']['project_info:third']['libraries'])) self.assertEqual(1, len(result['targets']['project_info:third']['roots'])) @@ -367,7 +365,7 @@ def test_with_dependencies(self): def test_jvm_app(self): result = self.execute_export_json('project_info:jvm_app') - self.assertEqual(sorted(['org.apache:apache-jar:12.12.2012', 'project_info.jar_lib']), + self.assertEqual(sorted(['org.apache:apache-jar:12.12.2012']), sorted(result['targets']['project_info:jvm_app']['libraries'])) def test_jvm_target(self): @@ -381,9 +379,7 @@ def test_jvm_target(self): 'project_info/this/is/a/source/Bar.scala']}, 'libraries': sorted([ 'org.apache:apache-jar:12.12.2012', - 'org.scala-lang:scala-library:2.10.5', - 'project_info.jar_lib', - '.scala-library', + 'org.scala-lang:scala-library:2.10.5' ]), 'id': 'project_info.jvm_target', # 'is_code_gen': False, @@ -411,20 +407,18 @@ def test_java_test(self): self.assertEqual(sorted([ 'org.apache:apache-jar:12.12.2012', 'junit:junit:{}'.format(JUnit.LIBRARY_REV), - 'project_info.jar_lib', 'project_info.test_resource', - '.junit_library', ]), sorted(result['targets']['project_info:java_test']['libraries'])) def test_jvm_binary(self): result = self.execute_export_json('project_info:jvm_binary') - self.assertEqual(sorted(['org.apache:apache-jar:12.12.2012', 'project_info.jar_lib']), + self.assertEqual(sorted(['org.apache:apache-jar:12.12.2012']), sorted(result['targets']['project_info:jvm_binary']['libraries'])) def test_top_dependency(self): result = self.execute_export_json('project_info:top_dependency') - self.assertEqual(sorted(['project_info.jvm_binary', 'project_info.jar_lib']), + self.assertEqual(sorted(['project_info.jvm_binary', 'org.apache:apache-jar:12.12.2012']), sorted(result['targets']['project_info:top_dependency']['libraries'])) self.assertEqual([], result['targets']['project_info:top_dependency']['targets']) @@ -598,13 +592,12 @@ def test_transitive_libs_only_added_if_dependency_is_not_modulizable(self): 'project_info.d', 'project_info.e', 'org.scala-lang:scala-library:2.10.5', - '.scala-library', ]), sorted(result_a['targets'][a_spec]['libraries']) ) result_ab = self.execute_export_json(a_spec, b_spec) self.assertEquals( - sorted(['org.scala-lang:scala-library:2.10.5', '.scala-library']), + sorted(['org.scala-lang:scala-library:2.10.5']), sorted(result_ab['targets'][a_spec]['libraries']) ) self.assertIn( @@ -617,7 +610,6 @@ def test_transitive_libs_only_added_if_dependency_is_not_modulizable(self): 'project_info.d', 'project_info.e', 'org.scala-lang:scala-library:2.10.5', - '.scala-library', ]), sorted(result_ab['targets'][b_spec]['libraries']) ) From 2f2b3fdc8c662aad73076b0aaee2103beea9d7e2 Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Fri, 20 Dec 2019 11:32:51 +0000 Subject: [PATCH 13/17] Treat every modulizable target as a target root when getting target info --- .../backend/project_info/tasks/export_dep_as_jar.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index 445f0ecfba7..de67583e27d 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -154,7 +154,7 @@ def _dependencies_to_include_in_libraries(self, t, modulizable_target_set): ) return dependencies_to_include - def _process_target(self, current_target, target_roots_set, modulizable_target_set, resource_target_map, runtime_classpath): + def _process_target(self, current_target, modulizable_target_set, resource_target_map, runtime_classpath): """ :type current_target:pants.build_graph.target.Target """ @@ -167,7 +167,7 @@ def _process_target(self, current_target, target_roots_set, modulizable_target_s 'target_type': ExportDepAsJar._get_target_type(current_target, resource_target_map), 'is_synthetic': current_target.is_synthetic, 'pants_target_type': self._get_pants_target_alias(type(current_target)), - 'is_target_root': current_target in target_roots_set, + 'is_target_root': current_target in modulizable_target_set, 'transitive': current_target.transitive, 'scope': str(current_target.scope) } @@ -210,7 +210,7 @@ def _full_library_set_for_target(target): libraries_for_target.update(_full_library_set_for_target(dep)) info['libraries'].extend(libraries_for_target) - if current_target in target_roots_set: + if current_target in modulizable_target_set: info['roots'] = [{ 'source_root': os.path.realpath(source_root_package_prefix[0]), 'package_prefix': source_root_package_prefix[1] @@ -344,11 +344,11 @@ def generate_targets_map(self, targets, runtime_classpath): libraries_map[t.id] = self._make_libraries_entry(t, resource_target_map, runtime_classpath) for target in modulizable_targets: - info = self._process_target(target, target_roots_set, modulizable_targets, resource_target_map, runtime_classpath) + info = self._process_target(target, modulizable_targets, resource_target_map, runtime_classpath) targets_map[target.address.spec] = info # If it is a target root or it is already a jar_library target, then no-op. - if target in target_roots_set or targets_map[target.address.spec]['pants_target_type'] == 'jar_library': + if target in modulizable_targets or targets_map[target.address.spec]['pants_target_type'] == 'jar_library': continue targets_map[target.address.spec]['pants_target_type'] = 'jar_library' From bc26ebf3a39783d74ce27fe93001d93532b98dea Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Fri, 20 Dec 2019 14:24:36 +0000 Subject: [PATCH 14/17] Remove broken noop conditional --- .../pants/backend/project_info/tasks/export_dep_as_jar.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py index de67583e27d..0e0716b19b4 100644 --- a/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py +++ b/src/python/pants/backend/project_info/tasks/export_dep_as_jar.py @@ -347,13 +347,6 @@ def generate_targets_map(self, targets, runtime_classpath): info = self._process_target(target, modulizable_targets, resource_target_map, runtime_classpath) targets_map[target.address.spec] = info - # If it is a target root or it is already a jar_library target, then no-op. - if target in modulizable_targets or targets_map[target.address.spec]['pants_target_type'] == 'jar_library': - continue - - targets_map[target.address.spec]['pants_target_type'] = 'jar_library' - targets_map[target.address.spec]['libraries'] = [t.id] - graph_info = self.initialize_graph_info() graph_info['targets'] = targets_map graph_info['libraries'] = libraries_map From fcdcd035f9ecd0e3869a47935d79147bd28e585c Mon Sep 17 00:00:00 2001 From: Yi Cheng Date: Fri, 20 Dec 2019 21:47:56 -0800 Subject: [PATCH 15/17] bump and explain --- src/docs/export.md | 22 +++++++++++++++++++ .../project_info/tasks/export_version.py | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/docs/export.md b/src/docs/export.md index f330cbb2dad..08a62bd8fb4 100644 --- a/src/docs/export.md +++ b/src/docs/export.md @@ -177,6 +177,28 @@ The following is an abbreviated export file from a command in the pants repo: # Export Format Changes +## 1.0.14 + +Export only modulizable targets for `export-dep-as-jar`, and the rest of targets will appears as libraries. + +Definition of `modulizable targets`: targets that should appear as modules in IntelliJ. + +For example, A -> B -> C -> D +Given `./panst export-dep-as-jar A`, +``` +modulizable_targets = [A] +libraries = [B,C,D] +``` + +Given `./panst export-dep-as-jar A C`, + ``` +modulizable_targets = [A, B, C] +libraries = [D] +``` +In this case, `B` is forced into a module even though it is not a target root because IntelliJ +does not allow a library to depend back onto a source module, +i.e. `B` has to be a module to be able to depend on `C`. + ## 1.0.13 Add `--available-target-types` option, which exports currently available target types. diff --git a/src/python/pants/backend/project_info/tasks/export_version.py b/src/python/pants/backend/project_info/tasks/export_version.py index b90f3761a88..d5333dee7dd 100644 --- a/src/python/pants/backend/project_info/tasks/export_version.py +++ b/src/python/pants/backend/project_info/tasks/export_version.py @@ -13,4 +13,4 @@ # # Note format changes in src/docs/export.md and update the Changelog section. # -DEFAULT_EXPORT_VERSION = '1.0.13' +DEFAULT_EXPORT_VERSION = '1.0.14' From 6822a083debd847adf9c204150b4f6759958d741 Mon Sep 17 00:00:00 2001 From: Yi Cheng Date: Fri, 20 Dec 2019 21:58:00 -0800 Subject: [PATCH 16/17] clarify --- src/docs/export.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/docs/export.md b/src/docs/export.md index 08a62bd8fb4..c553170e43b 100644 --- a/src/docs/export.md +++ b/src/docs/export.md @@ -181,7 +181,9 @@ The following is an abbreviated export file from a command in the pants repo: Export only modulizable targets for `export-dep-as-jar`, and the rest of targets will appears as libraries. -Definition of `modulizable targets`: targets that should appear as modules in IntelliJ. +Definition of `modulizable_targets`: +1. Conceptually: targets that should appear as modules in IntelliJ. +2. Computationally: dependees of target roots within the transitive context. For example, A -> B -> C -> D Given `./panst export-dep-as-jar A`, From e37b48158ceeceff254000211d97d69e21c7a10b Mon Sep 17 00:00:00 2001 From: Yi Cheng Date: Sat, 21 Dec 2019 00:18:09 -0800 Subject: [PATCH 17/17] fix grammer --- src/docs/export.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/export.md b/src/docs/export.md index c553170e43b..65112b2745b 100644 --- a/src/docs/export.md +++ b/src/docs/export.md @@ -179,7 +179,7 @@ The following is an abbreviated export file from a command in the pants repo: ## 1.0.14 -Export only modulizable targets for `export-dep-as-jar`, and the rest of targets will appears as libraries. +Export only modulizable targets for `export-dep-as-jar`, and the rest of targets will appear as libraries. Definition of `modulizable_targets`: 1. Conceptually: targets that should appear as modules in IntelliJ.