blob: 64af9e9702b8bbe7554fc6b0867e2ee8d166c445 [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
11
LaMont Jones5d2edcb2019-12-23 11:32:03 -070012from chromite.api import controller
Alex Klein076841b2019-08-29 15:19:39 -060013from chromite.api import faux
Alex Klein231d2da2019-07-22 16:44:45 -060014from chromite.api import validate
LaMont Jones5d2edcb2019-12-23 11:32:03 -070015from chromite.api.controller import controller_util
Tiancong Wang24a3df72019-08-20 15:48:51 -070016from chromite.api.gen.chromite.api import toolchain_pb2
LaMont Jonesb20b3d92019-11-23 11:47:48 -070017from chromite.api.gen.chromiumos.builder_config_pb2 import BuilderConfig
LaMont Jones5d2edcb2019-12-23 11:32:03 -070018from chromite.lib import cros_logging as logging
19from chromite.lib import toolchain_util
Tiancong Wangaf050172019-07-10 11:52:03 -070020
LaMont Jonesb20b3d92019-11-23 11:47:48 -070021# TODO(crbug/1019868): Add handlers as needed.
22_Handlers = collections.namedtuple('_Handlers', ['name', 'prepare', 'bundle'])
23_TOOLCHAIN_ARTIFACT_HANDLERS = {
24 BuilderConfig.Artifacts.UNVERIFIED_ORDERING_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070025 _Handlers('UnverifiedOrderingFile',
26 toolchain_util.PrepareForBuild,
27 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070028 BuilderConfig.Artifacts.VERIFIED_ORDERING_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070029 _Handlers('VerifiedOrderingFile',
30 toolchain_util.PrepareForBuild,
31 toolchain_util.BundleArtifacts),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070032 BuilderConfig.Artifacts.CHROME_CLANG_WARNINGS_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070033 _Handlers('ChromeClangWarningsFile',
34 toolchain_util.PrepareForBuild, None),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070035 BuilderConfig.Artifacts.UNVERIFIED_LLVM_PGO_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070036 _Handlers('UnverifiedLlvmPgoFile',
37 toolchain_util.PrepareForBuild, None),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070038 BuilderConfig.Artifacts.UNVERIFIED_CHROME_AFDO_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070039 _Handlers('UnverifiedChromeAfdoFile',
40 toolchain_util.PrepareForBuild, None),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070041 BuilderConfig.Artifacts.VERIFIED_CHROME_AFDO_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070042 _Handlers('VerifiedChromeAfdoFile',
43 toolchain_util.PrepareForBuild, None),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070044 BuilderConfig.Artifacts.VERIFIED_KERNEL_AFDO_FILE:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070045 _Handlers('VerifiedKernelAfdoFile',
46 toolchain_util.PrepareForBuild, None),
LaMont Jonesb20b3d92019-11-23 11:47:48 -070047}
48
49
50# TODO(crbug/1031213): When @faux is expanded to have more than success/failure,
51# this should be changed.
52@faux.all_empty
LaMont Jones5d2edcb2019-12-23 11:32:03 -070053@validate.require('artifact_types')
54# Note: chroot and sysroot are unspecified the first time that the build_target
55# recipe calls PrepareForBuild. The second time, they are specified. No
56# validation check because "all" values are valid.
LaMont Jonesb20b3d92019-11-23 11:47:48 -070057@validate.validation_complete
58def PrepareForBuild(input_proto, output_proto, _config):
59 """Prepare to build toolchain artifacts.
60
61 The handlers (from _TOOLCHAIN_ARTIFACT_HANDLERS above) are called with:
62 artifact_name (str): name of the artifact type.
LaMont Jones5d2edcb2019-12-23 11:32:03 -070063 chroot (chroot_lib.Chroot): chroot. Will be None if the chroot has not
64 yet been created.
65 sysroot_path (str): sysroot path inside the chroot (e.g., /build/atlas).
66 Will be an empty string if the sysroot has not yet been created.
67 build_target_name (str): name of the build target (e.g., atlas). Will be
68 an empty string if the sysroot has not yet been created.
69 input_artifacts ({(str) name:[str gs_locations]}): locations for possible
70 input artifacts. The handler is expected to know which keys it should
71 be using, and ignore any keys that it does not understand.
LaMont Jonesa215f1e2019-12-06 10:18:58 -070072
73 They locate and modify any ebuilds and/or source required for the artifact
74 being created, then return a value from toolchain_util.PrepareForBuildReturn.
LaMont Jonesb20b3d92019-11-23 11:47:48 -070075
LaMont Jones5d2edcb2019-12-23 11:32:03 -070076 This function sets output_proto.build_relevance to the result.
77
LaMont Jonesb20b3d92019-11-23 11:47:48 -070078 Args:
79 input_proto (PrepareForToolchainBuildRequest): The input proto
80 output_proto (PrepareForToolchainBuildResponse): The output proto
81 _config (api_config.ApiConfig): The API call config.
82 """
LaMont Jones5d2edcb2019-12-23 11:32:03 -070083 if input_proto.chroot.path:
84 chroot = controller_util.ParseChroot(input_proto.chroot)
85 else:
86 chroot = None
LaMont Jones4579e8c2019-12-06 14:20:37 -070087
LaMont Jones5d2edcb2019-12-23 11:32:03 -070088 input_artifacts = collections.defaultdict(list)
89 for art in input_proto.input_artifacts:
90 item = _TOOLCHAIN_ARTIFACT_HANDLERS.get(art.input_artifact_type)
91 if item:
92 input_artifacts[item.name].extend(
93 ['gs://%s' % str(x) for x in art.input_artifact_gs_locations])
94
95 results = set()
96 sysroot_path = input_proto.sysroot.path
97 build_target = input_proto.sysroot.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -070098 for artifact_type in input_proto.artifact_types:
LaMont Jones5d2edcb2019-12-23 11:32:03 -070099 # Unknown artifact_types are an error.
100 handler = _TOOLCHAIN_ARTIFACT_HANDLERS[artifact_type]
101 if handler.prepare:
LaMont Jonesa215f1e2019-12-06 10:18:58 -0700102 results.add(handler.prepare(
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700103 handler.name, chroot, sysroot_path, build_target, input_artifacts))
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700104
105 # Translate the returns from the handlers we called.
106 # If any NEEDED => NEEDED
107 # elif any UNKNOWN => UNKNOWN
108 # elif any POINTLESS => POINTLESS
109 # else UNKNOWN.
110 proto_resp = toolchain_pb2.PrepareForToolchainBuildResponse
111 if toolchain_util.PrepareForBuildReturn.NEEDED in results:
112 output_proto.build_relevance = proto_resp.NEEDED
113 elif toolchain_util.PrepareForBuildReturn.UNKNOWN in results:
114 output_proto.build_relevance = proto_resp.UNKNOWN
115 elif toolchain_util.PrepareForBuildReturn.POINTLESS in results:
116 output_proto.build_relevance = proto_resp.POINTLESS
117 else:
118 output_proto.build_relevance = proto_resp.UNKNOWN
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700119 return controller.RETURN_CODE_SUCCESS
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700120
121
122# TODO(crbug/1031213): When @faux is expanded to have more than success/failure,
123# this should be changed.
124@faux.all_empty
LaMont Jones4579e8c2019-12-06 14:20:37 -0700125@validate.require('chroot.path', 'sysroot.path', 'sysroot.build_target.name',
126 'output_dir', 'artifact_types')
127@validate.exists('output_dir')
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700128@validate.validation_complete
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700129def BundleArtifacts(input_proto, output_proto, _config):
130 """Bundle toolchain artifacts.
131
132 The handlers (from _TOOLCHAIN_ARTIFACT_HANDLERS above) are called with:
LaMont Jonesa215f1e2019-12-06 10:18:58 -0700133 artifact_name (str): name of the artifact type
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700134 chroot (chroot_lib.Chroot): chroot
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700135 sysroot_path (str): sysroot path inside the chroot (e.g., /build/atlas)
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700136 chrome_root (str): path to chrome root. (e.g., /b/s/w/ir/k/chrome)
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700137 build_target_name (str): name of the build target (e.g., atlas)
138 output_dir (str): absolute path where artifacts are being bundled.
139 (e.g., /b/s/w/ir/k/recipe_cleanup/artifactssptfMU)
140
141 Note: the actual upload to GS is done by CI, not here.
142
143 Args:
144 input_proto (BundleToolchainRequest): The input proto
145 output_proto (BundleToolchainResponse): The output proto
146 _config (api_config.ApiConfig): The API call config.
147 """
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700148 chroot = controller_util.ParseChroot(input_proto.chroot)
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700149
150 for artifact_type in input_proto.artifact_types:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700151 if artifact_type not in _TOOLCHAIN_ARTIFACT_HANDLERS:
152 logging.error('%s not understood', artifact_type)
153 return controller.RETURN_CODE_UNRECOVERABLE
154 handler = _TOOLCHAIN_ARTIFACT_HANDLERS[artifact_type]
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700155 if handler and handler.bundle:
156 artifacts = handler.bundle(
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700157 handler.name, chroot, input_proto.sysroot.path,
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700158 input_proto.sysroot.build_target.name, input_proto.output_dir)
159 if artifacts:
LaMont Jones5d2edcb2019-12-23 11:32:03 -0700160 art_info = output_proto.artifacts_info.add()
161 art_info.artifact_type = artifact_type
162 for artifact in artifacts:
163 art_info.artifacts.add().path = artifact
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700164
165
166# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
167_NAMES_FOR_AFDO_ARTIFACTS = {
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700168 toolchain_pb2.ORDERFILE: 'orderfile',
169 toolchain_pb2.KERNEL_AFDO: 'kernel_afdo',
170 toolchain_pb2.CHROME_AFDO: 'chrome_afdo'
171}
172
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700173# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700174# Using a function instead of a dict because we need to mock these
175# functions in unittest, and mock doesn't play well with a dict definition.
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700176def _GetMethodForUpdatingAFDOArtifacts(artifact_type):
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700177 return {
178 toolchain_pb2.ORDERFILE: toolchain_util.OrderfileUpdateChromeEbuild,
179 toolchain_pb2.KERNEL_AFDO: toolchain_util.AFDOUpdateKernelEbuild,
180 toolchain_pb2.CHROME_AFDO: toolchain_util.AFDOUpdateChromeEbuild
181 }[artifact_type]
Tiancong Wang24a3df72019-08-20 15:48:51 -0700182
Tiancong Wangaf050172019-07-10 11:52:03 -0700183
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700184# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700185def _UpdateEbuildWithAFDOArtifactsResponse(_input_proto, output_proto, _config):
186 """Add successful status to the faux response."""
187 output_proto.status = True
188
189
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700190# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700191@faux.success(_UpdateEbuildWithAFDOArtifactsResponse)
192@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600193@validate.require('build_target.name')
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700194@validate.is_in('artifact_type', _NAMES_FOR_AFDO_ARTIFACTS)
Alex Klein231d2da2019-07-22 16:44:45 -0600195@validate.validation_complete
Tiancong Wang24a3df72019-08-20 15:48:51 -0700196def UpdateEbuildWithAFDOArtifacts(input_proto, output_proto, _config):
197 """Update Chrome or kernel ebuild with most recent unvetted artifacts.
Tiancong Wangaf050172019-07-10 11:52:03 -0700198
199 Args:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700200 input_proto (VerifyAFDOArtifactsRequest): The input proto
201 output_proto (VerifyAFDOArtifactsResponse): The output proto
Alex Klein231d2da2019-07-22 16:44:45 -0600202 _config (api_config.ApiConfig): The API call config.
Tiancong Wangaf050172019-07-10 11:52:03 -0700203 """
Tiancong Wangaf050172019-07-10 11:52:03 -0700204 board = input_proto.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700205 update_method = _GetMethodForUpdatingAFDOArtifacts(input_proto.artifact_type)
Tiancong Wangf9c736c2019-08-26 13:54:38 -0700206 output_proto.status = update_method(board)
Tiancong Wangaf050172019-07-10 11:52:03 -0700207
208
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700209# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700210def _UploadVettedAFDOArtifactsResponse(_input_proto, output_proto, _config):
211 """Add successful status to the faux response."""
212 output_proto.status = True
213
214
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700215# TODO(crbug/1019868): Remove legacy code when cbuildbot builders are gone.
Michael Mortensen54bd70a2019-11-21 14:45:38 -0700216@faux.success(_UploadVettedAFDOArtifactsResponse)
217@faux.empty_error
Tiancong Wang24a3df72019-08-20 15:48:51 -0700218@validate.require('build_target.name')
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700219@validate.is_in('artifact_type', _NAMES_FOR_AFDO_ARTIFACTS)
Alex Klein231d2da2019-07-22 16:44:45 -0600220@validate.validation_complete
Tiancong Wang24a3df72019-08-20 15:48:51 -0700221def UploadVettedAFDOArtifacts(input_proto, output_proto, _config):
Tiancong Wangaf050172019-07-10 11:52:03 -0700222 """Upload a vetted orderfile to GS bucket.
223
224 Args:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700225 input_proto (VerifyAFDOArtifactsRequest): The input proto
226 output_proto (VerifyAFDOArtifactsResponse): The output proto
Alex Klein231d2da2019-07-22 16:44:45 -0600227 _config (api_config.ApiConfig): The API call config.
Tiancong Wangaf050172019-07-10 11:52:03 -0700228 """
Tiancong Wang24a3df72019-08-20 15:48:51 -0700229 board = input_proto.build_target.name
LaMont Jonesb20b3d92019-11-23 11:47:48 -0700230 artifact_type = _NAMES_FOR_AFDO_ARTIFACTS[input_proto.artifact_type]
Tiancong Wang24a3df72019-08-20 15:48:51 -0700231 output_proto.status = toolchain_util.UploadAndPublishVettedAFDOArtifacts(
232 artifact_type, board)