| #!/usr/bin/env python3 |
| # |
| # Copyright 2018 - The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """Collect the source paths from dependency information.""" |
| |
| from __future__ import absolute_import |
| |
| import glob |
| import logging |
| import os |
| import re |
| |
| from aidegen import constant |
| from aidegen.lib import errors |
| from aidegen.lib import common_util |
| from aidegen.lib.common_util import COLORED_INFO |
| from atest import atest_utils |
| |
| # Parse package name from the package declaration line of a java. |
| # Group matches "foo.bar" of line "package foo.bar;" or "package foo.bar" |
| _PACKAGE_RE = re.compile(r'\s*package\s+(?P<package>[^(;|\s)]+)\s*', re.I) |
| |
| _ANDROID_SUPPORT_PATH_KEYWORD = 'prebuilts/sdk/current/' |
| # File extensions |
| _JAR_EXT = '.jar' |
| _JAVA_EXT = '.java' |
| _KOTLIN_EXT = '.kt' |
| _SRCJAR_EXT = '.srcjar' |
| |
| _TARGET_LIBS = [_JAR_EXT] |
| _TARGET_FILES = [_JAVA_EXT, _KOTLIN_EXT] |
| _JARJAR_RULES_FILE = 'jarjar-rules.txt' |
| _KEY_JARJAR_RULES = 'jarjar_rules' |
| _KEY_JARS = 'jars' |
| _KEY_TESTS = 'tests' |
| _NAME_AAPT2 = 'aapt2' |
| _TARGET_R_JAR = 'R.jar' |
| _TARGET_AAPT2_SRCJAR = _NAME_AAPT2 + _SRCJAR_EXT |
| _TARGET_BUILD_FILES = [_TARGET_AAPT2_SRCJAR, _TARGET_R_JAR] |
| _IGNORE_DIRS = [ |
| # The java files under this directory have to be ignored because it will |
| # cause duplicated classes by libcore/ojluni/src/main/java. |
| 'libcore/ojluni/src/lambda/java' |
| ] |
| _DIS_ROBO_BUILD_ENV_VAR = {'DISABLE_ROBO_RUN_TESTS': 'true'} |
| # When we use atest_utils.build(), there is a command length limit on |
| # soong_ui.bash. We reserve 5000 characters for rewriting the command line |
| # in soong_ui.bash. |
| _CMD_LENGTH_BUFFER = 5000 |
| # For each argument, it need a space to separate following argument. |
| _BLANK_SIZE = 1 |
| |
| |
| def multi_projects_locate_source(projects, verbose): |
| """Locate the paths of dependent source folders and jar files with projects. |
| |
| Args: |
| projects: A list of ProjectInfo instances. Information of a project such |
| as project relative path, project real path, project |
| dependencies. |
| verbose: A boolean, if true displays full build output. |
| """ |
| for project in projects: |
| locate_source(project, verbose, project.config.depth, |
| project.config.ide_name, |
| build=not project.config.is_skip_build) |
| |
| |
| def locate_source(project, verbose, depth, ide_name, build=True): |
| """Locate the paths of dependent source folders and jar files. |
| |
| Try to reference source folder path as dependent module unless the |
| dependent module should be referenced to a jar file, such as modules have |
| jars and jarjar_rules parameter. |
| For example: |
| Module: asm-6.0 |
| java_import { |
| name: 'asm-6.0', |
| host_supported: true, |
| jars: ['asm-6.0.jar'], |
| } |
| Module: bouncycastle |
| java_library { |
| name: 'bouncycastle', |
| ... |
| target: { |
| android: { |
| jarjar_rules: 'jarjar-rules.txt', |
| }, |
| }, |
| } |
| |
| Args: |
| project: A ProjectInfo instance. Information of a project such as |
| project relative path, project real path, project dependencies. |
| verbose: A boolean, if true displays full build output. |
| depth: An integer shows the depth of module dependency referenced by |
| source. Zero means the max module depth. |
| ide_name: A string stands for the IDE name, default is IntelliJ. |
| build: A boolean default to true, if true skip building jar and srcjar |
| files, otherwise build them. |
| |
| Example usage: |
| project.source_path = locate_source(project, verbose, False) |
| E.g. |
| project.source_path = { |
| 'source_folder_path': ['path/to/source/folder1', |
| 'path/to/source/folder2', ...], |
| 'test_folder_path': ['path/to/test/folder', ...], |
| 'jar_path': ['path/to/jar/file1', 'path/to/jar/file2', ...] |
| } |
| """ |
| if not hasattr(project, 'dep_modules') or not project.dep_modules: |
| raise errors.EmptyModuleDependencyError( |
| 'Dependent modules dictionary is empty.') |
| dependencies = project.source_path |
| rebuild_targets = set() |
| for module_name, module_data in project.dep_modules.items(): |
| module = _generate_moduledata(module_name, module_data, ide_name, |
| project.project_relative_path, depth) |
| module.locate_sources_path() |
| dependencies['source_folder_path'].update(module.src_dirs) |
| dependencies['test_folder_path'].update(module.test_dirs) |
| dependencies['r_java_path'].update(module.r_java_paths) |
| dependencies['srcjar_path'].update(module.srcjar_paths) |
| _append_jars_as_dependencies(dependencies, module) |
| if module.build_targets: |
| rebuild_targets |= module.build_targets |
| if rebuild_targets: |
| if build: |
| _batch_build_dependencies(verbose, rebuild_targets) |
| locate_source(project, verbose, depth, ide_name, build=False) |
| else: |
| logging.warning('Jar or srcjar files build failed:\n\t%s.', |
| '\n\t'.join(rebuild_targets)) |
| |
| |
| def _batch_build_dependencies(verbose, rebuild_targets): |
| """Batch build the jar or srcjar files of the modules if they don't exist. |
| |
| Command line has the max length limit, MAX_ARG_STRLEN, and |
| MAX_ARG_STRLEN = (PAGE_SIZE * 32). |
| If the build command is longer than MAX_ARG_STRLEN, this function will |
| separate the rebuild_targets into chunks with size less or equal to |
| MAX_ARG_STRLEN to make sure it can be built successfully. |
| |
| Args: |
| verbose: A boolean, if true displays full build output. |
| rebuild_targets: A set of jar or srcjar files which do not exist. |
| """ |
| logging.info('Ready to build the jar or srcjar files. Files count = %s', |
| str(len(rebuild_targets))) |
| arg_max = os.sysconf("SC_PAGE_SIZE") * 32 - _CMD_LENGTH_BUFFER |
| rebuild_targets = list(rebuild_targets) |
| for start, end in iter(_separate_build_targets( |
| rebuild_targets, arg_max)): |
| _build_target(rebuild_targets[start: end], verbose) |
| |
| |
| def _build_target(targets, verbose): |
| """Build the jar or srcjar files. |
| |
| Use -k to keep going when some targets can't be built or build failed. |
| Use -j to speed up building. |
| |
| Args: |
| targets: A list of jar or srcjar files which need to build. |
| verbose: A boolean, if true displays full build output. |
| """ |
| build_cmd = ['-k', '-j'] |
| build_cmd.extend(list(targets)) |
| if not atest_utils.build(build_cmd, verbose, _DIS_ROBO_BUILD_ENV_VAR): |
| message = ('Build failed!\n{}\nAIDEGen will proceed but dependency ' |
| 'correctness is not guaranteed if not all targets being ' |
| 'built successfully.'.format('\n'.join(targets))) |
| print('\n{} {}\n'.format(COLORED_INFO('Warning:'), message)) |
| |
| |
| def _separate_build_targets(build_targets, max_length): |
| """Separate the build_targets by limit the command size to max command |
| length. |
| |
| Args: |
| build_targets: A list to be separated. |
| max_length: The max number of each build command length. |
| |
| Yields: |
| The start index and end index of build_targets. |
| """ |
| arg_len = 0 |
| first_item_index = 0 |
| for i, item in enumerate(build_targets): |
| arg_len = arg_len + len(item) + _BLANK_SIZE |
| if arg_len > max_length: |
| yield first_item_index, i |
| first_item_index = i |
| arg_len = len(item) + _BLANK_SIZE |
| if first_item_index < len(build_targets): |
| yield first_item_index, len(build_targets) |
| |
| |
| def _generate_moduledata(module_name, module_data, ide_name, project_relpath, |
| depth): |
| """Generate a module class to collect dependencies in IntelliJ or Eclipse. |
| |
| Args: |
| module_name: Name of the module. |
| module_data: A dictionary holding a module information. |
| ide_name: A string stands for the IDE name. |
| project_relpath: A string stands for the project's relative path. |
| depth: An integer shows the depth of module dependency referenced by |
| source. Zero means the max module depth. |
| |
| Returns: |
| A ModuleData class. |
| """ |
| if ide_name == constant.IDE_ECLIPSE: |
| return EclipseModuleData(module_name, module_data, project_relpath) |
| return ModuleData(module_name, module_data, depth) |
| |
| |
| def _append_jars_as_dependencies(dependent_data, module): |
| """Add given module's jar files into dependent_data as dependencies. |
| |
| Args: |
| dependent_data: A dictionary contains the dependent source paths and |
| jar files. |
| module: A ModuleData instance. |
| """ |
| if module.jar_files: |
| dependent_data['jar_path'].update(module.jar_files) |
| for jar in list(module.jar_files): |
| dependent_data['jar_module_path'].update({jar: module.module_path}) |
| # Collecting the jar files of default core modules as dependencies. |
| if constant.KEY_DEPENDENCIES in module.module_data: |
| dependent_data['jar_path'].update([ |
| x for x in module.module_data[constant.KEY_DEPENDENCIES] |
| if common_util.is_target(x, _TARGET_LIBS) |
| ]) |
| |
| |
| class ModuleData(): |
| """ModuleData class. |
| |
| Attributes: |
| All following relative paths stand for the path relative to the android |
| repo root. |
| |
| module_path: A string of the relative path to the module. |
| src_dirs: A set to keep the unique source folder relative paths. |
| test_dirs: A set to keep the unique test folder relative paths. |
| jar_files: A set to keep the unique jar file relative paths. |
| r_java_paths: A set to keep the R folder paths to use in Eclipse. |
| srcjar_paths: A set to keep the srcjar source root paths to use in |
| IntelliJ. |
| referenced_by_jar: A boolean to check if the module is referenced by a |
| jar file. |
| build_targets: A set to keep the unique build target jar or srcjar file |
| relative paths which are ready to be rebuld. |
| missing_jars: A set to keep the jar file relative paths if it doesn't |
| exist. |
| specific_soong_path: A string of the relative path to the module's |
| intermediates folder under out/. |
| """ |
| |
| def __init__(self, module_name, module_data, depth): |
| """Initialize ModuleData. |
| |
| Args: |
| module_name: Name of the module. |
| module_data: A dictionary holding a module information. |
| depth: An integer shows the depth of module dependency referenced by |
| source. Zero means the max module depth. |
| For example: |
| { |
| 'class': ['APPS'], |
| 'path': ['path/to/the/module'], |
| 'depth': 0, |
| 'dependencies': ['bouncycastle', 'ims-common'], |
| 'srcs': [ |
| 'path/to/the/module/src/com/android/test.java', |
| 'path/to/the/module/src/com/google/test.java', |
| 'out/soong/.intermediates/path/to/the/module/test/src/ |
| com/android/test.srcjar' |
| ], |
| 'installed': ['out/target/product/generic_x86_64/ |
| system/framework/framework.jar'], |
| 'jars': ['settings.jar'], |
| 'jarjar_rules': ['jarjar-rules.txt'] |
| } |
| """ |
| assert module_name, 'Module name can\'t be null.' |
| assert module_data, 'Module data of %s can\'t be null.' % module_name |
| self.module_name = module_name |
| self.module_data = module_data |
| self._init_module_path() |
| self._init_module_depth(depth) |
| self.src_dirs = set() |
| self.test_dirs = set() |
| self.jar_files = set() |
| self.r_java_paths = set() |
| self.srcjar_paths = set() |
| self.referenced_by_jar = False |
| self.build_targets = set() |
| self.missing_jars = set() |
| self.specific_soong_path = os.path.join( |
| 'out/soong/.intermediates', self.module_path, self.module_name) |
| |
| def _is_app_module(self): |
| """Check if the current module's class is APPS""" |
| return self._check_key('class') and 'APPS' in self.module_data['class'] |
| |
| def _is_target_module(self): |
| """Check if the current module is a target module. |
| |
| A target module is the target project or a module under the |
| target project and it's module depth is 0. |
| For example: aidegen Settings framework |
| The target projects are Settings and framework so they are also |
| target modules. And the dependent module SettingsUnitTests's path |
| is packages/apps/Settings/tests/unit so it also a target module. |
| """ |
| return self.module_depth == 0 |
| |
| def _collect_r_srcs_paths(self): |
| """Collect the source folder of R.java. |
| |
| Check if the path of aapt2.srcjar or R.jar exists, which is the value of |
| key "srcjars" in module_data. If the path of both 2 cases doesn't exist, |
| build it onto an intermediates directory. |
| |
| For IntelliJ, we can set the srcjar file as a source root for |
| dependency. For Eclipse, we still use the R folder as dependencies until |
| we figure out how to set srcjar file as dependency. |
| # TODO(b/135594800): Set aapt2.srcjar or R.jar as a dependency in |
| Eclipse. |
| """ |
| if (self._is_app_module() and self._is_target_module() and |
| self._check_key(constant.KEY_SRCJARS)): |
| for srcjar in self.module_data[constant.KEY_SRCJARS]: |
| if not os.path.exists(common_util.get_abs_path(srcjar)): |
| self.build_targets.add(srcjar) |
| self._collect_srcjar_path(srcjar) |
| r_dir = self._get_r_dir(srcjar) |
| if r_dir: |
| self.r_java_paths.add(r_dir) |
| |
| def _collect_srcjar_path(self, srcjar): |
| """Collect the source folders from a srcjar path. |
| |
| Set the aapt2.srcjar or R.jar as source root: |
| Case aapt2.srcjar: |
| The source path string is |
| out/.../Bluetooth_intermediates/aapt2.srcjar |
| The source content descriptor is |
| out/.../Bluetooth_intermediates/aapt2.srcjar!/. |
| Case R.jar: |
| The source path string is out/soong/.../gen/R.jar. |
| The source content descriptor is out/soong/.../gen/R.jar!/. |
| |
| Args: |
| srcjar: A file path string relative to ANDROID_BUILD_TOP, the build |
| target of the module to generate R.java. |
| """ |
| if os.path.basename(srcjar) in _TARGET_BUILD_FILES: |
| self.srcjar_paths.add('%s!/' % srcjar) |
| |
| @staticmethod |
| def _get_r_dir(srcjar): |
| """Get the source folder of R.java for Eclipse. |
| |
| Args: |
| srcjar: A file path string, the build target of the module to |
| generate R.java. |
| |
| Returns: |
| A relative source folder path string, and return None if the target |
| file name is not aapt2.srcjar or R.jar. |
| """ |
| target_folder, target_file = os.path.split(srcjar) |
| if target_file == _TARGET_AAPT2_SRCJAR: |
| return os.path.join(target_folder, _NAME_AAPT2) |
| if target_file == _TARGET_R_JAR: |
| return os.path.join(target_folder, _NAME_AAPT2, 'R') |
| return None |
| |
| def _init_module_path(self): |
| """Inintialize self.module_path.""" |
| self.module_path = (self.module_data[constant.KEY_PATH][0] |
| if self._check_key(constant.KEY_PATH) else '') |
| |
| def _init_module_depth(self, depth): |
| """Initialize module depth's settings. |
| |
| Set the module's depth from module info when user have -d parameter. |
| Set the -d value from user input, default to 0. |
| |
| Args: |
| depth: the depth to be set. |
| """ |
| self.module_depth = (int(self.module_data[constant.KEY_DEPTH]) |
| if depth else 0) |
| self.depth_by_source = depth |
| |
| def _is_android_supported_module(self): |
| """Determine if this is an Android supported module.""" |
| return self.module_path.startswith(_ANDROID_SUPPORT_PATH_KEYWORD) |
| |
| def _check_jarjar_rules_exist(self): |
| """Check if jarjar rules exist.""" |
| return (_KEY_JARJAR_RULES in self.module_data and |
| self.module_data[_KEY_JARJAR_RULES][0] == _JARJAR_RULES_FILE) |
| |
| def _check_jars_exist(self): |
| """Check if jars exist.""" |
| return self._check_key(_KEY_JARS) |
| |
| def _check_classes_jar_exist(self): |
| """Check if classes_jar exist.""" |
| return self._check_key(constant.KEY_CLASSES_JAR) |
| |
| def _collect_srcs_paths(self): |
| """Collect source folder paths in src_dirs from module_data['srcs'].""" |
| if self._check_key(constant.KEY_SRCS): |
| scanned_dirs = set() |
| for src_item in self.module_data[constant.KEY_SRCS]: |
| src_dir = None |
| src_item = os.path.relpath(src_item) |
| if src_item.endswith(_SRCJAR_EXT): |
| self._append_jar_from_installed(self.specific_soong_path) |
| elif common_util.is_target(src_item, _TARGET_FILES): |
| # Only scan one java file in each source directories. |
| src_item_dir = os.path.dirname(src_item) |
| if src_item_dir not in scanned_dirs: |
| scanned_dirs.add(src_item_dir) |
| src_dir = self._get_source_folder(src_item) |
| else: |
| # To record what files except java and srcjar in the srcs. |
| logging.debug('%s is not in parsing scope.', src_item) |
| if src_dir: |
| self._add_to_source_or_test_dirs(src_dir) |
| |
| def _check_key(self, key): |
| """Check if key is in self.module_data and not empty. |
| |
| Args: |
| key: the key to be checked. |
| """ |
| return key in self.module_data and self.module_data[key] |
| |
| def _add_to_source_or_test_dirs(self, src_dir): |
| """Add folder to source or test directories. |
| |
| Args: |
| src_dir: the directory to be added. |
| """ |
| if not any(path in src_dir for path in _IGNORE_DIRS): |
| if self._is_test_module(src_dir): |
| self.test_dirs.add(src_dir) |
| else: |
| self.src_dirs.add(src_dir) |
| |
| @staticmethod |
| def _is_test_module(src_dir): |
| """Check if the module path is a test module path. |
| |
| Args: |
| src_dir: the directory to be checked. |
| |
| Returns: |
| True if module path is a test module path, otherwise False. |
| """ |
| return _KEY_TESTS in src_dir.split(os.sep) |
| |
| def _get_source_folder(self, java_file): |
| """Parsing a java to get the package name to filter out source path. |
| |
| Args: |
| java_file: A string, the java file with relative path. |
| e.g. path/to/the/java/file.java |
| |
| Returns: |
| source_folder: A string of path to source folder(e.g. src/main/java) |
| or none when it failed to get package name. |
| """ |
| abs_java_path = common_util.get_abs_path(java_file) |
| if os.path.exists(abs_java_path): |
| package_name = self._get_package_name(abs_java_path) |
| if package_name: |
| return self._parse_source_path(java_file, package_name) |
| return None |
| |
| @staticmethod |
| def _parse_source_path(java_file, package_name): |
| """Parse the source path by filter out the package name. |
| |
| Case 1: |
| java file: a/b/c/d/e.java |
| package name: c.d |
| The source folder is a/b. |
| |
| Case 2: |
| java file: a/b/c.d/e.java |
| package name: c.d |
| The source folder is a/b. |
| |
| Case 3: |
| java file: a/b/c/d/e.java |
| package name: x.y |
| The source folder is a/b/c/d. |
| |
| Case 4: |
| java file: a/b/c.d/e/c/d/f.java |
| package name: c.d |
| The source folder is a/b/c.d/e. |
| |
| Case 5: |
| java file: a/b/c.d/e/c.d/e/f.java |
| package name: c.d.e |
| The source folder is a/b/c.d/e. |
| |
| Args: |
| java_file: A string of the java file relative path. |
| package_name: A string of the java file's package name. |
| |
| Returns: |
| A string, the source folder path. |
| """ |
| java_file_name = os.path.basename(java_file) |
| pattern = r'%s/%s$' % (package_name, java_file_name) |
| search_result = re.search(pattern, java_file) |
| if search_result: |
| return java_file[:search_result.start()].strip(os.sep) |
| return os.path.dirname(java_file) |
| |
| @staticmethod |
| def _get_package_name(abs_java_path): |
| """Get the package name by parsing a java file. |
| |
| Args: |
| abs_java_path: A string of the java file with absolute path. |
| e.g. /root/path/to/the/java/file.java |
| |
| Returns: |
| package_name: A string of package name. |
| """ |
| package_name = None |
| with open(abs_java_path) as data: |
| for line in data.read().splitlines(): |
| match = _PACKAGE_RE.match(line) |
| if match: |
| package_name = match.group('package') |
| break |
| return package_name |
| |
| def _append_jar_file(self, jar_path): |
| """Append a path to the jar file into self.jar_files if it's exists. |
| |
| Args: |
| jar_path: A path supposed to be a jar file. |
| |
| Returns: |
| Boolean: True if jar_path is an existing jar file. |
| """ |
| if common_util.is_target(jar_path, _TARGET_LIBS): |
| self.referenced_by_jar = True |
| if os.path.isfile(common_util.get_abs_path(jar_path)): |
| self.jar_files.add(jar_path) |
| else: |
| self.missing_jars.add(jar_path) |
| return True |
| return False |
| |
| def _append_classes_jar(self): |
| """Append the jar file as dependency for prebuilt modules.""" |
| for jar in self.module_data[constant.KEY_CLASSES_JAR]: |
| if self._append_jar_file(jar): |
| break |
| |
| def _append_jar_from_installed(self, specific_dir=None): |
| """Append a jar file's path to the list of jar_files with matching |
| path_prefix. |
| |
| There might be more than one jar in "installed" parameter and only the |
| first jar file is returned. If specific_dir is set, the jar file must be |
| under the specific directory or its sub-directory. |
| |
| Args: |
| specific_dir: A string of path. |
| """ |
| if self._check_key(constant.KEY_INSTALLED): |
| for jar in self.module_data[constant.KEY_INSTALLED]: |
| if specific_dir and not jar.startswith(specific_dir): |
| continue |
| if self._append_jar_file(jar): |
| break |
| |
| def _set_jars_jarfile(self): |
| """Append prebuilt jars of module into self.jar_files. |
| |
| Some modules' sources are prebuilt jar files instead of source java |
| files. The jar files can be imported into IntelliJ as a dependency |
| directly. There is only jar file name in self.module_data['jars'], it |
| has to be combined with self.module_data['path'] to append into |
| self.jar_files. |
| For example: |
| 'asm-6.0': { |
| 'jars': [ |
| 'asm-6.0.jar' |
| ], |
| 'path': [ |
| 'prebuilts/misc/common/asm' |
| ], |
| }, |
| Path to the jar file is prebuilts/misc/common/asm/asm-6.0.jar. |
| """ |
| if self._check_key(_KEY_JARS): |
| for jar_name in self.module_data[_KEY_JARS]: |
| if self._check_key(constant.KEY_INSTALLED): |
| self._append_jar_from_installed() |
| else: |
| jar_path = os.path.join(self.module_path, jar_name) |
| jar_abs = common_util.get_abs_path(jar_path) |
| if not os.path.isfile(jar_abs) and jar_name.endswith( |
| 'prebuilt.jar'): |
| rel_path = self._get_jar_path_from_prebuilts(jar_name) |
| if rel_path: |
| jar_path = rel_path |
| self._append_jar_file(jar_path) |
| |
| @staticmethod |
| def _get_jar_path_from_prebuilts(jar_name): |
| """Get prebuilt jar file from prebuilts folder. |
| |
| If the prebuilt jar file we get from method _set_jars_jarfile() does not |
| exist, we should search the prebuilt jar file in prebuilts folder. |
| For example: |
| 'platformprotos': { |
| 'jars': [ |
| 'platformprotos-prebuilt.jar' |
| ], |
| 'path': [ |
| 'frameworks/base' |
| ], |
| }, |
| We get an incorrect path: 'frameworks/base/platformprotos-prebuilt.jar' |
| If the file does not exist, we should search the file name from |
| prebuilts folder. If we can get the correct path from 'prebuilts', we |
| can replace it with the incorrect path. |
| |
| Args: |
| jar_name: The prebuilt jar file name. |
| |
| Return: |
| A relative prebuilt jar file path if found, otherwise None. |
| """ |
| rel_path = '' |
| search = os.sep.join( |
| [common_util.get_android_root_dir(), 'prebuilts/**', jar_name]) |
| results = glob.glob(search, recursive=True) |
| if results: |
| jar_abs = results[0] |
| rel_path = os.path.relpath( |
| jar_abs, common_util.get_android_root_dir()) |
| return rel_path |
| |
| def locate_sources_path(self): |
| """Locate source folders' paths or jar files.""" |
| if self.module_depth > self.depth_by_source: |
| self._append_jar_from_installed(self.specific_soong_path) |
| else: |
| if self._is_android_supported_module(): |
| self._append_jar_from_installed() |
| elif self._check_jarjar_rules_exist(): |
| self._append_jar_from_installed(self.specific_soong_path) |
| elif self._check_jars_exist(): |
| self._set_jars_jarfile() |
| self._collect_srcs_paths() |
| # If there is no source/tests folder of the module, reference the |
| # module by jar. |
| if not self.src_dirs and not self.test_dirs: |
| # Add the classes.jar from the classes_jar attribute as |
| # dependency if it exists. If the classes.jar doesn't exist, |
| # find the jar file from the installed attribute and add the jar |
| # as dependency. |
| if self._check_classes_jar_exist(): |
| self._append_classes_jar() |
| else: |
| self._append_jar_from_installed() |
| self._collect_r_srcs_paths() |
| if self.referenced_by_jar and self.missing_jars: |
| self.build_targets |= self.missing_jars |
| |
| |
| class EclipseModuleData(ModuleData): |
| """Deal with modules data for Eclipse |
| |
| Only project target modules use source folder type and the other ones use |
| jar as their source. We'll combine both to establish the whole project's |
| dependencies. If the source folder used to build dependency jar file exists |
| in Android, we should provide the jar file path as <linkedResource> item in |
| source data. |
| """ |
| |
| def __init__(self, module_name, module_data, project_relpath): |
| """Initialize EclipseModuleData. |
| |
| Only project target modules apply source folder type, so set the depth |
| of module referenced by source to 0. |
| |
| Args: |
| module_name: String type, name of the module. |
| module_data: A dictionary contains a module information. |
| project_relpath: A string stands for the project's relative path. |
| """ |
| super().__init__(module_name, module_data, depth=0) |
| self.is_project = common_util.is_project_path_relative_module( |
| module_data, project_relpath) |
| |
| def locate_sources_path(self): |
| """Locate source folders' paths or jar files. |
| |
| Only collect source folders for the project modules and collect jar |
| files for the other dependent modules. |
| """ |
| if self.is_project: |
| self._locate_project_source_path() |
| else: |
| self._locate_jar_path() |
| if self.referenced_by_jar and self.missing_jars: |
| self.build_targets |= self.missing_jars |
| |
| def _locate_project_source_path(self): |
| """Locate the source folder paths of the project module. |
| |
| A project module is the target modules or paths that users key in |
| aidegen command. Collecting the source folders is necessary for |
| developers to edit code. And also collect the central R folder for the |
| dependency of resources. |
| """ |
| self._collect_srcs_paths() |
| self._collect_r_srcs_paths() |
| |
| def _locate_jar_path(self): |
| """Locate the jar path of the module. |
| |
| Use jar files for dependency modules for Eclipse. Collect the jar file |
| path with different cases. |
| """ |
| if self._check_jarjar_rules_exist(): |
| self._append_jar_from_installed(self.specific_soong_path) |
| elif self._check_jars_exist(): |
| self._set_jars_jarfile() |
| elif self._check_classes_jar_exist(): |
| self._append_classes_jar() |
| else: |
| self._append_jar_from_installed() |