~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/tools/buildman/control.py

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2013 The Chromium OS Authors.
 
2
#
 
3
# SPDX-License-Identifier:      GPL-2.0+
 
4
#
 
5
 
 
6
import multiprocessing
 
7
import os
 
8
import sys
 
9
 
 
10
import board
 
11
import bsettings
 
12
from builder import Builder
 
13
import gitutil
 
14
import patchstream
 
15
import terminal
 
16
import toolchain
 
17
 
 
18
def GetPlural(count):
 
19
    """Returns a plural 's' if count is not 1"""
 
20
    return 's' if count != 1 else ''
 
21
 
 
22
def GetActionSummary(is_summary, count, selected, options):
 
23
    """Return a string summarising the intended action.
 
24
 
 
25
    Returns:
 
26
        Summary string.
 
27
    """
 
28
    count = (count + options.step - 1) / options.step
 
29
    str = '%s %d commit%s for %d boards' % (
 
30
        'Summary of' if is_summary else 'Building', count, GetPlural(count),
 
31
        len(selected))
 
32
    str += ' (%d thread%s, %d job%s per thread)' % (options.threads,
 
33
            GetPlural(options.threads), options.jobs, GetPlural(options.jobs))
 
34
    return str
 
35
 
 
36
def ShowActions(series, why_selected, boards_selected, builder, options):
 
37
    """Display a list of actions that we would take, if not a dry run.
 
38
 
 
39
    Args:
 
40
        series: Series object
 
41
        why_selected: Dictionary where each key is a buildman argument
 
42
                provided by the user, and the value is the boards brought
 
43
                in by that argument. For example, 'arm' might bring in
 
44
                400 boards, so in this case the key would be 'arm' and
 
45
                the value would be a list of board names.
 
46
        boards_selected: Dict of selected boards, key is target name,
 
47
                value is Board object
 
48
        builder: The builder that will be used to build the commits
 
49
        options: Command line options object
 
50
    """
 
51
    col = terminal.Color()
 
52
    print 'Dry run, so not doing much. But I would do this:'
 
53
    print
 
54
    print GetActionSummary(False, len(series.commits), boards_selected,
 
55
            options)
 
56
    print 'Build directory: %s' % builder.base_dir
 
57
    for upto in range(0, len(series.commits), options.step):
 
58
        commit = series.commits[upto]
 
59
        print '   ', col.Color(col.YELLOW, commit.hash, bright=False),
 
60
        print commit.subject
 
61
    print
 
62
    for arg in why_selected:
 
63
        if arg != 'all':
 
64
            print arg, ': %d boards' % why_selected[arg]
 
65
    print ('Total boards to build for each commit: %d\n' %
 
66
            why_selected['all'])
 
67
 
 
68
def DoBuildman(options, args):
 
69
    """The main control code for buildman
 
70
 
 
71
    Args:
 
72
        options: Command line options object
 
73
        args: Command line arguments (list of strings)
 
74
    """
 
75
    gitutil.Setup()
 
76
 
 
77
    bsettings.Setup()
 
78
    options.git_dir = os.path.join(options.git, '.git')
 
79
 
 
80
    toolchains = toolchain.Toolchains()
 
81
    toolchains.Scan(options.list_tool_chains)
 
82
    if options.list_tool_chains:
 
83
        toolchains.List()
 
84
        print
 
85
        return
 
86
 
 
87
    # Work out how many commits to build. We want to build everything on the
 
88
    # branch. We also build the upstream commit as a control so we can see
 
89
    # problems introduced by the first commit on the branch.
 
90
    col = terminal.Color()
 
91
    count = options.count
 
92
    if count == -1:
 
93
        if not options.branch:
 
94
            str = 'Please use -b to specify a branch to build'
 
95
            print col.Color(col.RED, str)
 
96
            sys.exit(1)
 
97
        count = gitutil.CountCommitsInBranch(options.git_dir, options.branch)
 
98
        if count is None:
 
99
            str = "Branch '%s' not found or has no upstream" % options.branch
 
100
            print col.Color(col.RED, str)
 
101
            sys.exit(1)
 
102
        count += 1   # Build upstream commit also
 
103
 
 
104
    if not count:
 
105
        str = ("No commits found to process in branch '%s': "
 
106
               "set branch's upstream or use -c flag" % options.branch)
 
107
        print col.Color(col.RED, str)
 
108
        sys.exit(1)
 
109
 
 
110
    # Work out what subset of the boards we are building
 
111
    boards = board.Boards()
 
112
    boards.ReadBoards(os.path.join(options.git, 'boards.cfg'))
 
113
    why_selected = boards.SelectBoards(args)
 
114
    selected = boards.GetSelected()
 
115
    if not len(selected):
 
116
        print col.Color(col.RED, 'No matching boards found')
 
117
        sys.exit(1)
 
118
 
 
119
    # Read the metadata from the commits. First look at the upstream commit,
 
120
    # then the ones in the branch. We would like to do something like
 
121
    # upstream/master~..branch but that isn't possible if upstream/master is
 
122
    # a merge commit (it will list all the commits that form part of the
 
123
    # merge)
 
124
    range_expr = gitutil.GetRangeInBranch(options.git_dir, options.branch)
 
125
    upstream_commit = gitutil.GetUpstream(options.git_dir, options.branch)
 
126
    series = patchstream.GetMetaDataForList(upstream_commit, options.git_dir,
 
127
            1)
 
128
    # Conflicting tags are not a problem for buildman, since it does not use
 
129
    # them. For example, Series-version is not useful for buildman. On the
 
130
    # other hand conflicting tags will cause an error. So allow later tags
 
131
    # to overwrite earlier ones.
 
132
    series.allow_overwrite = True
 
133
    series = patchstream.GetMetaDataForList(range_expr, options.git_dir, None,
 
134
            series)
 
135
 
 
136
    # By default we have one thread per CPU. But if there are not enough jobs
 
137
    # we can have fewer threads and use a high '-j' value for make.
 
138
    if not options.threads:
 
139
        options.threads = min(multiprocessing.cpu_count(), len(selected))
 
140
    if not options.jobs:
 
141
        options.jobs = max(1, (multiprocessing.cpu_count() +
 
142
                len(selected) - 1) / len(selected))
 
143
 
 
144
    if not options.step:
 
145
        options.step = len(series.commits) - 1
 
146
 
 
147
    # Create a new builder with the selected options
 
148
    output_dir = os.path.join(options.output_dir, options.branch)
 
149
    builder = Builder(toolchains, output_dir, options.git_dir,
 
150
            options.threads, options.jobs, checkout=True,
 
151
            show_unknown=options.show_unknown, step=options.step)
 
152
    builder.force_config_on_failure = not options.quick
 
153
 
 
154
    # For a dry run, just show our actions as a sanity check
 
155
    if options.dry_run:
 
156
        ShowActions(series, why_selected, selected, builder, options)
 
157
    else:
 
158
        builder.force_build = options.force_build
 
159
 
 
160
        # Work out which boards to build
 
161
        board_selected = boards.GetSelectedDict()
 
162
 
 
163
        print GetActionSummary(options.summary, count, board_selected, options)
 
164
 
 
165
        if options.summary:
 
166
            # We can't show function sizes without board details at present
 
167
            if options.show_bloat:
 
168
                options.show_detail = True
 
169
            builder.ShowSummary(series.commits, board_selected,
 
170
                    options.show_errors, options.show_sizes,
 
171
                    options.show_detail, options.show_bloat)
 
172
        else:
 
173
            builder.BuildBoards(series.commits, board_selected,
 
174
                    options.show_errors, options.keep_outputs)