• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright 2019, The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""Module Info class used to hold cached merged_module_info.json."""
18
19import json
20import logging
21import os
22
23from pathlib import Path
24
25from atest import constants
26from atest import module_info
27
28from aidegen import constant
29from aidegen.lib import common_util
30from aidegen.lib import module_info_util
31from aidegen.lib.singleton import Singleton
32
33
34class AidegenModuleInfo(module_info.ModuleInfo, metaclass=Singleton):
35    """Class that offers fast/easy lookup for Module related details."""
36
37    def _load_module_info_file(self, module_file):
38        """Loads the module file.
39
40        Args:
41            module_file: String of path to file to load up. Used for testing.
42
43        Returns:
44            Tuple of module_info_target and a json object.
45        """
46        # If module_file is specified, we're testing so we don't care if
47        # module_info_target stays None.
48        module_info_target = None
49        file_path = module_file
50
51        if not file_path:
52            module_info_target, file_path = self._discover_mod_file_and_target(
53                self.force_build)
54            self.mod_info_file_path = Path(file_path)
55
56        logging.debug('Loading %s as module-info.', file_path)
57        with open(file_path, 'r', encoding='utf8') as json_file:
58            mod_info = json.load(json_file)
59
60        return module_info_target, mod_info
61
62    @staticmethod
63    def _discover_mod_file_and_target(force_build):
64        """Find the module file.
65
66        If force_build is True, we'll remove module_bp_java_deps.json first and
67        let module_info_util.generate_merged_module_info regenerate it again.
68
69        Args:
70            force_build: Boolean to indicate if we should rebuild the
71                         module_info file regardless if it's created or not.
72
73        Returns:
74            Tuple of the relative and absolute paths of the merged module info
75            file.
76        """
77        module_file_path = common_util.get_blueprint_json_path(
78            constant.BLUEPRINT_JAVA_JSONFILE_NAME)
79        if force_build and os.path.isfile(module_file_path):
80            os.remove(module_file_path)
81        merged_file_path = os.path.join(common_util.get_soong_out_path(),
82                                        constant.MERGED_MODULE_INFO)
83        if not os.path.isfile(merged_file_path):
84            logging.debug(
85                'Generating %s - this is required for the initial runs.',
86                merged_file_path)
87        data = module_info_util.generate_merged_module_info()
88        common_util.dump_json_dict(merged_file_path, data)
89        merged_file_rel_path = os.path.relpath(
90            merged_file_path, common_util.get_android_root_dir())
91        return merged_file_rel_path, merged_file_path
92
93    @staticmethod
94    def is_target_module(mod_info):
95        """Determine if the module is a target module.
96
97        Determine if a module's class is in TARGET_CLASSES.
98
99        Args:
100            mod_info: A module's module-info dictionary to be checked.
101
102        Returns:
103            A boolean, true if it is a target module, otherwise false.
104        """
105        if mod_info:
106            return any(
107                x in mod_info.get(constants.MODULE_CLASS, [])
108                for x in constant.TARGET_CLASSES)
109        return False
110
111    @staticmethod
112    def is_project_path_relative_module(mod_info, rel_path):
113        """Determine if the given project path is relative to the module.
114
115        The rules:
116           1. If constant.KEY_PATH not in mod_info, we can't tell if it's a
117              module return False.
118           2. If rel_path is empty, it's under Android root, return True.
119           3. If module's path equals or starts with rel_path return True,
120              otherwise return False.
121
122        Args:
123            mod_info: the module-info dictionary of the checked module.
124            rel_path: project's relative path
125
126        Returns:
127            True if it's the given project path is relative to the module,
128            otherwise False.
129        """
130        if (constant.KEY_PATH not in mod_info
131                or not mod_info[constant.KEY_PATH]):
132            return False
133        path = mod_info[constant.KEY_PATH][0]
134        if rel_path == '':
135            return True
136        if (constant.KEY_CLASS in mod_info
137                and common_util.is_source_under_relative_path(path, rel_path)):
138            return True
139        return False
140