xref: /OK3568_Linux_fs/u-boot/tools/buildman/board.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun# Copyright (c) 2012 The Chromium OS Authors.
2*4882a593Smuzhiyun#
3*4882a593Smuzhiyun# SPDX-License-Identifier:	GPL-2.0+
4*4882a593Smuzhiyun#
5*4882a593Smuzhiyun
6*4882a593Smuzhiyunimport re
7*4882a593Smuzhiyun
8*4882a593Smuzhiyunclass Expr:
9*4882a593Smuzhiyun    """A single regular expression for matching boards to build"""
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun    def __init__(self, expr):
12*4882a593Smuzhiyun        """Set up a new Expr object.
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun        Args:
15*4882a593Smuzhiyun            expr: String cotaining regular expression to store
16*4882a593Smuzhiyun        """
17*4882a593Smuzhiyun        self._expr = expr
18*4882a593Smuzhiyun        self._re = re.compile(expr)
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun    def Matches(self, props):
21*4882a593Smuzhiyun        """Check if any of the properties match the regular expression.
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun        Args:
24*4882a593Smuzhiyun           props: List of properties to check
25*4882a593Smuzhiyun        Returns:
26*4882a593Smuzhiyun           True if any of the properties match the regular expression
27*4882a593Smuzhiyun        """
28*4882a593Smuzhiyun        for prop in props:
29*4882a593Smuzhiyun            if self._re.match(prop):
30*4882a593Smuzhiyun                return True
31*4882a593Smuzhiyun        return False
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun    def __str__(self):
34*4882a593Smuzhiyun        return self._expr
35*4882a593Smuzhiyun
36*4882a593Smuzhiyunclass Term:
37*4882a593Smuzhiyun    """A list of expressions each of which must match with properties.
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun    This provides a list of 'AND' expressions, meaning that each must
40*4882a593Smuzhiyun    match the board properties for that board to be built.
41*4882a593Smuzhiyun    """
42*4882a593Smuzhiyun    def __init__(self):
43*4882a593Smuzhiyun        self._expr_list = []
44*4882a593Smuzhiyun        self._board_count = 0
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun    def AddExpr(self, expr):
47*4882a593Smuzhiyun        """Add an Expr object to the list to check.
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun        Args:
50*4882a593Smuzhiyun            expr: New Expr object to add to the list of those that must
51*4882a593Smuzhiyun                  match for a board to be built.
52*4882a593Smuzhiyun        """
53*4882a593Smuzhiyun        self._expr_list.append(Expr(expr))
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun    def __str__(self):
56*4882a593Smuzhiyun        """Return some sort of useful string describing the term"""
57*4882a593Smuzhiyun        return '&'.join([str(expr) for expr in self._expr_list])
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun    def Matches(self, props):
60*4882a593Smuzhiyun        """Check if any of the properties match this term
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun        Each of the expressions in the term is checked. All must match.
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun        Args:
65*4882a593Smuzhiyun           props: List of properties to check
66*4882a593Smuzhiyun        Returns:
67*4882a593Smuzhiyun           True if all of the expressions in the Term match, else False
68*4882a593Smuzhiyun        """
69*4882a593Smuzhiyun        for expr in self._expr_list:
70*4882a593Smuzhiyun            if not expr.Matches(props):
71*4882a593Smuzhiyun                return False
72*4882a593Smuzhiyun        return True
73*4882a593Smuzhiyun
74*4882a593Smuzhiyunclass Board:
75*4882a593Smuzhiyun    """A particular board that we can build"""
76*4882a593Smuzhiyun    def __init__(self, status, arch, cpu, soc, vendor, board_name, target, options):
77*4882a593Smuzhiyun        """Create a new board type.
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun        Args:
80*4882a593Smuzhiyun            status: define whether the board is 'Active' or 'Orphaned'
81*4882a593Smuzhiyun            arch: Architecture name (e.g. arm)
82*4882a593Smuzhiyun            cpu: Cpu name (e.g. arm1136)
83*4882a593Smuzhiyun            soc: Name of SOC, or '' if none (e.g. mx31)
84*4882a593Smuzhiyun            vendor: Name of vendor (e.g. armltd)
85*4882a593Smuzhiyun            board_name: Name of board (e.g. integrator)
86*4882a593Smuzhiyun            target: Target name (use make <target>_defconfig to configure)
87*4882a593Smuzhiyun            options: board-specific options (e.g. integratorcp:CM1136)
88*4882a593Smuzhiyun        """
89*4882a593Smuzhiyun        self.target = target
90*4882a593Smuzhiyun        self.arch = arch
91*4882a593Smuzhiyun        self.cpu = cpu
92*4882a593Smuzhiyun        self.board_name = board_name
93*4882a593Smuzhiyun        self.vendor = vendor
94*4882a593Smuzhiyun        self.soc = soc
95*4882a593Smuzhiyun        self.options = options
96*4882a593Smuzhiyun        self.props = [self.target, self.arch, self.cpu, self.board_name,
97*4882a593Smuzhiyun                      self.vendor, self.soc, self.options]
98*4882a593Smuzhiyun        self.build_it = False
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun
101*4882a593Smuzhiyunclass Boards:
102*4882a593Smuzhiyun    """Manage a list of boards."""
103*4882a593Smuzhiyun    def __init__(self):
104*4882a593Smuzhiyun        # Use a simple list here, sinc OrderedDict requires Python 2.7
105*4882a593Smuzhiyun        self._boards = []
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun    def AddBoard(self, board):
108*4882a593Smuzhiyun        """Add a new board to the list.
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun        The board's target member must not already exist in the board list.
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun        Args:
113*4882a593Smuzhiyun            board: board to add
114*4882a593Smuzhiyun        """
115*4882a593Smuzhiyun        self._boards.append(board)
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun    def ReadBoards(self, fname):
118*4882a593Smuzhiyun        """Read a list of boards from a board file.
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun        Create a board object for each and add it to our _boards list.
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun        Args:
123*4882a593Smuzhiyun            fname: Filename of boards.cfg file
124*4882a593Smuzhiyun        """
125*4882a593Smuzhiyun        with open(fname, 'r') as fd:
126*4882a593Smuzhiyun            for line in fd:
127*4882a593Smuzhiyun                if line[0] == '#':
128*4882a593Smuzhiyun                    continue
129*4882a593Smuzhiyun                fields = line.split()
130*4882a593Smuzhiyun                if not fields:
131*4882a593Smuzhiyun                    continue
132*4882a593Smuzhiyun                for upto in range(len(fields)):
133*4882a593Smuzhiyun                    if fields[upto] == '-':
134*4882a593Smuzhiyun                        fields[upto] = ''
135*4882a593Smuzhiyun                while len(fields) < 8:
136*4882a593Smuzhiyun                    fields.append('')
137*4882a593Smuzhiyun                if len(fields) > 8:
138*4882a593Smuzhiyun                    fields = fields[:8]
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun                board = Board(*fields)
141*4882a593Smuzhiyun                self.AddBoard(board)
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun    def GetList(self):
145*4882a593Smuzhiyun        """Return a list of available boards.
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun        Returns:
148*4882a593Smuzhiyun            List of Board objects
149*4882a593Smuzhiyun        """
150*4882a593Smuzhiyun        return self._boards
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun    def GetDict(self):
153*4882a593Smuzhiyun        """Build a dictionary containing all the boards.
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun        Returns:
156*4882a593Smuzhiyun            Dictionary:
157*4882a593Smuzhiyun                key is board.target
158*4882a593Smuzhiyun                value is board
159*4882a593Smuzhiyun        """
160*4882a593Smuzhiyun        board_dict = {}
161*4882a593Smuzhiyun        for board in self._boards:
162*4882a593Smuzhiyun            board_dict[board.target] = board
163*4882a593Smuzhiyun        return board_dict
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun    def GetSelectedDict(self):
166*4882a593Smuzhiyun        """Return a dictionary containing the selected boards
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun        Returns:
169*4882a593Smuzhiyun            List of Board objects that are marked selected
170*4882a593Smuzhiyun        """
171*4882a593Smuzhiyun        board_dict = {}
172*4882a593Smuzhiyun        for board in self._boards:
173*4882a593Smuzhiyun            if board.build_it:
174*4882a593Smuzhiyun                board_dict[board.target] = board
175*4882a593Smuzhiyun        return board_dict
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun    def GetSelected(self):
178*4882a593Smuzhiyun        """Return a list of selected boards
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun        Returns:
181*4882a593Smuzhiyun            List of Board objects that are marked selected
182*4882a593Smuzhiyun        """
183*4882a593Smuzhiyun        return [board for board in self._boards if board.build_it]
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun    def GetSelectedNames(self):
186*4882a593Smuzhiyun        """Return a list of selected boards
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun        Returns:
189*4882a593Smuzhiyun            List of board names that are marked selected
190*4882a593Smuzhiyun        """
191*4882a593Smuzhiyun        return [board.target for board in self._boards if board.build_it]
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun    def _BuildTerms(self, args):
194*4882a593Smuzhiyun        """Convert command line arguments to a list of terms.
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun        This deals with parsing of the arguments. It handles the '&'
197*4882a593Smuzhiyun        operator, which joins several expressions into a single Term.
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun        For example:
200*4882a593Smuzhiyun            ['arm & freescale sandbox', 'tegra']
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun        will produce 3 Terms containing expressions as follows:
203*4882a593Smuzhiyun            arm, freescale
204*4882a593Smuzhiyun            sandbox
205*4882a593Smuzhiyun            tegra
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun        The first Term has two expressions, both of which must match for
208*4882a593Smuzhiyun        a board to be selected.
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun        Args:
211*4882a593Smuzhiyun            args: List of command line arguments
212*4882a593Smuzhiyun        Returns:
213*4882a593Smuzhiyun            A list of Term objects
214*4882a593Smuzhiyun        """
215*4882a593Smuzhiyun        syms = []
216*4882a593Smuzhiyun        for arg in args:
217*4882a593Smuzhiyun            for word in arg.split():
218*4882a593Smuzhiyun                sym_build = []
219*4882a593Smuzhiyun                for term in word.split('&'):
220*4882a593Smuzhiyun                    if term:
221*4882a593Smuzhiyun                        sym_build.append(term)
222*4882a593Smuzhiyun                    sym_build.append('&')
223*4882a593Smuzhiyun                syms += sym_build[:-1]
224*4882a593Smuzhiyun        terms = []
225*4882a593Smuzhiyun        term = None
226*4882a593Smuzhiyun        oper = None
227*4882a593Smuzhiyun        for sym in syms:
228*4882a593Smuzhiyun            if sym == '&':
229*4882a593Smuzhiyun                oper = sym
230*4882a593Smuzhiyun            elif oper:
231*4882a593Smuzhiyun                term.AddExpr(sym)
232*4882a593Smuzhiyun                oper = None
233*4882a593Smuzhiyun            else:
234*4882a593Smuzhiyun                if term:
235*4882a593Smuzhiyun                    terms.append(term)
236*4882a593Smuzhiyun                term = Term()
237*4882a593Smuzhiyun                term.AddExpr(sym)
238*4882a593Smuzhiyun        if term:
239*4882a593Smuzhiyun            terms.append(term)
240*4882a593Smuzhiyun        return terms
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun    def SelectBoards(self, args, exclude=[]):
243*4882a593Smuzhiyun        """Mark boards selected based on args
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun        Args:
246*4882a593Smuzhiyun            args: List of strings specifying boards to include, either named,
247*4882a593Smuzhiyun                  or by their target, architecture, cpu, vendor or soc. If
248*4882a593Smuzhiyun                  empty, all boards are selected.
249*4882a593Smuzhiyun            exclude: List of boards to exclude, regardless of 'args'
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun        Returns:
252*4882a593Smuzhiyun            Dictionary which holds the list of boards which were selected
253*4882a593Smuzhiyun            due to each argument, arranged by argument.
254*4882a593Smuzhiyun        """
255*4882a593Smuzhiyun        result = {}
256*4882a593Smuzhiyun        terms = self._BuildTerms(args)
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun        result['all'] = []
259*4882a593Smuzhiyun        for term in terms:
260*4882a593Smuzhiyun            result[str(term)] = []
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun        exclude_list = []
263*4882a593Smuzhiyun        for expr in exclude:
264*4882a593Smuzhiyun            exclude_list.append(Expr(expr))
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun        for board in self._boards:
267*4882a593Smuzhiyun            matching_term = None
268*4882a593Smuzhiyun            build_it = False
269*4882a593Smuzhiyun            if terms:
270*4882a593Smuzhiyun                match = False
271*4882a593Smuzhiyun                for term in terms:
272*4882a593Smuzhiyun                    if term.Matches(board.props):
273*4882a593Smuzhiyun                        matching_term = str(term)
274*4882a593Smuzhiyun                        build_it = True
275*4882a593Smuzhiyun                        break
276*4882a593Smuzhiyun            else:
277*4882a593Smuzhiyun                build_it = True
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun            # Check that it is not specifically excluded
280*4882a593Smuzhiyun            for expr in exclude_list:
281*4882a593Smuzhiyun                if expr.Matches(board.props):
282*4882a593Smuzhiyun                    build_it = False
283*4882a593Smuzhiyun                    break
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun            if build_it:
286*4882a593Smuzhiyun                board.build_it = True
287*4882a593Smuzhiyun                if matching_term:
288*4882a593Smuzhiyun                    result[matching_term].append(board.target)
289*4882a593Smuzhiyun                result['all'].append(board.target)
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun        return result
292