blob: 56d21293e09e2f7fd461c6ba6ec0484cb7e0c1a4 [file] [log] [blame]
Tiancong Wangaf050172019-07-10 11:52:03 -07001# -*- coding: utf-8 -*-
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Toolchain-related operations."""
7
8from __future__ import print_function
9
LaMont Jonesb20b3d92019-11-23 11:47:48 -070010import collections
Mike Frysingeref94e4c2020-02-10 23:59:54 -050011import sys
LaMont Jonesb20b3d92019-11-23 11:47:48 -070012
LaMont Jones5d2edcb2019-12-23 11:32:03 -070013from chromite.api import controller
Alex Klein076841b2019-08-29 15:19:39 -060014from chromite.api import faux
Alex Klein231d2da2019-07-22 16:44:45 -060015from chromite.api import validate
LaMont Jones5d2edcb2019-12-23 11:32:03 -070016from chromite.api.controller import controller_util
Tiancong Wang24a3df72019-08-20 15:48:51 -070017from chromite.api.gen.chromite.api import toolchain_pb2
LaMont Jonesb20b3d92019-11-23 11:47:48 -070018from chromite.api.gen.chromiumos.builder_config_pb2 import BuilderConfig
LaMont Jones5d2edcb2019-12-23 11:32:03 -070019from chromite.lib import cros_logging as logging
20from chromite.lib import toolchain_util
Tiancong Wangaf050172019-07-10 11:52:03 -070021
Mike Frysingeref94e4c2020-02-10 23:59:54 -050022
23assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
24
25
LaMont Jonesb20b3d92019-11-23 11:47:48 -070026# TODO(crbug/1019868): Add handlers as needed.
27_Handlers = collections.namedtuple('_Handlers', ['name', 'prepare', 'bundle'])
28_TOOLCHAIN_ARTIFACT_HANDLERS = {
29 BuilderConfig.Artifacts.UNVERIFIED_ORDERING_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070030 _Handlers('UnverifiedOrderingFile',
31 toolchain_util.PrepareForBuild,
32 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070033 BuilderConfig.Artifacts.VERIFIED_ORDERING_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070034 _Handlers('VerifiedOrderingFile',
35 toolchain_util.PrepareForBuild,
36 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070037 BuilderConfig.Artifacts.CHROME_CLANG_WARNINGS_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070038 _Handlers('ChromeClangWarningsFile',
LaMont Jones90bab632020-01-27 15:58:26 -070039 toolchain_util.PrepareForBuild,
40 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070041 BuilderConfig.Artifacts.UNVERIFIED_LLVM_PGO_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070042 _Handlers('UnverifiedLlvmPgoFile',
LaMont Jones90bab632020-01-27 15:58:26 -070043 toolchain_util.PrepareForBuild,
44 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070045 BuilderConfig.Artifacts.UNVERIFIED_CHROME_AFDO_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070046 _Handlers('UnverifiedChromeAfdoFile',
LaMont Jones90bab632020-01-27 15:58:26 -070047 toolchain_util.PrepareForBuild,
48 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070049 BuilderConfig.Artifacts.VERIFIED_CHROME_AFDO_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070050 _Handlers('VerifiedChromeAfdoFile',
LaMont Jones90bab632020-01-27 15:58:26 -070051 toolchain_util.PrepareForBuild,
52 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070053 BuilderConfig.Artifacts.VERIFIED_KERNEL_AFDO_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070054 _Handlers('VerifiedKernelAfdoFile',
LaMont Jones90bab632020-01-27 15:58:26 -070055 toolchain_util.PrepareForBuild,
56 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070057}
58
59
60# TODO(crbug/1031213): When @faux is expanded to have more than success/failure,
61# this should be changed.
62@faux.all_empty
LaMont Jones5d2edcb2019-12-23 11:32:03 -070063@validate.require('artifact_types')
64# Note: chroot and sysroot are unspecified the first time that the build_target
65# recipe calls PrepareForBuild. The second time, they are specified. No
66# validation check because "all" values are valid.
LaMont Jonesb20b3d92019-11-23 11:47:48 -070067@validate.validation_complete
68def PrepareForBuild(input_proto, output_proto, _config):
69 """Prepare to build toolchain artifacts.
70
71 The handlers (from _TOOLCHAIN_ARTIFACT_HANDLERS above) are called with:
72 artifact_name (str): name of the artifact type.
LaMont Jones5d2edcb2019-12-23 11:32:03 -070073 chroot (chroot_lib.Chroot): chroot. Will be None if the chroot has not
74 yet been created.
75 sysroot_path (str): sysroot path inside the chroot (e.g., /build/atlas).
76 Will be an empty string if the sysroot has not yet been created.
77 build_target_name (str): name of the build target (e.g., atlas). Will be
78 an empty string if the sysroot has not yet been created.
79 input_artifacts ({(str) name:[str gs_locations]}): locations for possible
80 input artifacts. The handler is expected to know which keys it should
81 be using, and ignore any keys that it does not understand.
LaMont Jonesa215f1e2019-12-06 10:18:58 -070082
83 They locate and modify any ebuilds and/or source required for the artifact
84 being created, then return a value from toolchain_util.PrepareForBuildReturn.
LaMont Jonesb20b3d92019-11-23 11:47:48 -070085
LaMont Jones5d2edcb2019-12-23 11:32:03 -070086 This function sets output_proto.build_relevance to the result.
87
LaMont Jonesb20b3d92019-11-23 11:47:48 -070088 Args:
89 input_proto (PrepareForToolchainBuildRequest): The input proto
90 output_proto (PrepareForToolchainBuildResponse): The output proto
91 _config (api_config.ApiConfig): The API call config.
92 """
LaMont Jones5d2edcb2019-12-23 11:32:03 -070093 if input_proto.chroot.path:
94 chroot = controller_util.ParseChroot(input_proto.chroot)
95 else:
96 chroot = None
LaMont Jones4579e8c2019-12-06 14:20:37 -070097
LaMont Jones5d2edcb2019-12-23 11:32:03 -070098 input_artifacts = collections.defaultdict(list)
99 for art in input_proto.input_artifacts:
100 item = _TOOLCHAIN_ARTIFACT_HANDLERS.get(art.input_artifact_type)
101 if item:
102 input_artifacts[item.name].extend(
103 ['gs://%s' % str(x) for x in art.input_artifact_gs_locations])
104
105 results = set()
106 sysroot_path = input_proto.sysroot.path
107 build_target = input_proto.sysroot.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700108 for artifact_type in input_proto.artifact_types:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700109 # Unknown artifact_types are an error.
110 handler = _TOOLCHAIN_ARTIFACT_HANDLERS[artifact_type]
111 if handler.prepare:
LaMont Jonesa215f1e2019-12-06 10:18:58 -0700112 results.add(handler.prepare(
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700113 handler.name, chroot, sysroot_path, build_target, input_artifacts))
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700114
115 # Translate the returns from the handlers we called.
116 # If any NEEDED => NEEDED
117 # elif any UNKNOWN => UNKNOWN
118 # elif any POINTLESS => POINTLESS
119 # else UNKNOWN.
120 proto_resp = toolchain_pb2.PrepareForToolchainBuildResponse
121 if toolchain_util.PrepareForBuildReturn.NEEDED in results:
122 output_proto.build_relevance = proto_resp.NEEDED
123 elif toolchain_util.PrepareForBuildReturn.UNKNOWN in results:
124 output_proto.build_relevance = proto_resp.UNKNOWN
125 elif toolchain_util.PrepareForBuildReturn.POINTLESS in results:
126 output_proto.build_relevance = proto_resp.POINTLESS
127 else:
128 output_proto.build_relevance = proto_resp.UNKNOWN
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700129 return controller.RETURN_CODE_SUCCESS
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700130
131
132# TODO(crbug/1031213): When @faux is expanded to have more than success/failure,
133# this should be changed.
134@faux.all_empty
LaMont Jones4579e8c2019-12-06 14:20:37 -0700135@validate.require('chroot.path', 'sysroot.path', 'sysroot.build_target.name',
136 'output_dir', 'artifact_types')
137@validate.exists('output_dir')
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700138@validate.validation_complete
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700139def BundleArtifacts(input_proto, output_proto, _config):
140 """Bundle toolchain artifacts.
141
142 The handlers (from _TOOLCHAIN_ARTIFACT_HANDLERS above) are called with:
LaMont Jonesa215f1e2019-12-06 10:18:58 -0700143 artifact_name (str): name of the artifact type
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700144 chroot (chroot_lib.Chroot): chroot
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700145 sysroot_path (str): sysroot path inside the chroot (e.g., /build/atlas)
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700146 chrome_root (str): path to chrome root. (e.g., /b/s/w/ir/k/chrome)
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700147 build_target_name (str): name of the build target (e.g., atlas)
148 output_dir (str): absolute path where artifacts are being bundled.
149 (e.g., /b/s/w/ir/k/recipe_cleanup/artifactssptfMU)
150
151 Note: the actual upload to GS is done by CI, not here.
152
153 Args:
154 input_proto (BundleToolchainRequest): The input proto
155 output_proto (BundleToolchainResponse): The output proto
156 _config (api_config.ApiConfig): The API call config.
157 """
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700158 chroot = controller_util.ParseChroot(input_proto.chroot)
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700159
160 for artifact_type in input_proto.artifact_types:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700161 if artifact_type not in _TOOLCHAIN_ARTIFACT_HANDLERS:
162 logging.error('%s not understood', artifact_type)
163 return controller.RETURN_CODE_UNRECOVERABLE
164 handler = _TOOLCHAIN_ARTIFACT_HANDLERS[artifact_type]
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700165 if handler and handler.bundle:
166 artifacts = handler.bundle(
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700167 handler.name, chroot, input_proto.sysroot.path,
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700168 input_proto.sysroot.build_target.name, input_proto.output_dir)
169 if artifacts:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700170 art_info = output_proto.artifacts_info.add()
171 art_info.artifact_type = artifact_type
172 for artifact in artifacts:
173 art_info.artifacts.add().path = artifact
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700174
175
176# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
177_NAMES_FOR_AFDO_ARTIFACTS = {
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700178 toolchain_pb2.ORDERFILE: 'orderfile',
179 toolchain_pb2.KERNEL_AFDO: 'kernel_afdo',
180 toolchain_pb2.CHROME_AFDO: 'chrome_afdo'
181}
182
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700183# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700184# Using a function instead of a dict because we need to mock these
185# functions in unittest, and mock doesn't play well with a dict definition.
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700186def _GetMethodForUpdatingAFDOArtifacts(artifact_type):
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700187 return {
188 toolchain_pb2.ORDERFILE: toolchain_util.OrderfileUpdateChromeEbuild,
189 toolchain_pb2.KERNEL_AFDO: toolchain_util.AFDOUpdateKernelEbuild,
190 toolchain_pb2.CHROME_AFDO: toolchain_util.AFDOUpdateChromeEbuild
191 }[artifact_type]
Tiancong Wang24a3df72019-08-20 15:48:51 -0700192
Tiancong Wangaf050172019-07-10 11:52:03 -0700193
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700194# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700195def _UpdateEbuildWithAFDOArtifactsResponse(_input_proto, output_proto, _config):
196 """Add successful status to the faux response."""
197 output_proto.status = True
198
199
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700200# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700201@faux.success(_UpdateEbuildWithAFDOArtifactsResponse)
202@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600203@validate.require('build_target.name')
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700204@validate.is_in('artifact_type', _NAMES_FOR_AFDO_ARTIFACTS)
Alex Klein231d2da2019-07-22 16:44:45 -0600205@validate.validation_complete
Tiancong Wang24a3df72019-08-20 15:48:51 -0700206def UpdateEbuildWithAFDOArtifacts(input_proto, output_proto, _config):
207 """Update Chrome or kernel ebuild with most recent unvetted artifacts.
Tiancong Wangaf050172019-07-10 11:52:03 -0700208
209 Args:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700210 input_proto (VerifyAFDOArtifactsRequest): The input proto
211 output_proto (VerifyAFDOArtifactsResponse): The output proto
Alex Klein231d2da2019-07-22 16:44:45 -0600212 _config (api_config.ApiConfig): The API call config.
Tiancong Wangaf050172019-07-10 11:52:03 -0700213 """
Tiancong Wangaf050172019-07-10 11:52:03 -0700214 board = input_proto.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700215 update_method = _GetMethodForUpdatingAFDOArtifacts(input_proto.artifact_type)
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700216 output_proto.status = update_method(board)
Tiancong Wangaf050172019-07-10 11:52:03 -0700217
218
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700219# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700220def _UploadVettedAFDOArtifactsResponse(_input_proto, output_proto, _config):
221 """Add successful status to the faux response."""
222 output_proto.status = True
223
224
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700225# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700226@faux.success(_UploadVettedAFDOArtifactsResponse)
227@faux.empty_error
Tiancong Wang24a3df72019-08-20 15:48:51 -0700228@validate.require('build_target.name')
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700229@validate.is_in('artifact_type', _NAMES_FOR_AFDO_ARTIFACTS)
Alex Klein231d2da2019-07-22 16:44:45 -0600230@validate.validation_complete
Tiancong Wang24a3df72019-08-20 15:48:51 -0700231def UploadVettedAFDOArtifacts(input_proto, output_proto, _config):
Tiancong Wangaf050172019-07-10 11:52:03 -0700232 """Upload a vetted orderfile to GS bucket.
233
234 Args:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700235 input_proto (VerifyAFDOArtifactsRequest): The input proto
236 output_proto (VerifyAFDOArtifactsResponse): The output proto
Alex Klein231d2da2019-07-22 16:44:45 -0600237 _config (api_config.ApiConfig): The API call config.
Tiancong Wangaf050172019-07-10 11:52:03 -0700238 """
Tiancong Wang24a3df72019-08-20 15:48:51 -0700239 board = input_proto.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700240 artifact_type = _NAMES_FOR_AFDO_ARTIFACTS[input_proto.artifact_type]
Tiancong Wang24a3df72019-08-20 15:48:51 -0700241 output_proto.status = toolchain_util.UploadAndPublishVettedAFDOArtifacts(
242 artifact_type, board)