Skip to content

Commit

Permalink
[jvm-compile] Copy compile classpath into runtime classpath even if a…
Browse files Browse the repository at this point in the history
…lready defined (#4310)

#Problem
In #4309, the problem was caused by jvm_compile assuming it is always first in the compile order. 

#Solution

This patch ensures the compile_classpath is mixed into the runtime classpath even if it has already been initialized.

#Result

Fixes #4309
  • Loading branch information
baroquebobcat committed Mar 7, 2017
1 parent f18c556 commit 8aeadcd
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 2 deletions.
9 changes: 9 additions & 0 deletions src/python/pants/backend/jvm/tasks/classpath_products.py
Expand Up @@ -305,6 +305,15 @@ def get_internal_classpath_entries_for_targets(self, targets, respect_excludes=T
return [(conf, cp_entry) for conf, cp_entry in classpath_tuples
if ClasspathEntry.is_internal_classpath_entry(cp_entry)]

def update(self, other):
"""Adds the contents of other to this ClasspathProducts."""
if self._pants_workdir != other._pants_workdir:
raise ValueError('Other ClasspathProducts from a different pants workdir {}'.format(other._pants_workdir))
for target, products in other._classpaths._products_by_target.items():
self._classpaths.add_for_target(target, products)
for target, products in other._excludes._products_by_target.items():
self._excludes.add_for_target(target, products)

def _filter_by_excludes(self, classpath_target_tuples, root_targets):
# Excludes are always applied transitively, so regardless of whether a transitive
# set of targets was included here, their closure must be included.
Expand Down
13 changes: 11 additions & 2 deletions src/python/pants/backend/jvm/tasks/jvm_compile/jvm_compile.py
Expand Up @@ -440,8 +440,7 @@ def execute(self):
return

# Clone the compile_classpath to the runtime_classpath.
compile_classpath = self.context.products.get_data('compile_classpath')
classpath_product = self.context.products.get_data('runtime_classpath', compile_classpath.copy)
classpath_product = self.create_runtime_classpath()

def classpath_for_context(context):
if self.get_options().use_classpath_jars:
Expand Down Expand Up @@ -484,6 +483,16 @@ def classpath_for_context(context):
classpath_product.remove_for_target(cc.target, [(conf, cc.classes_dir)])
classpath_product.add_for_target(cc.target, [(conf, cc.jar_file)])

def create_runtime_classpath(self):
compile_classpath = self.context.products.get_data('compile_classpath')
classpath_product = self.context.products.get_data('runtime_classpath')
if not classpath_product:
classpath_product = self.context.products.get_data('runtime_classpath', compile_classpath.copy)
else:
classpath_product.update(compile_classpath)

return classpath_product

def do_compile(self,
invalidation_check,
compile_contexts,
Expand Down
11 changes: 11 additions & 0 deletions tests/python/pants_test/backend/jvm/tasks/jvm_compile/BUILD
Expand Up @@ -13,6 +13,17 @@ python_tests(
],
)

python_tests(
name = 'jvm_compile',
sources = ['test_jvm_compile.py'],
dependencies = [
'src/python/pants/backend/jvm/tasks:classpath_products',
'src/python/pants/backend/jvm/tasks/jvm_compile',
'tests/python/pants_test/tasks:task_test_base',
],
)


python_library(
name='base_compile_integration_test',
sources=['base_compile_integration_test.py'],
Expand Down
@@ -0,0 +1,49 @@
# coding=utf-8
# Copyright 2017 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from __future__ import (absolute_import, division, generators, nested_scopes, print_function,
unicode_literals, with_statement)

import os

from pants.backend.jvm.targets.java_library import JavaLibrary
from pants.backend.jvm.tasks.classpath_products import ClasspathProducts
from pants.backend.jvm.tasks.jvm_compile.jvm_compile import JvmCompile
from pants_test.tasks.task_test_base import TaskTestBase


class DummyJvmCompile(JvmCompile):

def create_analysis_tools(self):
return None


class JvmCompileTest(TaskTestBase):
DEFAULT_CONF = 'default'

@classmethod
def task_type(cls):
return DummyJvmCompile

def test_if_runtime_classpath_exists(self):
target = self.make_target(
'java/classpath:java_lib',
target_type=JavaLibrary,
sources=['com/foo/Bar.java'],
)

context = self.context(target_roots=[target])
compile_classpath = context.products.get_data('compile_classpath', ClasspathProducts.init_func(self.pants_workdir))

compile_entry = os.path.join(self.pants_workdir, 'compile-entry')
pre_init_runtime_entry = os.path.join(self.pants_workdir, 'pre-inited-runtime-entry')
compile_classpath.add_for_targets([target], [('default', compile_entry)])
runtime_classpath = context.products.get_data('runtime_classpath', ClasspathProducts.init_func(self.pants_workdir))

runtime_classpath.add_for_targets([target], [('default', pre_init_runtime_entry)])

task = self.create_task(context)
resulting_classpath = task.create_runtime_classpath()
self.assertEqual([('default', pre_init_runtime_entry), ('default', compile_entry)],
resulting_classpath.get_for_target(target))

0 comments on commit 8aeadcd

Please sign in to comment.