blob: 0e7c94480d7847e29aaec1efb6a12d088cb8ec13 [file] [log] [blame]
Chris Parsonsf3c96ef2020-09-29 02:23:17 -04001// Copyright 2020 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
18 "bytes"
19 "errors"
20 "fmt"
Chris Parsonsa798d962020-10-12 23:44:08 -040021 "io/ioutil"
Chris Parsonsf3c96ef2020-09-29 02:23:17 -040022 "os"
23 "os/exec"
Chris Parsonsa798d962020-10-12 23:44:08 -040024 "path/filepath"
Chris Parsonsf3c96ef2020-09-29 02:23:17 -040025 "runtime"
26 "strings"
27 "sync"
Chris Parsonsa798d962020-10-12 23:44:08 -040028
Chris Parsons944e7d02021-03-11 11:08:46 -050029 "android/soong/bazel/cquery"
Liz Kammer8206d4f2021-03-03 16:40:52 -050030
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -050031 "github.com/google/blueprint/bootstrap"
32
Patrice Arruda05ab2d02020-12-12 06:24:26 +000033 "android/soong/bazel"
34 "android/soong/shared"
Chris Parsonsf3c96ef2020-09-29 02:23:17 -040035)
36
Liz Kammerf29df7c2021-04-02 13:37:39 -040037type cqueryRequest interface {
38 // Name returns a string name for this request type. Such request type names must be unique,
39 // and must only consist of alphanumeric characters.
40 Name() string
41
42 // StarlarkFunctionBody returns a starlark function body to process this request type.
43 // The returned string is the body of a Starlark function which obtains
44 // all request-relevant information about a target and returns a string containing
45 // this information.
46 // The function should have the following properties:
47 // - `target` is the only parameter to this function (a configured target).
48 // - The return value must be a string.
49 // - The function body should not be indented outside of its own scope.
50 StarlarkFunctionBody() string
51}
52
Chris Parsonsf3c96ef2020-09-29 02:23:17 -040053// Map key to describe bazel cquery requests.
54type cqueryKey struct {
Chris Parsonsb0f8ac42020-10-23 16:48:08 -040055 label string
Liz Kammerf29df7c2021-04-02 13:37:39 -040056 requestType cqueryRequest
Chris Parsons8d6e4332021-02-22 16:13:50 -050057 archType ArchType
Chris Parsonsf3c96ef2020-09-29 02:23:17 -040058}
59
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux0d990452021-08-11 16:46:13 +000060// bazelHandler is the interface for a helper object related to deferring to Bazel for
61// processing a module (during Bazel mixed builds). Individual module types should define
62// their own bazel handler if they support deferring to Bazel.
63type BazelHandler interface {
64 // Issue query to Bazel to retrieve information about Bazel's view of the current module.
65 // If Bazel returns this information, set module properties on the current module to reflect
66 // the returned information.
67 // Returns true if information was available from Bazel, false if bazel invocation still needs to occur.
68 GenerateBazelBuildActions(ctx ModuleContext, label string) bool
69}
70
Chris Parsonsf3c96ef2020-09-29 02:23:17 -040071type BazelContext interface {
72 // The below methods involve queuing cquery requests to be later invoked
73 // by bazel. If any of these methods return (_, false), then the request
74 // has been queued to be run later.
75
76 // Returns result files built by building the given bazel target label.
Chris Parsons944e7d02021-03-11 11:08:46 -050077 GetOutputFiles(label string, archType ArchType) ([]string, bool)
Chris Parsons8d6e4332021-02-22 16:13:50 -050078
Chris Parsons944e7d02021-03-11 11:08:46 -050079 // TODO(cparsons): Other cquery-related methods should be added here.
80 // Returns the results of GetOutputFiles and GetCcObjectFiles in a single query (in that order).
Liz Kammerfe23bf32021-04-09 16:17:05 -040081 GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error)
Liz Kammer3f9e1552021-04-02 18:47:09 -040082
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxa05a2552021-08-11 16:48:30 +000083 // Returns the executable binary resultant from building together the python sources
84 GetPythonBinary(label string, archType ArchType) (string, bool)
85
Chris Parsonsf3c96ef2020-09-29 02:23:17 -040086 // ** End cquery methods
87
88 // Issues commands to Bazel to receive results for all cquery requests
89 // queued in the BazelContext.
90 InvokeBazel() error
91
92 // Returns true if bazel is enabled for the given configuration.
93 BazelEnabled() bool
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -050094
95 // Returns the bazel output base (the root directory for all bazel intermediate outputs).
96 OutputBase() string
97
98 // Returns build statements which should get registered to reflect Bazel's outputs.
99 BuildStatementsToRegister() []bazel.BuildStatement
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400100}
101
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400102type bazelRunner interface {
103 issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand, extraFlags ...string) (string, string, error)
104}
105
106type bazelPaths struct {
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400107 homeDir string
108 bazelPath string
109 outputBase string
110 workspaceDir string
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400111 buildDir string
Patrice Arruda05ab2d02020-12-12 06:24:26 +0000112 metricsDir string
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400113}
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400114
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400115// A context object which tracks queued requests that need to be made to Bazel,
116// and their results after the requests have been made.
117type bazelContext struct {
118 bazelRunner
119 paths *bazelPaths
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400120 requests map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
121 requestMutex sync.Mutex // requests can be written in parallel
122
123 results map[cqueryKey]string // Results of cquery requests after Bazel invocations
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500124
125 // Build statements which should get registered to reflect Bazel's outputs.
126 buildStatements []bazel.BuildStatement
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400127}
128
129var _ BazelContext = &bazelContext{}
130
131// A bazel context to use when Bazel is disabled.
132type noopBazelContext struct{}
133
134var _ BazelContext = noopBazelContext{}
135
136// A bazel context to use for tests.
137type MockBazelContext struct {
Liz Kammera92e8442021-04-07 20:25:21 -0400138 OutputBaseDir string
139
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxa05a2552021-08-11 16:48:30 +0000140 LabelToOutputFiles map[string][]string
141 LabelToCcInfo map[string]cquery.CcInfo
142 LabelToPythonBinary map[string]string
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400143}
144
Chris Parsons944e7d02021-03-11 11:08:46 -0500145func (m MockBazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) {
Liz Kammera92e8442021-04-07 20:25:21 -0400146 result, ok := m.LabelToOutputFiles[label]
Chris Parsons8d6e4332021-02-22 16:13:50 -0500147 return result, ok
148}
149
Liz Kammerfe23bf32021-04-09 16:17:05 -0400150func (m MockBazelContext) GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error) {
Liz Kammerb71794d2021-04-09 14:07:00 -0400151 result, ok := m.LabelToCcInfo[label]
Liz Kammerfe23bf32021-04-09 16:17:05 -0400152 return result, ok, nil
Liz Kammer3f9e1552021-04-02 18:47:09 -0400153}
154
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxa05a2552021-08-11 16:48:30 +0000155func (m MockBazelContext) GetPythonBinary(label string, archType ArchType) (string, bool) {
156 result, ok := m.LabelToPythonBinary[label]
157 return result, ok
158}
159
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400160func (m MockBazelContext) InvokeBazel() error {
161 panic("unimplemented")
162}
163
164func (m MockBazelContext) BazelEnabled() bool {
165 return true
166}
167
Liz Kammera92e8442021-04-07 20:25:21 -0400168func (m MockBazelContext) OutputBase() string { return m.OutputBaseDir }
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500169
170func (m MockBazelContext) BuildStatementsToRegister() []bazel.BuildStatement {
171 return []bazel.BuildStatement{}
172}
173
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400174var _ BazelContext = MockBazelContext{}
175
Chris Parsons944e7d02021-03-11 11:08:46 -0500176func (bazelCtx *bazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) {
177 rawString, ok := bazelCtx.cquery(label, cquery.GetOutputFiles, archType)
178 var ret []string
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400179 if ok {
Chris Parsons944e7d02021-03-11 11:08:46 -0500180 bazelOutput := strings.TrimSpace(rawString)
Liz Kammerf29df7c2021-04-02 13:37:39 -0400181 ret = cquery.GetOutputFiles.ParseResult(bazelOutput)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400182 }
Chris Parsons944e7d02021-03-11 11:08:46 -0500183 return ret, ok
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400184}
185
Liz Kammerfe23bf32021-04-09 16:17:05 -0400186func (bazelCtx *bazelContext) GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error) {
Liz Kammerb71794d2021-04-09 14:07:00 -0400187 result, ok := bazelCtx.cquery(label, cquery.GetCcInfo, archType)
Liz Kammer3f9e1552021-04-02 18:47:09 -0400188 if !ok {
Liz Kammerfe23bf32021-04-09 16:17:05 -0400189 return cquery.CcInfo{}, ok, nil
Liz Kammer3f9e1552021-04-02 18:47:09 -0400190 }
191
192 bazelOutput := strings.TrimSpace(result)
Liz Kammerfe23bf32021-04-09 16:17:05 -0400193 ret, err := cquery.GetCcInfo.ParseResult(bazelOutput)
194 return ret, ok, err
Liz Kammer3f9e1552021-04-02 18:47:09 -0400195}
196
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxa05a2552021-08-11 16:48:30 +0000197func (bazelCtx *bazelContext) GetPythonBinary(label string, archType ArchType) (string, bool) {
198 rawString, ok := bazelCtx.cquery(label, cquery.GetPythonBinary, archType)
199 var ret string
200 if ok {
201 bazelOutput := strings.TrimSpace(rawString)
202 ret = cquery.GetPythonBinary.ParseResult(bazelOutput)
203 }
204 return ret, ok
205}
206
Chris Parsons944e7d02021-03-11 11:08:46 -0500207func (n noopBazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) {
Chris Parsons8d6e4332021-02-22 16:13:50 -0500208 panic("unimplemented")
209}
210
Liz Kammerfe23bf32021-04-09 16:17:05 -0400211func (n noopBazelContext) GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error) {
Chris Parsons808d84c2021-03-09 20:43:32 -0500212 panic("unimplemented")
213}
214
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxa05a2552021-08-11 16:48:30 +0000215func (n noopBazelContext) GetPythonBinary(label string, archType ArchType) (string, bool) {
216 panic("unimplemented")
217}
218
Liz Kammer3f9e1552021-04-02 18:47:09 -0400219func (n noopBazelContext) GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool) {
220 panic("unimplemented")
221}
222
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400223func (n noopBazelContext) InvokeBazel() error {
224 panic("unimplemented")
225}
226
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500227func (m noopBazelContext) OutputBase() string {
228 return ""
229}
230
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400231func (n noopBazelContext) BazelEnabled() bool {
232 return false
233}
234
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500235func (m noopBazelContext) BuildStatementsToRegister() []bazel.BuildStatement {
236 return []bazel.BuildStatement{}
237}
238
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400239func NewBazelContext(c *config) (BazelContext, error) {
Chris Parsons8b77a002020-10-27 18:59:25 -0400240 // TODO(cparsons): Assess USE_BAZEL=1 instead once "mixed Soong/Bazel builds"
241 // are production ready.
Jingwen Chen442b1a42021-06-17 07:02:15 +0000242 if !c.IsEnvTrue("USE_BAZEL_ANALYSIS") {
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400243 return noopBazelContext{}, nil
244 }
245
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400246 p, err := bazelPathsFromConfig(c)
247 if err != nil {
248 return nil, err
249 }
250 return &bazelContext{
251 bazelRunner: &builtinBazelRunner{},
252 paths: p,
253 requests: make(map[cqueryKey]bool),
254 }, nil
255}
256
257func bazelPathsFromConfig(c *config) (*bazelPaths, error) {
258 p := bazelPaths{
259 buildDir: c.buildDir,
260 }
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400261 missingEnvVars := []string{}
262 if len(c.Getenv("BAZEL_HOME")) > 1 {
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400263 p.homeDir = c.Getenv("BAZEL_HOME")
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400264 } else {
265 missingEnvVars = append(missingEnvVars, "BAZEL_HOME")
266 }
267 if len(c.Getenv("BAZEL_PATH")) > 1 {
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400268 p.bazelPath = c.Getenv("BAZEL_PATH")
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400269 } else {
270 missingEnvVars = append(missingEnvVars, "BAZEL_PATH")
271 }
272 if len(c.Getenv("BAZEL_OUTPUT_BASE")) > 1 {
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400273 p.outputBase = c.Getenv("BAZEL_OUTPUT_BASE")
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400274 } else {
275 missingEnvVars = append(missingEnvVars, "BAZEL_OUTPUT_BASE")
276 }
277 if len(c.Getenv("BAZEL_WORKSPACE")) > 1 {
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400278 p.workspaceDir = c.Getenv("BAZEL_WORKSPACE")
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400279 } else {
280 missingEnvVars = append(missingEnvVars, "BAZEL_WORKSPACE")
281 }
Patrice Arruda05ab2d02020-12-12 06:24:26 +0000282 if len(c.Getenv("BAZEL_METRICS_DIR")) > 1 {
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400283 p.metricsDir = c.Getenv("BAZEL_METRICS_DIR")
Patrice Arruda05ab2d02020-12-12 06:24:26 +0000284 } else {
285 missingEnvVars = append(missingEnvVars, "BAZEL_METRICS_DIR")
286 }
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400287 if len(missingEnvVars) > 0 {
288 return nil, errors.New(fmt.Sprintf("missing required env vars to use bazel: %s", missingEnvVars))
289 } else {
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400290 return &p, nil
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400291 }
292}
293
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400294func (p *bazelPaths) BazelMetricsDir() string {
295 return p.metricsDir
Patrice Arruda05ab2d02020-12-12 06:24:26 +0000296}
297
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400298func (context *bazelContext) BazelEnabled() bool {
299 return true
300}
301
302// Adds a cquery request to the Bazel request queue, to be later invoked, or
303// returns the result of the given request if the request was already made.
304// If the given request was already made (and the results are available), then
305// returns (result, true). If the request is queued but no results are available,
306// then returns ("", false).
Liz Kammerf29df7c2021-04-02 13:37:39 -0400307func (context *bazelContext) cquery(label string, requestType cqueryRequest,
Chris Parsons8d6e4332021-02-22 16:13:50 -0500308 archType ArchType) (string, bool) {
309 key := cqueryKey{label, requestType, archType}
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400310 if result, ok := context.results[key]; ok {
311 return result, true
312 } else {
313 context.requestMutex.Lock()
314 defer context.requestMutex.Unlock()
315 context.requests[key] = true
316 return "", false
317 }
318}
319
320func pwdPrefix() string {
321 // Darwin doesn't have /proc
322 if runtime.GOOS != "darwin" {
323 return "PWD=/proc/self/cwd"
324 }
325 return ""
326}
327
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400328type bazelCommand struct {
329 command string
330 // query or label
331 expression string
332}
333
334type mockBazelRunner struct {
335 bazelCommandResults map[bazelCommand]string
336 commands []bazelCommand
337}
338
339func (r *mockBazelRunner) issueBazelCommand(paths *bazelPaths,
340 runName bazel.RunName,
341 command bazelCommand,
342 extraFlags ...string) (string, string, error) {
343 r.commands = append(r.commands, command)
344 if ret, ok := r.bazelCommandResults[command]; ok {
345 return ret, "", nil
346 }
347 return "", "", nil
348}
349
350type builtinBazelRunner struct{}
351
Chris Parsons808d84c2021-03-09 20:43:32 -0500352// Issues the given bazel command with given build label and additional flags.
353// Returns (stdout, stderr, error). The first and second return values are strings
354// containing the stdout and stderr of the run command, and an error is returned if
355// the invocation returned an error code.
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400356func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand,
Chris Parsons808d84c2021-03-09 20:43:32 -0500357 extraFlags ...string) (string, string, error) {
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200358 cmdFlags := []string{"--output_base=" + absolutePath(paths.outputBase), command.command}
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400359 cmdFlags = append(cmdFlags, command.expression)
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400360 cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(paths, runName))
Jingwen Chen91220d72021-03-24 02:18:33 -0400361
362 // Set default platforms to canonicalized values for mixed builds requests.
363 // If these are set in the bazelrc, they will have values that are
364 // non-canonicalized to @sourceroot labels, and thus be invalid when
365 // referenced from the buildroot.
366 //
367 // The actual platform values here may be overridden by configuration
368 // transitions from the buildroot.
Chris Parsonsee423b02021-02-08 23:04:59 -0500369 cmdFlags = append(cmdFlags,
Liz Kammerc0c66092021-07-26 17:38:47 -0400370 fmt.Sprintf("--platforms=%s", "//build/bazel/platforms:android_target"))
Chris Parsonsee423b02021-02-08 23:04:59 -0500371 cmdFlags = append(cmdFlags,
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200372 fmt.Sprintf("--extra_toolchains=%s", "//prebuilts/clang/host/linux-x86:all"))
Jingwen Chen91220d72021-03-24 02:18:33 -0400373 // This should be parameterized on the host OS, but let's restrict to linux
374 // to keep things simple for now.
375 cmdFlags = append(cmdFlags,
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200376 fmt.Sprintf("--host_platform=%s", "//build/bazel/platforms:linux_x86_64"))
Jingwen Chen91220d72021-03-24 02:18:33 -0400377
Chris Parsons8d6e4332021-02-22 16:13:50 -0500378 // Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network.
379 cmdFlags = append(cmdFlags, "--experimental_repository_disable_download")
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400380 cmdFlags = append(cmdFlags, extraFlags...)
381
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400382 bazelCmd := exec.Command(paths.bazelPath, cmdFlags...)
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200383 bazelCmd.Dir = absolutePath(paths.syntheticWorkspaceDir())
Lukacs T. Berki3069dd92021-05-11 16:54:29 +0200384 bazelCmd.Env = append(os.Environ(),
385 "HOME="+paths.homeDir,
386 pwdPrefix(),
387 "BUILD_DIR="+absolutePath(paths.buildDir),
Jingwen Chen8c523582021-06-01 11:19:53 +0000388 // Make OUT_DIR absolute here so tools/bazel.sh uses the correct
389 // OUT_DIR at <root>/out, instead of <root>/out/soong/workspace/out.
390 "OUT_DIR="+absolutePath(paths.outDir()),
Chris Parsons8d6e4332021-02-22 16:13:50 -0500391 // Disables local host detection of gcc; toolchain information is defined
392 // explicitly in BUILD files.
393 "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1")
Colin Crossff0278b2020-10-09 19:24:15 -0700394 stderr := &bytes.Buffer{}
395 bazelCmd.Stderr = stderr
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400396
397 if output, err := bazelCmd.Output(); err != nil {
Chris Parsons808d84c2021-03-09 20:43:32 -0500398 return "", string(stderr.Bytes()),
399 fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400400 } else {
Chris Parsons808d84c2021-03-09 20:43:32 -0500401 return string(output), string(stderr.Bytes()), nil
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400402 }
403}
404
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400405func (context *bazelContext) mainBzlFileContents() []byte {
Chris Parsons8d6e4332021-02-22 16:13:50 -0500406 // TODO(cparsons): Define configuration transitions programmatically based
407 // on available archs.
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400408 contents := `
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500409#####################################################
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400410# This file is generated by soong_build. Do not edit.
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500411#####################################################
412
Chris Parsonsad0b5ba2021-03-29 21:09:24 -0400413def _config_node_transition_impl(settings, attr):
Chris Parsons8d6e4332021-02-22 16:13:50 -0500414 return {
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200415 "//command_line_option:platforms": "@//build/bazel/platforms:android_%s" % attr.arch,
Chris Parsons8d6e4332021-02-22 16:13:50 -0500416 }
417
Chris Parsonsad0b5ba2021-03-29 21:09:24 -0400418_config_node_transition = transition(
419 implementation = _config_node_transition_impl,
Chris Parsons8d6e4332021-02-22 16:13:50 -0500420 inputs = [],
421 outputs = [
422 "//command_line_option:platforms",
423 ],
424)
425
Chris Parsonsad0b5ba2021-03-29 21:09:24 -0400426def _passthrough_rule_impl(ctx):
427 return [DefaultInfo(files = depset(ctx.files.deps))]
428
429config_node = rule(
430 implementation = _passthrough_rule_impl,
431 attrs = {
432 "arch" : attr.string(mandatory = True),
433 "deps" : attr.label_list(cfg = _config_node_transition),
434 "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
435 },
Chris Parsons8d6e4332021-02-22 16:13:50 -0500436)
437
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400438
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500439# Rule representing the root of the build, to depend on all Bazel targets that
440# are required for the build. Building this target will build the entire Bazel
441# build tree.
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400442mixed_build_root = rule(
Chris Parsonsad0b5ba2021-03-29 21:09:24 -0400443 implementation = _passthrough_rule_impl,
Chris Parsons8d6e4332021-02-22 16:13:50 -0500444 attrs = {
Chris Parsonsad0b5ba2021-03-29 21:09:24 -0400445 "deps" : attr.label_list(),
Chris Parsons8d6e4332021-02-22 16:13:50 -0500446 },
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400447)
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500448
449def _phony_root_impl(ctx):
450 return []
451
452# Rule to depend on other targets but build nothing.
453# This is useful as follows: building a target of this rule will generate
454# symlink forests for all dependencies of the target, without executing any
455# actions of the build.
456phony_root = rule(
457 implementation = _phony_root_impl,
458 attrs = {"deps" : attr.label_list()},
459)
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400460`
461 return []byte(contents)
462}
463
464func (context *bazelContext) mainBuildFileContents() []byte {
Chris Parsons8d6e4332021-02-22 16:13:50 -0500465 // TODO(cparsons): Map label to attribute programmatically; don't use hard-coded
466 // architecture mapping.
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400467 formatString := `
468# This file is generated by soong_build. Do not edit.
Chris Parsonsad0b5ba2021-03-29 21:09:24 -0400469load(":main.bzl", "config_node", "mixed_build_root", "phony_root")
470
471%s
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400472
473mixed_build_root(name = "buildroot",
Chris Parsonsad0b5ba2021-03-29 21:09:24 -0400474 deps = [%s],
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400475)
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500476
477phony_root(name = "phonyroot",
478 deps = [":buildroot"],
479)
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400480`
Chris Parsonsad0b5ba2021-03-29 21:09:24 -0400481 configNodeFormatString := `
482config_node(name = "%s",
483 arch = "%s",
484 deps = [%s],
485)
486`
487
488 configNodesSection := ""
489
490 labelsByArch := map[string][]string{}
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400491 for val, _ := range context.requests {
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200492 labelString := fmt.Sprintf("\"@%s\"", val.label)
Chris Parsonsad0b5ba2021-03-29 21:09:24 -0400493 archString := getArchString(val)
494 labelsByArch[archString] = append(labelsByArch[archString], labelString)
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400495 }
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400496
Chris Parsonsad0b5ba2021-03-29 21:09:24 -0400497 configNodeLabels := []string{}
498 for archString, labels := range labelsByArch {
499 configNodeLabels = append(configNodeLabels, fmt.Sprintf("\":%s\"", archString))
500 labelsString := strings.Join(labels, ",\n ")
501 configNodesSection += fmt.Sprintf(configNodeFormatString, archString, archString, labelsString)
502 }
503
504 return []byte(fmt.Sprintf(formatString, configNodesSection, strings.Join(configNodeLabels, ",\n ")))
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400505}
506
Chris Parsons944e7d02021-03-11 11:08:46 -0500507func indent(original string) string {
508 result := ""
509 for _, line := range strings.Split(original, "\n") {
510 result += " " + line + "\n"
511 }
512 return result
513}
514
Chris Parsons808d84c2021-03-09 20:43:32 -0500515// Returns the file contents of the buildroot.cquery file that should be used for the cquery
516// expression in order to obtain information about buildroot and its dependencies.
517// The contents of this file depend on the bazelContext's requests; requests are enumerated
518// and grouped by their request type. The data retrieved for each label depends on its
519// request type.
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400520func (context *bazelContext) cqueryStarlarkFileContents() []byte {
Liz Kammerf29df7c2021-04-02 13:37:39 -0400521 requestTypeToCqueryIdEntries := map[cqueryRequest][]string{}
Chris Parsons944e7d02021-03-11 11:08:46 -0500522 for val, _ := range context.requests {
523 cqueryId := getCqueryId(val)
524 mapEntryString := fmt.Sprintf("%q : True", cqueryId)
525 requestTypeToCqueryIdEntries[val.requestType] =
526 append(requestTypeToCqueryIdEntries[val.requestType], mapEntryString)
527 }
528 labelRegistrationMapSection := ""
529 functionDefSection := ""
530 mainSwitchSection := ""
531
532 mapDeclarationFormatString := `
533%s = {
534 %s
535}
536`
537 functionDefFormatString := `
538def %s(target):
539%s
540`
541 mainSwitchSectionFormatString := `
542 if id_string in %s:
543 return id_string + ">>" + %s(target)
544`
545
Liz Kammer66ffdb72021-04-02 13:26:07 -0400546 for requestType, _ := range requestTypeToCqueryIdEntries {
Chris Parsons944e7d02021-03-11 11:08:46 -0500547 labelMapName := requestType.Name() + "_Labels"
548 functionName := requestType.Name() + "_Fn"
549 labelRegistrationMapSection += fmt.Sprintf(mapDeclarationFormatString,
550 labelMapName,
551 strings.Join(requestTypeToCqueryIdEntries[requestType], ",\n "))
552 functionDefSection += fmt.Sprintf(functionDefFormatString,
553 functionName,
554 indent(requestType.StarlarkFunctionBody()))
555 mainSwitchSection += fmt.Sprintf(mainSwitchSectionFormatString,
556 labelMapName, functionName)
557 }
558
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400559 formatString := `
560# This file is generated by soong_build. Do not edit.
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400561
Chris Parsons944e7d02021-03-11 11:08:46 -0500562# Label Map Section
563%s
Chris Parsons8d6e4332021-02-22 16:13:50 -0500564
Chris Parsons944e7d02021-03-11 11:08:46 -0500565# Function Def Section
566%s
Chris Parsons8d6e4332021-02-22 16:13:50 -0500567
568def get_arch(target):
569 buildoptions = build_options(target)
570 platforms = build_options(target)["//command_line_option:platforms"]
571 if len(platforms) != 1:
572 # An individual configured target should have only one platform architecture.
573 # Note that it's fine for there to be multiple architectures for the same label,
574 # but each is its own configured target.
575 fail("expected exactly 1 platform for " + str(target.label) + " but got " + str(platforms))
576 platform_name = build_options(target)["//command_line_option:platforms"][0].name
577 if platform_name == "host":
578 return "HOST"
Chris Parsons94a0bba2021-06-04 15:03:47 -0400579 elif platform_name.startswith("android_"):
580 return platform_name[len("android_"):]
581 elif platform_name.startswith("linux_"):
582 return platform_name[len("linux_"):]
583 else:
584 fail("expected platform name of the form 'android_<arch>' or 'linux_<arch>', but was " + str(platforms))
Chris Parsons8d6e4332021-02-22 16:13:50 -0500585 return "UNKNOWN"
Chris Parsons8d6e4332021-02-22 16:13:50 -0500586
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400587def format(target):
Chris Parsons8d6e4332021-02-22 16:13:50 -0500588 id_string = str(target.label) + "|" + get_arch(target)
Chris Parsons944e7d02021-03-11 11:08:46 -0500589
590 # Main switch section
591 %s
592 # This target was not requested via cquery, and thus must be a dependency
593 # of a requested target.
594 return id_string + ">>NONE"
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400595`
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400596
Chris Parsons944e7d02021-03-11 11:08:46 -0500597 return []byte(fmt.Sprintf(formatString, labelRegistrationMapSection, functionDefSection,
598 mainSwitchSection))
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400599}
600
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200601// Returns a path containing build-related metadata required for interfacing
602// with Bazel. Example: out/soong/bazel.
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400603func (p *bazelPaths) intermediatesDir() string {
604 return filepath.Join(p.buildDir, "bazel")
Chris Parsons8ccdb632020-11-17 15:41:01 -0500605}
606
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200607// Returns the path where the contents of the @soong_injection repository live.
608// It is used by Soong to tell Bazel things it cannot over the command line.
609func (p *bazelPaths) injectedFilesDir() string {
Liz Kammer09f947d2021-05-12 14:51:49 -0400610 return filepath.Join(p.buildDir, bazel.SoongInjectionDirName)
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200611}
612
613// Returns the path of the synthetic Bazel workspace that contains a symlink
614// forest composed the whole source tree and BUILD files generated by bp2build.
615func (p *bazelPaths) syntheticWorkspaceDir() string {
616 return filepath.Join(p.buildDir, "workspace")
617}
618
Jingwen Chen8c523582021-06-01 11:19:53 +0000619// Returns the path to the top level out dir ($OUT_DIR).
620func (p *bazelPaths) outDir() string {
621 return filepath.Dir(p.buildDir)
622}
623
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400624// Issues commands to Bazel to receive results for all cquery requests
625// queued in the BazelContext.
626func (context *bazelContext) InvokeBazel() error {
627 context.results = make(map[cqueryKey]string)
628
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400629 var cqueryOutput string
Chris Parsons808d84c2021-03-09 20:43:32 -0500630 var cqueryErr string
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400631 var err error
Chris Parsons8ccdb632020-11-17 15:41:01 -0500632
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200633 soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
Lukacs T. Berki3069dd92021-05-11 16:54:29 +0200634 mixedBuildsPath := filepath.Join(soongInjectionPath, "mixed_builds")
635 if _, err := os.Stat(mixedBuildsPath); os.IsNotExist(err) {
636 err = os.MkdirAll(mixedBuildsPath, 0777)
Chris Parsons07c1e4a2021-01-19 17:19:16 -0500637 }
Chris Parsons8ccdb632020-11-17 15:41:01 -0500638 if err != nil {
639 return err
640 }
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200641
642 err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666)
643 if err != nil {
644 return err
645 }
646
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400647 err = ioutil.WriteFile(
Lukacs T. Berki3069dd92021-05-11 16:54:29 +0200648 filepath.Join(mixedBuildsPath, "main.bzl"),
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400649 context.mainBzlFileContents(), 0666)
650 if err != nil {
651 return err
652 }
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200653
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400654 err = ioutil.WriteFile(
Lukacs T. Berki3069dd92021-05-11 16:54:29 +0200655 filepath.Join(mixedBuildsPath, "BUILD.bazel"),
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400656 context.mainBuildFileContents(), 0666)
657 if err != nil {
658 return err
659 }
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200660 cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400661 err = ioutil.WriteFile(
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800662 absolutePath(cqueryFileRelpath),
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400663 context.cqueryStarlarkFileContents(), 0666)
664 if err != nil {
665 return err
666 }
Lukacs T. Berki3069dd92021-05-11 16:54:29 +0200667 buildrootLabel := "@soong_injection//mixed_builds:buildroot"
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400668 cqueryOutput, cqueryErr, err = context.issueBazelCommand(
669 context.paths,
670 bazel.CqueryBuildRootRunName,
671 bazelCommand{"cquery", fmt.Sprintf("kind(rule, deps(%s))", buildrootLabel)},
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400672 "--output=starlark",
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200673 "--starlark:file="+absolutePath(cqueryFileRelpath))
674 err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"),
Chris Parsons8d6e4332021-02-22 16:13:50 -0500675 []byte(cqueryOutput), 0666)
676 if err != nil {
677 return err
678 }
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400679
680 if err != nil {
681 return err
682 }
683
684 cqueryResults := map[string]string{}
685 for _, outputLine := range strings.Split(cqueryOutput, "\n") {
686 if strings.Contains(outputLine, ">>") {
687 splitLine := strings.SplitN(outputLine, ">>", 2)
688 cqueryResults[splitLine[0]] = splitLine[1]
689 }
690 }
691
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400692 for val, _ := range context.requests {
Chris Parsons8d6e4332021-02-22 16:13:50 -0500693 if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
Chris Parsonsb0f8ac42020-10-23 16:48:08 -0400694 context.results[val] = string(cqueryResult)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400695 } else {
Chris Parsons808d84c2021-03-09 20:43:32 -0500696 return fmt.Errorf("missing result for bazel target %s. query output: [%s], cquery err: [%s]",
697 getCqueryId(val), cqueryOutput, cqueryErr)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400698 }
699 }
700
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500701 // Issue an aquery command to retrieve action information about the bazel build tree.
702 //
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400703 // TODO(cparsons): Use --target_pattern_file to avoid command line limits.
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500704 var aqueryOutput string
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400705 aqueryOutput, _, err = context.issueBazelCommand(
706 context.paths,
707 bazel.AqueryBuildRootRunName,
708 bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)},
709 // Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
710 // proto sources, which would add a number of unnecessary dependencies.
711 "--output=jsonproto")
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400712
713 if err != nil {
714 return err
715 }
716
Chris Parsons4f069892021-01-15 12:22:41 -0500717 context.buildStatements, err = bazel.AqueryBuildStatements([]byte(aqueryOutput))
718 if err != nil {
719 return err
720 }
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500721
722 // Issue a build command of the phony root to generate symlink forests for dependencies of the
723 // Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
724 // but some of symlinks may be required to resolve source dependencies of the build.
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400725 _, _, err = context.issueBazelCommand(
726 context.paths,
727 bazel.BazelBuildPhonyRootRunName,
Lukacs T. Berki3069dd92021-05-11 16:54:29 +0200728 bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"})
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500729
730 if err != nil {
731 return err
732 }
733
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400734 // Clear requests.
735 context.requests = map[cqueryKey]bool{}
736 return nil
737}
Chris Parsonsa798d962020-10-12 23:44:08 -0400738
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500739func (context *bazelContext) BuildStatementsToRegister() []bazel.BuildStatement {
740 return context.buildStatements
741}
742
743func (context *bazelContext) OutputBase() string {
Liz Kammer8d62a4f2021-04-08 09:47:28 -0400744 return context.paths.outputBase
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500745}
746
Chris Parsonsa798d962020-10-12 23:44:08 -0400747// Singleton used for registering BUILD file ninja dependencies (needed
748// for correctness of builds which use Bazel.
749func BazelSingleton() Singleton {
750 return &bazelSingleton{}
751}
752
753type bazelSingleton struct{}
754
755func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500756 // bazelSingleton is a no-op if mixed-soong-bazel-builds are disabled.
757 if !ctx.Config().BazelContext.BazelEnabled() {
758 return
759 }
Chris Parsonsa798d962020-10-12 23:44:08 -0400760
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500761 // Add ninja file dependencies for files which all bazel invocations require.
762 bazelBuildList := absolutePath(filepath.Join(
Lukacs T. Berkid518e1a2021-04-14 13:49:50 +0200763 filepath.Dir(bootstrap.CmdlineArgs.ModuleListFile), "bazel.list"))
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500764 ctx.AddNinjaFileDeps(bazelBuildList)
765
766 data, err := ioutil.ReadFile(bazelBuildList)
767 if err != nil {
768 ctx.Errorf(err.Error())
769 }
770 files := strings.Split(strings.TrimSpace(string(data)), "\n")
771 for _, file := range files {
772 ctx.AddNinjaFileDeps(file)
773 }
774
775 // Register bazel-owned build statements (obtained from the aquery invocation).
776 for index, buildStatement := range ctx.Config().BazelContext.BuildStatementsToRegister() {
Chris Parsons8d6e4332021-02-22 16:13:50 -0500777 if len(buildStatement.Command) < 1 {
Rupert Shuttlewortha29903f2021-04-06 16:17:33 +0000778 panic(fmt.Sprintf("unhandled build statement: %v", buildStatement))
Chris Parsons8d6e4332021-02-22 16:13:50 -0500779 }
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500780 rule := NewRuleBuilder(pctx, ctx)
781 cmd := rule.Command()
Chris Parsons94a0bba2021-06-04 15:03:47 -0400782
783 // cd into Bazel's execution root, which is the action cwd.
784 cmd.Text(fmt.Sprintf("cd %s/execroot/__main__ && ", ctx.Config().BazelContext.OutputBase()))
785
786 for _, pair := range buildStatement.Env {
787 // Set per-action env variables, if any.
788 cmd.Flag(pair.Key + "=" + pair.Value)
789 }
790
791 // The actual Bazel action.
792 cmd.Text(" " + buildStatement.Command)
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500793
794 for _, outputPath := range buildStatement.OutputPaths {
795 cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath))
Chris Parsonsa798d962020-10-12 23:44:08 -0400796 }
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500797 for _, inputPath := range buildStatement.InputPaths {
798 cmd.Implicit(PathForBazelOut(ctx, inputPath))
Chris Parsonsa798d962020-10-12 23:44:08 -0400799 }
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500800
Liz Kammerde116852021-03-25 16:42:37 -0400801 if depfile := buildStatement.Depfile; depfile != nil {
802 cmd.ImplicitDepFile(PathForBazelOut(ctx, *depfile))
803 }
804
Liz Kammerc49e6822021-06-08 15:04:11 -0400805 for _, symlinkPath := range buildStatement.SymlinkPaths {
806 cmd.ImplicitSymlinkOutput(PathForBazelOut(ctx, symlinkPath))
807 }
808
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500809 // This is required to silence warnings pertaining to unexpected timestamps. Particularly,
810 // some Bazel builtins (such as files in the bazel_tools directory) have far-future
811 // timestamps. Without restat, Ninja would emit warnings that the input files of a
812 // build statement have later timestamps than the outputs.
813 rule.Restat()
814
Liz Kammer13548d72020-12-16 11:13:30 -0800815 rule.Build(fmt.Sprintf("bazel %d", index), buildStatement.Mnemonic)
Chris Parsonsa798d962020-10-12 23:44:08 -0400816 }
817}
Chris Parsons8d6e4332021-02-22 16:13:50 -0500818
819func getCqueryId(key cqueryKey) string {
Lukacs T. Berkid6cd8132021-04-20 13:01:07 +0200820 return key.label + "|" + getArchString(key)
Chris Parsons8d6e4332021-02-22 16:13:50 -0500821}
822
823func getArchString(key cqueryKey) string {
824 arch := key.archType.Name
825 if len(arch) > 0 {
826 return arch
827 } else {
828 return "x86_64"
829 }
830}