blob: d5befd95c1668b888d58b0f82a89431f93abc13a [file] [log] [blame]
Colin Cross8e0c5112015-01-23 14:15:10 -08001// Copyright 2014 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
Jamie Gennis1bc967e2014-05-27 16:34:41 -070015package bootstrap
16
17import (
Jamie Gennis1bc967e2014-05-27 16:34:41 -070018 "fmt"
Dan Willemsenc54c0722017-07-24 20:28:41 -070019 "go/build"
Jamie Gennis1bc967e2014-05-27 16:34:41 -070020 "path/filepath"
Dan Willemsenf14e0962017-02-06 14:00:10 -080021 "runtime"
Jamie Gennis1bc967e2014-05-27 16:34:41 -070022 "strings"
Colin Cross4572edd2015-05-13 14:36:24 -070023
24 "github.com/google/blueprint"
25 "github.com/google/blueprint/pathtools"
Jamie Gennis1bc967e2014-05-27 16:34:41 -070026)
27
Colin Cross16fec722019-10-17 13:41:20 -070028const mainSubDir = ".primary"
Dan Willemsen4d6af1f2015-09-11 16:55:53 -070029const bootstrapSubDir = ".bootstrap"
30const miniBootstrapSubDir = ".minibootstrap"
Jamie Gennis598fe762014-06-06 14:21:57 -070031
Jamie Gennis1bc967e2014-05-27 16:34:41 -070032var (
Jamie Gennis6cafc2c2015-03-20 22:39:29 -040033 pctx = blueprint.NewPackageContext("github.com/google/blueprint/bootstrap")
Jamie Gennis1bc967e2014-05-27 16:34:41 -070034
Dan Willemsenfdeb7242015-07-24 16:53:27 -070035 goTestMainCmd = pctx.StaticVariable("goTestMainCmd", filepath.Join(bootstrapDir, "bin", "gotestmain"))
Dan Willemsenc7697ce2015-09-17 20:59:51 -070036 goTestRunnerCmd = pctx.StaticVariable("goTestRunnerCmd", filepath.Join(bootstrapDir, "bin", "gotestrunner"))
Dan Willemsenfdeb7242015-07-24 16:53:27 -070037 pluginGenSrcCmd = pctx.StaticVariable("pluginGenSrcCmd", filepath.Join(bootstrapDir, "bin", "loadplugins"))
Jamie Gennis2fb20952014-10-03 02:49:58 -070038
Dan Willemsenc54c0722017-07-24 20:28:41 -070039 parallelCompile = pctx.StaticVariable("parallelCompile", func() string {
40 // Parallel compilation is only supported on >= go1.9
41 for _, r := range build.Default.ReleaseTags {
42 if r == "go1.9" {
Dan Willemsen20c343b2018-03-02 15:03:24 -080043 numCpu := runtime.NumCPU()
44 // This will cause us to recompile all go programs if the
45 // number of cpus changes. We don't get a lot of benefit from
46 // higher values, so cap this to make it cheaper to move trees
47 // between machines.
48 if numCpu > 8 {
49 numCpu = 8
50 }
51 return fmt.Sprintf("-c %d", numCpu)
Dan Willemsenc54c0722017-07-24 20:28:41 -070052 }
53 }
54 return ""
55 }())
56
Dan Willemsenc20adea2015-08-01 15:07:27 -070057 compile = pctx.StaticRule("compile",
Jamie Gennis1bc967e2014-05-27 16:34:41 -070058 blueprint.RuleParams{
Colin Cross6c92af92018-09-28 16:15:58 -070059 Command: "GOROOT='$goRoot' $compileCmd $parallelCompile -o $out.tmp " +
Lukacs T. Berki07a91f02021-03-17 15:01:51 +010060 "$debugFlags -p $pkgPath -complete $incFlags -pack $in && " +
Colin Cross6c92af92018-09-28 16:15:58 -070061 "if cmp --quiet $out.tmp $out; then rm $out.tmp; else mv -f $out.tmp $out; fi",
Dan Willemsenfce63d32015-11-17 14:21:45 -080062 CommandDeps: []string{"$compileCmd"},
Dan Willemsenc20adea2015-08-01 15:07:27 -070063 Description: "compile $out",
Colin Cross6c92af92018-09-28 16:15:58 -070064 Restat: true,
Jamie Gennis1bc967e2014-05-27 16:34:41 -070065 },
66 "pkgPath", "incFlags")
67
Jamie Gennis2fb20952014-10-03 02:49:58 -070068 link = pctx.StaticRule("link",
Jamie Gennis1bc967e2014-05-27 16:34:41 -070069 blueprint.RuleParams{
Colin Cross6c92af92018-09-28 16:15:58 -070070 Command: "GOROOT='$goRoot' $linkCmd -o $out.tmp $libDirFlags $in && " +
71 "if cmp --quiet $out.tmp $out; then rm $out.tmp; else mv -f $out.tmp $out; fi",
Dan Willemsenfce63d32015-11-17 14:21:45 -080072 CommandDeps: []string{"$linkCmd"},
Dan Willemsenc20adea2015-08-01 15:07:27 -070073 Description: "link $out",
Colin Cross6c92af92018-09-28 16:15:58 -070074 Restat: true,
Jamie Gennis1bc967e2014-05-27 16:34:41 -070075 },
76 "libDirFlags")
77
Dan Willemsen87ba2942015-06-23 17:21:00 -070078 goTestMain = pctx.StaticRule("gotestmain",
79 blueprint.RuleParams{
80 Command: "$goTestMainCmd -o $out -pkg $pkg $in",
Dan Willemsenfce63d32015-11-17 14:21:45 -080081 CommandDeps: []string{"$goTestMainCmd"},
Dan Willemsen87ba2942015-06-23 17:21:00 -070082 Description: "gotestmain $out",
83 },
84 "pkg")
85
Dan Willemsenfdeb7242015-07-24 16:53:27 -070086 pluginGenSrc = pctx.StaticRule("pluginGenSrc",
87 blueprint.RuleParams{
88 Command: "$pluginGenSrcCmd -o $out -p $pkg $plugins",
Dan Willemsenfce63d32015-11-17 14:21:45 -080089 CommandDeps: []string{"$pluginGenSrcCmd"},
Dan Willemsenfdeb7242015-07-24 16:53:27 -070090 Description: "create $out",
91 },
92 "pkg", "plugins")
93
Dan Willemsen87ba2942015-06-23 17:21:00 -070094 test = pctx.StaticRule("test",
95 blueprint.RuleParams{
Dan Willemsenc7697ce2015-09-17 20:59:51 -070096 Command: "$goTestRunnerCmd -p $pkgSrcDir -f $out -- $in -test.short",
Dan Willemsenfce63d32015-11-17 14:21:45 -080097 CommandDeps: []string{"$goTestRunnerCmd"},
Dan Willemsen87ba2942015-06-23 17:21:00 -070098 Description: "test $pkg",
99 },
100 "pkg", "pkgSrcDir")
101
Jamie Gennis2fb20952014-10-03 02:49:58 -0700102 cp = pctx.StaticRule("cp",
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700103 blueprint.RuleParams{
104 Command: "cp $in $out",
105 Description: "cp $out",
Jamie Genniscbc6f862014-06-05 20:00:22 -0700106 },
107 "generator")
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700108
Jamie Gennis2fb20952014-10-03 02:49:58 -0700109 bootstrap = pctx.StaticRule("bootstrap",
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700110 blueprint.RuleParams{
Dan Willemsen991f7602015-09-17 22:48:04 -0700111 Command: "BUILDDIR=$buildDir $bootstrapCmd -i $in",
Dan Willemsenfce63d32015-11-17 14:21:45 -0800112 CommandDeps: []string{"$bootstrapCmd"},
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700113 Description: "bootstrap $in",
114 Generator: true,
115 })
116
Dan Willemsen91a657e2015-07-22 17:05:59 -0700117 touch = pctx.StaticRule("touch",
118 blueprint.RuleParams{
119 Command: "touch $out",
120 Description: "touch $out",
121 },
122 "depfile", "generator")
123
Dan Willemsenb6d88a42016-11-01 17:12:28 -0700124 generateBuildNinja = pctx.StaticRule("build.ninja",
125 blueprint.RuleParams{
Lukacs T. Berkif802ffc2021-02-17 11:59:10 +0100126 // TODO: it's kinda ugly that some parameters are computed from
127 // environment variables and some from Ninja parameters, but it's probably
128 // better to not to touch that while Blueprint and Soong are separate
Lukacs T. Berki0bd3de32021-03-08 13:09:19 +0100129 // NOTE: The spaces at EOL are important because otherwise Ninja would
130 // omit all spaces between the different options.
131 Command: `cd "$$(dirname "$builder")" && ` +
132 `BUILDER="$$PWD/$$(basename "$builder")" && ` +
133 `cd / && ` +
134 `env -i "$$BUILDER" ` +
Lukacs T. Berki0bd3de32021-03-08 13:09:19 +0100135 ` --top "$$TOP" ` +
Lukacs T. Berki77ef79b2021-04-12 12:07:02 +0200136 ` --out "$buildDir" ` +
Lukacs T. Berki0bd3de32021-03-08 13:09:19 +0100137 ` -n "$ninjaBuildDir" ` +
138 ` -d "$out.d" ` +
Lukacs T. Berki77ef79b2021-04-12 12:07:02 +0200139 ` $extra`,
Dan Willemsenb6d88a42016-11-01 17:12:28 -0700140 CommandDeps: []string{"$builder"},
141 Description: "$builder $out",
Dan Willemsen2d9b59b2017-12-18 09:14:16 -0800142 Deps: blueprint.DepsGCC,
Dan Willemsenb6d88a42016-11-01 17:12:28 -0700143 Depfile: "$out.d",
144 Restat: true,
145 },
Lukacs T. Berki77ef79b2021-04-12 12:07:02 +0200146 "builder", "extra")
Dan Willemsenb6d88a42016-11-01 17:12:28 -0700147
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700148 // Work around a Ninja issue. See https://github.com/martine/ninja/pull/634
Jamie Gennis2fb20952014-10-03 02:49:58 -0700149 phony = pctx.StaticRule("phony",
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700150 blueprint.RuleParams{
151 Command: "# phony $out",
152 Description: "phony $out",
153 Generator: true,
154 },
155 "depfile")
156
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700157 _ = pctx.VariableFunc("BinDir", func(config interface{}) (string, error) {
Lukacs T. Berki53537442021-03-12 08:31:19 +0100158 return bootstrapBinDir(config), nil
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700159 })
160
161 _ = pctx.VariableFunc("ToolDir", func(config interface{}) (string, error) {
162 return toolDir(config), nil
163 })
Colin Cross4572edd2015-05-13 14:36:24 -0700164
Colin Cross16fec722019-10-17 13:41:20 -0700165 docsDir = filepath.Join(mainDir, "docs")
Dan Willemsen4d6af1f2015-09-11 16:55:53 -0700166
Colin Cross16fec722019-10-17 13:41:20 -0700167 mainDir = filepath.Join("$buildDir", mainSubDir)
Dan Willemsenc7697ce2015-09-17 20:59:51 -0700168 bootstrapDir = filepath.Join("$buildDir", bootstrapSubDir)
Dan Willemsen4d6af1f2015-09-11 16:55:53 -0700169 miniBootstrapDir = filepath.Join("$buildDir", miniBootstrapSubDir)
Dan Willemsen1e723212017-07-18 19:37:37 -0700170
171 minibpFile = filepath.Join(miniBootstrapDir, "minibp")
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700172)
173
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700174type GoBinaryTool interface {
175 InstallPath() string
176
177 // So that other packages can't implement this interface
178 isGoBinary()
179}
180
Lukacs T. Berki53537442021-03-12 08:31:19 +0100181func bootstrapBinDir(config interface{}) string {
182 return filepath.Join(config.(BootstrapConfig).BuildDir(), bootstrapSubDir, "bin")
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700183}
184
185func toolDir(config interface{}) string {
186 if c, ok := config.(ConfigBlueprintToolLocation); ok {
187 return filepath.Join(c.BlueprintToolLocation())
188 }
Lukacs T. Berki53537442021-03-12 08:31:19 +0100189 return filepath.Join(config.(BootstrapConfig).BuildDir(), "bin")
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700190}
191
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700192func pluginDeps(ctx blueprint.BottomUpMutatorContext) {
193 if pkg, ok := ctx.Module().(*goPackage); ok {
Colin Crossd2458a22020-09-09 13:03:57 -0700194 if ctx.PrimaryModule() == ctx.Module() {
195 for _, plugin := range pkg.properties.PluginFor {
196 ctx.AddReverseDependency(ctx.Module(), nil, plugin)
197 }
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700198 }
199 }
200}
201
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700202type goPackageProducer interface {
203 GoPkgRoot() string
204 GoPackageTarget() string
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700205 GoTestTargets() []string
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700206}
207
208func isGoPackageProducer(module blueprint.Module) bool {
209 _, ok := module.(goPackageProducer)
210 return ok
211}
212
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700213type goPluginProvider interface {
214 GoPkgPath() string
215 IsPluginFor(string) bool
216}
217
218func isGoPluginFor(name string) func(blueprint.Module) bool {
219 return func(module blueprint.Module) bool {
220 if plugin, ok := module.(goPluginProvider); ok {
221 return plugin.IsPluginFor(name)
222 }
223 return false
224 }
225}
226
Colin Crossd2458a22020-09-09 13:03:57 -0700227func IsBootstrapModule(module blueprint.Module) bool {
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700228 _, isPackage := module.(*goPackage)
229 _, isBinary := module.(*goBinary)
230 return isPackage || isBinary
231}
232
233func isBootstrapBinaryModule(module blueprint.Module) bool {
234 _, isBinary := module.(*goBinary)
235 return isBinary
236}
237
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700238// A goPackage is a module for building Go packages.
239type goPackage struct {
Colin Cross0b7e83e2016-05-17 14:58:05 -0700240 blueprint.SimpleName
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700241 properties struct {
Colin Cross0b7e83e2016-05-17 14:58:05 -0700242 Deps []string
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700243 PkgPath string
244 Srcs []string
245 TestSrcs []string
246 PluginFor []string
Colin Cross910242b2016-04-11 15:41:52 -0700247
Dan Willemsenf14e0962017-02-06 14:00:10 -0800248 Darwin struct {
249 Srcs []string
250 TestSrcs []string
251 }
252 Linux struct {
253 Srcs []string
254 TestSrcs []string
255 }
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700256 }
257
258 // The root dir in which the package .a file is located. The full .a file
259 // path will be "packageRoot/PkgPath.a"
260 pkgRoot string
261
262 // The path of the .a file that is to be built.
263 archiveFile string
Dan Willemsen30a80c32015-06-24 19:21:21 -0700264
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700265 // The path of the test result file.
266 testResultFile []string
Dan Willemsen87ba2942015-06-23 17:21:00 -0700267
Dan Willemsen30a80c32015-06-24 19:21:21 -0700268 // The bootstrap Config
269 config *Config
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700270}
271
272var _ goPackageProducer = (*goPackage)(nil)
273
Dan Willemsen30a80c32015-06-24 19:21:21 -0700274func newGoPackageModuleFactory(config *Config) func() (blueprint.Module, []interface{}) {
275 return func() (blueprint.Module, []interface{}) {
276 module := &goPackage{
Colin Cross910242b2016-04-11 15:41:52 -0700277 config: config,
Dan Willemsen30a80c32015-06-24 19:21:21 -0700278 }
Colin Cross0b7e83e2016-05-17 14:58:05 -0700279 return module, []interface{}{&module.properties, &module.SimpleName.Properties}
Dan Willemsen30a80c32015-06-24 19:21:21 -0700280 }
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700281}
282
Colin Cross0b7e83e2016-05-17 14:58:05 -0700283func (g *goPackage) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
Colin Crossd2458a22020-09-09 13:03:57 -0700284 if ctx.Module() != ctx.PrimaryModule() {
285 return nil
286 }
Colin Cross0b7e83e2016-05-17 14:58:05 -0700287 return g.properties.Deps
288}
289
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700290func (g *goPackage) GoPkgPath() string {
291 return g.properties.PkgPath
292}
293
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700294func (g *goPackage) GoPkgRoot() string {
295 return g.pkgRoot
296}
297
298func (g *goPackage) GoPackageTarget() string {
299 return g.archiveFile
300}
301
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700302func (g *goPackage) GoTestTargets() []string {
303 return g.testResultFile
Dan Willemsen87ba2942015-06-23 17:21:00 -0700304}
305
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700306func (g *goPackage) IsPluginFor(name string) bool {
307 for _, plugin := range g.properties.PluginFor {
308 if plugin == name {
309 return true
310 }
311 }
312 return false
313}
314
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700315func (g *goPackage) GenerateBuildActions(ctx blueprint.ModuleContext) {
Colin Crossd2458a22020-09-09 13:03:57 -0700316 // Allow the primary builder to create multiple variants. Any variants after the first
317 // will copy outputs from the first.
318 if ctx.Module() != ctx.PrimaryModule() {
319 primary := ctx.PrimaryModule().(*goPackage)
320 g.pkgRoot = primary.pkgRoot
321 g.archiveFile = primary.archiveFile
322 g.testResultFile = primary.testResultFile
323 return
324 }
325
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700326 var (
327 name = ctx.ModuleName()
328 hasPlugins = false
329 pluginSrc = ""
330 genSrcs = []string{}
331 )
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700332
333 if g.properties.PkgPath == "" {
334 ctx.ModuleErrorf("module %s did not specify a valid pkgPath", name)
335 return
336 }
337
Colin Cross16fec722019-10-17 13:41:20 -0700338 g.pkgRoot = packageRoot(ctx, g.config)
Dan Willemsen87ba2942015-06-23 17:21:00 -0700339 g.archiveFile = filepath.Join(g.pkgRoot,
340 filepath.FromSlash(g.properties.PkgPath)+".a")
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700341
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700342 ctx.VisitDepsDepthFirstIf(isGoPluginFor(name),
343 func(module blueprint.Module) { hasPlugins = true })
344 if hasPlugins {
Colin Cross16fec722019-10-17 13:41:20 -0700345 pluginSrc = filepath.Join(moduleGenSrcDir(ctx, g.config), "plugin.go")
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700346 genSrcs = append(genSrcs, pluginSrc)
347 }
348
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700349 if hasPlugins && !buildGoPluginLoader(ctx, g.properties.PkgPath, pluginSrc) {
350 return
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700351 }
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700352
353 var srcs, testSrcs []string
354 if runtime.GOOS == "darwin" {
355 srcs = append(g.properties.Srcs, g.properties.Darwin.Srcs...)
356 testSrcs = append(g.properties.TestSrcs, g.properties.Darwin.TestSrcs...)
357 } else if runtime.GOOS == "linux" {
358 srcs = append(g.properties.Srcs, g.properties.Linux.Srcs...)
359 testSrcs = append(g.properties.TestSrcs, g.properties.Linux.TestSrcs...)
360 }
361
Colin Crossf8975142020-06-11 16:22:36 -0700362 if g.config.runGoTests {
363 testArchiveFile := filepath.Join(testRoot(ctx, g.config),
364 filepath.FromSlash(g.properties.PkgPath)+".a")
365 g.testResultFile = buildGoTest(ctx, testRoot(ctx, g.config), testArchiveFile,
366 g.properties.PkgPath, srcs, genSrcs,
Colin Cross0cdec992020-07-09 14:24:56 -0700367 testSrcs, g.config.useValidations)
Colin Crossf8975142020-06-11 16:22:36 -0700368 }
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700369
370 buildGoPackage(ctx, g.pkgRoot, g.properties.PkgPath, g.archiveFile,
371 srcs, genSrcs)
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700372}
373
374// A goBinary is a module for building executable binaries from Go sources.
375type goBinary struct {
Colin Cross0b7e83e2016-05-17 14:58:05 -0700376 blueprint.SimpleName
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700377 properties struct {
Colin Cross0b7e83e2016-05-17 14:58:05 -0700378 Deps []string
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700379 Srcs []string
Dan Willemsen87ba2942015-06-23 17:21:00 -0700380 TestSrcs []string
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700381 PrimaryBuilder bool
Dan Willemsenf60525a2017-07-19 18:48:01 -0700382 Default bool
Colin Cross910242b2016-04-11 15:41:52 -0700383
Dan Willemsenf14e0962017-02-06 14:00:10 -0800384 Darwin struct {
385 Srcs []string
386 TestSrcs []string
387 }
388 Linux struct {
389 Srcs []string
390 TestSrcs []string
391 }
392
Dan Willemsen734f20c2018-07-21 13:03:35 -0700393 Tool_dir bool `blueprint:"mutated"`
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700394 }
Dan Willemsen30a80c32015-06-24 19:21:21 -0700395
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700396 installPath string
397
Dan Willemsen30a80c32015-06-24 19:21:21 -0700398 // The bootstrap Config
399 config *Config
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700400}
401
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700402var _ GoBinaryTool = (*goBinary)(nil)
403
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700404func newGoBinaryModuleFactory(config *Config, tooldir bool) func() (blueprint.Module, []interface{}) {
Dan Willemsen30a80c32015-06-24 19:21:21 -0700405 return func() (blueprint.Module, []interface{}) {
406 module := &goBinary{
Colin Cross910242b2016-04-11 15:41:52 -0700407 config: config,
Dan Willemsen30a80c32015-06-24 19:21:21 -0700408 }
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700409 module.properties.Tool_dir = tooldir
Colin Cross0b7e83e2016-05-17 14:58:05 -0700410 return module, []interface{}{&module.properties, &module.SimpleName.Properties}
Dan Willemsen30a80c32015-06-24 19:21:21 -0700411 }
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700412}
413
Colin Cross0b7e83e2016-05-17 14:58:05 -0700414func (g *goBinary) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
Colin Crossd2458a22020-09-09 13:03:57 -0700415 if ctx.Module() != ctx.PrimaryModule() {
416 return nil
417 }
Colin Cross0b7e83e2016-05-17 14:58:05 -0700418 return g.properties.Deps
419}
420
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700421func (g *goBinary) isGoBinary() {}
Dan Willemsenbe275232016-05-26 10:07:59 -0700422func (g *goBinary) InstallPath() string {
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700423 return g.installPath
Dan Willemsenbe275232016-05-26 10:07:59 -0700424}
425
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700426func (g *goBinary) GenerateBuildActions(ctx blueprint.ModuleContext) {
Colin Crossd2458a22020-09-09 13:03:57 -0700427 // Allow the primary builder to create multiple variants. Any variants after the first
428 // will copy outputs from the first.
429 if ctx.Module() != ctx.PrimaryModule() {
430 primary := ctx.PrimaryModule().(*goBinary)
431 g.installPath = primary.installPath
432 return
433 }
434
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700435 var (
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700436 name = ctx.ModuleName()
Colin Cross16fec722019-10-17 13:41:20 -0700437 objDir = moduleObjDir(ctx, g.config)
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700438 archiveFile = filepath.Join(objDir, name+".a")
Colin Cross16fec722019-10-17 13:41:20 -0700439 testArchiveFile = filepath.Join(testRoot(ctx, g.config), name+".a")
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700440 aoutFile = filepath.Join(objDir, "a.out")
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700441 hasPlugins = false
442 pluginSrc = ""
443 genSrcs = []string{}
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700444 )
445
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700446 if g.properties.Tool_dir {
447 g.installPath = filepath.Join(toolDir(ctx.Config()), name)
448 } else {
Lukacs T. Berki7d2e60e2021-03-08 16:47:28 +0100449 g.installPath = filepath.Join(stageDir(g.config), "bin", name)
Dan Willemsen87f71fa2017-09-13 15:19:22 -0700450 }
451
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700452 ctx.VisitDepsDepthFirstIf(isGoPluginFor(name),
453 func(module blueprint.Module) { hasPlugins = true })
454 if hasPlugins {
Colin Cross16fec722019-10-17 13:41:20 -0700455 pluginSrc = filepath.Join(moduleGenSrcDir(ctx, g.config), "plugin.go")
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700456 genSrcs = append(genSrcs, pluginSrc)
457 }
458
Colin Cross0cdec992020-07-09 14:24:56 -0700459 var testDeps []string
Dan Willemsen87ba2942015-06-23 17:21:00 -0700460
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700461 if hasPlugins && !buildGoPluginLoader(ctx, "main", pluginSrc) {
462 return
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700463 }
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700464
465 var srcs, testSrcs []string
466 if runtime.GOOS == "darwin" {
467 srcs = append(g.properties.Srcs, g.properties.Darwin.Srcs...)
468 testSrcs = append(g.properties.TestSrcs, g.properties.Darwin.TestSrcs...)
469 } else if runtime.GOOS == "linux" {
470 srcs = append(g.properties.Srcs, g.properties.Linux.Srcs...)
471 testSrcs = append(g.properties.TestSrcs, g.properties.Linux.TestSrcs...)
472 }
473
474 if g.config.runGoTests {
Colin Cross0cdec992020-07-09 14:24:56 -0700475 testDeps = buildGoTest(ctx, testRoot(ctx, g.config), testArchiveFile,
476 name, srcs, genSrcs, testSrcs, g.config.useValidations)
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700477 }
478
Colin Crossa2bc5852019-09-06 14:25:28 -0700479 buildGoPackage(ctx, objDir, "main", archiveFile, srcs, genSrcs)
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700480
Colin Cross6c92af92018-09-28 16:15:58 -0700481 var linkDeps []string
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700482 var libDirFlags []string
483 ctx.VisitDepsDepthFirstIf(isGoPackageProducer,
484 func(module blueprint.Module) {
485 dep := module.(goPackageProducer)
Colin Cross6c92af92018-09-28 16:15:58 -0700486 linkDeps = append(linkDeps, dep.GoPackageTarget())
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700487 libDir := dep.GoPkgRoot()
488 libDirFlags = append(libDirFlags, "-L "+libDir)
Colin Cross0cdec992020-07-09 14:24:56 -0700489 testDeps = append(testDeps, dep.GoTestTargets()...)
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700490 })
491
492 linkArgs := map[string]string{}
493 if len(libDirFlags) > 0 {
494 linkArgs["libDirFlags"] = strings.Join(libDirFlags, " ")
495 }
496
497 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross6c92af92018-09-28 16:15:58 -0700498 Rule: link,
499 Outputs: []string{aoutFile},
500 Inputs: []string{archiveFile},
501 Implicits: linkDeps,
502 Args: linkArgs,
503 Optional: true,
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700504 })
505
Colin Cross0cdec992020-07-09 14:24:56 -0700506 var orderOnlyDeps, validationDeps []string
507 if g.config.useValidations {
508 validationDeps = testDeps
509 } else {
510 orderOnlyDeps = testDeps
511 }
512
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700513 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross0cdec992020-07-09 14:24:56 -0700514 Rule: cp,
515 Outputs: []string{g.installPath},
516 Inputs: []string{aoutFile},
517 OrderOnly: orderOnlyDeps,
518 Validations: validationDeps,
519 Optional: !g.properties.Default,
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700520 })
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700521}
522
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700523func buildGoPluginLoader(ctx blueprint.ModuleContext, pkgPath, pluginSrc string) bool {
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700524 ret := true
525 name := ctx.ModuleName()
526
527 var pluginPaths []string
528 ctx.VisitDepsDepthFirstIf(isGoPluginFor(name),
529 func(module blueprint.Module) {
530 plugin := module.(goPluginProvider)
531 pluginPaths = append(pluginPaths, plugin.GoPkgPath())
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700532 })
533
534 ctx.Build(pctx, blueprint.BuildParams{
Dan Willemsenfce63d32015-11-17 14:21:45 -0800535 Rule: pluginGenSrc,
536 Outputs: []string{pluginSrc},
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700537 Args: map[string]string{
538 "pkg": pkgPath,
539 "plugins": strings.Join(pluginPaths, " "),
540 },
Dan Willemsenf60525a2017-07-19 18:48:01 -0700541 Optional: true,
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700542 })
543
544 return ret
545}
546
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700547func buildGoPackage(ctx blueprint.ModuleContext, pkgRoot string,
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700548 pkgPath string, archiveFile string, srcs []string, genSrcs []string) {
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700549
Jamie Gennis9e2a4c22014-11-09 11:52:56 -0800550 srcDir := moduleSrcDir(ctx)
Jamie Gennisb9314562014-06-06 14:37:07 -0700551 srcFiles := pathtools.PrefixPaths(srcs, srcDir)
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700552 srcFiles = append(srcFiles, genSrcs...)
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700553
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700554 var incFlags []string
Dan Willemsenfce63d32015-11-17 14:21:45 -0800555 var deps []string
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700556 ctx.VisitDepsDepthFirstIf(isGoPackageProducer,
557 func(module blueprint.Module) {
558 dep := module.(goPackageProducer)
559 incDir := dep.GoPkgRoot()
560 target := dep.GoPackageTarget()
561 incFlags = append(incFlags, "-I "+incDir)
Colin Cross5e3594f2014-10-22 13:22:22 -0700562 deps = append(deps, target)
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700563 })
564
Dan Willemsenc20adea2015-08-01 15:07:27 -0700565 compileArgs := map[string]string{
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700566 "pkgPath": pkgPath,
567 }
568
569 if len(incFlags) > 0 {
Dan Willemsenc20adea2015-08-01 15:07:27 -0700570 compileArgs["incFlags"] = strings.Join(incFlags, " ")
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700571 }
572
Jamie Gennis2fb20952014-10-03 02:49:58 -0700573 ctx.Build(pctx, blueprint.BuildParams{
Dan Willemsenc20adea2015-08-01 15:07:27 -0700574 Rule: compile,
Colin Crossdaf64992014-10-22 10:55:28 -0700575 Outputs: []string{archiveFile},
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700576 Inputs: srcFiles,
Colin Cross5e3594f2014-10-22 13:22:22 -0700577 Implicits: deps,
Dan Willemsenc20adea2015-08-01 15:07:27 -0700578 Args: compileArgs,
Dan Willemsenf60525a2017-07-19 18:48:01 -0700579 Optional: true,
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700580 })
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700581}
582
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700583func buildGoTest(ctx blueprint.ModuleContext, testRoot, testPkgArchive,
Colin Cross0cdec992020-07-09 14:24:56 -0700584 pkgPath string, srcs, genSrcs, testSrcs []string, useValidations bool) []string {
Dan Willemsen87ba2942015-06-23 17:21:00 -0700585
586 if len(testSrcs) == 0 {
587 return nil
588 }
589
590 srcDir := moduleSrcDir(ctx)
591 testFiles := pathtools.PrefixPaths(testSrcs, srcDir)
592
593 mainFile := filepath.Join(testRoot, "test.go")
594 testArchive := filepath.Join(testRoot, "test.a")
595 testFile := filepath.Join(testRoot, "test")
596 testPassed := filepath.Join(testRoot, "test.passed")
597
598 buildGoPackage(ctx, testRoot, pkgPath, testPkgArchive,
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700599 append(srcs, testSrcs...), genSrcs)
Dan Willemsen87ba2942015-06-23 17:21:00 -0700600
601 ctx.Build(pctx, blueprint.BuildParams{
Dan Willemsenfce63d32015-11-17 14:21:45 -0800602 Rule: goTestMain,
603 Outputs: []string{mainFile},
604 Inputs: testFiles,
Dan Willemsen87ba2942015-06-23 17:21:00 -0700605 Args: map[string]string{
606 "pkg": pkgPath,
607 },
Dan Willemsenf60525a2017-07-19 18:48:01 -0700608 Optional: true,
Dan Willemsen87ba2942015-06-23 17:21:00 -0700609 })
610
Colin Cross1be9abc2018-10-24 13:11:33 -0700611 linkDeps := []string{testPkgArchive}
Dan Willemsen87ba2942015-06-23 17:21:00 -0700612 libDirFlags := []string{"-L " + testRoot}
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700613 testDeps := []string{}
Dan Willemsen87ba2942015-06-23 17:21:00 -0700614 ctx.VisitDepsDepthFirstIf(isGoPackageProducer,
615 func(module blueprint.Module) {
616 dep := module.(goPackageProducer)
Colin Cross0e58dc02018-10-05 11:12:53 -0700617 linkDeps = append(linkDeps, dep.GoPackageTarget())
Dan Willemsen87ba2942015-06-23 17:21:00 -0700618 libDir := dep.GoPkgRoot()
619 libDirFlags = append(libDirFlags, "-L "+libDir)
Dan Willemsen9bd6b382016-11-02 00:43:00 -0700620 testDeps = append(testDeps, dep.GoTestTargets()...)
Dan Willemsen87ba2942015-06-23 17:21:00 -0700621 })
622
623 ctx.Build(pctx, blueprint.BuildParams{
Dan Willemsenc20adea2015-08-01 15:07:27 -0700624 Rule: compile,
Dan Willemsen87ba2942015-06-23 17:21:00 -0700625 Outputs: []string{testArchive},
626 Inputs: []string{mainFile},
Dan Willemsenfce63d32015-11-17 14:21:45 -0800627 Implicits: []string{testPkgArchive},
Dan Willemsen87ba2942015-06-23 17:21:00 -0700628 Args: map[string]string{
629 "pkgPath": "main",
630 "incFlags": "-I " + testRoot,
631 },
Dan Willemsenf60525a2017-07-19 18:48:01 -0700632 Optional: true,
Dan Willemsen87ba2942015-06-23 17:21:00 -0700633 })
634
635 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross0e58dc02018-10-05 11:12:53 -0700636 Rule: link,
637 Outputs: []string{testFile},
638 Inputs: []string{testArchive},
639 Implicits: linkDeps,
Dan Willemsen87ba2942015-06-23 17:21:00 -0700640 Args: map[string]string{
641 "libDirFlags": strings.Join(libDirFlags, " "),
642 },
Dan Willemsenf60525a2017-07-19 18:48:01 -0700643 Optional: true,
Dan Willemsen87ba2942015-06-23 17:21:00 -0700644 })
645
Colin Cross0cdec992020-07-09 14:24:56 -0700646 var orderOnlyDeps, validationDeps []string
647 if useValidations {
648 validationDeps = testDeps
649 } else {
650 orderOnlyDeps = testDeps
651 }
652
Dan Willemsen87ba2942015-06-23 17:21:00 -0700653 ctx.Build(pctx, blueprint.BuildParams{
Colin Cross0cdec992020-07-09 14:24:56 -0700654 Rule: test,
655 Outputs: []string{testPassed},
656 Inputs: []string{testFile},
657 OrderOnly: orderOnlyDeps,
658 Validations: validationDeps,
Dan Willemsen87ba2942015-06-23 17:21:00 -0700659 Args: map[string]string{
660 "pkg": pkgPath,
661 "pkgSrcDir": filepath.Dir(testFiles[0]),
662 },
Dan Willemsenf60525a2017-07-19 18:48:01 -0700663 Optional: true,
Dan Willemsen87ba2942015-06-23 17:21:00 -0700664 })
665
666 return []string{testPassed}
667}
668
Dan Willemsen30a80c32015-06-24 19:21:21 -0700669type singleton struct {
670 // The bootstrap Config
671 config *Config
672}
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700673
Dan Willemsen30a80c32015-06-24 19:21:21 -0700674func newSingletonFactory(config *Config) func() blueprint.Singleton {
675 return func() blueprint.Singleton {
676 return &singleton{
677 config: config,
678 }
679 }
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700680}
681
682func (s *singleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
683 // Find the module that's marked as the "primary builder", which means it's
684 // creating the binary that we'll use to generate the non-bootstrap
685 // build.ninja file.
686 var primaryBuilders []*goBinary
Dan Willemsenbe275232016-05-26 10:07:59 -0700687 // blueprintTools contains blueprint go binaries that will be built in StageMain
688 var blueprintTools []string
Colin Crossf8975142020-06-11 16:22:36 -0700689 ctx.VisitAllModulesIf(isBootstrapBinaryModule,
690 func(module blueprint.Module) {
Colin Crossd2458a22020-09-09 13:03:57 -0700691 if ctx.PrimaryModule(module) == module {
692 binaryModule := module.(*goBinary)
Colin Crossf8975142020-06-11 16:22:36 -0700693
Colin Crossd2458a22020-09-09 13:03:57 -0700694 if binaryModule.properties.Tool_dir {
695 blueprintTools = append(blueprintTools, binaryModule.InstallPath())
696 }
697 if binaryModule.properties.PrimaryBuilder {
698 primaryBuilders = append(primaryBuilders, binaryModule)
699 }
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700700 }
Colin Crossf8975142020-06-11 16:22:36 -0700701 })
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700702
Lukacs T. Berki77ef79b2021-04-12 12:07:02 +0200703 var primaryBuilderCmdlinePrefix []string
704 var primaryBuilderName string
Dan Willemsenb6d88a42016-11-01 17:12:28 -0700705
Lukacs T. Berki77ef79b2021-04-12 12:07:02 +0200706 if len(primaryBuilders) == 0 {
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700707 // If there's no primary builder module then that means we'll use minibp
708 // as the primary builder. We can trigger its primary builder mode with
709 // the -p flag.
710 primaryBuilderName = "minibp"
Lukacs T. Berki77ef79b2021-04-12 12:07:02 +0200711 primaryBuilderCmdlinePrefix = append(primaryBuilderCmdlinePrefix, "-p")
712 } else if len(primaryBuilders) > 1 {
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700713 ctx.Errorf("multiple primary builder modules present:")
714 for _, primaryBuilder := range primaryBuilders {
715 ctx.ModuleErrorf(primaryBuilder, "<-- module %s",
716 ctx.ModuleName(primaryBuilder))
717 }
718 return
Lukacs T. Berki77ef79b2021-04-12 12:07:02 +0200719 } else {
720 primaryBuilderName = ctx.ModuleName(primaryBuilders[0])
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700721 }
722
Dan Willemsen852191d2015-07-13 23:28:37 -0700723 primaryBuilderFile := filepath.Join("$BinDir", primaryBuilderName)
Dan Willemsencd4e0ce2017-07-19 22:43:30 -0700724 ctx.SetNinjaBuildDir(pctx, "${ninjaBuildDir}")
Dan Willemsenefd2de72015-07-22 17:06:06 -0700725
Dan Willemsenab223a52018-07-05 21:56:59 -0700726 if s.config.stage == StagePrimary {
Lukacs T. Berki77ef79b2021-04-12 12:07:02 +0200727 ctx.AddSubninja(s.config.globFile)
Dan Willemsenefd2de72015-07-22 17:06:06 -0700728
Lukacs T. Berki77ef79b2021-04-12 12:07:02 +0200729 for _, i := range s.config.primaryBuilderInvocations {
730 flags := make([]string, 0)
731 flags = append(flags, primaryBuilderCmdlinePrefix...)
732 flags = append(flags, i.Args...)
733
734 // Build the main build.ninja
735 ctx.Build(pctx, blueprint.BuildParams{
736 Rule: generateBuildNinja,
737 Outputs: i.Outputs,
738 Inputs: i.Inputs,
739 Args: map[string]string{
740 "builder": primaryBuilderFile,
741 "extra": strings.Join(flags, " "),
742 },
743 })
Dan Willemsenab223a52018-07-05 21:56:59 -0700744 }
Dan Willemsenab223a52018-07-05 21:56:59 -0700745 }
Colin Cross4572edd2015-05-13 14:36:24 -0700746
Dan Willemsenaf456ea2017-07-19 19:22:34 -0700747 if s.config.stage == StageMain {
Jamie Gennis7ab5f3c2014-06-11 15:51:08 -0700748 if primaryBuilderName == "minibp" {
749 // This is a standalone Blueprint build, so we copy the minibp
750 // binary to the "bin" directory to make it easier to find.
Dan Willemsenf0ca9012015-07-13 18:11:49 -0700751 finalMinibp := filepath.Join("$buildDir", "bin", primaryBuilderName)
Jamie Gennis2fb20952014-10-03 02:49:58 -0700752 ctx.Build(pctx, blueprint.BuildParams{
Jamie Gennis7ab5f3c2014-06-11 15:51:08 -0700753 Rule: cp,
754 Inputs: []string{primaryBuilderFile},
755 Outputs: []string{finalMinibp},
756 })
757 }
Dan Willemsenbe275232016-05-26 10:07:59 -0700758
Colin Cross5eb116a2017-12-11 14:58:45 -0800759 // Generate build system docs for the primary builder. Generating docs reads the source
760 // files used to build the primary builder, but that dependency will be picked up through
761 // the dependency on the primary builder itself. There are no dependencies on the
762 // Blueprints files, as any relevant changes to the Blueprints files would have caused
763 // a rebuild of the primary builder.
764 docsFile := filepath.Join(docsDir, primaryBuilderName+".html")
765 bigbpDocs := ctx.Rule(pctx, "bigbpDocs",
766 blueprint.RuleParams{
Lukacs T. Berki78df8532021-04-14 10:28:54 +0200767 Command: fmt.Sprintf("%s -b $buildDir --docs $out %s", primaryBuilderFile,
768 s.config.topLevelBlueprintsFile),
Colin Cross5eb116a2017-12-11 14:58:45 -0800769 CommandDeps: []string{primaryBuilderFile},
770 Description: fmt.Sprintf("%s docs $out", primaryBuilderName),
771 })
772
773 ctx.Build(pctx, blueprint.BuildParams{
774 Rule: bigbpDocs,
775 Outputs: []string{docsFile},
776 })
777
778 // Add a phony target for building the documentation
779 ctx.Build(pctx, blueprint.BuildParams{
780 Rule: blueprint.Phony,
781 Outputs: []string{"blueprint_docs"},
782 Inputs: []string{docsFile},
783 })
784
785 // Add a phony target for building various tools that are part of blueprint
Dan Willemsenbe275232016-05-26 10:07:59 -0700786 ctx.Build(pctx, blueprint.BuildParams{
787 Rule: blueprint.Phony,
788 Outputs: []string{"blueprint_tools"},
789 Inputs: blueprintTools,
790 })
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700791 }
792}
793
Colin Cross16fec722019-10-17 13:41:20 -0700794func stageDir(config *Config) string {
795 if config.stage == StageMain {
796 return mainDir
797 } else {
798 return bootstrapDir
799 }
800}
801
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700802// packageRoot returns the module-specific package root directory path. This
803// directory is where the final package .a files are output and where dependant
804// modules search for this package via -I arguments.
Colin Cross16fec722019-10-17 13:41:20 -0700805func packageRoot(ctx blueprint.ModuleContext, config *Config) string {
806 return filepath.Join(stageDir(config), ctx.ModuleName(), "pkg")
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700807}
808
Dan Willemsen87ba2942015-06-23 17:21:00 -0700809// testRoot returns the module-specific package root directory path used for
810// building tests. The .a files generated here will include everything from
811// packageRoot, plus the test-only code.
Colin Cross16fec722019-10-17 13:41:20 -0700812func testRoot(ctx blueprint.ModuleContext, config *Config) string {
813 return filepath.Join(stageDir(config), ctx.ModuleName(), "test")
Dan Willemsen87ba2942015-06-23 17:21:00 -0700814}
815
Jamie Gennis9e2a4c22014-11-09 11:52:56 -0800816// moduleSrcDir returns the path of the directory that all source file paths are
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700817// specified relative to.
Jamie Gennis9e2a4c22014-11-09 11:52:56 -0800818func moduleSrcDir(ctx blueprint.ModuleContext) string {
819 return filepath.Join("$srcDir", ctx.ModuleDir())
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700820}
821
Jamie Gennis9e2a4c22014-11-09 11:52:56 -0800822// moduleObjDir returns the module-specific object directory path.
Colin Cross16fec722019-10-17 13:41:20 -0700823func moduleObjDir(ctx blueprint.ModuleContext, config *Config) string {
824 return filepath.Join(stageDir(config), ctx.ModuleName(), "obj")
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700825}
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700826
827// moduleGenSrcDir returns the module-specific generated sources path.
Colin Cross16fec722019-10-17 13:41:20 -0700828func moduleGenSrcDir(ctx blueprint.ModuleContext, config *Config) string {
829 return filepath.Join(stageDir(config), ctx.ModuleName(), "gen")
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700830}