1#!/usr/bin/env python3
2#
3# Arm SCP/MCP Software
4# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
5#
6# SPDX-License-Identifier: BSD-3-Clause
7#
8
9from dataclasses import dataclass, field
10from typing import List, Tuple
11
12
13@dataclass(frozen=True, eq=True)
14class Parameter:
15    '''
16    Parameter with its special arguments if needed
17    '''
18    name: str
19    arguments: Tuple[str] = field(default_factory=tuple)
20
21
22@dataclass(frozen=True, eq=True)
23class Build:
24    '''
25    Specific build configuration
26    '''
27    name: str
28    toolchain: Parameter
29    build_type: Parameter
30    log_level: Parameter
31    variant: Parameter = None
32
33    def tag(self):
34        build_str = 'Product: {} - Toolchain: {} - Mode: {}'.format(
35                                                        self.name,
36                                                        self.toolchain.name,
37                                                        self.build_type.name)
38        if self.variant:
39            build_str += ' - Variant {}'.format(self.variant.name)
40        if self.log_level:
41            build_str += ' - Log Level {}'.format(self.log_level.name)
42        return build_str
43
44    def file_name(self):
45        filename = self.name + "_" + self.toolchain.name + "_" + \
46            self.build_type.name[0]
47        if self.log_level:
48            filename += "_" + self.log_level.name
49        if self.variant:
50            filename += "_" + self.variant.name[0]
51        filename += ".txt"
52        return filename
53
54    def command(self):
55        cmd = 'make -f Makefile.cmake '
56        cmd += 'PRODUCT={} TOOLCHAIN={} MODE={} '.format(self.name,
57                                                         self.toolchain.name,
58                                                         self.build_type.name)
59        if self.log_level:
60            cmd += 'LOG_LEVEL={} '.format(self.log_level.name)
61        if self.variant:
62            cmd += 'PLATFORM_VARIANT=\"{}\" '.format(self.variant.name)
63            for extra in self.variant.arguments:
64                cmd += Build.__extra_arg__(extra)
65        for extra in self.toolchain.arguments:
66            cmd += Build.__extra_arg__(extra)
67        for extra in self.build_type.arguments:
68            cmd += Build.__extra_arg__(extra)
69        return cmd
70
71    @classmethod
72    def __extra_arg__(cls, parameter: str) -> str:
73        return 'EXTRA_CONFIG_ARGS+={} '.format(parameter)
74
75
76@dataclass
77class Product:
78    '''
79    This class defines platform build parameters to simplify configuration
80    for testing. It also generates build commands.
81    '''
82    name: str
83    toolchains: List[Parameter] = field(default_factory=lambda: [
84        Parameter('GNU'),
85        Parameter('ArmClang'),
86        Parameter('Clang', ('-DSCP_LLVM_SYSROOT_CC=arm-none-eabi-gcc',)),
87        ])
88    build_types: List[Parameter] = field(default_factory=lambda: [
89        Parameter('debug'),
90        Parameter('release'),
91        ])
92    variants: List[Parameter] = field(default_factory=lambda: [None])
93    log_level: Parameter = None
94
95    @property
96    def builds(self) -> List[Build]:
97        builds = []
98        for toolchain in self.toolchains:
99            for build_type in self.build_types:
100                for variant in self.variants:
101                    builds.append(Build(
102                        self.name,
103                        toolchain,
104                        build_type,
105                        self.log_level,
106                        variant))
107        return builds
108