build_process.py 9.4 KB
Newer Older
M
mamingshuai 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (c) 2020 Huawei Device Co., Ltd.
# 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.
#

import os
P
pilipala195 已提交
20
import sys
M
mamingshuai 已提交
21 22 23 24 25 26 27
from collections import defaultdict

from hb.common.utils import exec_command
from hb.common.utils import makedirs
from hb.common.utils import remove_path
from hb.common.utils import hb_info
from hb.common.utils import hb_warning
G
gzyang 已提交
28
from hb.common.utils import OHOSException
M
mamingshuai 已提交
29 30 31 32
from hb.common.config import Config
from hb.cts.cts import CTS
from hb.common.device import Device
from hb.common.product import Product
P
pilipala195 已提交
33
from hb.build.fs_process import Packer
34
from hb.build.patch_process import Patch
Y
yangming_ha 已提交
35
from distutils.spawn import find_executable
M
mamingshuai 已提交
36 37

class Build():
G
gzyang 已提交
38
    def __init__(self, component=None):
M
mamingshuai 已提交
39 40 41 42 43 44 45 46
        self.config = Config()

        # Get gn args ready
        self._args_list = []
        self._target = None
        self._compiler = None
        self._test = None

G
gzyang 已提交
47 48 49
        self.target = component
        self.check_in_device()

M
mamingshuai 已提交
50 51 52 53 54 55
    @property
    def target(self):
        return self._target

    @target.setter
    def target(self, component):
G
gzyang 已提交
56 57 58 59
        if component is None or not len(component):
            return
        component = component[0]

M
mamingshuai 已提交
60 61 62 63 64
        cts = CTS()
        cts.init_from_json()
        for subsystem_cls in cts:
            for cname, component_cls in subsystem_cls:
                if cname == component:
65
                    if not len(component_cls.adapted_board) or\
M
mamingshuai 已提交
66
                       self.config.board in component_cls.adapted_board:
67
                        if not len(component_cls.adapted_kernel) or\
M
mamingshuai 已提交
68 69 70 71 72 73
                           self.config.kernel in component_cls.adapted_kernel:
                            self._target = component_cls.targets
                            self.register_args('ohos_build_target',
                                               self._target)
                            return

G
gzyang 已提交
74
        raise OHOSException(f'Component {component} not found')
M
mamingshuai 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93

    @property
    def compiler(self):
        return self._compiler

    @compiler.setter
    def compiler(self, value):
        self._compiler = value
        self.register_args('ohos_build_compiler_specified', self._compiler)
        if self._compiler == 'clang':
            self.register_args('ohos_build_compiler_dir',
                               self.config.clang_path)

    @property
    def test(self):
        return self._test

    @test.setter
    def test(self, test_args):
94
        cmd_list = ['xts', 'notest']
M
mamingshuai 已提交
95
        if test_args[0] in cmd_list:
96 97 98 99 100 101
            if test_args[0] == 'notest':
                self.register_args('ohos_test_args', 'notest')
            else:
                self._test = test_args[1]
                if len(test_args) > 1:
                    self.register_args('ohos_xts_test_args', self._test)
M
mamingshuai 已提交
102
        else:
G
gzyang 已提交
103
            raise OHOSException('Error: wrong input of test')
M
mamingshuai 已提交
104 105 106 107 108 109 110 111 112 113

    def register_args(self, args_name, args_value, quota=True):
        if quota:
            if isinstance(args_value, list):
                self._args_list += ['{}="{}"'.format(args_name,
                                                     "&&".join(args_value))]
            else:
                self._args_list += ['{}="{}"'.format(args_name, args_value)]
        else:
            self._args_list += ['{}={}'.format(args_name, args_value)]
G
gzyang 已提交
114 115
        if args_name == 'ohos_build_target' and len(args_value):
            self.config.fs_attr = None
M
mamingshuai 已提交
116

117 118
    def build(self, full_compile, patch=False, ninja=True, cmd_args=None):
        cmd_list = self.get_cmd(full_compile, patch, ninja)
M
mamingshuai 已提交
119

120 121 122
        # enable ccache if it installed.
        ccache_path = find_executable('ccache')
        if ccache_path is not None:
Y
yangming_ha 已提交
123
            self.register_args('ohos_build_enable_ccache', 'true',  quota=False)
124

M
mamingshuai 已提交
125 126 127 128 129
        if cmd_args is None:
            cmd_args = defaultdict(list)
        for exec_cmd in cmd_list:
            exec_cmd(cmd_args)

G
gzyang 已提交
130
        hb_info(f'{os.path.basename(self.config.out_path)} build success')
M
mamingshuai 已提交
131 132
        return 0

133
    def get_cmd(self, full_compile, patch, ninja):
M
mamingshuai 已提交
134 135 136 137
        if not ninja:
            self.register_args('ohos_full_compile', 'true', quota=False)
            return [self.gn_build]

G
gzyang 已提交
138 139
        cmd_list = []

M
mamingshuai 已提交
140 141 142 143
        build_ninja = os.path.join(self.config.out_path, 'build.ninja')
        if not os.path.isfile(build_ninja):
            self.register_args('ohos_full_compile', 'true', quota=False)
            makedirs(self.config.out_path)
G
gzyang 已提交
144 145
            cmd_list = [self.gn_build, self.ninja_build]
        elif full_compile:
M
mamingshuai 已提交
146 147 148
            self.register_args('ohos_full_compile', 'true', quota=False)
            remove_path(self.config.out_path)
            makedirs(self.config.out_path)
G
gzyang 已提交
149 150 151 152
            cmd_list = [self.gn_build, self.ninja_build]
        else:
            self.register_args('ohos_full_compile', 'false', quota=False)
            cmd_list = [self.ninja_build]
M
mamingshuai 已提交
153

154 155 156 157
        if patch:
            patch = Patch()
            cmd_list = [patch.patch_make] + cmd_list

G
gzyang 已提交
158 159 160 161 162
        if self.config.fs_attr is not None:
            packer = Packer()
            cmd_list.append(packer.fs_make)

        return cmd_list
M
mamingshuai 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175 176

    def gn_build(self, cmd_args):
        # Clean out path
        remove_path(self.config.out_path)
        makedirs(self.config.out_path)

        # Gn cmd init and execute
        gn_path = self.config.gn_path
        gn_args = cmd_args.get('gn', [])
        gn_cmd = [gn_path,
                  'gen',
                  self.config.out_path,
                  '--root={}'.format(self.config.root_path),
                  '--dotfile={}/.gn'.format(self.config.build_path),
P
pilipala195 已提交
177
                  f'--script-executable={sys.executable}',
M
mamingshuai 已提交
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
                  '--args={}'.format(" ".join(self._args_list))] + gn_args
        exec_command(gn_cmd, log_path=self.config.log_path)

    def gn_clean(self, out_path=None):
        # Gn cmd init and execute
        gn_path = self.config.gn_path

        if out_path is not None:
            self.config.out_path = os.path.abspath(out_path)
        else:
            self.config.out_path = os.path.join(self.config.root_path,
                                                'out',
                                                self.config.board,
                                                self.config.product)

        if not os.path.isdir(self.config.out_path):
            hb_warning('{} not found'.format(self.config.out_path))
            return

        gn_cmd = [gn_path,
                  '--root={}'.format(self.config.root_path),
                  '--dotfile={}/.gn'.format(self.config.build_path),
                  'clean',
                  self.config.out_path]
        exec_command(gn_cmd, log_path=self.config.log_path)

    def ninja_build(self, cmd_args):
        ninja_path = self.config.ninja_path

        ninja_args = cmd_args.get('ninja', [])
        ninja_cmd = [ninja_path,
                     '-w',
                     'dupbuild=warn',
                     '-C',
                     self.config.out_path] + ninja_args
        exec_command(ninja_cmd, log_path=self.config.log_path, log_filter=True)

    def check_in_device(self):
        if self._target is None and Device.is_in_device():
            # Compile device board
            device_path, kernel, board = Device.device_menuconfig()
G
gzyang 已提交
219 220 221 222 223 224 225 226
            hb_info(f'{device_path}')
            # build device, no need to set root manually,
            # so set it speculatively.
            self.config.root_path = os.path.abspath(os.path.join(device_path,
                                                                 os.pardir,
                                                                 os.pardir,
                                                                 os.pardir,
                                                                 os.pardir))
M
mamingshuai 已提交
227 228 229
            self.config.out_path = os.path.join(self.config.root_path,
                                                'out',
                                                board)
G
gzyang 已提交
230
            self.compiler = Device.get_compiler(device_path)
G
gzyang 已提交
231 232
            gn_device_path = os.path.dirname(device_path)
            gn_kernel_path = device_path
M
mamingshuai 已提交
233 234 235 236 237
            self.register_args('ohos_build_target', [gn_device_path])
            self.register_args('device_path', gn_kernel_path)
            self.register_args('ohos_kernel_type', kernel)
        else:
            # Compile product in "hb set"
G
gzyang 已提交
238
            self.compiler = Device.get_compiler(self.config.device_path)
G
gzyang 已提交
239 240
            self.register_args('product_path', self.config.product_path)
            self.register_args('device_path', self.config.device_path)
M
mamingshuai 已提交
241 242 243 244 245 246 247 248 249
            self.register_args('ohos_kernel_type', self.config.kernel)

            product_json = os.path.join(self.config.product_path,
                                        'config.json')
            self._args_list += Product.get_features(product_json)
            self.config.out_path = os.path.join(self.config.root_path,
                                                'out',
                                                self.config.board,
                                                self.config.product)