• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4#
5# Copyright (c) 2020 Huawei Device Co., Ltd.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19import os
20import subprocess
21from datetime import datetime
22from distutils.spawn import find_executable
23from hb_internal.common.utils import exec_command
24from hb_internal.common.utils import hb_warning
25
26
27class PreBuild:
28    def __init__(self, config):
29        self._root_path = config.root_path
30        self._out_path = config.out_path
31        self._log_path = config.log_path
32
33    def set_ccache(self):
34        ccache_base = os.environ.get('CCACHE_BASE')
35        if ccache_base is None:
36            ccache_base = os.path.join(self._root_path, '.ccache')
37            if not os.path.exists(ccache_base):
38                os.makedirs(ccache_base)
39        logfile = os.path.join(self._root_path, 'ccache.log')
40        if os.path.exists(logfile):
41            oldfile = os.path.join(self._root_path, 'ccache.log.old')
42            if os.path.exists(oldfile):
43                os.unlink(oldfile)
44            os.rename(logfile, oldfile)
45
46        ccache_path = find_executable('ccache')
47        if ccache_path is None:
48            hb_warning('Failed to find ccache, ccache disabled.')
49            return
50        os.environ['CCACHE_EXEC'] = ccache_path
51        os.environ['CCACHE_LOGFILE'] = logfile
52        os.environ['USE_CCACHE'] = '1'
53        os.environ['CCACHE_DIR'] = ccache_base
54        os.environ['CCACHE_MASK'] = '002'
55
56        cmd = ['ccache', '-M', '50G']
57        exec_command(cmd, log_path=self._log_path)
58
59    def set_pycache(self):
60        pycache_dir = os.path.join(self._root_path, '.pycache')
61        os.environ['PYCACHE_DIR'] = pycache_dir
62        pyd_start_cmd = [
63            'python3',
64            '{}/build/scripts/util/pyd.py'.format(self._root_path),
65            '--root',
66            pycache_dir,
67            '--start',
68        ]
69        cmd = ['/bin/bash', '-c', ' '.join(pyd_start_cmd), '&']
70        subprocess.Popen(cmd)
71
72    def rename_last_logfile(self):
73        logfile = os.path.join(self._out_path, 'build.log')
74        if os.path.exists(logfile):
75            mtime = os.stat(logfile).st_mtime
76            os.rename(logfile, '{}/build.{}.log'.format(self._out_path, mtime))
77
78    def prepare(self, args):
79        actions = [self.set_ccache, self.rename_last_logfile]
80        for action in actions:
81            action()
82
83
84class PostBuild:
85    def __init__(self, config):
86        self._root_path = config.root_path
87        self._out_path = config.out_path
88        self._log_path = config.log_path
89
90    def clean(self, start_time):
91        self.stat_ccache()
92        self.generate_ninja_trace(start_time)
93        self.get_warning_list()
94        self.compute_overlap_rate()
95
96    def stat_pycache(self):
97        cmd = [
98            'python3', '{}/build/scripts/util/pyd.py'.format(self._root_path),
99            '--stat'
100        ]
101        exec_command(cmd, log_path=self._log_path)
102
103    def manage_cache_data(self):
104        cmd = [
105            'python3', '{}/build/scripts/util/pyd.py'.format(self._root_path),
106            '--manage'
107        ]
108        exec_command(cmd, log_path=self._log_path)
109
110    def stop_pyd(self):
111        cmd = [
112            'python3', '{}/build/scripts/util/pyd.py'.format(self._root_path),
113            '--stop'
114        ]
115        exec_command(cmd, log_path=self._log_path)
116
117    def stat_ccache(self):
118        ccache_path = find_executable('ccache')
119        if ccache_path is None:
120            return
121        cmd = [
122            'python3', '{}/build/scripts/summary_ccache_hitrate.py'.format(
123                self._root_path), '{}/ccache.log'.format(self._root_path)
124        ]
125        exec_command(cmd, log_path=self._log_path)
126
127    def get_warning_list(self):
128        cmd = [
129            'python3',
130            '{}/build/scripts/get_warnings.py'.format(self._root_path),
131            '--build-log-file',
132            '{}/build.log'.format(self._out_path),
133            '--warning-out-file',
134            '{}/packages/WarningList.txt'.format(self._out_path),
135        ]
136        exec_command(cmd, log_path=self._log_path)
137
138    def generate_ninja_trace(self, start_time):
139        def get_unixtime(dt):
140            epoch = datetime.utcfromtimestamp(0)
141            unixtime = '%f' % ((dt - epoch).total_seconds() * 10**9)
142            return str(unixtime)
143
144        cmd = [
145            'python3',
146            '{}/build/scripts/ninja2trace.py'.format(self._root_path),
147            '--ninja-log',
148            '{}/.ninja_log'.format(self._out_path),
149            "--trace-file",
150            "{}/build.trace".format(self._out_path),
151            "--ninja-start-time",
152            get_unixtime(start_time),
153            "--duration-file",
154            "{}/sorted_action_duration.txt".format(self._out_path),
155        ]
156        exec_command(cmd, log_path=self._log_path)
157
158    def compute_overlap_rate(self):
159        cmd = [
160            'python3',
161            '{}/build/ohos/statistics/build_overlap_statistics.py'.format(
162                self._root_path), "--build-out-dir", self._out_path,
163            "--subsystem-config-file",
164            "{}/build/subsystem_config.json".format(self._root_path),
165            "--root-source-dir", self._root_path
166        ]
167        exec_command(cmd, log_path=self._log_path)
168