diff --git a/src/python/pants/backend/android/targets/android_target.py b/src/python/pants/backend/android/targets/android_target.py index c8dac4a5308..d5882a07797 100644 --- a/src/python/pants/backend/android/targets/android_target.py +++ b/src/python/pants/backend/android/targets/android_target.py @@ -8,12 +8,11 @@ import os from xml.dom.minidom import parse +from pants.backend.jvm.targets.jvm_target import JvmTarget from pants.base.exceptions import TargetDefinitionException -from pants.base.payload import JvmTargetPayload -from pants.base.target import Target -class AndroidTarget(Target): +class AndroidTarget(JvmTarget): """A base class for all Android targets.""" # Missing attributes from the AndroidManifest would eventually error in the compilation process. @@ -21,13 +20,8 @@ class AndroidTarget(Target): class BadManifestError(Exception): """Indicates an invalid android manifest.""" - def __init__(self, address=None, - sources=None, - sources_rel_path=None, - excludes=None, - provides=None, # most recent build_tools_version should be defined elsewhere build_tools_version="19.1.0", manifest=None, @@ -48,14 +42,7 @@ def __init__(self, :param release_type: Which keystore is used to sign target: 'debug' or 'release'. Set as 'debug' by default. """ - - sources_rel_path = sources_rel_path or address.spec_path - # No reasons why we might need AndroidPayload have presented themselves yet - payload = JvmTargetPayload(sources=sources, - sources_rel_path=sources_rel_path, - provides=provides, - excludes=excludes) - super(AndroidTarget, self).__init__(address=address, payload=payload, **kwargs) + super(AndroidTarget, self).__init__(address=address, **kwargs) self.add_labels('android') self.build_tools_version = build_tools_version @@ -63,7 +50,7 @@ def __init__(self, if not os.path.isfile(os.path.join(address.spec_path, manifest)): raise TargetDefinitionException(self, 'Android targets must specify a \'manifest\' ' - 'that points to the \'AndroidManifest.xml\'') + 'that points to the \'AndroidManifest.xml\'') self.manifest = os.path.join(self.address.spec_path, manifest) self.package = self.get_package_name() self.target_sdk = self.get_target_sdk() diff --git a/src/python/pants/backend/android/tasks/aapt_gen.py b/src/python/pants/backend/android/tasks/aapt_gen.py index 748c59a1266..1f351f9cb79 100644 --- a/src/python/pants/backend/android/tasks/aapt_gen.py +++ b/src/python/pants/backend/android/tasks/aapt_gen.py @@ -9,11 +9,15 @@ import subprocess from twitter.common import log +from twitter.common.collections import OrderedSet from twitter.common.dirutil import safe_mkdir + from pants.backend.android.targets.android_resources import AndroidResources from pants.backend.android.tasks.android_task import AndroidTask from pants.backend.codegen.tasks.code_gen import CodeGen +from pants.backend.jvm.targets.jar_dependency import JarDependency +from pants.backend.jvm.targets.jar_library import JarLibrary from pants.backend.jvm.targets.java_library import JavaLibrary from pants.base.address import SyntheticAddress from pants.base.build_environment import get_buildroot @@ -55,7 +59,7 @@ def setup_parser(cls, option_group, args, mkflag): @classmethod def _calculate_genfile(cls, package): - return os.path.join('bin', cls.package_path(package), 'R.java') + return os.path.join(cls.package_path(package), 'R.java') def __init__(self, context, workdir): super(AaptGen, self).__init__(context, workdir) @@ -63,6 +67,18 @@ def __init__(self, context, workdir): self._forced_build_tools_version = context.options.build_tools_version self._forced_ignored_assets = context.options.ignored_assets self._forced_target_sdk = context.options.target_sdk + self._jar_library_by_sdk = {} + + def prepare(self, round_manager): + super(AaptGen, self).prepare(round_manager) + + # prepare exactly N android jar targets where N is the number of SDKs in-play + sdks = set(ar.target_sdk for ar in self.context.targets(predicate=self.is_gentarget)) + for sdk in sdks: + jar_url = 'file://{0}'.format(self.android_jar_tool(sdk)) + jar = JarDependency(org='com.google', name='android', rev=sdk, url=jar_url) + address = SyntheticAddress(self.workdir, '{0}-jars'.format(sdk)) + self._jar_library_by_sdk[sdk] = self.context.add_new_target(address, JarLibrary, jars=[jar]) def is_gentarget(self, target): return isinstance(target, AndroidResources) @@ -117,22 +133,20 @@ def genlang(self, lang, targets): raise TaskError('Android aapt tool exited non-zero ({code})'.format(code=result)) def createtarget(self, lang, gentarget, dependees): - aapt_gen_file = self._calculate_genfile(gentarget.package) spec_path = os.path.join(os.path.relpath(self.workdir, get_buildroot()), 'bin') address = SyntheticAddress(spec_path=spec_path, target_name=gentarget.id) + aapt_gen_file = self._calculate_genfile(gentarget.package) + deps = OrderedSet([self._jar_library_by_sdk[gentarget.target_sdk]]) tgt = self.context.add_new_target(address, JavaLibrary, derived_from=gentarget, - sources=aapt_gen_file, - dependencies=[]) - + sources=[aapt_gen_file], + dependencies=deps) for dependee in dependees: dependee.inject_dependency(tgt.address) return tgt - def _aapt_out(self): - # TODO (mateor) Does this have potential for collision (chances of same package name?) return os.path.join(self.workdir, 'bin') def aapt_tool(self, build_tools_version):