xref: /aosp_15_r20/build/blueprint/bootstrap/bootstrap.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2014 Google Inc. All rights reserved.
2*1fa6dee9SAndroid Build Coastguard Worker//
3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*1fa6dee9SAndroid Build Coastguard Worker//
7*1fa6dee9SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*1fa6dee9SAndroid Build Coastguard Worker//
9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License.
14*1fa6dee9SAndroid Build Coastguard Worker
15*1fa6dee9SAndroid Build Coastguard Workerpackage bootstrap
16*1fa6dee9SAndroid Build Coastguard Worker
17*1fa6dee9SAndroid Build Coastguard Workerimport (
18*1fa6dee9SAndroid Build Coastguard Worker	"encoding/json"
19*1fa6dee9SAndroid Build Coastguard Worker	"fmt"
20*1fa6dee9SAndroid Build Coastguard Worker	"path/filepath"
21*1fa6dee9SAndroid Build Coastguard Worker	"runtime"
22*1fa6dee9SAndroid Build Coastguard Worker	"strings"
23*1fa6dee9SAndroid Build Coastguard Worker
24*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint"
25*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/pathtools"
26*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
27*1fa6dee9SAndroid Build Coastguard Worker)
28*1fa6dee9SAndroid Build Coastguard Worker
29*1fa6dee9SAndroid Build Coastguard Workervar (
30*1fa6dee9SAndroid Build Coastguard Worker	pctx = blueprint.NewPackageContext("github.com/google/blueprint/bootstrap")
31*1fa6dee9SAndroid Build Coastguard Worker
32*1fa6dee9SAndroid Build Coastguard Worker	goTestMainCmd   = pctx.StaticVariable("goTestMainCmd", filepath.Join("$ToolDir", "gotestmain"))
33*1fa6dee9SAndroid Build Coastguard Worker	goTestRunnerCmd = pctx.StaticVariable("goTestRunnerCmd", filepath.Join("$ToolDir", "gotestrunner"))
34*1fa6dee9SAndroid Build Coastguard Worker	pluginGenSrcCmd = pctx.StaticVariable("pluginGenSrcCmd", filepath.Join("$ToolDir", "loadplugins"))
35*1fa6dee9SAndroid Build Coastguard Worker
36*1fa6dee9SAndroid Build Coastguard Worker	parallelCompile = pctx.StaticVariable("parallelCompile", func() string {
37*1fa6dee9SAndroid Build Coastguard Worker		numCpu := runtime.NumCPU()
38*1fa6dee9SAndroid Build Coastguard Worker		// This will cause us to recompile all go programs if the
39*1fa6dee9SAndroid Build Coastguard Worker		// number of cpus changes. We don't get a lot of benefit from
40*1fa6dee9SAndroid Build Coastguard Worker		// higher values, so cap this to make it cheaper to move trees
41*1fa6dee9SAndroid Build Coastguard Worker		// between machines.
42*1fa6dee9SAndroid Build Coastguard Worker		if numCpu > 8 {
43*1fa6dee9SAndroid Build Coastguard Worker			numCpu = 8
44*1fa6dee9SAndroid Build Coastguard Worker		}
45*1fa6dee9SAndroid Build Coastguard Worker		return fmt.Sprintf("-c %d", numCpu)
46*1fa6dee9SAndroid Build Coastguard Worker	}())
47*1fa6dee9SAndroid Build Coastguard Worker
48*1fa6dee9SAndroid Build Coastguard Worker	compile = pctx.StaticRule("compile",
49*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
50*1fa6dee9SAndroid Build Coastguard Worker			Command: "GOROOT='$goRoot' $compileCmd $parallelCompile -o $out.tmp " +
51*1fa6dee9SAndroid Build Coastguard Worker				"$debugFlags -p $pkgPath -complete $incFlags $embedFlags -pack $in && " +
52*1fa6dee9SAndroid Build Coastguard Worker				"if cmp --quiet $out.tmp $out; then rm $out.tmp; else mv -f $out.tmp $out; fi",
53*1fa6dee9SAndroid Build Coastguard Worker			CommandDeps: []string{"$compileCmd"},
54*1fa6dee9SAndroid Build Coastguard Worker			Description: "compile $out",
55*1fa6dee9SAndroid Build Coastguard Worker			Restat:      true,
56*1fa6dee9SAndroid Build Coastguard Worker		},
57*1fa6dee9SAndroid Build Coastguard Worker		"pkgPath", "incFlags", "embedFlags")
58*1fa6dee9SAndroid Build Coastguard Worker
59*1fa6dee9SAndroid Build Coastguard Worker	link = pctx.StaticRule("link",
60*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
61*1fa6dee9SAndroid Build Coastguard Worker			Command: "GOROOT='$goRoot' $linkCmd -o $out.tmp $libDirFlags $in && " +
62*1fa6dee9SAndroid Build Coastguard Worker				"if cmp --quiet $out.tmp $out; then rm $out.tmp; else mv -f $out.tmp $out; fi",
63*1fa6dee9SAndroid Build Coastguard Worker			CommandDeps: []string{"$linkCmd"},
64*1fa6dee9SAndroid Build Coastguard Worker			Description: "link $out",
65*1fa6dee9SAndroid Build Coastguard Worker			Restat:      true,
66*1fa6dee9SAndroid Build Coastguard Worker		},
67*1fa6dee9SAndroid Build Coastguard Worker		"libDirFlags")
68*1fa6dee9SAndroid Build Coastguard Worker
69*1fa6dee9SAndroid Build Coastguard Worker	goTestMain = pctx.StaticRule("gotestmain",
70*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
71*1fa6dee9SAndroid Build Coastguard Worker			Command:     "$goTestMainCmd -o $out -pkg $pkg $in",
72*1fa6dee9SAndroid Build Coastguard Worker			CommandDeps: []string{"$goTestMainCmd"},
73*1fa6dee9SAndroid Build Coastguard Worker			Description: "gotestmain $out",
74*1fa6dee9SAndroid Build Coastguard Worker		},
75*1fa6dee9SAndroid Build Coastguard Worker		"pkg")
76*1fa6dee9SAndroid Build Coastguard Worker
77*1fa6dee9SAndroid Build Coastguard Worker	pluginGenSrc = pctx.StaticRule("pluginGenSrc",
78*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
79*1fa6dee9SAndroid Build Coastguard Worker			Command:     "$pluginGenSrcCmd -o $out -p $pkg $plugins",
80*1fa6dee9SAndroid Build Coastguard Worker			CommandDeps: []string{"$pluginGenSrcCmd"},
81*1fa6dee9SAndroid Build Coastguard Worker			Description: "create $out",
82*1fa6dee9SAndroid Build Coastguard Worker		},
83*1fa6dee9SAndroid Build Coastguard Worker		"pkg", "plugins")
84*1fa6dee9SAndroid Build Coastguard Worker
85*1fa6dee9SAndroid Build Coastguard Worker	test = pctx.StaticRule("test",
86*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
87*1fa6dee9SAndroid Build Coastguard Worker			Command:     "$goTestRunnerCmd -p $pkgSrcDir -f $out -- $in -test.short",
88*1fa6dee9SAndroid Build Coastguard Worker			CommandDeps: []string{"$goTestRunnerCmd"},
89*1fa6dee9SAndroid Build Coastguard Worker			Description: "test $pkg",
90*1fa6dee9SAndroid Build Coastguard Worker		},
91*1fa6dee9SAndroid Build Coastguard Worker		"pkg", "pkgSrcDir")
92*1fa6dee9SAndroid Build Coastguard Worker
93*1fa6dee9SAndroid Build Coastguard Worker	cp = pctx.StaticRule("cp",
94*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
95*1fa6dee9SAndroid Build Coastguard Worker			Command:     "cp $in $out",
96*1fa6dee9SAndroid Build Coastguard Worker			Description: "cp $out",
97*1fa6dee9SAndroid Build Coastguard Worker		},
98*1fa6dee9SAndroid Build Coastguard Worker		"generator")
99*1fa6dee9SAndroid Build Coastguard Worker
100*1fa6dee9SAndroid Build Coastguard Worker	touch = pctx.StaticRule("touch",
101*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
102*1fa6dee9SAndroid Build Coastguard Worker			Command:     "touch $out",
103*1fa6dee9SAndroid Build Coastguard Worker			Description: "touch $out",
104*1fa6dee9SAndroid Build Coastguard Worker		},
105*1fa6dee9SAndroid Build Coastguard Worker		"depfile", "generator")
106*1fa6dee9SAndroid Build Coastguard Worker
107*1fa6dee9SAndroid Build Coastguard Worker	cat = pctx.StaticRule("Cat",
108*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
109*1fa6dee9SAndroid Build Coastguard Worker			Command:     "rm -f $out && cat $in > $out",
110*1fa6dee9SAndroid Build Coastguard Worker			Description: "concatenate files to $out",
111*1fa6dee9SAndroid Build Coastguard Worker		})
112*1fa6dee9SAndroid Build Coastguard Worker
113*1fa6dee9SAndroid Build Coastguard Worker	// ubuntu 14.04 offcially use dash for /bin/sh, and its builtin echo command
114*1fa6dee9SAndroid Build Coastguard Worker	// doesn't support -e option. Therefore we force to use /bin/bash when writing out
115*1fa6dee9SAndroid Build Coastguard Worker	// content to file.
116*1fa6dee9SAndroid Build Coastguard Worker	writeFile = pctx.StaticRule("writeFile",
117*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
118*1fa6dee9SAndroid Build Coastguard Worker			Command:     `rm -f $out && /bin/bash -c 'echo -e -n "$$0" > $out' $content`,
119*1fa6dee9SAndroid Build Coastguard Worker			Description: "writing file $out",
120*1fa6dee9SAndroid Build Coastguard Worker		},
121*1fa6dee9SAndroid Build Coastguard Worker		"content")
122*1fa6dee9SAndroid Build Coastguard Worker
123*1fa6dee9SAndroid Build Coastguard Worker	generateBuildNinja = pctx.StaticRule("build.ninja",
124*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
125*1fa6dee9SAndroid Build Coastguard Worker			// TODO: it's kinda ugly that some parameters are computed from
126*1fa6dee9SAndroid Build Coastguard Worker			// environment variables and some from Ninja parameters, but it's probably
127*1fa6dee9SAndroid Build Coastguard Worker			// better to not to touch that while Blueprint and Soong are separate
128*1fa6dee9SAndroid Build Coastguard Worker			// NOTE: The spaces at EOL are important because otherwise Ninja would
129*1fa6dee9SAndroid Build Coastguard Worker			// omit all spaces between the different options.
130*1fa6dee9SAndroid Build Coastguard Worker			Command: `cd "$$(dirname "$builder")" && ` +
131*1fa6dee9SAndroid Build Coastguard Worker				`BUILDER="$$PWD/$$(basename "$builder")" && ` +
132*1fa6dee9SAndroid Build Coastguard Worker				`cd / && ` +
133*1fa6dee9SAndroid Build Coastguard Worker				`env -i $env "$$BUILDER" ` +
134*1fa6dee9SAndroid Build Coastguard Worker				`    --top "$$TOP" ` +
135*1fa6dee9SAndroid Build Coastguard Worker				`    --soong_out "$soongOutDir" ` +
136*1fa6dee9SAndroid Build Coastguard Worker				`    --out "$outDir" ` +
137*1fa6dee9SAndroid Build Coastguard Worker				`    $extra`,
138*1fa6dee9SAndroid Build Coastguard Worker			CommandDeps: []string{"$builder"},
139*1fa6dee9SAndroid Build Coastguard Worker			Description: "$builder $out",
140*1fa6dee9SAndroid Build Coastguard Worker			Deps:        blueprint.DepsGCC,
141*1fa6dee9SAndroid Build Coastguard Worker			Depfile:     "$out.d",
142*1fa6dee9SAndroid Build Coastguard Worker			Restat:      true,
143*1fa6dee9SAndroid Build Coastguard Worker		},
144*1fa6dee9SAndroid Build Coastguard Worker		"builder", "env", "extra", "pool")
145*1fa6dee9SAndroid Build Coastguard Worker
146*1fa6dee9SAndroid Build Coastguard Worker	// Work around a Ninja issue.  See https://github.com/martine/ninja/pull/634
147*1fa6dee9SAndroid Build Coastguard Worker	phony = pctx.StaticRule("phony",
148*1fa6dee9SAndroid Build Coastguard Worker		blueprint.RuleParams{
149*1fa6dee9SAndroid Build Coastguard Worker			Command:     "# phony $out",
150*1fa6dee9SAndroid Build Coastguard Worker			Description: "phony $out",
151*1fa6dee9SAndroid Build Coastguard Worker			Generator:   true,
152*1fa6dee9SAndroid Build Coastguard Worker		},
153*1fa6dee9SAndroid Build Coastguard Worker		"depfile")
154*1fa6dee9SAndroid Build Coastguard Worker
155*1fa6dee9SAndroid Build Coastguard Worker	_ = pctx.VariableFunc("ToolDir", func(ctx blueprint.VariableFuncContext, config interface{}) (string, error) {
156*1fa6dee9SAndroid Build Coastguard Worker		return config.(BootstrapConfig).HostToolDir(), nil
157*1fa6dee9SAndroid Build Coastguard Worker	})
158*1fa6dee9SAndroid Build Coastguard Worker)
159*1fa6dee9SAndroid Build Coastguard Worker
160*1fa6dee9SAndroid Build Coastguard Workervar (
161*1fa6dee9SAndroid Build Coastguard Worker	// echoEscaper escapes a string such that passing it to "echo -e" will produce the input value.
162*1fa6dee9SAndroid Build Coastguard Worker	echoEscaper = strings.NewReplacer(
163*1fa6dee9SAndroid Build Coastguard Worker		`\`, `\\`, // First escape existing backslashes so they aren't interpreted by `echo -e`.
164*1fa6dee9SAndroid Build Coastguard Worker		"\n", `\n`, // Then replace newlines with \n
165*1fa6dee9SAndroid Build Coastguard Worker	)
166*1fa6dee9SAndroid Build Coastguard Worker)
167*1fa6dee9SAndroid Build Coastguard Worker
168*1fa6dee9SAndroid Build Coastguard Worker// shardString takes a string and returns a slice of strings where the length of each one is
169*1fa6dee9SAndroid Build Coastguard Worker// at most shardSize.
170*1fa6dee9SAndroid Build Coastguard Workerfunc shardString(s string, shardSize int) []string {
171*1fa6dee9SAndroid Build Coastguard Worker	if len(s) == 0 {
172*1fa6dee9SAndroid Build Coastguard Worker		return nil
173*1fa6dee9SAndroid Build Coastguard Worker	}
174*1fa6dee9SAndroid Build Coastguard Worker	ret := make([]string, 0, (len(s)+shardSize-1)/shardSize)
175*1fa6dee9SAndroid Build Coastguard Worker	for len(s) > shardSize {
176*1fa6dee9SAndroid Build Coastguard Worker		ret = append(ret, s[0:shardSize])
177*1fa6dee9SAndroid Build Coastguard Worker		s = s[shardSize:]
178*1fa6dee9SAndroid Build Coastguard Worker	}
179*1fa6dee9SAndroid Build Coastguard Worker	if len(s) > 0 {
180*1fa6dee9SAndroid Build Coastguard Worker		ret = append(ret, s)
181*1fa6dee9SAndroid Build Coastguard Worker	}
182*1fa6dee9SAndroid Build Coastguard Worker	return ret
183*1fa6dee9SAndroid Build Coastguard Worker}
184*1fa6dee9SAndroid Build Coastguard Worker
185*1fa6dee9SAndroid Build Coastguard Worker// writeFileRule creates a ninja rule to write contents to a file.  The contents will be
186*1fa6dee9SAndroid Build Coastguard Worker// escaped so that the file contains exactly the contents passed to the function.
187*1fa6dee9SAndroid Build Coastguard Workerfunc writeFileRule(ctx blueprint.ModuleContext, outputFile string, content string) {
188*1fa6dee9SAndroid Build Coastguard Worker	// This is MAX_ARG_STRLEN subtracted with some safety to account for shell escapes
189*1fa6dee9SAndroid Build Coastguard Worker	const SHARD_SIZE = 131072 - 10000
190*1fa6dee9SAndroid Build Coastguard Worker
191*1fa6dee9SAndroid Build Coastguard Worker	buildWriteFileRule := func(outputFile string, content string) {
192*1fa6dee9SAndroid Build Coastguard Worker		content = echoEscaper.Replace(content)
193*1fa6dee9SAndroid Build Coastguard Worker		content = proptools.NinjaEscape(proptools.ShellEscapeIncludingSpaces(content))
194*1fa6dee9SAndroid Build Coastguard Worker		if content == "" {
195*1fa6dee9SAndroid Build Coastguard Worker			content = "''"
196*1fa6dee9SAndroid Build Coastguard Worker		}
197*1fa6dee9SAndroid Build Coastguard Worker		ctx.Build(pctx, blueprint.BuildParams{
198*1fa6dee9SAndroid Build Coastguard Worker			Rule:        writeFile,
199*1fa6dee9SAndroid Build Coastguard Worker			Outputs:     []string{outputFile},
200*1fa6dee9SAndroid Build Coastguard Worker			Description: "write " + outputFile,
201*1fa6dee9SAndroid Build Coastguard Worker			Args: map[string]string{
202*1fa6dee9SAndroid Build Coastguard Worker				"content": content,
203*1fa6dee9SAndroid Build Coastguard Worker			},
204*1fa6dee9SAndroid Build Coastguard Worker		})
205*1fa6dee9SAndroid Build Coastguard Worker	}
206*1fa6dee9SAndroid Build Coastguard Worker
207*1fa6dee9SAndroid Build Coastguard Worker	if len(content) > SHARD_SIZE {
208*1fa6dee9SAndroid Build Coastguard Worker		var chunks []string
209*1fa6dee9SAndroid Build Coastguard Worker		for i, c := range shardString(content, SHARD_SIZE) {
210*1fa6dee9SAndroid Build Coastguard Worker			tempPath := fmt.Sprintf("%s.%d", outputFile, i)
211*1fa6dee9SAndroid Build Coastguard Worker			buildWriteFileRule(tempPath, c)
212*1fa6dee9SAndroid Build Coastguard Worker			chunks = append(chunks, tempPath)
213*1fa6dee9SAndroid Build Coastguard Worker		}
214*1fa6dee9SAndroid Build Coastguard Worker		ctx.Build(pctx, blueprint.BuildParams{
215*1fa6dee9SAndroid Build Coastguard Worker			Rule:        cat,
216*1fa6dee9SAndroid Build Coastguard Worker			Inputs:      chunks,
217*1fa6dee9SAndroid Build Coastguard Worker			Outputs:     []string{outputFile},
218*1fa6dee9SAndroid Build Coastguard Worker			Description: "Merging to " + outputFile,
219*1fa6dee9SAndroid Build Coastguard Worker		})
220*1fa6dee9SAndroid Build Coastguard Worker		return
221*1fa6dee9SAndroid Build Coastguard Worker	}
222*1fa6dee9SAndroid Build Coastguard Worker	buildWriteFileRule(outputFile, content)
223*1fa6dee9SAndroid Build Coastguard Worker}
224*1fa6dee9SAndroid Build Coastguard Worker
225*1fa6dee9SAndroid Build Coastguard Workertype pluginDependencyTag struct {
226*1fa6dee9SAndroid Build Coastguard Worker	blueprint.BaseDependencyTag
227*1fa6dee9SAndroid Build Coastguard Worker}
228*1fa6dee9SAndroid Build Coastguard Worker
229*1fa6dee9SAndroid Build Coastguard Workertype bootstrapDependencies interface {
230*1fa6dee9SAndroid Build Coastguard Worker	bootstrapDeps(ctx blueprint.BottomUpMutatorContext)
231*1fa6dee9SAndroid Build Coastguard Worker}
232*1fa6dee9SAndroid Build Coastguard Worker
233*1fa6dee9SAndroid Build Coastguard Workervar pluginDepTag = pluginDependencyTag{}
234*1fa6dee9SAndroid Build Coastguard Worker
235*1fa6dee9SAndroid Build Coastguard Workerfunc BootstrapDeps(ctx blueprint.BottomUpMutatorContext) {
236*1fa6dee9SAndroid Build Coastguard Worker	if pkg, ok := ctx.Module().(bootstrapDependencies); ok {
237*1fa6dee9SAndroid Build Coastguard Worker		pkg.bootstrapDeps(ctx)
238*1fa6dee9SAndroid Build Coastguard Worker	}
239*1fa6dee9SAndroid Build Coastguard Worker}
240*1fa6dee9SAndroid Build Coastguard Worker
241*1fa6dee9SAndroid Build Coastguard Workertype PackageInfo struct {
242*1fa6dee9SAndroid Build Coastguard Worker	PkgPath       string
243*1fa6dee9SAndroid Build Coastguard Worker	PkgRoot       string
244*1fa6dee9SAndroid Build Coastguard Worker	PackageTarget string
245*1fa6dee9SAndroid Build Coastguard Worker	TestTargets   []string
246*1fa6dee9SAndroid Build Coastguard Worker}
247*1fa6dee9SAndroid Build Coastguard Worker
248*1fa6dee9SAndroid Build Coastguard Workervar PackageProvider = blueprint.NewProvider[*PackageInfo]()
249*1fa6dee9SAndroid Build Coastguard Worker
250*1fa6dee9SAndroid Build Coastguard Workertype BinaryInfo struct {
251*1fa6dee9SAndroid Build Coastguard Worker	IntermediatePath string
252*1fa6dee9SAndroid Build Coastguard Worker	InstallPath      string
253*1fa6dee9SAndroid Build Coastguard Worker	TestTargets      []string
254*1fa6dee9SAndroid Build Coastguard Worker}
255*1fa6dee9SAndroid Build Coastguard Worker
256*1fa6dee9SAndroid Build Coastguard Workervar BinaryProvider = blueprint.NewProvider[*BinaryInfo]()
257*1fa6dee9SAndroid Build Coastguard Worker
258*1fa6dee9SAndroid Build Coastguard Workertype DocsPackageInfo struct {
259*1fa6dee9SAndroid Build Coastguard Worker	PkgPath string
260*1fa6dee9SAndroid Build Coastguard Worker	Srcs    []string
261*1fa6dee9SAndroid Build Coastguard Worker}
262*1fa6dee9SAndroid Build Coastguard Worker
263*1fa6dee9SAndroid Build Coastguard Workervar DocsPackageProvider = blueprint.NewMutatorProvider[*DocsPackageInfo]("bootstrap_deps")
264*1fa6dee9SAndroid Build Coastguard Worker
265*1fa6dee9SAndroid Build Coastguard Worker// A GoPackage is a module for building Go packages.
266*1fa6dee9SAndroid Build Coastguard Workertype GoPackage struct {
267*1fa6dee9SAndroid Build Coastguard Worker	blueprint.SimpleName
268*1fa6dee9SAndroid Build Coastguard Worker	properties struct {
269*1fa6dee9SAndroid Build Coastguard Worker		Deps      []string
270*1fa6dee9SAndroid Build Coastguard Worker		PkgPath   string
271*1fa6dee9SAndroid Build Coastguard Worker		Srcs      []string
272*1fa6dee9SAndroid Build Coastguard Worker		TestSrcs  []string
273*1fa6dee9SAndroid Build Coastguard Worker		TestData  []string
274*1fa6dee9SAndroid Build Coastguard Worker		PluginFor []string
275*1fa6dee9SAndroid Build Coastguard Worker		EmbedSrcs []string
276*1fa6dee9SAndroid Build Coastguard Worker		// The visibility property is unused in blueprint, but exists so that soong
277*1fa6dee9SAndroid Build Coastguard Worker		// can add one and not have the bp files fail to parse during the bootstrap build.
278*1fa6dee9SAndroid Build Coastguard Worker		Visibility []string
279*1fa6dee9SAndroid Build Coastguard Worker
280*1fa6dee9SAndroid Build Coastguard Worker		Darwin struct {
281*1fa6dee9SAndroid Build Coastguard Worker			Srcs     []string
282*1fa6dee9SAndroid Build Coastguard Worker			TestSrcs []string
283*1fa6dee9SAndroid Build Coastguard Worker		}
284*1fa6dee9SAndroid Build Coastguard Worker		Linux struct {
285*1fa6dee9SAndroid Build Coastguard Worker			Srcs     []string
286*1fa6dee9SAndroid Build Coastguard Worker			TestSrcs []string
287*1fa6dee9SAndroid Build Coastguard Worker		}
288*1fa6dee9SAndroid Build Coastguard Worker	}
289*1fa6dee9SAndroid Build Coastguard Worker}
290*1fa6dee9SAndroid Build Coastguard Worker
291*1fa6dee9SAndroid Build Coastguard Workerfunc newGoPackageModuleFactory() func() (blueprint.Module, []interface{}) {
292*1fa6dee9SAndroid Build Coastguard Worker	return func() (blueprint.Module, []interface{}) {
293*1fa6dee9SAndroid Build Coastguard Worker		module := &GoPackage{}
294*1fa6dee9SAndroid Build Coastguard Worker		return module, []interface{}{&module.properties, &module.SimpleName.Properties}
295*1fa6dee9SAndroid Build Coastguard Worker	}
296*1fa6dee9SAndroid Build Coastguard Worker}
297*1fa6dee9SAndroid Build Coastguard Worker
298*1fa6dee9SAndroid Build Coastguard Worker// Properties returns the list of property structs to be used for registering a wrapped module type.
299*1fa6dee9SAndroid Build Coastguard Workerfunc (g *GoPackage) Properties() []interface{} {
300*1fa6dee9SAndroid Build Coastguard Worker	return []interface{}{&g.properties}
301*1fa6dee9SAndroid Build Coastguard Worker}
302*1fa6dee9SAndroid Build Coastguard Worker
303*1fa6dee9SAndroid Build Coastguard Workerfunc (g *GoPackage) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
304*1fa6dee9SAndroid Build Coastguard Worker	return g.properties.Deps
305*1fa6dee9SAndroid Build Coastguard Worker}
306*1fa6dee9SAndroid Build Coastguard Worker
307*1fa6dee9SAndroid Build Coastguard Workerfunc (g *GoPackage) bootstrapDeps(ctx blueprint.BottomUpMutatorContext) {
308*1fa6dee9SAndroid Build Coastguard Worker	for _, plugin := range g.properties.PluginFor {
309*1fa6dee9SAndroid Build Coastguard Worker		ctx.AddReverseDependency(ctx.Module(), pluginDepTag, plugin)
310*1fa6dee9SAndroid Build Coastguard Worker	}
311*1fa6dee9SAndroid Build Coastguard Worker	blueprint.SetProvider(ctx, DocsPackageProvider, &DocsPackageInfo{
312*1fa6dee9SAndroid Build Coastguard Worker		PkgPath: g.properties.PkgPath,
313*1fa6dee9SAndroid Build Coastguard Worker		Srcs:    g.properties.Srcs,
314*1fa6dee9SAndroid Build Coastguard Worker	})
315*1fa6dee9SAndroid Build Coastguard Worker}
316*1fa6dee9SAndroid Build Coastguard Worker
317*1fa6dee9SAndroid Build Coastguard Workerfunc (g *GoPackage) GenerateBuildActions(ctx blueprint.ModuleContext) {
318*1fa6dee9SAndroid Build Coastguard Worker	var (
319*1fa6dee9SAndroid Build Coastguard Worker		name       = ctx.ModuleName()
320*1fa6dee9SAndroid Build Coastguard Worker		hasPlugins = false
321*1fa6dee9SAndroid Build Coastguard Worker		pluginSrc  = ""
322*1fa6dee9SAndroid Build Coastguard Worker		genSrcs    = []string{}
323*1fa6dee9SAndroid Build Coastguard Worker	)
324*1fa6dee9SAndroid Build Coastguard Worker
325*1fa6dee9SAndroid Build Coastguard Worker	if g.properties.PkgPath == "" {
326*1fa6dee9SAndroid Build Coastguard Worker		ctx.ModuleErrorf("module %s did not specify a valid pkgPath", name)
327*1fa6dee9SAndroid Build Coastguard Worker		return
328*1fa6dee9SAndroid Build Coastguard Worker	}
329*1fa6dee9SAndroid Build Coastguard Worker
330*1fa6dee9SAndroid Build Coastguard Worker	pkgRoot := packageRoot(ctx)
331*1fa6dee9SAndroid Build Coastguard Worker	archiveFile := filepath.Join(pkgRoot,
332*1fa6dee9SAndroid Build Coastguard Worker		filepath.FromSlash(g.properties.PkgPath)+".a")
333*1fa6dee9SAndroid Build Coastguard Worker
334*1fa6dee9SAndroid Build Coastguard Worker	ctx.VisitDepsDepthFirst(func(module blueprint.Module) {
335*1fa6dee9SAndroid Build Coastguard Worker		if ctx.OtherModuleDependencyTag(module) == pluginDepTag {
336*1fa6dee9SAndroid Build Coastguard Worker			hasPlugins = true
337*1fa6dee9SAndroid Build Coastguard Worker		}
338*1fa6dee9SAndroid Build Coastguard Worker	})
339*1fa6dee9SAndroid Build Coastguard Worker	if hasPlugins {
340*1fa6dee9SAndroid Build Coastguard Worker		pluginSrc = filepath.Join(moduleGenSrcDir(ctx), "plugin.go")
341*1fa6dee9SAndroid Build Coastguard Worker		genSrcs = append(genSrcs, pluginSrc)
342*1fa6dee9SAndroid Build Coastguard Worker	}
343*1fa6dee9SAndroid Build Coastguard Worker
344*1fa6dee9SAndroid Build Coastguard Worker	if hasPlugins && !buildGoPluginLoader(ctx, g.properties.PkgPath, pluginSrc) {
345*1fa6dee9SAndroid Build Coastguard Worker		return
346*1fa6dee9SAndroid Build Coastguard Worker	}
347*1fa6dee9SAndroid Build Coastguard Worker
348*1fa6dee9SAndroid Build Coastguard Worker	var srcs, testSrcs []string
349*1fa6dee9SAndroid Build Coastguard Worker	if runtime.GOOS == "darwin" {
350*1fa6dee9SAndroid Build Coastguard Worker		srcs = append(g.properties.Srcs, g.properties.Darwin.Srcs...)
351*1fa6dee9SAndroid Build Coastguard Worker		testSrcs = append(g.properties.TestSrcs, g.properties.Darwin.TestSrcs...)
352*1fa6dee9SAndroid Build Coastguard Worker	} else if runtime.GOOS == "linux" {
353*1fa6dee9SAndroid Build Coastguard Worker		srcs = append(g.properties.Srcs, g.properties.Linux.Srcs...)
354*1fa6dee9SAndroid Build Coastguard Worker		testSrcs = append(g.properties.TestSrcs, g.properties.Linux.TestSrcs...)
355*1fa6dee9SAndroid Build Coastguard Worker	}
356*1fa6dee9SAndroid Build Coastguard Worker
357*1fa6dee9SAndroid Build Coastguard Worker	testArchiveFile := filepath.Join(testRoot(ctx),
358*1fa6dee9SAndroid Build Coastguard Worker		filepath.FromSlash(g.properties.PkgPath)+".a")
359*1fa6dee9SAndroid Build Coastguard Worker	testResultFile := buildGoTest(ctx, testRoot(ctx), testArchiveFile,
360*1fa6dee9SAndroid Build Coastguard Worker		g.properties.PkgPath, srcs, genSrcs, testSrcs, g.properties.EmbedSrcs)
361*1fa6dee9SAndroid Build Coastguard Worker
362*1fa6dee9SAndroid Build Coastguard Worker	// Don't build for test-only packages
363*1fa6dee9SAndroid Build Coastguard Worker	if len(srcs) == 0 && len(genSrcs) == 0 {
364*1fa6dee9SAndroid Build Coastguard Worker		ctx.Build(pctx, blueprint.BuildParams{
365*1fa6dee9SAndroid Build Coastguard Worker			Rule:     touch,
366*1fa6dee9SAndroid Build Coastguard Worker			Outputs:  []string{archiveFile},
367*1fa6dee9SAndroid Build Coastguard Worker			Optional: true,
368*1fa6dee9SAndroid Build Coastguard Worker		})
369*1fa6dee9SAndroid Build Coastguard Worker		return
370*1fa6dee9SAndroid Build Coastguard Worker	}
371*1fa6dee9SAndroid Build Coastguard Worker
372*1fa6dee9SAndroid Build Coastguard Worker	buildGoPackage(ctx, pkgRoot, g.properties.PkgPath, archiveFile,
373*1fa6dee9SAndroid Build Coastguard Worker		srcs, genSrcs, g.properties.EmbedSrcs)
374*1fa6dee9SAndroid Build Coastguard Worker	blueprint.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs})
375*1fa6dee9SAndroid Build Coastguard Worker	blueprint.SetProvider(ctx, PackageProvider, &PackageInfo{
376*1fa6dee9SAndroid Build Coastguard Worker		PkgPath:       g.properties.PkgPath,
377*1fa6dee9SAndroid Build Coastguard Worker		PkgRoot:       pkgRoot,
378*1fa6dee9SAndroid Build Coastguard Worker		PackageTarget: archiveFile,
379*1fa6dee9SAndroid Build Coastguard Worker		TestTargets:   testResultFile,
380*1fa6dee9SAndroid Build Coastguard Worker	})
381*1fa6dee9SAndroid Build Coastguard Worker}
382*1fa6dee9SAndroid Build Coastguard Worker
383*1fa6dee9SAndroid Build Coastguard Worker// A GoBinary is a module for building executable binaries from Go sources.
384*1fa6dee9SAndroid Build Coastguard Workertype GoBinary struct {
385*1fa6dee9SAndroid Build Coastguard Worker	blueprint.SimpleName
386*1fa6dee9SAndroid Build Coastguard Worker	properties struct {
387*1fa6dee9SAndroid Build Coastguard Worker		Deps           []string
388*1fa6dee9SAndroid Build Coastguard Worker		Srcs           []string
389*1fa6dee9SAndroid Build Coastguard Worker		TestSrcs       []string
390*1fa6dee9SAndroid Build Coastguard Worker		TestData       []string
391*1fa6dee9SAndroid Build Coastguard Worker		EmbedSrcs      []string
392*1fa6dee9SAndroid Build Coastguard Worker		PrimaryBuilder bool
393*1fa6dee9SAndroid Build Coastguard Worker		Default        bool
394*1fa6dee9SAndroid Build Coastguard Worker		// The visibility property is unused in blueprint, but exists so that soong
395*1fa6dee9SAndroid Build Coastguard Worker		// can add one and not have the bp files fail to parse during the bootstrap build.
396*1fa6dee9SAndroid Build Coastguard Worker		Visibility []string
397*1fa6dee9SAndroid Build Coastguard Worker
398*1fa6dee9SAndroid Build Coastguard Worker		Darwin struct {
399*1fa6dee9SAndroid Build Coastguard Worker			Srcs     []string
400*1fa6dee9SAndroid Build Coastguard Worker			TestSrcs []string
401*1fa6dee9SAndroid Build Coastguard Worker		}
402*1fa6dee9SAndroid Build Coastguard Worker		Linux struct {
403*1fa6dee9SAndroid Build Coastguard Worker			Srcs     []string
404*1fa6dee9SAndroid Build Coastguard Worker			TestSrcs []string
405*1fa6dee9SAndroid Build Coastguard Worker		}
406*1fa6dee9SAndroid Build Coastguard Worker	}
407*1fa6dee9SAndroid Build Coastguard Worker
408*1fa6dee9SAndroid Build Coastguard Worker	installPath string
409*1fa6dee9SAndroid Build Coastguard Worker
410*1fa6dee9SAndroid Build Coastguard Worker	// skipInstall can be set to true by a module type that wraps GoBinary to skip the install rule,
411*1fa6dee9SAndroid Build Coastguard Worker	// allowing the wrapping module type to create the install rule itself.
412*1fa6dee9SAndroid Build Coastguard Worker	skipInstall bool
413*1fa6dee9SAndroid Build Coastguard Worker
414*1fa6dee9SAndroid Build Coastguard Worker	// outputFile is set to the path to the intermediate output file.
415*1fa6dee9SAndroid Build Coastguard Worker	outputFile string
416*1fa6dee9SAndroid Build Coastguard Worker}
417*1fa6dee9SAndroid Build Coastguard Worker
418*1fa6dee9SAndroid Build Coastguard Workerfunc newGoBinaryModuleFactory() func() (blueprint.Module, []interface{}) {
419*1fa6dee9SAndroid Build Coastguard Worker	return func() (blueprint.Module, []interface{}) {
420*1fa6dee9SAndroid Build Coastguard Worker		module := &GoBinary{}
421*1fa6dee9SAndroid Build Coastguard Worker		return module, []interface{}{&module.properties, &module.SimpleName.Properties}
422*1fa6dee9SAndroid Build Coastguard Worker	}
423*1fa6dee9SAndroid Build Coastguard Worker}
424*1fa6dee9SAndroid Build Coastguard Worker
425*1fa6dee9SAndroid Build Coastguard Workerfunc (g *GoBinary) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
426*1fa6dee9SAndroid Build Coastguard Worker	return g.properties.Deps
427*1fa6dee9SAndroid Build Coastguard Worker}
428*1fa6dee9SAndroid Build Coastguard Worker
429*1fa6dee9SAndroid Build Coastguard Workerfunc (g *GoBinary) bootstrapDeps(ctx blueprint.BottomUpMutatorContext) {
430*1fa6dee9SAndroid Build Coastguard Worker	if g.properties.PrimaryBuilder {
431*1fa6dee9SAndroid Build Coastguard Worker		blueprint.SetProvider(ctx, PrimaryBuilderProvider, PrimaryBuilderInfo{})
432*1fa6dee9SAndroid Build Coastguard Worker	}
433*1fa6dee9SAndroid Build Coastguard Worker}
434*1fa6dee9SAndroid Build Coastguard Worker
435*1fa6dee9SAndroid Build Coastguard Worker// IntermediateFile returns the path to the final linked intermedate file.
436*1fa6dee9SAndroid Build Coastguard Workerfunc (g *GoBinary) IntermediateFile() string {
437*1fa6dee9SAndroid Build Coastguard Worker	return g.outputFile
438*1fa6dee9SAndroid Build Coastguard Worker}
439*1fa6dee9SAndroid Build Coastguard Worker
440*1fa6dee9SAndroid Build Coastguard Worker// SetSkipInstall is called by module types that wrap GoBinary to skip the install rule,
441*1fa6dee9SAndroid Build Coastguard Worker// allowing the wrapping module type to create the install rule itself.
442*1fa6dee9SAndroid Build Coastguard Workerfunc (g *GoBinary) SetSkipInstall() {
443*1fa6dee9SAndroid Build Coastguard Worker	g.skipInstall = true
444*1fa6dee9SAndroid Build Coastguard Worker}
445*1fa6dee9SAndroid Build Coastguard Worker
446*1fa6dee9SAndroid Build Coastguard Worker// Properties returns the list of property structs to be used for registering a wrapped module type.
447*1fa6dee9SAndroid Build Coastguard Workerfunc (g *GoBinary) Properties() []interface{} {
448*1fa6dee9SAndroid Build Coastguard Worker	return []interface{}{&g.properties}
449*1fa6dee9SAndroid Build Coastguard Worker}
450*1fa6dee9SAndroid Build Coastguard Worker
451*1fa6dee9SAndroid Build Coastguard Workerfunc (g *GoBinary) GenerateBuildActions(ctx blueprint.ModuleContext) {
452*1fa6dee9SAndroid Build Coastguard Worker	var (
453*1fa6dee9SAndroid Build Coastguard Worker		name            = ctx.ModuleName()
454*1fa6dee9SAndroid Build Coastguard Worker		objDir          = moduleObjDir(ctx)
455*1fa6dee9SAndroid Build Coastguard Worker		archiveFile     = filepath.Join(objDir, name+".a")
456*1fa6dee9SAndroid Build Coastguard Worker		testArchiveFile = filepath.Join(testRoot(ctx), name+".a")
457*1fa6dee9SAndroid Build Coastguard Worker		aoutFile        = filepath.Join(objDir, name)
458*1fa6dee9SAndroid Build Coastguard Worker		hasPlugins      = false
459*1fa6dee9SAndroid Build Coastguard Worker		pluginSrc       = ""
460*1fa6dee9SAndroid Build Coastguard Worker		genSrcs         = []string{}
461*1fa6dee9SAndroid Build Coastguard Worker	)
462*1fa6dee9SAndroid Build Coastguard Worker
463*1fa6dee9SAndroid Build Coastguard Worker	if !g.skipInstall {
464*1fa6dee9SAndroid Build Coastguard Worker		g.installPath = filepath.Join(ctx.Config().(BootstrapConfig).HostToolDir(), name)
465*1fa6dee9SAndroid Build Coastguard Worker	}
466*1fa6dee9SAndroid Build Coastguard Worker
467*1fa6dee9SAndroid Build Coastguard Worker	ctx.VisitDirectDeps(func(module blueprint.Module) {
468*1fa6dee9SAndroid Build Coastguard Worker		if ctx.OtherModuleDependencyTag(module) == pluginDepTag {
469*1fa6dee9SAndroid Build Coastguard Worker			hasPlugins = true
470*1fa6dee9SAndroid Build Coastguard Worker		}
471*1fa6dee9SAndroid Build Coastguard Worker	})
472*1fa6dee9SAndroid Build Coastguard Worker	if hasPlugins {
473*1fa6dee9SAndroid Build Coastguard Worker		pluginSrc = filepath.Join(moduleGenSrcDir(ctx), "plugin.go")
474*1fa6dee9SAndroid Build Coastguard Worker		genSrcs = append(genSrcs, pluginSrc)
475*1fa6dee9SAndroid Build Coastguard Worker	}
476*1fa6dee9SAndroid Build Coastguard Worker
477*1fa6dee9SAndroid Build Coastguard Worker	var testDeps []string
478*1fa6dee9SAndroid Build Coastguard Worker
479*1fa6dee9SAndroid Build Coastguard Worker	if hasPlugins && !buildGoPluginLoader(ctx, "main", pluginSrc) {
480*1fa6dee9SAndroid Build Coastguard Worker		return
481*1fa6dee9SAndroid Build Coastguard Worker	}
482*1fa6dee9SAndroid Build Coastguard Worker
483*1fa6dee9SAndroid Build Coastguard Worker	var srcs, testSrcs []string
484*1fa6dee9SAndroid Build Coastguard Worker	if runtime.GOOS == "darwin" {
485*1fa6dee9SAndroid Build Coastguard Worker		srcs = append(g.properties.Srcs, g.properties.Darwin.Srcs...)
486*1fa6dee9SAndroid Build Coastguard Worker		testSrcs = append(g.properties.TestSrcs, g.properties.Darwin.TestSrcs...)
487*1fa6dee9SAndroid Build Coastguard Worker	} else if runtime.GOOS == "linux" {
488*1fa6dee9SAndroid Build Coastguard Worker		srcs = append(g.properties.Srcs, g.properties.Linux.Srcs...)
489*1fa6dee9SAndroid Build Coastguard Worker		testSrcs = append(g.properties.TestSrcs, g.properties.Linux.TestSrcs...)
490*1fa6dee9SAndroid Build Coastguard Worker	}
491*1fa6dee9SAndroid Build Coastguard Worker
492*1fa6dee9SAndroid Build Coastguard Worker	testResultFile := buildGoTest(ctx, testRoot(ctx), testArchiveFile,
493*1fa6dee9SAndroid Build Coastguard Worker		name, srcs, genSrcs, testSrcs, g.properties.EmbedSrcs)
494*1fa6dee9SAndroid Build Coastguard Worker	testDeps = append(testDeps, testResultFile...)
495*1fa6dee9SAndroid Build Coastguard Worker
496*1fa6dee9SAndroid Build Coastguard Worker	buildGoPackage(ctx, objDir, "main", archiveFile, srcs, genSrcs, g.properties.EmbedSrcs)
497*1fa6dee9SAndroid Build Coastguard Worker
498*1fa6dee9SAndroid Build Coastguard Worker	var linkDeps []string
499*1fa6dee9SAndroid Build Coastguard Worker	var libDirFlags []string
500*1fa6dee9SAndroid Build Coastguard Worker	ctx.VisitDepsDepthFirst(func(module blueprint.Module) {
501*1fa6dee9SAndroid Build Coastguard Worker		if info, ok := blueprint.OtherModuleProvider(ctx, module, PackageProvider); ok {
502*1fa6dee9SAndroid Build Coastguard Worker			linkDeps = append(linkDeps, info.PackageTarget)
503*1fa6dee9SAndroid Build Coastguard Worker			libDir := info.PkgRoot
504*1fa6dee9SAndroid Build Coastguard Worker			libDirFlags = append(libDirFlags, "-L "+libDir)
505*1fa6dee9SAndroid Build Coastguard Worker			testDeps = append(testDeps, info.TestTargets...)
506*1fa6dee9SAndroid Build Coastguard Worker		}
507*1fa6dee9SAndroid Build Coastguard Worker	})
508*1fa6dee9SAndroid Build Coastguard Worker
509*1fa6dee9SAndroid Build Coastguard Worker	linkArgs := map[string]string{}
510*1fa6dee9SAndroid Build Coastguard Worker	if len(libDirFlags) > 0 {
511*1fa6dee9SAndroid Build Coastguard Worker		linkArgs["libDirFlags"] = strings.Join(libDirFlags, " ")
512*1fa6dee9SAndroid Build Coastguard Worker	}
513*1fa6dee9SAndroid Build Coastguard Worker
514*1fa6dee9SAndroid Build Coastguard Worker	ctx.Build(pctx, blueprint.BuildParams{
515*1fa6dee9SAndroid Build Coastguard Worker		Rule:      link,
516*1fa6dee9SAndroid Build Coastguard Worker		Outputs:   []string{aoutFile},
517*1fa6dee9SAndroid Build Coastguard Worker		Inputs:    []string{archiveFile},
518*1fa6dee9SAndroid Build Coastguard Worker		Implicits: linkDeps,
519*1fa6dee9SAndroid Build Coastguard Worker		Args:      linkArgs,
520*1fa6dee9SAndroid Build Coastguard Worker		Optional:  true,
521*1fa6dee9SAndroid Build Coastguard Worker	})
522*1fa6dee9SAndroid Build Coastguard Worker
523*1fa6dee9SAndroid Build Coastguard Worker	g.outputFile = aoutFile
524*1fa6dee9SAndroid Build Coastguard Worker
525*1fa6dee9SAndroid Build Coastguard Worker	var validations []string
526*1fa6dee9SAndroid Build Coastguard Worker	if ctx.Config().(BootstrapConfig).RunGoTests() {
527*1fa6dee9SAndroid Build Coastguard Worker		validations = testDeps
528*1fa6dee9SAndroid Build Coastguard Worker	}
529*1fa6dee9SAndroid Build Coastguard Worker
530*1fa6dee9SAndroid Build Coastguard Worker	if !g.skipInstall {
531*1fa6dee9SAndroid Build Coastguard Worker		ctx.Build(pctx, blueprint.BuildParams{
532*1fa6dee9SAndroid Build Coastguard Worker			Rule:        cp,
533*1fa6dee9SAndroid Build Coastguard Worker			Outputs:     []string{g.installPath},
534*1fa6dee9SAndroid Build Coastguard Worker			Inputs:      []string{aoutFile},
535*1fa6dee9SAndroid Build Coastguard Worker			Validations: validations,
536*1fa6dee9SAndroid Build Coastguard Worker			Optional:    !g.properties.Default,
537*1fa6dee9SAndroid Build Coastguard Worker		})
538*1fa6dee9SAndroid Build Coastguard Worker	}
539*1fa6dee9SAndroid Build Coastguard Worker
540*1fa6dee9SAndroid Build Coastguard Worker	blueprint.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs})
541*1fa6dee9SAndroid Build Coastguard Worker	blueprint.SetProvider(ctx, BinaryProvider, &BinaryInfo{
542*1fa6dee9SAndroid Build Coastguard Worker		IntermediatePath: g.outputFile,
543*1fa6dee9SAndroid Build Coastguard Worker		InstallPath:      g.installPath,
544*1fa6dee9SAndroid Build Coastguard Worker		TestTargets:      testResultFile,
545*1fa6dee9SAndroid Build Coastguard Worker	})
546*1fa6dee9SAndroid Build Coastguard Worker}
547*1fa6dee9SAndroid Build Coastguard Worker
548*1fa6dee9SAndroid Build Coastguard Workerfunc buildGoPluginLoader(ctx blueprint.ModuleContext, pkgPath, pluginSrc string) bool {
549*1fa6dee9SAndroid Build Coastguard Worker	ret := true
550*1fa6dee9SAndroid Build Coastguard Worker
551*1fa6dee9SAndroid Build Coastguard Worker	var pluginPaths []string
552*1fa6dee9SAndroid Build Coastguard Worker	ctx.VisitDirectDeps(func(module blueprint.Module) {
553*1fa6dee9SAndroid Build Coastguard Worker		if ctx.OtherModuleDependencyTag(module) == pluginDepTag {
554*1fa6dee9SAndroid Build Coastguard Worker			if info, ok := blueprint.OtherModuleProvider(ctx, module, PackageProvider); ok {
555*1fa6dee9SAndroid Build Coastguard Worker				pluginPaths = append(pluginPaths, info.PkgPath)
556*1fa6dee9SAndroid Build Coastguard Worker			}
557*1fa6dee9SAndroid Build Coastguard Worker		}
558*1fa6dee9SAndroid Build Coastguard Worker	})
559*1fa6dee9SAndroid Build Coastguard Worker
560*1fa6dee9SAndroid Build Coastguard Worker	ctx.Build(pctx, blueprint.BuildParams{
561*1fa6dee9SAndroid Build Coastguard Worker		Rule:    pluginGenSrc,
562*1fa6dee9SAndroid Build Coastguard Worker		Outputs: []string{pluginSrc},
563*1fa6dee9SAndroid Build Coastguard Worker		Args: map[string]string{
564*1fa6dee9SAndroid Build Coastguard Worker			"pkg":     pkgPath,
565*1fa6dee9SAndroid Build Coastguard Worker			"plugins": strings.Join(pluginPaths, " "),
566*1fa6dee9SAndroid Build Coastguard Worker		},
567*1fa6dee9SAndroid Build Coastguard Worker		Optional: true,
568*1fa6dee9SAndroid Build Coastguard Worker	})
569*1fa6dee9SAndroid Build Coastguard Worker
570*1fa6dee9SAndroid Build Coastguard Worker	return ret
571*1fa6dee9SAndroid Build Coastguard Worker}
572*1fa6dee9SAndroid Build Coastguard Worker
573*1fa6dee9SAndroid Build Coastguard Workerfunc generateEmbedcfgFile(ctx blueprint.ModuleContext, files []string, srcDir string, embedcfgFile string) {
574*1fa6dee9SAndroid Build Coastguard Worker	embedcfg := struct {
575*1fa6dee9SAndroid Build Coastguard Worker		Patterns map[string][]string
576*1fa6dee9SAndroid Build Coastguard Worker		Files    map[string]string
577*1fa6dee9SAndroid Build Coastguard Worker	}{
578*1fa6dee9SAndroid Build Coastguard Worker		make(map[string][]string, len(files)),
579*1fa6dee9SAndroid Build Coastguard Worker		make(map[string]string, len(files)),
580*1fa6dee9SAndroid Build Coastguard Worker	}
581*1fa6dee9SAndroid Build Coastguard Worker
582*1fa6dee9SAndroid Build Coastguard Worker	for _, file := range files {
583*1fa6dee9SAndroid Build Coastguard Worker		embedcfg.Patterns[file] = []string{file}
584*1fa6dee9SAndroid Build Coastguard Worker		embedcfg.Files[file] = filepath.Join(srcDir, file)
585*1fa6dee9SAndroid Build Coastguard Worker	}
586*1fa6dee9SAndroid Build Coastguard Worker
587*1fa6dee9SAndroid Build Coastguard Worker	embedcfgData, err := json.Marshal(&embedcfg)
588*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
589*1fa6dee9SAndroid Build Coastguard Worker		ctx.ModuleErrorf("Failed to marshal embedcfg data: %s", err.Error())
590*1fa6dee9SAndroid Build Coastguard Worker	}
591*1fa6dee9SAndroid Build Coastguard Worker
592*1fa6dee9SAndroid Build Coastguard Worker	writeFileRule(ctx, embedcfgFile, string(embedcfgData))
593*1fa6dee9SAndroid Build Coastguard Worker}
594*1fa6dee9SAndroid Build Coastguard Worker
595*1fa6dee9SAndroid Build Coastguard Workerfunc buildGoPackage(ctx blueprint.ModuleContext, pkgRoot string,
596*1fa6dee9SAndroid Build Coastguard Worker	pkgPath string, archiveFile string, srcs []string, genSrcs []string, embedSrcs []string) {
597*1fa6dee9SAndroid Build Coastguard Worker
598*1fa6dee9SAndroid Build Coastguard Worker	srcDir := moduleSrcDir(ctx)
599*1fa6dee9SAndroid Build Coastguard Worker	srcFiles := pathtools.PrefixPaths(srcs, srcDir)
600*1fa6dee9SAndroid Build Coastguard Worker	srcFiles = append(srcFiles, genSrcs...)
601*1fa6dee9SAndroid Build Coastguard Worker
602*1fa6dee9SAndroid Build Coastguard Worker	var incFlags []string
603*1fa6dee9SAndroid Build Coastguard Worker	var deps []string
604*1fa6dee9SAndroid Build Coastguard Worker	ctx.VisitDepsDepthFirst(func(module blueprint.Module) {
605*1fa6dee9SAndroid Build Coastguard Worker		if info, ok := blueprint.OtherModuleProvider(ctx, module, PackageProvider); ok {
606*1fa6dee9SAndroid Build Coastguard Worker			incDir := info.PkgRoot
607*1fa6dee9SAndroid Build Coastguard Worker			target := info.PackageTarget
608*1fa6dee9SAndroid Build Coastguard Worker			incFlags = append(incFlags, "-I "+incDir)
609*1fa6dee9SAndroid Build Coastguard Worker			deps = append(deps, target)
610*1fa6dee9SAndroid Build Coastguard Worker		}
611*1fa6dee9SAndroid Build Coastguard Worker	})
612*1fa6dee9SAndroid Build Coastguard Worker
613*1fa6dee9SAndroid Build Coastguard Worker	compileArgs := map[string]string{
614*1fa6dee9SAndroid Build Coastguard Worker		"pkgPath": pkgPath,
615*1fa6dee9SAndroid Build Coastguard Worker	}
616*1fa6dee9SAndroid Build Coastguard Worker
617*1fa6dee9SAndroid Build Coastguard Worker	if len(incFlags) > 0 {
618*1fa6dee9SAndroid Build Coastguard Worker		compileArgs["incFlags"] = strings.Join(incFlags, " ")
619*1fa6dee9SAndroid Build Coastguard Worker	}
620*1fa6dee9SAndroid Build Coastguard Worker
621*1fa6dee9SAndroid Build Coastguard Worker	if len(embedSrcs) > 0 {
622*1fa6dee9SAndroid Build Coastguard Worker		embedcfgFile := archiveFile + ".embedcfg"
623*1fa6dee9SAndroid Build Coastguard Worker		generateEmbedcfgFile(ctx, embedSrcs, srcDir, embedcfgFile)
624*1fa6dee9SAndroid Build Coastguard Worker		compileArgs["embedFlags"] = "-embedcfg " + embedcfgFile
625*1fa6dee9SAndroid Build Coastguard Worker		deps = append(deps, embedcfgFile)
626*1fa6dee9SAndroid Build Coastguard Worker	}
627*1fa6dee9SAndroid Build Coastguard Worker
628*1fa6dee9SAndroid Build Coastguard Worker	ctx.Build(pctx, blueprint.BuildParams{
629*1fa6dee9SAndroid Build Coastguard Worker		Rule:      compile,
630*1fa6dee9SAndroid Build Coastguard Worker		Outputs:   []string{archiveFile},
631*1fa6dee9SAndroid Build Coastguard Worker		Inputs:    srcFiles,
632*1fa6dee9SAndroid Build Coastguard Worker		Implicits: deps,
633*1fa6dee9SAndroid Build Coastguard Worker		Args:      compileArgs,
634*1fa6dee9SAndroid Build Coastguard Worker		Optional:  true,
635*1fa6dee9SAndroid Build Coastguard Worker	})
636*1fa6dee9SAndroid Build Coastguard Worker}
637*1fa6dee9SAndroid Build Coastguard Worker
638*1fa6dee9SAndroid Build Coastguard Workerfunc buildGoTest(ctx blueprint.ModuleContext, testRoot, testPkgArchive,
639*1fa6dee9SAndroid Build Coastguard Worker	pkgPath string, srcs, genSrcs, testSrcs []string, embedSrcs []string) []string {
640*1fa6dee9SAndroid Build Coastguard Worker
641*1fa6dee9SAndroid Build Coastguard Worker	if len(testSrcs) == 0 {
642*1fa6dee9SAndroid Build Coastguard Worker		return nil
643*1fa6dee9SAndroid Build Coastguard Worker	}
644*1fa6dee9SAndroid Build Coastguard Worker
645*1fa6dee9SAndroid Build Coastguard Worker	srcDir := moduleSrcDir(ctx)
646*1fa6dee9SAndroid Build Coastguard Worker	testFiles := pathtools.PrefixPaths(testSrcs, srcDir)
647*1fa6dee9SAndroid Build Coastguard Worker
648*1fa6dee9SAndroid Build Coastguard Worker	mainFile := filepath.Join(testRoot, "test.go")
649*1fa6dee9SAndroid Build Coastguard Worker	testArchive := filepath.Join(testRoot, "test.a")
650*1fa6dee9SAndroid Build Coastguard Worker	testFile := filepath.Join(testRoot, "test")
651*1fa6dee9SAndroid Build Coastguard Worker	testPassed := filepath.Join(testRoot, "test.passed")
652*1fa6dee9SAndroid Build Coastguard Worker
653*1fa6dee9SAndroid Build Coastguard Worker	buildGoPackage(ctx, testRoot, pkgPath, testPkgArchive,
654*1fa6dee9SAndroid Build Coastguard Worker		append(srcs, testSrcs...), genSrcs, embedSrcs)
655*1fa6dee9SAndroid Build Coastguard Worker
656*1fa6dee9SAndroid Build Coastguard Worker	ctx.Build(pctx, blueprint.BuildParams{
657*1fa6dee9SAndroid Build Coastguard Worker		Rule:    goTestMain,
658*1fa6dee9SAndroid Build Coastguard Worker		Outputs: []string{mainFile},
659*1fa6dee9SAndroid Build Coastguard Worker		Inputs:  testFiles,
660*1fa6dee9SAndroid Build Coastguard Worker		Args: map[string]string{
661*1fa6dee9SAndroid Build Coastguard Worker			"pkg": pkgPath,
662*1fa6dee9SAndroid Build Coastguard Worker		},
663*1fa6dee9SAndroid Build Coastguard Worker		Optional: true,
664*1fa6dee9SAndroid Build Coastguard Worker	})
665*1fa6dee9SAndroid Build Coastguard Worker
666*1fa6dee9SAndroid Build Coastguard Worker	linkDeps := []string{testPkgArchive}
667*1fa6dee9SAndroid Build Coastguard Worker	libDirFlags := []string{"-L " + testRoot}
668*1fa6dee9SAndroid Build Coastguard Worker	testDeps := []string{}
669*1fa6dee9SAndroid Build Coastguard Worker	ctx.VisitDepsDepthFirst(func(module blueprint.Module) {
670*1fa6dee9SAndroid Build Coastguard Worker		if info, ok := blueprint.OtherModuleProvider(ctx, module, PackageProvider); ok {
671*1fa6dee9SAndroid Build Coastguard Worker			linkDeps = append(linkDeps, info.PackageTarget)
672*1fa6dee9SAndroid Build Coastguard Worker			libDir := info.PkgRoot
673*1fa6dee9SAndroid Build Coastguard Worker			libDirFlags = append(libDirFlags, "-L "+libDir)
674*1fa6dee9SAndroid Build Coastguard Worker			testDeps = append(testDeps, info.TestTargets...)
675*1fa6dee9SAndroid Build Coastguard Worker		}
676*1fa6dee9SAndroid Build Coastguard Worker	})
677*1fa6dee9SAndroid Build Coastguard Worker
678*1fa6dee9SAndroid Build Coastguard Worker	ctx.Build(pctx, blueprint.BuildParams{
679*1fa6dee9SAndroid Build Coastguard Worker		Rule:      compile,
680*1fa6dee9SAndroid Build Coastguard Worker		Outputs:   []string{testArchive},
681*1fa6dee9SAndroid Build Coastguard Worker		Inputs:    []string{mainFile},
682*1fa6dee9SAndroid Build Coastguard Worker		Implicits: []string{testPkgArchive},
683*1fa6dee9SAndroid Build Coastguard Worker		Args: map[string]string{
684*1fa6dee9SAndroid Build Coastguard Worker			"pkgPath":  "main",
685*1fa6dee9SAndroid Build Coastguard Worker			"incFlags": "-I " + testRoot,
686*1fa6dee9SAndroid Build Coastguard Worker		},
687*1fa6dee9SAndroid Build Coastguard Worker		Optional: true,
688*1fa6dee9SAndroid Build Coastguard Worker	})
689*1fa6dee9SAndroid Build Coastguard Worker
690*1fa6dee9SAndroid Build Coastguard Worker	ctx.Build(pctx, blueprint.BuildParams{
691*1fa6dee9SAndroid Build Coastguard Worker		Rule:      link,
692*1fa6dee9SAndroid Build Coastguard Worker		Outputs:   []string{testFile},
693*1fa6dee9SAndroid Build Coastguard Worker		Inputs:    []string{testArchive},
694*1fa6dee9SAndroid Build Coastguard Worker		Implicits: linkDeps,
695*1fa6dee9SAndroid Build Coastguard Worker		Args: map[string]string{
696*1fa6dee9SAndroid Build Coastguard Worker			"libDirFlags": strings.Join(libDirFlags, " "),
697*1fa6dee9SAndroid Build Coastguard Worker		},
698*1fa6dee9SAndroid Build Coastguard Worker		Optional: true,
699*1fa6dee9SAndroid Build Coastguard Worker	})
700*1fa6dee9SAndroid Build Coastguard Worker
701*1fa6dee9SAndroid Build Coastguard Worker	ctx.Build(pctx, blueprint.BuildParams{
702*1fa6dee9SAndroid Build Coastguard Worker		Rule:        test,
703*1fa6dee9SAndroid Build Coastguard Worker		Outputs:     []string{testPassed},
704*1fa6dee9SAndroid Build Coastguard Worker		Inputs:      []string{testFile},
705*1fa6dee9SAndroid Build Coastguard Worker		Validations: testDeps,
706*1fa6dee9SAndroid Build Coastguard Worker		Args: map[string]string{
707*1fa6dee9SAndroid Build Coastguard Worker			"pkg":       pkgPath,
708*1fa6dee9SAndroid Build Coastguard Worker			"pkgSrcDir": filepath.Dir(testFiles[0]),
709*1fa6dee9SAndroid Build Coastguard Worker		},
710*1fa6dee9SAndroid Build Coastguard Worker		Optional: true,
711*1fa6dee9SAndroid Build Coastguard Worker	})
712*1fa6dee9SAndroid Build Coastguard Worker
713*1fa6dee9SAndroid Build Coastguard Worker	return []string{testPassed}
714*1fa6dee9SAndroid Build Coastguard Worker}
715*1fa6dee9SAndroid Build Coastguard Worker
716*1fa6dee9SAndroid Build Coastguard Workervar PrimaryBuilderProvider = blueprint.NewMutatorProvider[PrimaryBuilderInfo]("bootstrap_deps")
717*1fa6dee9SAndroid Build Coastguard Worker
718*1fa6dee9SAndroid Build Coastguard Workertype PrimaryBuilderInfo struct{}
719*1fa6dee9SAndroid Build Coastguard Worker
720*1fa6dee9SAndroid Build Coastguard Workertype singleton struct {
721*1fa6dee9SAndroid Build Coastguard Worker}
722*1fa6dee9SAndroid Build Coastguard Worker
723*1fa6dee9SAndroid Build Coastguard Workerfunc newSingletonFactory() func() blueprint.Singleton {
724*1fa6dee9SAndroid Build Coastguard Worker	return func() blueprint.Singleton {
725*1fa6dee9SAndroid Build Coastguard Worker		return &singleton{}
726*1fa6dee9SAndroid Build Coastguard Worker	}
727*1fa6dee9SAndroid Build Coastguard Worker}
728*1fa6dee9SAndroid Build Coastguard Worker
729*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
730*1fa6dee9SAndroid Build Coastguard Worker	// Find the module that's marked as the "primary builder", which means it's
731*1fa6dee9SAndroid Build Coastguard Worker	// creating the binary that we'll use to generate the non-bootstrap
732*1fa6dee9SAndroid Build Coastguard Worker	// build.ninja file.
733*1fa6dee9SAndroid Build Coastguard Worker	var primaryBuilders []string
734*1fa6dee9SAndroid Build Coastguard Worker	// blueprintTools contains blueprint go binaries that will be built in StageMain
735*1fa6dee9SAndroid Build Coastguard Worker	var blueprintTools []string
736*1fa6dee9SAndroid Build Coastguard Worker	// blueprintTools contains the test outputs of go tests that can be run in StageMain
737*1fa6dee9SAndroid Build Coastguard Worker	var blueprintTests []string
738*1fa6dee9SAndroid Build Coastguard Worker	// blueprintGoPackages contains all blueprint go packages that can be built in StageMain
739*1fa6dee9SAndroid Build Coastguard Worker	var blueprintGoPackages []string
740*1fa6dee9SAndroid Build Coastguard Worker	ctx.VisitAllModules(func(module blueprint.Module) {
741*1fa6dee9SAndroid Build Coastguard Worker		if ctx.PrimaryModule(module) == module {
742*1fa6dee9SAndroid Build Coastguard Worker			if binaryInfo, ok := blueprint.SingletonModuleProvider(ctx, module, BinaryProvider); ok {
743*1fa6dee9SAndroid Build Coastguard Worker				if binaryInfo.InstallPath != "" {
744*1fa6dee9SAndroid Build Coastguard Worker					blueprintTools = append(blueprintTools, binaryInfo.InstallPath)
745*1fa6dee9SAndroid Build Coastguard Worker				}
746*1fa6dee9SAndroid Build Coastguard Worker				blueprintTests = append(blueprintTests, binaryInfo.TestTargets...)
747*1fa6dee9SAndroid Build Coastguard Worker				if _, ok := blueprint.SingletonModuleProvider(ctx, module, PrimaryBuilderProvider); ok {
748*1fa6dee9SAndroid Build Coastguard Worker					primaryBuilders = append(primaryBuilders, binaryInfo.InstallPath)
749*1fa6dee9SAndroid Build Coastguard Worker				}
750*1fa6dee9SAndroid Build Coastguard Worker			}
751*1fa6dee9SAndroid Build Coastguard Worker
752*1fa6dee9SAndroid Build Coastguard Worker			if packageInfo, ok := blueprint.SingletonModuleProvider(ctx, module, PackageProvider); ok {
753*1fa6dee9SAndroid Build Coastguard Worker				blueprintGoPackages = append(blueprintGoPackages, packageInfo.PackageTarget)
754*1fa6dee9SAndroid Build Coastguard Worker				blueprintTests = append(blueprintTests, packageInfo.TestTargets...)
755*1fa6dee9SAndroid Build Coastguard Worker			}
756*1fa6dee9SAndroid Build Coastguard Worker		}
757*1fa6dee9SAndroid Build Coastguard Worker	})
758*1fa6dee9SAndroid Build Coastguard Worker
759*1fa6dee9SAndroid Build Coastguard Worker	var primaryBuilderCmdlinePrefix []string
760*1fa6dee9SAndroid Build Coastguard Worker	var primaryBuilderFile string
761*1fa6dee9SAndroid Build Coastguard Worker
762*1fa6dee9SAndroid Build Coastguard Worker	if len(primaryBuilders) == 0 {
763*1fa6dee9SAndroid Build Coastguard Worker		ctx.Errorf("no primary builder module present")
764*1fa6dee9SAndroid Build Coastguard Worker		return
765*1fa6dee9SAndroid Build Coastguard Worker	} else if len(primaryBuilders) > 1 {
766*1fa6dee9SAndroid Build Coastguard Worker		ctx.Errorf("multiple primary builder modules present: %q", primaryBuilders)
767*1fa6dee9SAndroid Build Coastguard Worker		return
768*1fa6dee9SAndroid Build Coastguard Worker	} else {
769*1fa6dee9SAndroid Build Coastguard Worker		primaryBuilderFile = primaryBuilders[0]
770*1fa6dee9SAndroid Build Coastguard Worker	}
771*1fa6dee9SAndroid Build Coastguard Worker
772*1fa6dee9SAndroid Build Coastguard Worker	ctx.SetOutDir(pctx, "${outDir}")
773*1fa6dee9SAndroid Build Coastguard Worker
774*1fa6dee9SAndroid Build Coastguard Worker	for _, subninja := range ctx.Config().(BootstrapConfig).Subninjas() {
775*1fa6dee9SAndroid Build Coastguard Worker		ctx.AddSubninja(subninja)
776*1fa6dee9SAndroid Build Coastguard Worker	}
777*1fa6dee9SAndroid Build Coastguard Worker
778*1fa6dee9SAndroid Build Coastguard Worker	for _, i := range ctx.Config().(BootstrapConfig).PrimaryBuilderInvocations() {
779*1fa6dee9SAndroid Build Coastguard Worker		flags := make([]string, 0)
780*1fa6dee9SAndroid Build Coastguard Worker		flags = append(flags, primaryBuilderCmdlinePrefix...)
781*1fa6dee9SAndroid Build Coastguard Worker		flags = append(flags, i.Args...)
782*1fa6dee9SAndroid Build Coastguard Worker
783*1fa6dee9SAndroid Build Coastguard Worker		pool := ""
784*1fa6dee9SAndroid Build Coastguard Worker		if i.Console {
785*1fa6dee9SAndroid Build Coastguard Worker			pool = "console"
786*1fa6dee9SAndroid Build Coastguard Worker		}
787*1fa6dee9SAndroid Build Coastguard Worker
788*1fa6dee9SAndroid Build Coastguard Worker		envAssignments := ""
789*1fa6dee9SAndroid Build Coastguard Worker		for k, v := range i.Env {
790*1fa6dee9SAndroid Build Coastguard Worker			// NB: This is rife with quoting issues but we don't care because we trust
791*1fa6dee9SAndroid Build Coastguard Worker			// soong_ui to not abuse this facility too much
792*1fa6dee9SAndroid Build Coastguard Worker			envAssignments += k + "=" + v + " "
793*1fa6dee9SAndroid Build Coastguard Worker		}
794*1fa6dee9SAndroid Build Coastguard Worker
795*1fa6dee9SAndroid Build Coastguard Worker		// Build the main build.ninja
796*1fa6dee9SAndroid Build Coastguard Worker		ctx.Build(pctx, blueprint.BuildParams{
797*1fa6dee9SAndroid Build Coastguard Worker			Rule:      generateBuildNinja,
798*1fa6dee9SAndroid Build Coastguard Worker			Outputs:   i.Outputs,
799*1fa6dee9SAndroid Build Coastguard Worker			Inputs:    i.Inputs,
800*1fa6dee9SAndroid Build Coastguard Worker			Implicits: i.Implicits,
801*1fa6dee9SAndroid Build Coastguard Worker			OrderOnly: i.OrderOnlyInputs,
802*1fa6dee9SAndroid Build Coastguard Worker			Args: map[string]string{
803*1fa6dee9SAndroid Build Coastguard Worker				"builder": primaryBuilderFile,
804*1fa6dee9SAndroid Build Coastguard Worker				"env":     envAssignments,
805*1fa6dee9SAndroid Build Coastguard Worker				"extra":   strings.Join(flags, " "),
806*1fa6dee9SAndroid Build Coastguard Worker				"pool":    pool,
807*1fa6dee9SAndroid Build Coastguard Worker			},
808*1fa6dee9SAndroid Build Coastguard Worker			// soong_ui explicitly requests what it wants to be build. This is
809*1fa6dee9SAndroid Build Coastguard Worker			// because the same Ninja file contains instructions to run
810*1fa6dee9SAndroid Build Coastguard Worker			// soong_build, run bp2build and to generate the JSON module graph.
811*1fa6dee9SAndroid Build Coastguard Worker			Optional:    true,
812*1fa6dee9SAndroid Build Coastguard Worker			Description: i.Description,
813*1fa6dee9SAndroid Build Coastguard Worker		})
814*1fa6dee9SAndroid Build Coastguard Worker	}
815*1fa6dee9SAndroid Build Coastguard Worker
816*1fa6dee9SAndroid Build Coastguard Worker	// Add a phony target for building various tools that are part of blueprint
817*1fa6dee9SAndroid Build Coastguard Worker	if len(blueprintTools) > 0 {
818*1fa6dee9SAndroid Build Coastguard Worker		ctx.Build(pctx, blueprint.BuildParams{
819*1fa6dee9SAndroid Build Coastguard Worker			Rule:    blueprint.Phony,
820*1fa6dee9SAndroid Build Coastguard Worker			Outputs: []string{"blueprint_tools"},
821*1fa6dee9SAndroid Build Coastguard Worker			Inputs:  blueprintTools,
822*1fa6dee9SAndroid Build Coastguard Worker		})
823*1fa6dee9SAndroid Build Coastguard Worker	}
824*1fa6dee9SAndroid Build Coastguard Worker
825*1fa6dee9SAndroid Build Coastguard Worker	// Add a phony target for running various tests that are part of blueprint
826*1fa6dee9SAndroid Build Coastguard Worker	ctx.Build(pctx, blueprint.BuildParams{
827*1fa6dee9SAndroid Build Coastguard Worker		Rule:    blueprint.Phony,
828*1fa6dee9SAndroid Build Coastguard Worker		Outputs: []string{"blueprint_tests"},
829*1fa6dee9SAndroid Build Coastguard Worker		Inputs:  blueprintTests,
830*1fa6dee9SAndroid Build Coastguard Worker	})
831*1fa6dee9SAndroid Build Coastguard Worker
832*1fa6dee9SAndroid Build Coastguard Worker	// Add a phony target for running go tests
833*1fa6dee9SAndroid Build Coastguard Worker	ctx.Build(pctx, blueprint.BuildParams{
834*1fa6dee9SAndroid Build Coastguard Worker		Rule:     blueprint.Phony,
835*1fa6dee9SAndroid Build Coastguard Worker		Outputs:  []string{"blueprint_go_packages"},
836*1fa6dee9SAndroid Build Coastguard Worker		Inputs:   blueprintGoPackages,
837*1fa6dee9SAndroid Build Coastguard Worker		Optional: true,
838*1fa6dee9SAndroid Build Coastguard Worker	})
839*1fa6dee9SAndroid Build Coastguard Worker}
840*1fa6dee9SAndroid Build Coastguard Worker
841*1fa6dee9SAndroid Build Coastguard Worker// packageRoot returns the module-specific package root directory path.  This
842*1fa6dee9SAndroid Build Coastguard Worker// directory is where the final package .a files are output and where dependant
843*1fa6dee9SAndroid Build Coastguard Worker// modules search for this package via -I arguments.
844*1fa6dee9SAndroid Build Coastguard Workerfunc packageRoot(ctx blueprint.ModuleContext) string {
845*1fa6dee9SAndroid Build Coastguard Worker	toolDir := ctx.Config().(BootstrapConfig).HostToolDir()
846*1fa6dee9SAndroid Build Coastguard Worker	return filepath.Join(toolDir, "go", ctx.ModuleName(), ctx.ModuleSubDir(), "pkg")
847*1fa6dee9SAndroid Build Coastguard Worker}
848*1fa6dee9SAndroid Build Coastguard Worker
849*1fa6dee9SAndroid Build Coastguard Worker// testRoot returns the module-specific package root directory path used for
850*1fa6dee9SAndroid Build Coastguard Worker// building tests. The .a files generated here will include everything from
851*1fa6dee9SAndroid Build Coastguard Worker// packageRoot, plus the test-only code.
852*1fa6dee9SAndroid Build Coastguard Workerfunc testRoot(ctx blueprint.ModuleContext) string {
853*1fa6dee9SAndroid Build Coastguard Worker	toolDir := ctx.Config().(BootstrapConfig).HostToolDir()
854*1fa6dee9SAndroid Build Coastguard Worker	return filepath.Join(toolDir, "go", ctx.ModuleName(), ctx.ModuleSubDir(), "test")
855*1fa6dee9SAndroid Build Coastguard Worker}
856*1fa6dee9SAndroid Build Coastguard Worker
857*1fa6dee9SAndroid Build Coastguard Worker// moduleSrcDir returns the path of the directory that all source file paths are
858*1fa6dee9SAndroid Build Coastguard Worker// specified relative to.
859*1fa6dee9SAndroid Build Coastguard Workerfunc moduleSrcDir(ctx blueprint.ModuleContext) string {
860*1fa6dee9SAndroid Build Coastguard Worker	return ctx.ModuleDir()
861*1fa6dee9SAndroid Build Coastguard Worker}
862*1fa6dee9SAndroid Build Coastguard Worker
863*1fa6dee9SAndroid Build Coastguard Worker// moduleObjDir returns the module-specific object directory path.
864*1fa6dee9SAndroid Build Coastguard Workerfunc moduleObjDir(ctx blueprint.ModuleContext) string {
865*1fa6dee9SAndroid Build Coastguard Worker	toolDir := ctx.Config().(BootstrapConfig).HostToolDir()
866*1fa6dee9SAndroid Build Coastguard Worker	return filepath.Join(toolDir, "go", ctx.ModuleName(), ctx.ModuleSubDir(), "obj")
867*1fa6dee9SAndroid Build Coastguard Worker}
868*1fa6dee9SAndroid Build Coastguard Worker
869*1fa6dee9SAndroid Build Coastguard Worker// moduleGenSrcDir returns the module-specific generated sources path.
870*1fa6dee9SAndroid Build Coastguard Workerfunc moduleGenSrcDir(ctx blueprint.ModuleContext) string {
871*1fa6dee9SAndroid Build Coastguard Worker	toolDir := ctx.Config().(BootstrapConfig).HostToolDir()
872*1fa6dee9SAndroid Build Coastguard Worker	return filepath.Join(toolDir, "go", ctx.ModuleName(), ctx.ModuleSubDir(), "gen")
873*1fa6dee9SAndroid Build Coastguard Worker}
874