blob: 73e09738e032bba303fd20610fc6b11637502152 [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_Handlers = collections.namedtuple('_Handlers', ['name', 'prepare', 'bundle'])
27_TOOLCHAIN_ARTIFACT_HANDLERS = {
LaMont Jonescd1503d2020-03-04 09:09:59 -070028 BuilderConfig.Artifacts.UNVERIFIED_CHROME_LLVM_ORDERFILE:
LaMont Jonesd3944582020-03-04 10:37:05 -070029 _Handlers('UnverifiedChromeLlvmOrderfile',
LaMont Jones5d2edcb2019-12-23 11:32:03 -070030 toolchain_util.PrepareForBuild,
31 toolchain_util.BundleArtifacts),
LaMont Jonescd1503d2020-03-04 09:09:59 -070032 BuilderConfig.Artifacts.VERIFIED_CHROME_LLVM_ORDERFILE:
LaMont Jonesd3944582020-03-04 10:37:05 -070033 _Handlers('VerifiedChromeLlvmOrderfile',
LaMont Jones5d2edcb2019-12-23 11:32:03 -070034 toolchain_util.PrepareForBuild,
35 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070036 BuilderConfig.Artifacts.CHROME_CLANG_WARNINGS_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070037 _Handlers('ChromeClangWarningsFile',
LaMont Jones90bab632020-01-27 15:58:26 -070038 toolchain_util.PrepareForBuild,
39 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070040 BuilderConfig.Artifacts.UNVERIFIED_LLVM_PGO_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070041 _Handlers('UnverifiedLlvmPgoFile',
LaMont Jones90bab632020-01-27 15:58:26 -070042 toolchain_util.PrepareForBuild,
43 toolchain_util.BundleArtifacts),
LaMont Jones45ca6c42020-02-05 09:39:09 -070044 BuilderConfig.Artifacts.UNVERIFIED_CHROME_BENCHMARK_AFDO_FILE:
45 _Handlers('UnverifiedChromeBenchmarkAfdoFile',
LaMont Jones90bab632020-01-27 15:58:26 -070046 toolchain_util.PrepareForBuild,
47 toolchain_util.BundleArtifacts),
LaMont Jones45ca6c42020-02-05 09:39:09 -070048 BuilderConfig.Artifacts.VERIFIED_CHROME_BENCHMARK_AFDO_FILE:
49 _Handlers('VerifiedChromeBenchmarkAfdoFile',
LaMont Jones90bab632020-01-27 15:58:26 -070050 toolchain_util.PrepareForBuild,
51 toolchain_util.BundleArtifacts),
LaMont Jones45ca6c42020-02-05 09:39:09 -070052 BuilderConfig.Artifacts.UNVERIFIED_KERNEL_CWP_AFDO_FILE:
53 _Handlers('UnverifiedKernelCwpAfdoFile',
54 toolchain_util.PrepareForBuild,
55 toolchain_util.BundleArtifacts),
56 BuilderConfig.Artifacts.VERIFIED_KERNEL_CWP_AFDO_FILE:
57 _Handlers('VerifiedKernelCwpAfdoFile',
58 toolchain_util.PrepareForBuild,
59 toolchain_util.BundleArtifacts),
60 BuilderConfig.Artifacts.UNVERIFIED_CHROME_CWP_AFDO_FILE:
61 _Handlers('UnverifiedChromeCwpAfdoFile',
62 toolchain_util.PrepareForBuild,
63 toolchain_util.BundleArtifacts),
64 BuilderConfig.Artifacts.VERIFIED_CHROME_CWP_AFDO_FILE:
65 _Handlers('VerifiedChromeCwpAfdoFile',
66 toolchain_util.PrepareForBuild,
67 toolchain_util.BundleArtifacts),
68 BuilderConfig.Artifacts.VERIFIED_RELEASE_AFDO_FILE:
69 _Handlers('VerifiedReleaseAfdoFile',
LaMont Jones90bab632020-01-27 15:58:26 -070070 toolchain_util.PrepareForBuild,
71 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070072}
73
74
75# TODO(crbug/1031213): When @faux is expanded to have more than success/failure,
76# this should be changed.
77@faux.all_empty
LaMont Jones5d2edcb2019-12-23 11:32:03 -070078@validate.require('artifact_types')
79# Note: chroot and sysroot are unspecified the first time that the build_target
80# recipe calls PrepareForBuild. The second time, they are specified. No
81# validation check because "all" values are valid.
LaMont Jonesb20b3d92019-11-23 11:47:48 -070082@validate.validation_complete
83def PrepareForBuild(input_proto, output_proto, _config):
84 """Prepare to build toolchain artifacts.
85
86 The handlers (from _TOOLCHAIN_ARTIFACT_HANDLERS above) are called with:
87 artifact_name (str): name of the artifact type.
LaMont Jones5d2edcb2019-12-23 11:32:03 -070088 chroot (chroot_lib.Chroot): chroot. Will be None if the chroot has not
89 yet been created.
90 sysroot_path (str): sysroot path inside the chroot (e.g., /build/atlas).
91 Will be an empty string if the sysroot has not yet been created.
92 build_target_name (str): name of the build target (e.g., atlas). Will be
93 an empty string if the sysroot has not yet been created.
94 input_artifacts ({(str) name:[str gs_locations]}): locations for possible
95 input artifacts. The handler is expected to know which keys it should
96 be using, and ignore any keys that it does not understand.
LaMont Jones45ca6c42020-02-05 09:39:09 -070097 additional_args ({(str) name: (str) value}) Dictionary of additional
98 arguments.
LaMont Jonesa215f1e2019-12-06 10:18:58 -070099
100 They locate and modify any ebuilds and/or source required for the artifact
101 being created, then return a value from toolchain_util.PrepareForBuildReturn.
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700102
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700103 This function sets output_proto.build_relevance to the result.
104
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700105 Args:
106 input_proto (PrepareForToolchainBuildRequest): The input proto
107 output_proto (PrepareForToolchainBuildResponse): The output proto
108 _config (api_config.ApiConfig): The API call config.
109 """
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700110 if input_proto.chroot.path:
111 chroot = controller_util.ParseChroot(input_proto.chroot)
112 else:
113 chroot = None
LaMont Jones4579e8c2019-12-06 14:20:37 -0700114
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700115 input_artifacts = collections.defaultdict(list)
116 for art in input_proto.input_artifacts:
117 item = _TOOLCHAIN_ARTIFACT_HANDLERS.get(art.input_artifact_type)
118 if item:
119 input_artifacts[item.name].extend(
120 ['gs://%s' % str(x) for x in art.input_artifact_gs_locations])
121
LaMont Jones45ca6c42020-02-05 09:39:09 -0700122 # Pass along any additional args.
123 additional_args = {}
124 which = input_proto.additional_args.WhichOneof('prepare_for_build_args')
125 if which:
126 # All of the additional arguments we understand are strings, so we can
127 # copy whichever argument we got without processing it.
128 additional_args[which] = getattr(input_proto.additional_args, which)
129
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700130 results = set()
131 sysroot_path = input_proto.sysroot.path
132 build_target = input_proto.sysroot.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700133 for artifact_type in input_proto.artifact_types:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700134 # Unknown artifact_types are an error.
135 handler = _TOOLCHAIN_ARTIFACT_HANDLERS[artifact_type]
136 if handler.prepare:
LaMont Jonesa215f1e2019-12-06 10:18:58 -0700137 results.add(handler.prepare(
LaMont Jones45ca6c42020-02-05 09:39:09 -0700138 handler.name, chroot, sysroot_path, build_target, input_artifacts,
139 additional_args))
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700140
141 # Translate the returns from the handlers we called.
142 # If any NEEDED => NEEDED
143 # elif any UNKNOWN => UNKNOWN
144 # elif any POINTLESS => POINTLESS
145 # else UNKNOWN.
146 proto_resp = toolchain_pb2.PrepareForToolchainBuildResponse
147 if toolchain_util.PrepareForBuildReturn.NEEDED in results:
148 output_proto.build_relevance = proto_resp.NEEDED
149 elif toolchain_util.PrepareForBuildReturn.UNKNOWN in results:
150 output_proto.build_relevance = proto_resp.UNKNOWN
151 elif toolchain_util.PrepareForBuildReturn.POINTLESS in results:
152 output_proto.build_relevance = proto_resp.POINTLESS
153 else:
154 output_proto.build_relevance = proto_resp.UNKNOWN
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700155 return controller.RETURN_CODE_SUCCESS
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700156
157
158# TODO(crbug/1031213): When @faux is expanded to have more than success/failure,
159# this should be changed.
160@faux.all_empty
LaMont Jones4579e8c2019-12-06 14:20:37 -0700161@validate.require('chroot.path', 'sysroot.path', 'sysroot.build_target.name',
162 'output_dir', 'artifact_types')
163@validate.exists('output_dir')
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700164@validate.validation_complete
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700165def BundleArtifacts(input_proto, output_proto, _config):
166 """Bundle toolchain artifacts.
167
168 The handlers (from _TOOLCHAIN_ARTIFACT_HANDLERS above) are called with:
LaMont Jonesa215f1e2019-12-06 10:18:58 -0700169 artifact_name (str): name of the artifact type
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700170 chroot (chroot_lib.Chroot): chroot
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700171 sysroot_path (str): sysroot path inside the chroot (e.g., /build/atlas)
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700172 chrome_root (str): path to chrome root. (e.g., /b/s/w/ir/k/chrome)
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700173 build_target_name (str): name of the build target (e.g., atlas)
174 output_dir (str): absolute path where artifacts are being bundled.
175 (e.g., /b/s/w/ir/k/recipe_cleanup/artifactssptfMU)
176
177 Note: the actual upload to GS is done by CI, not here.
178
179 Args:
180 input_proto (BundleToolchainRequest): The input proto
181 output_proto (BundleToolchainResponse): The output proto
182 _config (api_config.ApiConfig): The API call config.
183 """
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700184 chroot = controller_util.ParseChroot(input_proto.chroot)
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700185
LaMont Jones45ca6c42020-02-05 09:39:09 -0700186 # Pass along any additional args.
187 additional_args = {}
188 which = input_proto.additional_args.WhichOneof('prepare_for_build_args')
189 if which:
190 # All of the additional arguments we understand are strings, so we can
191 # copy whichever argument we got without processing it.
192 additional_args[which] = getattr(input_proto.additional_args, which)
193
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700194 for artifact_type in input_proto.artifact_types:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700195 if artifact_type not in _TOOLCHAIN_ARTIFACT_HANDLERS:
196 logging.error('%s not understood', artifact_type)
197 return controller.RETURN_CODE_UNRECOVERABLE
198 handler = _TOOLCHAIN_ARTIFACT_HANDLERS[artifact_type]
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700199 if handler and handler.bundle:
200 artifacts = handler.bundle(
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700201 handler.name, chroot, input_proto.sysroot.path,
LaMont Jones45ca6c42020-02-05 09:39:09 -0700202 input_proto.sysroot.build_target.name, input_proto.output_dir,
203 additional_args)
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700204 if artifacts:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700205 art_info = output_proto.artifacts_info.add()
206 art_info.artifact_type = artifact_type
207 for artifact in artifacts:
208 art_info.artifacts.add().path = artifact
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700209
210
211# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
212_NAMES_FOR_AFDO_ARTIFACTS = {
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700213 toolchain_pb2.ORDERFILE: 'orderfile',
214 toolchain_pb2.KERNEL_AFDO: 'kernel_afdo',
215 toolchain_pb2.CHROME_AFDO: 'chrome_afdo'
216}
217
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700218# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700219# Using a function instead of a dict because we need to mock these
220# functions in unittest, and mock doesn't play well with a dict definition.
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700221def _GetMethodForUpdatingAFDOArtifacts(artifact_type):
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700222 return {
223 toolchain_pb2.ORDERFILE: toolchain_util.OrderfileUpdateChromeEbuild,
224 toolchain_pb2.KERNEL_AFDO: toolchain_util.AFDOUpdateKernelEbuild,
225 toolchain_pb2.CHROME_AFDO: toolchain_util.AFDOUpdateChromeEbuild
226 }[artifact_type]
Tiancong Wang24a3df72019-08-20 15:48:51 -0700227
Tiancong Wangaf050172019-07-10 11:52:03 -0700228
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700229# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700230def _UpdateEbuildWithAFDOArtifactsResponse(_input_proto, output_proto, _config):
231 """Add successful status to the faux response."""
232 output_proto.status = True
233
234
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700235# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700236@faux.success(_UpdateEbuildWithAFDOArtifactsResponse)
237@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600238@validate.require('build_target.name')
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700239@validate.is_in('artifact_type', _NAMES_FOR_AFDO_ARTIFACTS)
Alex Klein231d2da2019-07-22 16:44:45 -0600240@validate.validation_complete
Tiancong Wang24a3df72019-08-20 15:48:51 -0700241def UpdateEbuildWithAFDOArtifacts(input_proto, output_proto, _config):
242 """Update Chrome or kernel ebuild with most recent unvetted artifacts.
Tiancong Wangaf050172019-07-10 11:52:03 -0700243
244 Args:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700245 input_proto (VerifyAFDOArtifactsRequest): The input proto
246 output_proto (VerifyAFDOArtifactsResponse): The output proto
Alex Klein231d2da2019-07-22 16:44:45 -0600247 _config (api_config.ApiConfig): The API call config.
Tiancong Wangaf050172019-07-10 11:52:03 -0700248 """
Tiancong Wangaf050172019-07-10 11:52:03 -0700249 board = input_proto.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700250 update_method = _GetMethodForUpdatingAFDOArtifacts(input_proto.artifact_type)
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700251 output_proto.status = update_method(board)
Tiancong Wangaf050172019-07-10 11:52:03 -0700252
253
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700254# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700255def _UploadVettedAFDOArtifactsResponse(_input_proto, output_proto, _config):
256 """Add successful status to the faux response."""
257 output_proto.status = True
258
259
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700260# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700261@faux.success(_UploadVettedAFDOArtifactsResponse)
262@faux.empty_error
Tiancong Wang24a3df72019-08-20 15:48:51 -0700263@validate.require('build_target.name')
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700264@validate.is_in('artifact_type', _NAMES_FOR_AFDO_ARTIFACTS)
Alex Klein231d2da2019-07-22 16:44:45 -0600265@validate.validation_complete
Tiancong Wang24a3df72019-08-20 15:48:51 -0700266def UploadVettedAFDOArtifacts(input_proto, output_proto, _config):
Tiancong Wangaf050172019-07-10 11:52:03 -0700267 """Upload a vetted orderfile to GS bucket.
268
269 Args:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700270 input_proto (VerifyAFDOArtifactsRequest): The input proto
271 output_proto (VerifyAFDOArtifactsResponse): The output proto
Alex Klein231d2da2019-07-22 16:44:45 -0600272 _config (api_config.ApiConfig): The API call config.
Tiancong Wangaf050172019-07-10 11:52:03 -0700273 """
Tiancong Wang24a3df72019-08-20 15:48:51 -0700274 board = input_proto.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700275 artifact_type = _NAMES_FOR_AFDO_ARTIFACTS[input_proto.artifact_type]
Tiancong Wang24a3df72019-08-20 15:48:51 -0700276 output_proto.status = toolchain_util.UploadAndPublishVettedAFDOArtifacts(
277 artifact_type, board)