| #!/usr/bin/env python3 |
| # |
| # Copyright 2019 - 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. |
| |
| """It is an AIDEGen sub task: generate the .project file for Eclipse.""" |
| |
| import os |
| |
| from aidegen import constant |
| from aidegen.lib import common_util |
| from aidegen.lib import project_file_gen |
| |
| |
| class EclipseConf(project_file_gen.ProjectFileGenerator): |
| """Class to generate project file under the module path for Eclipse. |
| |
| Attributes: |
| module_abspath: The absolute path of the target project. |
| module_relpath: The relative path of the target project. |
| module_name: The name of the target project. |
| jar_module_paths: A dict records a mapping of jar file and module path. |
| r_java_paths: A list contains the relative folder paths of the R.java |
| files. |
| project_file: The absolutely path of .project file. |
| template_project_content: A string of a template project_file content. |
| project_content: A string ready to be written into project_file. |
| src_paths: A list contains the project's source paths. |
| classpath_file: The absolutely path of .classpath file. |
| classpath_content: A string ready to be written into classpath_file. |
| """ |
| # Constants of .project file |
| _TEMPLATE_PROJECT_FILE = os.path.join(common_util.get_aidegen_root_dir(), |
| 'templates/eclipse/project.xml') |
| _PROJECT_LINK = (' <link><name>{}</name><type>2</type>' |
| '<location>{}</location></link>\n') |
| _PROJECT_FILENAME = '.project' |
| |
| # constans of .classpath file |
| _TEMPLATE_CLASSPATH_FILE = os.path.join(common_util.get_aidegen_root_dir(), |
| 'templates/eclipse/classpath.xml') |
| _CLASSPATH_SRC_ENTRY = ' <classpathentry kind="src" path="{}"/>\n' |
| _EXCLUDE_ANDROID_BP_ENTRY = (' <classpathentry excluding="Android.bp" ' |
| 'kind="src" path="{}"/>\n') |
| _CLASSPATH_LIB_ENTRY = (' <classpathentry exported="true" kind="lib" ' |
| 'path="{}" sourcepath="{}"/>\n') |
| _CLASSPATH_FILENAME = '.classpath' |
| |
| def __init__(self, project): |
| """Initialize class. |
| |
| Args: |
| project: A ProjectInfo instance. |
| """ |
| super().__init__(project) |
| self.module_abspath = project.project_absolute_path |
| self.module_relpath = project.project_relative_path |
| self.module_name = project.module_name |
| self.jar_module_paths = project.source_path['jar_module_path'] |
| self.r_java_paths = list(project.source_path['r_java_path']) |
| # Related value for generating .project. |
| self.project_file = os.path.join(self.module_abspath, |
| self._PROJECT_FILENAME) |
| self.template_project_content = common_util.read_file_content( |
| self._TEMPLATE_PROJECT_FILE) |
| self.project_content = '' |
| # Related value for generating .classpath. |
| self.src_paths = list(project.source_path['source_folder_path']) |
| self.src_paths.extend(project.source_path['test_folder_path']) |
| self.classpath_file = os.path.join(self.module_abspath, |
| self._CLASSPATH_FILENAME) |
| self.classpath_content = common_util.read_file_content( |
| self._TEMPLATE_CLASSPATH_FILE) |
| |
| def _gen_r_link(self): |
| """Generate the link resources of the R paths. |
| |
| E.g. |
| <link> |
| <name>dependencies/out/target/common/R</name> |
| <type>2</type> |
| <location>{ANDROID_ROOT_PATH}/out/target/common/R</location> |
| </link> |
| |
| Returns: A set contains R paths link resources strings. |
| """ |
| return {self._gen_link(r_path) for r_path in self.r_java_paths} |
| |
| def _gen_src_links(self, relpaths): |
| """Generate the link resources from relpaths. |
| |
| Args: |
| relpaths: A list of module paths which are relative to |
| ANDROID_BUILD_TOP. |
| e.g. ['relpath/to/module1', 'relpath/to/module2', ...] |
| |
| Returns: A set includes all unique link resources. |
| """ |
| return {self._gen_link(relpath) for relpath in relpaths} |
| |
| @classmethod |
| def _gen_link(cls, relpath): |
| """Generate a link resource from a relative path. |
| |
| E.g. |
| <link> |
| <name>dependencies/path/to/relpath</name> |
| <type>2</type> |
| <location>/absolute/path/to/relpath</location> |
| </link> |
| |
| Args: |
| relpath: A string of a relative path to Android_BUILD_TOP. |
| |
| Returns: A string of link resource. |
| """ |
| alias_name = os.path.join(constant.KEY_DEPENDENCIES, relpath) |
| abs_path = os.path.join(common_util.get_android_root_dir(), relpath) |
| return cls._PROJECT_LINK.format(alias_name, abs_path) |
| |
| def _create_project_content(self): |
| """Create the project file .project under the module.""" |
| # links is a set to save unique link resources. |
| links = self._gen_src_links(self.jar_module_paths.values()) |
| links.update(self._gen_r_link()) |
| self.project_content = self.template_project_content.format( |
| PROJECTNAME=self.module_name, |
| LINKEDRESOURCES=''.join(sorted(list(links)))) |
| |
| def _gen_r_path_entries(self): |
| """Generate the class path entries for the R paths. |
| |
| E.g. |
| <classpathentry kind="src" |
| path="dependencies/out/target/common/R"/> |
| <classpathentry kind="src" |
| path="dependencies/out/soong/.intermediates/packages/apps/ |
| Settings/Settings/android_common/gen/aapt2/R"/> |
| |
| Returns: A list of the R path's class path entry. |
| """ |
| r_entry_list = [] |
| for r_path in self.r_java_paths: |
| alias_path = os.path.join(constant.KEY_DEPENDENCIES, r_path) |
| r_entry_list.append(self._CLASSPATH_SRC_ENTRY.format(alias_path)) |
| return r_entry_list |
| |
| def _gen_src_path_entries(self): |
| """Generate the class path entries from srcs. |
| |
| If the Android.bp file exists, generate the following content in |
| .classpath file to avoid copying the Android.bp to the bin folder under |
| current project directory. |
| <classpathentry excluding="Android.bp" kind="src" |
| path="clearcut_client"/> |
| |
| E.g. |
| The source folder paths list: |
| ['packages/apps/Settings/src', |
| 'packages/apps/Settings/tests/robotests/src', |
| 'packages/apps/Settings/tests/uitests/src', |
| 'packages/apps/Settings/tests/unit/src' |
| ] |
| It will generate the related <classpathentry> list: |
| ['<classpathentry kind="src" path="src"/>', |
| '<classpathentry kind="src" path="tests/robotests/src"/>', |
| '<classpathentry kind="src" path="tests/uitests/src"/>', |
| '<classpathentry kind="src" path="tests/unit/src"/>' |
| ] |
| |
| Returns: A list of source folders' class path entries. |
| """ |
| src_path_entries = [] |
| for src in self.src_paths: |
| src_abspath = os.path.join(common_util.get_android_root_dir(), src) |
| src = src.replace(self.module_relpath, '').strip(os.sep) |
| if common_util.exist_android_bp(src_abspath): |
| src_path_entries.append( |
| self._EXCLUDE_ANDROID_BP_ENTRY.format(src)) |
| else: |
| src_path_entries.append(self._CLASSPATH_SRC_ENTRY.format(src)) |
| return src_path_entries |
| |
| def _gen_jar_path_entries(self): |
| """Generate the jar files' class path entries. |
| |
| The self.jar_module_paths is a dictionary. |
| e.g. |
| {'/abspath/to/the/file.jar': 'relpath/to/the/module'} |
| This method will generate the <classpathentry> for each jar file. |
| The format of <classpathentry> looks like: |
| <classpathentry exported="true" kind="lib" |
| path="/abspath/to/the/file.jar" |
| sourcepath="dependencies/relpath/to/the/module"/> |
| |
| Returns: A list of jar files' class path entries. |
| """ |
| jar_entries = [] |
| for jar_relpath, module_relpath in self.jar_module_paths.items(): |
| jar_abspath = os.path.join(common_util.get_android_root_dir(), |
| jar_relpath) |
| alias_module_path = os.path.join(constant.KEY_DEPENDENCIES, |
| module_relpath) |
| jar_entries.append(self._CLASSPATH_LIB_ENTRY.format( |
| jar_abspath, alias_module_path)) |
| return jar_entries |
| |
| def _create_classpath_content(self): |
| """Create the project file .classpath under the module.""" |
| src_entries = self._gen_src_path_entries() |
| src_entries.extend(self._gen_r_path_entries()) |
| jar_entries = self._gen_jar_path_entries() |
| self.classpath_content = self.classpath_content.format( |
| SRC=''.join(sorted(src_entries)), |
| LIB=''.join(sorted(jar_entries))) |
| |
| def generate_project_file(self): |
| """Generate .project file of the target module.""" |
| self._create_project_content() |
| common_util.file_generate(self.project_file, self.project_content) |
| |
| def generate_classpath_file(self): |
| """Generate .classpath file of the target module.""" |
| self._create_classpath_content() |
| common_util.file_generate(self.classpath_file, self.classpath_content) |
| |
| @classmethod |
| def generate_ide_project_files(cls, projects): |
| """Generate Eclipse project files by a list of ProjectInfo instances. |
| |
| Args: |
| projects: A list of ProjectInfo instances. |
| """ |
| for project in projects: |
| eclipse_configure = EclipseConf(project) |
| eclipse_configure.generate_project_file() |
| eclipse_configure.generate_classpath_file() |