blob: cc80ec88db306173bf34fd343d4bbb07f916652b [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
LaMont Jonesfd68cb12020-04-29 16:43:06 -060021from chromite.api.gen.chromite.api.artifacts_pb2 import PrepareForBuildResponse
Tiancong Wangaf050172019-07-10 11:52:03 -070022
Mike Frysingeref94e4c2020-02-10 23:59:54 -050023
24assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
25
26
LaMont Jonesb20b3d92019-11-23 11:47:48 -070027_Handlers = collections.namedtuple('_Handlers', ['name', 'prepare', 'bundle'])
28_TOOLCHAIN_ARTIFACT_HANDLERS = {
LaMont Jonescd1503d2020-03-04 09:09:59 -070029 BuilderConfig.Artifacts.UNVERIFIED_CHROME_LLVM_ORDERFILE:
LaMont Jonesd3944582020-03-04 10:37:05 -070030 _Handlers('UnverifiedChromeLlvmOrderfile',
LaMont Jones5d2edcb2019-12-23 11:32:03 -070031 toolchain_util.PrepareForBuild,
32 toolchain_util.BundleArtifacts),
LaMont Jonescd1503d2020-03-04 09:09:59 -070033 BuilderConfig.Artifacts.VERIFIED_CHROME_LLVM_ORDERFILE:
LaMont Jones3fed7f22020-03-04 10:15:11 -070034 _Handlers('VerifiedChromeLlvmOrderfile', toolchain_util.PrepareForBuild,
LaMont Jones5d2edcb2019-12-23 11:32:03 -070035 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070036 BuilderConfig.Artifacts.CHROME_CLANG_WARNINGS_FILE:
LaMont Jones3fed7f22020-03-04 10:15:11 -070037 _Handlers('ChromeClangWarningsFile', toolchain_util.PrepareForBuild,
LaMont Jones90bab632020-01-27 15:58:26 -070038 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070039 BuilderConfig.Artifacts.UNVERIFIED_LLVM_PGO_FILE:
LaMont Jones3fed7f22020-03-04 10:15:11 -070040 _Handlers('UnverifiedLlvmPgoFile', toolchain_util.PrepareForBuild,
LaMont Jones90bab632020-01-27 15:58:26 -070041 toolchain_util.BundleArtifacts),
LaMont Jones45ca6c42020-02-05 09:39:09 -070042 BuilderConfig.Artifacts.UNVERIFIED_CHROME_BENCHMARK_AFDO_FILE:
43 _Handlers('UnverifiedChromeBenchmarkAfdoFile',
LaMont Jones90bab632020-01-27 15:58:26 -070044 toolchain_util.PrepareForBuild,
45 toolchain_util.BundleArtifacts),
LaMont Jones3fed7f22020-03-04 10:15:11 -070046 BuilderConfig.Artifacts.CHROME_DEBUG_BINARY:
47 _Handlers('ChromeDebugBinary',
48 toolchain_util.PrepareForBuild,
49 toolchain_util.BundleArtifacts),
LaMont Jones53bddd02020-03-12 15:02:54 -060050 BuilderConfig.Artifacts.UNVERIFIED_CHROME_BENCHMARK_PERF_FILE:
51 _Handlers('UnverifiedChromeBenchmarkPerfFile',
52 toolchain_util.PrepareForBuild,
53 toolchain_util.BundleArtifacts),
LaMont Jones45ca6c42020-02-05 09:39:09 -070054 BuilderConfig.Artifacts.VERIFIED_CHROME_BENCHMARK_AFDO_FILE:
55 _Handlers('VerifiedChromeBenchmarkAfdoFile',
LaMont Jones90bab632020-01-27 15:58:26 -070056 toolchain_util.PrepareForBuild,
57 toolchain_util.BundleArtifacts),
LaMont Jones45ca6c42020-02-05 09:39:09 -070058 BuilderConfig.Artifacts.UNVERIFIED_KERNEL_CWP_AFDO_FILE:
LaMont Jones3fed7f22020-03-04 10:15:11 -070059 _Handlers('UnverifiedKernelCwpAfdoFile', toolchain_util.PrepareForBuild,
LaMont Jones45ca6c42020-02-05 09:39:09 -070060 toolchain_util.BundleArtifacts),
61 BuilderConfig.Artifacts.VERIFIED_KERNEL_CWP_AFDO_FILE:
LaMont Jones3fed7f22020-03-04 10:15:11 -070062 _Handlers('VerifiedKernelCwpAfdoFile', toolchain_util.PrepareForBuild,
LaMont Jones45ca6c42020-02-05 09:39:09 -070063 toolchain_util.BundleArtifacts),
64 BuilderConfig.Artifacts.UNVERIFIED_CHROME_CWP_AFDO_FILE:
LaMont Jones3fed7f22020-03-04 10:15:11 -070065 _Handlers('UnverifiedChromeCwpAfdoFile', toolchain_util.PrepareForBuild,
LaMont Jones45ca6c42020-02-05 09:39:09 -070066 toolchain_util.BundleArtifacts),
67 BuilderConfig.Artifacts.VERIFIED_CHROME_CWP_AFDO_FILE:
LaMont Jones3fed7f22020-03-04 10:15:11 -070068 _Handlers('VerifiedChromeCwpAfdoFile', toolchain_util.PrepareForBuild,
LaMont Jones45ca6c42020-02-05 09:39:09 -070069 toolchain_util.BundleArtifacts),
70 BuilderConfig.Artifacts.VERIFIED_RELEASE_AFDO_FILE:
LaMont Jones3fed7f22020-03-04 10:15:11 -070071 _Handlers('VerifiedReleaseAfdoFile', toolchain_util.PrepareForBuild,
LaMont Jones90bab632020-01-27 15:58:26 -070072 toolchain_util.BundleArtifacts),
Tiancong Wang91cf1dd2020-05-05 10:30:22 -070073 BuilderConfig.Artifacts.TOOLCHAIN_WARNING_LOGS:
74 _Handlers('ToolchainWarningLogs', toolchain_util.PrepareForBuild,
75 toolchain_util.BundleArtifacts),
Tiancong Wangfe3dbd22020-06-12 15:45:55 -070076 BuilderConfig.Artifacts.CHROME_AFDO_PROFILE_FOR_ANDROID_LINUX:
77 _Handlers('ChromeAFDOProfileForAndroidLinux',
78 toolchain_util.PrepareForBuild,
79 toolchain_util.BundleArtifacts),
Jian Cai6190cc82020-06-12 16:24:32 -070080 BuilderConfig.Artifacts.CLANG_CRASH_DIAGNOSES:
81 _Handlers('ClangCrashDiagnoses', toolchain_util.PrepareForBuild,
82 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070083}
84
85
LaMont Jonese7821672020-04-09 08:56:26 -060086def _GetProfileInfoDict(profile_info):
87 """Convert profile_info to a dict.
88
89 Args:
90 profile_info (ArtifactProfileInfo): The artifact profile_info.
91
92 Returns:
93 A dictionary containing profile info.
94 """
95 ret = {}
96 which = profile_info.WhichOneof('artifact_profile_info')
97 if which:
98 value = getattr(profile_info, which)
99 # If it is a message, then use the contents of the message. This works as
100 # long as simple types do not have a 'DESCRIPTOR' attribute. (And protobuf
101 # messages do.)
102 if getattr(value, 'DESCRIPTOR', None):
103 ret.update({k.name: v for k, v in value.ListFields()})
104 else:
105 ret[which] = value
106 return ret
107
108
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700109# TODO(crbug/1031213): When @faux is expanded to have more than success/failure,
110# this should be changed.
111@faux.all_empty
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700112@validate.require('artifact_types')
113# Note: chroot and sysroot are unspecified the first time that the build_target
114# recipe calls PrepareForBuild. The second time, they are specified. No
115# validation check because "all" values are valid.
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700116@validate.validation_complete
117def PrepareForBuild(input_proto, output_proto, _config):
118 """Prepare to build toolchain artifacts.
119
120 The handlers (from _TOOLCHAIN_ARTIFACT_HANDLERS above) are called with:
121 artifact_name (str): name of the artifact type.
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700122 chroot (chroot_lib.Chroot): chroot. Will be None if the chroot has not
123 yet been created.
124 sysroot_path (str): sysroot path inside the chroot (e.g., /build/atlas).
125 Will be an empty string if the sysroot has not yet been created.
126 build_target_name (str): name of the build target (e.g., atlas). Will be
127 an empty string if the sysroot has not yet been created.
128 input_artifacts ({(str) name:[str gs_locations]}): locations for possible
129 input artifacts. The handler is expected to know which keys it should
130 be using, and ignore any keys that it does not understand.
LaMont Jonese7821672020-04-09 08:56:26 -0600131 profile_info ({(str) name: (str) value}) Dictionary containing profile
132 information.
LaMont Jonesa215f1e2019-12-06 10:18:58 -0700133
134 They locate and modify any ebuilds and/or source required for the artifact
135 being created, then return a value from toolchain_util.PrepareForBuildReturn.
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700136
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700137 This function sets output_proto.build_relevance to the result.
138
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700139 Args:
140 input_proto (PrepareForToolchainBuildRequest): The input proto
141 output_proto (PrepareForToolchainBuildResponse): The output proto
142 _config (api_config.ApiConfig): The API call config.
143 """
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700144 if input_proto.chroot.path:
145 chroot = controller_util.ParseChroot(input_proto.chroot)
146 else:
147 chroot = None
LaMont Jones4579e8c2019-12-06 14:20:37 -0700148
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700149 input_artifacts = collections.defaultdict(list)
150 for art in input_proto.input_artifacts:
151 item = _TOOLCHAIN_ARTIFACT_HANDLERS.get(art.input_artifact_type)
152 if item:
153 input_artifacts[item.name].extend(
154 ['gs://%s' % str(x) for x in art.input_artifact_gs_locations])
155
LaMont Jonese7821672020-04-09 08:56:26 -0600156 profile_info = _GetProfileInfoDict(input_proto.profile_info)
LaMont Jones45ca6c42020-02-05 09:39:09 -0700157
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700158 results = set()
159 sysroot_path = input_proto.sysroot.path
160 build_target = input_proto.sysroot.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700161 for artifact_type in input_proto.artifact_types:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700162 # Unknown artifact_types are an error.
163 handler = _TOOLCHAIN_ARTIFACT_HANDLERS[artifact_type]
164 if handler.prepare:
LaMont Jonesa215f1e2019-12-06 10:18:58 -0700165 results.add(handler.prepare(
LaMont Jones45ca6c42020-02-05 09:39:09 -0700166 handler.name, chroot, sysroot_path, build_target, input_artifacts,
LaMont Jonese7821672020-04-09 08:56:26 -0600167 profile_info))
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700168
169 # Translate the returns from the handlers we called.
170 # If any NEEDED => NEEDED
171 # elif any UNKNOWN => UNKNOWN
172 # elif any POINTLESS => POINTLESS
173 # else UNKNOWN.
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700174 if toolchain_util.PrepareForBuildReturn.NEEDED in results:
LaMont Jonesfd68cb12020-04-29 16:43:06 -0600175 output_proto.build_relevance = PrepareForBuildResponse.NEEDED
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700176 elif toolchain_util.PrepareForBuildReturn.UNKNOWN in results:
LaMont Jonesfd68cb12020-04-29 16:43:06 -0600177 output_proto.build_relevance = PrepareForBuildResponse.UNKNOWN
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700178 elif toolchain_util.PrepareForBuildReturn.POINTLESS in results:
LaMont Jonesfd68cb12020-04-29 16:43:06 -0600179 output_proto.build_relevance = PrepareForBuildResponse.POINTLESS
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700180 else:
LaMont Jonesfd68cb12020-04-29 16:43:06 -0600181 output_proto.build_relevance = PrepareForBuildResponse.UNKNOWN
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700182 return controller.RETURN_CODE_SUCCESS
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700183
184
185# TODO(crbug/1031213): When @faux is expanded to have more than success/failure,
186# this should be changed.
187@faux.all_empty
LaMont Jonese911df02020-04-16 12:40:17 -0600188@validate.require('chroot.path', 'output_dir', 'artifact_types')
LaMont Jones4579e8c2019-12-06 14:20:37 -0700189@validate.exists('output_dir')
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700190@validate.validation_complete
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700191def BundleArtifacts(input_proto, output_proto, _config):
192 """Bundle toolchain artifacts.
193
194 The handlers (from _TOOLCHAIN_ARTIFACT_HANDLERS above) are called with:
LaMont Jonesa215f1e2019-12-06 10:18:58 -0700195 artifact_name (str): name of the artifact type
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700196 chroot (chroot_lib.Chroot): chroot
LaMont Jonese911df02020-04-16 12:40:17 -0600197 sysroot_path (str): sysroot path inside the chroot (e.g., /build/atlas),
198 or None.
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700199 chrome_root (str): path to chrome root. (e.g., /b/s/w/ir/k/chrome)
LaMont Jonese911df02020-04-16 12:40:17 -0600200 build_target_name (str): name of the build target (e.g., atlas), or None.
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700201 output_dir (str): absolute path where artifacts are being bundled.
202 (e.g., /b/s/w/ir/k/recipe_cleanup/artifactssptfMU)
LaMont Jonese7821672020-04-09 08:56:26 -0600203 profile_info ({(str) name: (str) value}) Dictionary containing profile
204 information.
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700205
206 Note: the actual upload to GS is done by CI, not here.
207
208 Args:
209 input_proto (BundleToolchainRequest): The input proto
210 output_proto (BundleToolchainResponse): The output proto
211 _config (api_config.ApiConfig): The API call config.
212 """
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700213 chroot = controller_util.ParseChroot(input_proto.chroot)
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700214
LaMont Jonese7821672020-04-09 08:56:26 -0600215 profile_info = _GetProfileInfoDict(input_proto.profile_info)
LaMont Jones45ca6c42020-02-05 09:39:09 -0700216
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700217 for artifact_type in input_proto.artifact_types:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700218 if artifact_type not in _TOOLCHAIN_ARTIFACT_HANDLERS:
219 logging.error('%s not understood', artifact_type)
220 return controller.RETURN_CODE_UNRECOVERABLE
221 handler = _TOOLCHAIN_ARTIFACT_HANDLERS[artifact_type]
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700222 if handler and handler.bundle:
223 artifacts = handler.bundle(
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700224 handler.name, chroot, input_proto.sysroot.path,
LaMont Jones45ca6c42020-02-05 09:39:09 -0700225 input_proto.sysroot.build_target.name, input_proto.output_dir,
LaMont Jonese7821672020-04-09 08:56:26 -0600226 profile_info)
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700227 if artifacts:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700228 art_info = output_proto.artifacts_info.add()
229 art_info.artifact_type = artifact_type
230 for artifact in artifacts:
231 art_info.artifacts.add().path = artifact
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700232
233
234# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
235_NAMES_FOR_AFDO_ARTIFACTS = {
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700236 toolchain_pb2.ORDERFILE: 'orderfile',
237 toolchain_pb2.KERNEL_AFDO: 'kernel_afdo',
238 toolchain_pb2.CHROME_AFDO: 'chrome_afdo'
239}
240
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700241# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700242# Using a function instead of a dict because we need to mock these
243# functions in unittest, and mock doesn't play well with a dict definition.
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700244def _GetMethodForUpdatingAFDOArtifacts(artifact_type):
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700245 return {
246 toolchain_pb2.ORDERFILE: toolchain_util.OrderfileUpdateChromeEbuild,
247 toolchain_pb2.KERNEL_AFDO: toolchain_util.AFDOUpdateKernelEbuild,
248 toolchain_pb2.CHROME_AFDO: toolchain_util.AFDOUpdateChromeEbuild
249 }[artifact_type]
Tiancong Wang24a3df72019-08-20 15:48:51 -0700250
Tiancong Wangaf050172019-07-10 11:52:03 -0700251
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700252# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700253def _UpdateEbuildWithAFDOArtifactsResponse(_input_proto, output_proto, _config):
254 """Add successful status to the faux response."""
255 output_proto.status = True
256
257
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700258# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700259@faux.success(_UpdateEbuildWithAFDOArtifactsResponse)
260@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600261@validate.require('build_target.name')
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700262@validate.is_in('artifact_type', _NAMES_FOR_AFDO_ARTIFACTS)
Alex Klein231d2da2019-07-22 16:44:45 -0600263@validate.validation_complete
Tiancong Wang24a3df72019-08-20 15:48:51 -0700264def UpdateEbuildWithAFDOArtifacts(input_proto, output_proto, _config):
265 """Update Chrome or kernel ebuild with most recent unvetted artifacts.
Tiancong Wangaf050172019-07-10 11:52:03 -0700266
267 Args:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700268 input_proto (VerifyAFDOArtifactsRequest): The input proto
269 output_proto (VerifyAFDOArtifactsResponse): The output proto
Alex Klein231d2da2019-07-22 16:44:45 -0600270 _config (api_config.ApiConfig): The API call config.
Tiancong Wangaf050172019-07-10 11:52:03 -0700271 """
Tiancong Wangaf050172019-07-10 11:52:03 -0700272 board = input_proto.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700273 update_method = _GetMethodForUpdatingAFDOArtifacts(input_proto.artifact_type)
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700274 output_proto.status = update_method(board)
Tiancong Wangaf050172019-07-10 11:52:03 -0700275
276
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700277# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700278def _UploadVettedAFDOArtifactsResponse(_input_proto, output_proto, _config):
279 """Add successful status to the faux response."""
280 output_proto.status = True
281
282
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700283# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700284@faux.success(_UploadVettedAFDOArtifactsResponse)
285@faux.empty_error
Tiancong Wang24a3df72019-08-20 15:48:51 -0700286@validate.require('build_target.name')
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700287@validate.is_in('artifact_type', _NAMES_FOR_AFDO_ARTIFACTS)
Alex Klein231d2da2019-07-22 16:44:45 -0600288@validate.validation_complete
Tiancong Wang24a3df72019-08-20 15:48:51 -0700289def UploadVettedAFDOArtifacts(input_proto, output_proto, _config):
Tiancong Wangaf050172019-07-10 11:52:03 -0700290 """Upload a vetted orderfile to GS bucket.
291
292 Args:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700293 input_proto (VerifyAFDOArtifactsRequest): The input proto
294 output_proto (VerifyAFDOArtifactsResponse): The output proto
Alex Klein231d2da2019-07-22 16:44:45 -0600295 _config (api_config.ApiConfig): The API call config.
Tiancong Wangaf050172019-07-10 11:52:03 -0700296 """
Tiancong Wang24a3df72019-08-20 15:48:51 -0700297 board = input_proto.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700298 artifact_type = _NAMES_FOR_AFDO_ARTIFACTS[input_proto.artifact_type]
Tiancong Wang24a3df72019-08-20 15:48:51 -0700299 output_proto.status = toolchain_util.UploadAndPublishVettedAFDOArtifacts(
300 artifact_type, board)