Colin Cross | 8e0c511 | 2015-01-23 14:15:10 -0800 | [diff] [blame] | 1 | // 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 Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 15 | package bootstrap |
| 16 | |
| 17 | import ( |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 18 | "fmt" |
Dan Willemsen | c54c072 | 2017-07-24 20:28:41 -0700 | [diff] [blame] | 19 | "go/build" |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 20 | "path/filepath" |
Dan Willemsen | f14e096 | 2017-02-06 14:00:10 -0800 | [diff] [blame] | 21 | "runtime" |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 22 | "strings" |
Colin Cross | 4572edd | 2015-05-13 14:36:24 -0700 | [diff] [blame] | 23 | |
| 24 | "github.com/google/blueprint" |
| 25 | "github.com/google/blueprint/pathtools" |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 26 | ) |
| 27 | |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 28 | const mainSubDir = ".primary" |
Dan Willemsen | 4d6af1f | 2015-09-11 16:55:53 -0700 | [diff] [blame] | 29 | const bootstrapSubDir = ".bootstrap" |
| 30 | const miniBootstrapSubDir = ".minibootstrap" |
Jamie Gennis | 598fe76 | 2014-06-06 14:21:57 -0700 | [diff] [blame] | 31 | |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 32 | var ( |
Jamie Gennis | 6cafc2c | 2015-03-20 22:39:29 -0400 | [diff] [blame] | 33 | pctx = blueprint.NewPackageContext("github.com/google/blueprint/bootstrap") |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 34 | |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 35 | goTestMainCmd = pctx.StaticVariable("goTestMainCmd", filepath.Join(bootstrapDir, "bin", "gotestmain")) |
Dan Willemsen | c7697ce | 2015-09-17 20:59:51 -0700 | [diff] [blame] | 36 | goTestRunnerCmd = pctx.StaticVariable("goTestRunnerCmd", filepath.Join(bootstrapDir, "bin", "gotestrunner")) |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 37 | pluginGenSrcCmd = pctx.StaticVariable("pluginGenSrcCmd", filepath.Join(bootstrapDir, "bin", "loadplugins")) |
Jamie Gennis | 2fb2095 | 2014-10-03 02:49:58 -0700 | [diff] [blame] | 38 | |
Dan Willemsen | c54c072 | 2017-07-24 20:28:41 -0700 | [diff] [blame] | 39 | 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 Willemsen | 20c343b | 2018-03-02 15:03:24 -0800 | [diff] [blame] | 43 | 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 Willemsen | c54c072 | 2017-07-24 20:28:41 -0700 | [diff] [blame] | 52 | } |
| 53 | } |
| 54 | return "" |
| 55 | }()) |
| 56 | |
Dan Willemsen | c20adea | 2015-08-01 15:07:27 -0700 | [diff] [blame] | 57 | compile = pctx.StaticRule("compile", |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 58 | blueprint.RuleParams{ |
Colin Cross | 6c92af9 | 2018-09-28 16:15:58 -0700 | [diff] [blame] | 59 | Command: "GOROOT='$goRoot' $compileCmd $parallelCompile -o $out.tmp " + |
Lukacs T. Berki | 07a91f0 | 2021-03-17 15:01:51 +0100 | [diff] [blame] | 60 | "$debugFlags -p $pkgPath -complete $incFlags -pack $in && " + |
Colin Cross | 6c92af9 | 2018-09-28 16:15:58 -0700 | [diff] [blame] | 61 | "if cmp --quiet $out.tmp $out; then rm $out.tmp; else mv -f $out.tmp $out; fi", |
Dan Willemsen | fce63d3 | 2015-11-17 14:21:45 -0800 | [diff] [blame] | 62 | CommandDeps: []string{"$compileCmd"}, |
Dan Willemsen | c20adea | 2015-08-01 15:07:27 -0700 | [diff] [blame] | 63 | Description: "compile $out", |
Colin Cross | 6c92af9 | 2018-09-28 16:15:58 -0700 | [diff] [blame] | 64 | Restat: true, |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 65 | }, |
| 66 | "pkgPath", "incFlags") |
| 67 | |
Jamie Gennis | 2fb2095 | 2014-10-03 02:49:58 -0700 | [diff] [blame] | 68 | link = pctx.StaticRule("link", |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 69 | blueprint.RuleParams{ |
Colin Cross | 6c92af9 | 2018-09-28 16:15:58 -0700 | [diff] [blame] | 70 | 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 Willemsen | fce63d3 | 2015-11-17 14:21:45 -0800 | [diff] [blame] | 72 | CommandDeps: []string{"$linkCmd"}, |
Dan Willemsen | c20adea | 2015-08-01 15:07:27 -0700 | [diff] [blame] | 73 | Description: "link $out", |
Colin Cross | 6c92af9 | 2018-09-28 16:15:58 -0700 | [diff] [blame] | 74 | Restat: true, |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 75 | }, |
| 76 | "libDirFlags") |
| 77 | |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 78 | goTestMain = pctx.StaticRule("gotestmain", |
| 79 | blueprint.RuleParams{ |
| 80 | Command: "$goTestMainCmd -o $out -pkg $pkg $in", |
Dan Willemsen | fce63d3 | 2015-11-17 14:21:45 -0800 | [diff] [blame] | 81 | CommandDeps: []string{"$goTestMainCmd"}, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 82 | Description: "gotestmain $out", |
| 83 | }, |
| 84 | "pkg") |
| 85 | |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 86 | pluginGenSrc = pctx.StaticRule("pluginGenSrc", |
| 87 | blueprint.RuleParams{ |
| 88 | Command: "$pluginGenSrcCmd -o $out -p $pkg $plugins", |
Dan Willemsen | fce63d3 | 2015-11-17 14:21:45 -0800 | [diff] [blame] | 89 | CommandDeps: []string{"$pluginGenSrcCmd"}, |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 90 | Description: "create $out", |
| 91 | }, |
| 92 | "pkg", "plugins") |
| 93 | |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 94 | test = pctx.StaticRule("test", |
| 95 | blueprint.RuleParams{ |
Dan Willemsen | c7697ce | 2015-09-17 20:59:51 -0700 | [diff] [blame] | 96 | Command: "$goTestRunnerCmd -p $pkgSrcDir -f $out -- $in -test.short", |
Dan Willemsen | fce63d3 | 2015-11-17 14:21:45 -0800 | [diff] [blame] | 97 | CommandDeps: []string{"$goTestRunnerCmd"}, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 98 | Description: "test $pkg", |
| 99 | }, |
| 100 | "pkg", "pkgSrcDir") |
| 101 | |
Jamie Gennis | 2fb2095 | 2014-10-03 02:49:58 -0700 | [diff] [blame] | 102 | cp = pctx.StaticRule("cp", |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 103 | blueprint.RuleParams{ |
| 104 | Command: "cp $in $out", |
| 105 | Description: "cp $out", |
Jamie Gennis | cbc6f86 | 2014-06-05 20:00:22 -0700 | [diff] [blame] | 106 | }, |
| 107 | "generator") |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 108 | |
Jamie Gennis | 2fb2095 | 2014-10-03 02:49:58 -0700 | [diff] [blame] | 109 | bootstrap = pctx.StaticRule("bootstrap", |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 110 | blueprint.RuleParams{ |
Dan Willemsen | 991f760 | 2015-09-17 22:48:04 -0700 | [diff] [blame] | 111 | Command: "BUILDDIR=$buildDir $bootstrapCmd -i $in", |
Dan Willemsen | fce63d3 | 2015-11-17 14:21:45 -0800 | [diff] [blame] | 112 | CommandDeps: []string{"$bootstrapCmd"}, |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 113 | Description: "bootstrap $in", |
| 114 | Generator: true, |
| 115 | }) |
| 116 | |
Dan Willemsen | 91a657e | 2015-07-22 17:05:59 -0700 | [diff] [blame] | 117 | touch = pctx.StaticRule("touch", |
| 118 | blueprint.RuleParams{ |
| 119 | Command: "touch $out", |
| 120 | Description: "touch $out", |
| 121 | }, |
| 122 | "depfile", "generator") |
| 123 | |
Dan Willemsen | b6d88a4 | 2016-11-01 17:12:28 -0700 | [diff] [blame] | 124 | generateBuildNinja = pctx.StaticRule("build.ninja", |
| 125 | blueprint.RuleParams{ |
Lukacs T. Berki | f802ffc | 2021-02-17 11:59:10 +0100 | [diff] [blame] | 126 | // 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. Berki | 0bd3de3 | 2021-03-08 13:09:19 +0100 | [diff] [blame] | 129 | // 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. Berki | 0bd3de3 | 2021-03-08 13:09:19 +0100 | [diff] [blame] | 135 | ` --top "$$TOP" ` + |
Lukacs T. Berki | 77ef79b | 2021-04-12 12:07:02 +0200 | [diff] [blame] | 136 | ` --out "$buildDir" ` + |
Lukacs T. Berki | 0bd3de3 | 2021-03-08 13:09:19 +0100 | [diff] [blame] | 137 | ` -n "$ninjaBuildDir" ` + |
| 138 | ` -d "$out.d" ` + |
Lukacs T. Berki | 77ef79b | 2021-04-12 12:07:02 +0200 | [diff] [blame] | 139 | ` $extra`, |
Dan Willemsen | b6d88a4 | 2016-11-01 17:12:28 -0700 | [diff] [blame] | 140 | CommandDeps: []string{"$builder"}, |
| 141 | Description: "$builder $out", |
Dan Willemsen | 2d9b59b | 2017-12-18 09:14:16 -0800 | [diff] [blame] | 142 | Deps: blueprint.DepsGCC, |
Dan Willemsen | b6d88a4 | 2016-11-01 17:12:28 -0700 | [diff] [blame] | 143 | Depfile: "$out.d", |
| 144 | Restat: true, |
| 145 | }, |
Lukacs T. Berki | 77ef79b | 2021-04-12 12:07:02 +0200 | [diff] [blame] | 146 | "builder", "extra") |
Dan Willemsen | b6d88a4 | 2016-11-01 17:12:28 -0700 | [diff] [blame] | 147 | |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 148 | // Work around a Ninja issue. See https://github.com/martine/ninja/pull/634 |
Jamie Gennis | 2fb2095 | 2014-10-03 02:49:58 -0700 | [diff] [blame] | 149 | phony = pctx.StaticRule("phony", |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 150 | blueprint.RuleParams{ |
| 151 | Command: "# phony $out", |
| 152 | Description: "phony $out", |
| 153 | Generator: true, |
| 154 | }, |
| 155 | "depfile") |
| 156 | |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 157 | _ = pctx.VariableFunc("BinDir", func(config interface{}) (string, error) { |
Lukacs T. Berki | 5353744 | 2021-03-12 08:31:19 +0100 | [diff] [blame] | 158 | return bootstrapBinDir(config), nil |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 159 | }) |
| 160 | |
| 161 | _ = pctx.VariableFunc("ToolDir", func(config interface{}) (string, error) { |
| 162 | return toolDir(config), nil |
| 163 | }) |
Colin Cross | 4572edd | 2015-05-13 14:36:24 -0700 | [diff] [blame] | 164 | |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 165 | docsDir = filepath.Join(mainDir, "docs") |
Dan Willemsen | 4d6af1f | 2015-09-11 16:55:53 -0700 | [diff] [blame] | 166 | |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 167 | mainDir = filepath.Join("$buildDir", mainSubDir) |
Dan Willemsen | c7697ce | 2015-09-17 20:59:51 -0700 | [diff] [blame] | 168 | bootstrapDir = filepath.Join("$buildDir", bootstrapSubDir) |
Dan Willemsen | 4d6af1f | 2015-09-11 16:55:53 -0700 | [diff] [blame] | 169 | miniBootstrapDir = filepath.Join("$buildDir", miniBootstrapSubDir) |
Dan Willemsen | 1e72321 | 2017-07-18 19:37:37 -0700 | [diff] [blame] | 170 | |
| 171 | minibpFile = filepath.Join(miniBootstrapDir, "minibp") |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 172 | ) |
| 173 | |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 174 | type GoBinaryTool interface { |
| 175 | InstallPath() string |
| 176 | |
| 177 | // So that other packages can't implement this interface |
| 178 | isGoBinary() |
| 179 | } |
| 180 | |
Lukacs T. Berki | 5353744 | 2021-03-12 08:31:19 +0100 | [diff] [blame] | 181 | func bootstrapBinDir(config interface{}) string { |
| 182 | return filepath.Join(config.(BootstrapConfig).BuildDir(), bootstrapSubDir, "bin") |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | func toolDir(config interface{}) string { |
| 186 | if c, ok := config.(ConfigBlueprintToolLocation); ok { |
| 187 | return filepath.Join(c.BlueprintToolLocation()) |
| 188 | } |
Lukacs T. Berki | 5353744 | 2021-03-12 08:31:19 +0100 | [diff] [blame] | 189 | return filepath.Join(config.(BootstrapConfig).BuildDir(), "bin") |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 190 | } |
| 191 | |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 192 | func pluginDeps(ctx blueprint.BottomUpMutatorContext) { |
| 193 | if pkg, ok := ctx.Module().(*goPackage); ok { |
Colin Cross | d2458a2 | 2020-09-09 13:03:57 -0700 | [diff] [blame] | 194 | if ctx.PrimaryModule() == ctx.Module() { |
| 195 | for _, plugin := range pkg.properties.PluginFor { |
| 196 | ctx.AddReverseDependency(ctx.Module(), nil, plugin) |
| 197 | } |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 198 | } |
| 199 | } |
| 200 | } |
| 201 | |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 202 | type goPackageProducer interface { |
| 203 | GoPkgRoot() string |
| 204 | GoPackageTarget() string |
Dan Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 205 | GoTestTargets() []string |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 206 | } |
| 207 | |
| 208 | func isGoPackageProducer(module blueprint.Module) bool { |
| 209 | _, ok := module.(goPackageProducer) |
| 210 | return ok |
| 211 | } |
| 212 | |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 213 | type goPluginProvider interface { |
| 214 | GoPkgPath() string |
| 215 | IsPluginFor(string) bool |
| 216 | } |
| 217 | |
| 218 | func 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 Cross | d2458a2 | 2020-09-09 13:03:57 -0700 | [diff] [blame] | 227 | func IsBootstrapModule(module blueprint.Module) bool { |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 228 | _, isPackage := module.(*goPackage) |
| 229 | _, isBinary := module.(*goBinary) |
| 230 | return isPackage || isBinary |
| 231 | } |
| 232 | |
| 233 | func isBootstrapBinaryModule(module blueprint.Module) bool { |
| 234 | _, isBinary := module.(*goBinary) |
| 235 | return isBinary |
| 236 | } |
| 237 | |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 238 | // A goPackage is a module for building Go packages. |
| 239 | type goPackage struct { |
Colin Cross | 0b7e83e | 2016-05-17 14:58:05 -0700 | [diff] [blame] | 240 | blueprint.SimpleName |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 241 | properties struct { |
Colin Cross | 0b7e83e | 2016-05-17 14:58:05 -0700 | [diff] [blame] | 242 | Deps []string |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 243 | PkgPath string |
| 244 | Srcs []string |
| 245 | TestSrcs []string |
| 246 | PluginFor []string |
Colin Cross | 910242b | 2016-04-11 15:41:52 -0700 | [diff] [blame] | 247 | |
Dan Willemsen | f14e096 | 2017-02-06 14:00:10 -0800 | [diff] [blame] | 248 | Darwin struct { |
| 249 | Srcs []string |
| 250 | TestSrcs []string |
| 251 | } |
| 252 | Linux struct { |
| 253 | Srcs []string |
| 254 | TestSrcs []string |
| 255 | } |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 256 | } |
| 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 Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 264 | |
Dan Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 265 | // The path of the test result file. |
| 266 | testResultFile []string |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 267 | |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 268 | // The bootstrap Config |
| 269 | config *Config |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 270 | } |
| 271 | |
| 272 | var _ goPackageProducer = (*goPackage)(nil) |
| 273 | |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 274 | func newGoPackageModuleFactory(config *Config) func() (blueprint.Module, []interface{}) { |
| 275 | return func() (blueprint.Module, []interface{}) { |
| 276 | module := &goPackage{ |
Colin Cross | 910242b | 2016-04-11 15:41:52 -0700 | [diff] [blame] | 277 | config: config, |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 278 | } |
Colin Cross | 0b7e83e | 2016-05-17 14:58:05 -0700 | [diff] [blame] | 279 | return module, []interface{}{&module.properties, &module.SimpleName.Properties} |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 280 | } |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 281 | } |
| 282 | |
Colin Cross | 0b7e83e | 2016-05-17 14:58:05 -0700 | [diff] [blame] | 283 | func (g *goPackage) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string { |
Colin Cross | d2458a2 | 2020-09-09 13:03:57 -0700 | [diff] [blame] | 284 | if ctx.Module() != ctx.PrimaryModule() { |
| 285 | return nil |
| 286 | } |
Colin Cross | 0b7e83e | 2016-05-17 14:58:05 -0700 | [diff] [blame] | 287 | return g.properties.Deps |
| 288 | } |
| 289 | |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 290 | func (g *goPackage) GoPkgPath() string { |
| 291 | return g.properties.PkgPath |
| 292 | } |
| 293 | |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 294 | func (g *goPackage) GoPkgRoot() string { |
| 295 | return g.pkgRoot |
| 296 | } |
| 297 | |
| 298 | func (g *goPackage) GoPackageTarget() string { |
| 299 | return g.archiveFile |
| 300 | } |
| 301 | |
Dan Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 302 | func (g *goPackage) GoTestTargets() []string { |
| 303 | return g.testResultFile |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 304 | } |
| 305 | |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 306 | func (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 Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 315 | func (g *goPackage) GenerateBuildActions(ctx blueprint.ModuleContext) { |
Colin Cross | d2458a2 | 2020-09-09 13:03:57 -0700 | [diff] [blame] | 316 | // 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 Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 326 | var ( |
| 327 | name = ctx.ModuleName() |
| 328 | hasPlugins = false |
| 329 | pluginSrc = "" |
| 330 | genSrcs = []string{} |
| 331 | ) |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 332 | |
| 333 | if g.properties.PkgPath == "" { |
| 334 | ctx.ModuleErrorf("module %s did not specify a valid pkgPath", name) |
| 335 | return |
| 336 | } |
| 337 | |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 338 | g.pkgRoot = packageRoot(ctx, g.config) |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 339 | g.archiveFile = filepath.Join(g.pkgRoot, |
| 340 | filepath.FromSlash(g.properties.PkgPath)+".a") |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 341 | |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 342 | ctx.VisitDepsDepthFirstIf(isGoPluginFor(name), |
| 343 | func(module blueprint.Module) { hasPlugins = true }) |
| 344 | if hasPlugins { |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 345 | pluginSrc = filepath.Join(moduleGenSrcDir(ctx, g.config), "plugin.go") |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 346 | genSrcs = append(genSrcs, pluginSrc) |
| 347 | } |
| 348 | |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 349 | if hasPlugins && !buildGoPluginLoader(ctx, g.properties.PkgPath, pluginSrc) { |
| 350 | return |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 351 | } |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 352 | |
| 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 Cross | f897514 | 2020-06-11 16:22:36 -0700 | [diff] [blame] | 362 | 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 Cross | 0cdec99 | 2020-07-09 14:24:56 -0700 | [diff] [blame] | 367 | testSrcs, g.config.useValidations) |
Colin Cross | f897514 | 2020-06-11 16:22:36 -0700 | [diff] [blame] | 368 | } |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 369 | |
| 370 | buildGoPackage(ctx, g.pkgRoot, g.properties.PkgPath, g.archiveFile, |
| 371 | srcs, genSrcs) |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 372 | } |
| 373 | |
| 374 | // A goBinary is a module for building executable binaries from Go sources. |
| 375 | type goBinary struct { |
Colin Cross | 0b7e83e | 2016-05-17 14:58:05 -0700 | [diff] [blame] | 376 | blueprint.SimpleName |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 377 | properties struct { |
Colin Cross | 0b7e83e | 2016-05-17 14:58:05 -0700 | [diff] [blame] | 378 | Deps []string |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 379 | Srcs []string |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 380 | TestSrcs []string |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 381 | PrimaryBuilder bool |
Dan Willemsen | f60525a | 2017-07-19 18:48:01 -0700 | [diff] [blame] | 382 | Default bool |
Colin Cross | 910242b | 2016-04-11 15:41:52 -0700 | [diff] [blame] | 383 | |
Dan Willemsen | f14e096 | 2017-02-06 14:00:10 -0800 | [diff] [blame] | 384 | Darwin struct { |
| 385 | Srcs []string |
| 386 | TestSrcs []string |
| 387 | } |
| 388 | Linux struct { |
| 389 | Srcs []string |
| 390 | TestSrcs []string |
| 391 | } |
| 392 | |
Dan Willemsen | 734f20c | 2018-07-21 13:03:35 -0700 | [diff] [blame] | 393 | Tool_dir bool `blueprint:"mutated"` |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 394 | } |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 395 | |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 396 | installPath string |
| 397 | |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 398 | // The bootstrap Config |
| 399 | config *Config |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 400 | } |
| 401 | |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 402 | var _ GoBinaryTool = (*goBinary)(nil) |
| 403 | |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 404 | func newGoBinaryModuleFactory(config *Config, tooldir bool) func() (blueprint.Module, []interface{}) { |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 405 | return func() (blueprint.Module, []interface{}) { |
| 406 | module := &goBinary{ |
Colin Cross | 910242b | 2016-04-11 15:41:52 -0700 | [diff] [blame] | 407 | config: config, |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 408 | } |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 409 | module.properties.Tool_dir = tooldir |
Colin Cross | 0b7e83e | 2016-05-17 14:58:05 -0700 | [diff] [blame] | 410 | return module, []interface{}{&module.properties, &module.SimpleName.Properties} |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 411 | } |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 412 | } |
| 413 | |
Colin Cross | 0b7e83e | 2016-05-17 14:58:05 -0700 | [diff] [blame] | 414 | func (g *goBinary) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string { |
Colin Cross | d2458a2 | 2020-09-09 13:03:57 -0700 | [diff] [blame] | 415 | if ctx.Module() != ctx.PrimaryModule() { |
| 416 | return nil |
| 417 | } |
Colin Cross | 0b7e83e | 2016-05-17 14:58:05 -0700 | [diff] [blame] | 418 | return g.properties.Deps |
| 419 | } |
| 420 | |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 421 | func (g *goBinary) isGoBinary() {} |
Dan Willemsen | be27523 | 2016-05-26 10:07:59 -0700 | [diff] [blame] | 422 | func (g *goBinary) InstallPath() string { |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 423 | return g.installPath |
Dan Willemsen | be27523 | 2016-05-26 10:07:59 -0700 | [diff] [blame] | 424 | } |
| 425 | |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 426 | func (g *goBinary) GenerateBuildActions(ctx blueprint.ModuleContext) { |
Colin Cross | d2458a2 | 2020-09-09 13:03:57 -0700 | [diff] [blame] | 427 | // 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 Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 435 | var ( |
Dan Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 436 | name = ctx.ModuleName() |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 437 | objDir = moduleObjDir(ctx, g.config) |
Dan Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 438 | archiveFile = filepath.Join(objDir, name+".a") |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 439 | testArchiveFile = filepath.Join(testRoot(ctx, g.config), name+".a") |
Dan Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 440 | aoutFile = filepath.Join(objDir, "a.out") |
Dan Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 441 | hasPlugins = false |
| 442 | pluginSrc = "" |
| 443 | genSrcs = []string{} |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 444 | ) |
| 445 | |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 446 | if g.properties.Tool_dir { |
| 447 | g.installPath = filepath.Join(toolDir(ctx.Config()), name) |
| 448 | } else { |
Lukacs T. Berki | 7d2e60e | 2021-03-08 16:47:28 +0100 | [diff] [blame] | 449 | g.installPath = filepath.Join(stageDir(g.config), "bin", name) |
Dan Willemsen | 87f71fa | 2017-09-13 15:19:22 -0700 | [diff] [blame] | 450 | } |
| 451 | |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 452 | ctx.VisitDepsDepthFirstIf(isGoPluginFor(name), |
| 453 | func(module blueprint.Module) { hasPlugins = true }) |
| 454 | if hasPlugins { |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 455 | pluginSrc = filepath.Join(moduleGenSrcDir(ctx, g.config), "plugin.go") |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 456 | genSrcs = append(genSrcs, pluginSrc) |
| 457 | } |
| 458 | |
Colin Cross | 0cdec99 | 2020-07-09 14:24:56 -0700 | [diff] [blame] | 459 | var testDeps []string |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 460 | |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 461 | if hasPlugins && !buildGoPluginLoader(ctx, "main", pluginSrc) { |
| 462 | return |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 463 | } |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 464 | |
| 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 Cross | 0cdec99 | 2020-07-09 14:24:56 -0700 | [diff] [blame] | 475 | testDeps = buildGoTest(ctx, testRoot(ctx, g.config), testArchiveFile, |
| 476 | name, srcs, genSrcs, testSrcs, g.config.useValidations) |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 477 | } |
| 478 | |
Colin Cross | a2bc585 | 2019-09-06 14:25:28 -0700 | [diff] [blame] | 479 | buildGoPackage(ctx, objDir, "main", archiveFile, srcs, genSrcs) |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 480 | |
Colin Cross | 6c92af9 | 2018-09-28 16:15:58 -0700 | [diff] [blame] | 481 | var linkDeps []string |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 482 | var libDirFlags []string |
| 483 | ctx.VisitDepsDepthFirstIf(isGoPackageProducer, |
| 484 | func(module blueprint.Module) { |
| 485 | dep := module.(goPackageProducer) |
Colin Cross | 6c92af9 | 2018-09-28 16:15:58 -0700 | [diff] [blame] | 486 | linkDeps = append(linkDeps, dep.GoPackageTarget()) |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 487 | libDir := dep.GoPkgRoot() |
| 488 | libDirFlags = append(libDirFlags, "-L "+libDir) |
Colin Cross | 0cdec99 | 2020-07-09 14:24:56 -0700 | [diff] [blame] | 489 | testDeps = append(testDeps, dep.GoTestTargets()...) |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 490 | }) |
| 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 Cross | 6c92af9 | 2018-09-28 16:15:58 -0700 | [diff] [blame] | 498 | Rule: link, |
| 499 | Outputs: []string{aoutFile}, |
| 500 | Inputs: []string{archiveFile}, |
| 501 | Implicits: linkDeps, |
| 502 | Args: linkArgs, |
| 503 | Optional: true, |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 504 | }) |
| 505 | |
Colin Cross | 0cdec99 | 2020-07-09 14:24:56 -0700 | [diff] [blame] | 506 | var orderOnlyDeps, validationDeps []string |
| 507 | if g.config.useValidations { |
| 508 | validationDeps = testDeps |
| 509 | } else { |
| 510 | orderOnlyDeps = testDeps |
| 511 | } |
| 512 | |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 513 | ctx.Build(pctx, blueprint.BuildParams{ |
Colin Cross | 0cdec99 | 2020-07-09 14:24:56 -0700 | [diff] [blame] | 514 | Rule: cp, |
| 515 | Outputs: []string{g.installPath}, |
| 516 | Inputs: []string{aoutFile}, |
| 517 | OrderOnly: orderOnlyDeps, |
| 518 | Validations: validationDeps, |
| 519 | Optional: !g.properties.Default, |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 520 | }) |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 521 | } |
| 522 | |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 523 | func buildGoPluginLoader(ctx blueprint.ModuleContext, pkgPath, pluginSrc string) bool { |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 524 | 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 Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 532 | }) |
| 533 | |
| 534 | ctx.Build(pctx, blueprint.BuildParams{ |
Dan Willemsen | fce63d3 | 2015-11-17 14:21:45 -0800 | [diff] [blame] | 535 | Rule: pluginGenSrc, |
| 536 | Outputs: []string{pluginSrc}, |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 537 | Args: map[string]string{ |
| 538 | "pkg": pkgPath, |
| 539 | "plugins": strings.Join(pluginPaths, " "), |
| 540 | }, |
Dan Willemsen | f60525a | 2017-07-19 18:48:01 -0700 | [diff] [blame] | 541 | Optional: true, |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 542 | }) |
| 543 | |
| 544 | return ret |
| 545 | } |
| 546 | |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 547 | func buildGoPackage(ctx blueprint.ModuleContext, pkgRoot string, |
Dan Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 548 | pkgPath string, archiveFile string, srcs []string, genSrcs []string) { |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 549 | |
Jamie Gennis | 9e2a4c2 | 2014-11-09 11:52:56 -0800 | [diff] [blame] | 550 | srcDir := moduleSrcDir(ctx) |
Jamie Gennis | b931456 | 2014-06-06 14:37:07 -0700 | [diff] [blame] | 551 | srcFiles := pathtools.PrefixPaths(srcs, srcDir) |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 552 | srcFiles = append(srcFiles, genSrcs...) |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 553 | |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 554 | var incFlags []string |
Dan Willemsen | fce63d3 | 2015-11-17 14:21:45 -0800 | [diff] [blame] | 555 | var deps []string |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 556 | 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 Cross | 5e3594f | 2014-10-22 13:22:22 -0700 | [diff] [blame] | 562 | deps = append(deps, target) |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 563 | }) |
| 564 | |
Dan Willemsen | c20adea | 2015-08-01 15:07:27 -0700 | [diff] [blame] | 565 | compileArgs := map[string]string{ |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 566 | "pkgPath": pkgPath, |
| 567 | } |
| 568 | |
| 569 | if len(incFlags) > 0 { |
Dan Willemsen | c20adea | 2015-08-01 15:07:27 -0700 | [diff] [blame] | 570 | compileArgs["incFlags"] = strings.Join(incFlags, " ") |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 571 | } |
| 572 | |
Jamie Gennis | 2fb2095 | 2014-10-03 02:49:58 -0700 | [diff] [blame] | 573 | ctx.Build(pctx, blueprint.BuildParams{ |
Dan Willemsen | c20adea | 2015-08-01 15:07:27 -0700 | [diff] [blame] | 574 | Rule: compile, |
Colin Cross | daf6499 | 2014-10-22 10:55:28 -0700 | [diff] [blame] | 575 | Outputs: []string{archiveFile}, |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 576 | Inputs: srcFiles, |
Colin Cross | 5e3594f | 2014-10-22 13:22:22 -0700 | [diff] [blame] | 577 | Implicits: deps, |
Dan Willemsen | c20adea | 2015-08-01 15:07:27 -0700 | [diff] [blame] | 578 | Args: compileArgs, |
Dan Willemsen | f60525a | 2017-07-19 18:48:01 -0700 | [diff] [blame] | 579 | Optional: true, |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 580 | }) |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 581 | } |
| 582 | |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 583 | func buildGoTest(ctx blueprint.ModuleContext, testRoot, testPkgArchive, |
Colin Cross | 0cdec99 | 2020-07-09 14:24:56 -0700 | [diff] [blame] | 584 | pkgPath string, srcs, genSrcs, testSrcs []string, useValidations bool) []string { |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 585 | |
| 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 Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 599 | append(srcs, testSrcs...), genSrcs) |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 600 | |
| 601 | ctx.Build(pctx, blueprint.BuildParams{ |
Dan Willemsen | fce63d3 | 2015-11-17 14:21:45 -0800 | [diff] [blame] | 602 | Rule: goTestMain, |
| 603 | Outputs: []string{mainFile}, |
| 604 | Inputs: testFiles, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 605 | Args: map[string]string{ |
| 606 | "pkg": pkgPath, |
| 607 | }, |
Dan Willemsen | f60525a | 2017-07-19 18:48:01 -0700 | [diff] [blame] | 608 | Optional: true, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 609 | }) |
| 610 | |
Colin Cross | 1be9abc | 2018-10-24 13:11:33 -0700 | [diff] [blame] | 611 | linkDeps := []string{testPkgArchive} |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 612 | libDirFlags := []string{"-L " + testRoot} |
Dan Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 613 | testDeps := []string{} |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 614 | ctx.VisitDepsDepthFirstIf(isGoPackageProducer, |
| 615 | func(module blueprint.Module) { |
| 616 | dep := module.(goPackageProducer) |
Colin Cross | 0e58dc0 | 2018-10-05 11:12:53 -0700 | [diff] [blame] | 617 | linkDeps = append(linkDeps, dep.GoPackageTarget()) |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 618 | libDir := dep.GoPkgRoot() |
| 619 | libDirFlags = append(libDirFlags, "-L "+libDir) |
Dan Willemsen | 9bd6b38 | 2016-11-02 00:43:00 -0700 | [diff] [blame] | 620 | testDeps = append(testDeps, dep.GoTestTargets()...) |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 621 | }) |
| 622 | |
| 623 | ctx.Build(pctx, blueprint.BuildParams{ |
Dan Willemsen | c20adea | 2015-08-01 15:07:27 -0700 | [diff] [blame] | 624 | Rule: compile, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 625 | Outputs: []string{testArchive}, |
| 626 | Inputs: []string{mainFile}, |
Dan Willemsen | fce63d3 | 2015-11-17 14:21:45 -0800 | [diff] [blame] | 627 | Implicits: []string{testPkgArchive}, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 628 | Args: map[string]string{ |
| 629 | "pkgPath": "main", |
| 630 | "incFlags": "-I " + testRoot, |
| 631 | }, |
Dan Willemsen | f60525a | 2017-07-19 18:48:01 -0700 | [diff] [blame] | 632 | Optional: true, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 633 | }) |
| 634 | |
| 635 | ctx.Build(pctx, blueprint.BuildParams{ |
Colin Cross | 0e58dc0 | 2018-10-05 11:12:53 -0700 | [diff] [blame] | 636 | Rule: link, |
| 637 | Outputs: []string{testFile}, |
| 638 | Inputs: []string{testArchive}, |
| 639 | Implicits: linkDeps, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 640 | Args: map[string]string{ |
| 641 | "libDirFlags": strings.Join(libDirFlags, " "), |
| 642 | }, |
Dan Willemsen | f60525a | 2017-07-19 18:48:01 -0700 | [diff] [blame] | 643 | Optional: true, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 644 | }) |
| 645 | |
Colin Cross | 0cdec99 | 2020-07-09 14:24:56 -0700 | [diff] [blame] | 646 | var orderOnlyDeps, validationDeps []string |
| 647 | if useValidations { |
| 648 | validationDeps = testDeps |
| 649 | } else { |
| 650 | orderOnlyDeps = testDeps |
| 651 | } |
| 652 | |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 653 | ctx.Build(pctx, blueprint.BuildParams{ |
Colin Cross | 0cdec99 | 2020-07-09 14:24:56 -0700 | [diff] [blame] | 654 | Rule: test, |
| 655 | Outputs: []string{testPassed}, |
| 656 | Inputs: []string{testFile}, |
| 657 | OrderOnly: orderOnlyDeps, |
| 658 | Validations: validationDeps, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 659 | Args: map[string]string{ |
| 660 | "pkg": pkgPath, |
| 661 | "pkgSrcDir": filepath.Dir(testFiles[0]), |
| 662 | }, |
Dan Willemsen | f60525a | 2017-07-19 18:48:01 -0700 | [diff] [blame] | 663 | Optional: true, |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 664 | }) |
| 665 | |
| 666 | return []string{testPassed} |
| 667 | } |
| 668 | |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 669 | type singleton struct { |
| 670 | // The bootstrap Config |
| 671 | config *Config |
| 672 | } |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 673 | |
Dan Willemsen | 30a80c3 | 2015-06-24 19:21:21 -0700 | [diff] [blame] | 674 | func newSingletonFactory(config *Config) func() blueprint.Singleton { |
| 675 | return func() blueprint.Singleton { |
| 676 | return &singleton{ |
| 677 | config: config, |
| 678 | } |
| 679 | } |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 680 | } |
| 681 | |
| 682 | func (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 Willemsen | be27523 | 2016-05-26 10:07:59 -0700 | [diff] [blame] | 687 | // blueprintTools contains blueprint go binaries that will be built in StageMain |
| 688 | var blueprintTools []string |
Colin Cross | f897514 | 2020-06-11 16:22:36 -0700 | [diff] [blame] | 689 | ctx.VisitAllModulesIf(isBootstrapBinaryModule, |
| 690 | func(module blueprint.Module) { |
Colin Cross | d2458a2 | 2020-09-09 13:03:57 -0700 | [diff] [blame] | 691 | if ctx.PrimaryModule(module) == module { |
| 692 | binaryModule := module.(*goBinary) |
Colin Cross | f897514 | 2020-06-11 16:22:36 -0700 | [diff] [blame] | 693 | |
Colin Cross | d2458a2 | 2020-09-09 13:03:57 -0700 | [diff] [blame] | 694 | if binaryModule.properties.Tool_dir { |
| 695 | blueprintTools = append(blueprintTools, binaryModule.InstallPath()) |
| 696 | } |
| 697 | if binaryModule.properties.PrimaryBuilder { |
| 698 | primaryBuilders = append(primaryBuilders, binaryModule) |
| 699 | } |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 700 | } |
Colin Cross | f897514 | 2020-06-11 16:22:36 -0700 | [diff] [blame] | 701 | }) |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 702 | |
Lukacs T. Berki | 77ef79b | 2021-04-12 12:07:02 +0200 | [diff] [blame] | 703 | var primaryBuilderCmdlinePrefix []string |
| 704 | var primaryBuilderName string |
Dan Willemsen | b6d88a4 | 2016-11-01 17:12:28 -0700 | [diff] [blame] | 705 | |
Lukacs T. Berki | 77ef79b | 2021-04-12 12:07:02 +0200 | [diff] [blame] | 706 | if len(primaryBuilders) == 0 { |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 707 | // 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. Berki | 77ef79b | 2021-04-12 12:07:02 +0200 | [diff] [blame] | 711 | primaryBuilderCmdlinePrefix = append(primaryBuilderCmdlinePrefix, "-p") |
| 712 | } else if len(primaryBuilders) > 1 { |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 713 | 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. Berki | 77ef79b | 2021-04-12 12:07:02 +0200 | [diff] [blame] | 719 | } else { |
| 720 | primaryBuilderName = ctx.ModuleName(primaryBuilders[0]) |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 721 | } |
| 722 | |
Dan Willemsen | 852191d | 2015-07-13 23:28:37 -0700 | [diff] [blame] | 723 | primaryBuilderFile := filepath.Join("$BinDir", primaryBuilderName) |
Dan Willemsen | cd4e0ce | 2017-07-19 22:43:30 -0700 | [diff] [blame] | 724 | ctx.SetNinjaBuildDir(pctx, "${ninjaBuildDir}") |
Dan Willemsen | efd2de7 | 2015-07-22 17:06:06 -0700 | [diff] [blame] | 725 | |
Dan Willemsen | ab223a5 | 2018-07-05 21:56:59 -0700 | [diff] [blame] | 726 | if s.config.stage == StagePrimary { |
Lukacs T. Berki | 77ef79b | 2021-04-12 12:07:02 +0200 | [diff] [blame] | 727 | ctx.AddSubninja(s.config.globFile) |
Dan Willemsen | efd2de7 | 2015-07-22 17:06:06 -0700 | [diff] [blame] | 728 | |
Lukacs T. Berki | 77ef79b | 2021-04-12 12:07:02 +0200 | [diff] [blame] | 729 | 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 Willemsen | ab223a5 | 2018-07-05 21:56:59 -0700 | [diff] [blame] | 744 | } |
Dan Willemsen | ab223a5 | 2018-07-05 21:56:59 -0700 | [diff] [blame] | 745 | } |
Colin Cross | 4572edd | 2015-05-13 14:36:24 -0700 | [diff] [blame] | 746 | |
Dan Willemsen | af456ea | 2017-07-19 19:22:34 -0700 | [diff] [blame] | 747 | if s.config.stage == StageMain { |
Jamie Gennis | 7ab5f3c | 2014-06-11 15:51:08 -0700 | [diff] [blame] | 748 | 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 Willemsen | f0ca901 | 2015-07-13 18:11:49 -0700 | [diff] [blame] | 751 | finalMinibp := filepath.Join("$buildDir", "bin", primaryBuilderName) |
Jamie Gennis | 2fb2095 | 2014-10-03 02:49:58 -0700 | [diff] [blame] | 752 | ctx.Build(pctx, blueprint.BuildParams{ |
Jamie Gennis | 7ab5f3c | 2014-06-11 15:51:08 -0700 | [diff] [blame] | 753 | Rule: cp, |
| 754 | Inputs: []string{primaryBuilderFile}, |
| 755 | Outputs: []string{finalMinibp}, |
| 756 | }) |
| 757 | } |
Dan Willemsen | be27523 | 2016-05-26 10:07:59 -0700 | [diff] [blame] | 758 | |
Colin Cross | 5eb116a | 2017-12-11 14:58:45 -0800 | [diff] [blame] | 759 | // 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. Berki | 78df853 | 2021-04-14 10:28:54 +0200 | [diff] [blame] | 767 | Command: fmt.Sprintf("%s -b $buildDir --docs $out %s", primaryBuilderFile, |
| 768 | s.config.topLevelBlueprintsFile), |
Colin Cross | 5eb116a | 2017-12-11 14:58:45 -0800 | [diff] [blame] | 769 | 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 Willemsen | be27523 | 2016-05-26 10:07:59 -0700 | [diff] [blame] | 786 | ctx.Build(pctx, blueprint.BuildParams{ |
| 787 | Rule: blueprint.Phony, |
| 788 | Outputs: []string{"blueprint_tools"}, |
| 789 | Inputs: blueprintTools, |
| 790 | }) |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 791 | } |
| 792 | } |
| 793 | |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 794 | func stageDir(config *Config) string { |
| 795 | if config.stage == StageMain { |
| 796 | return mainDir |
| 797 | } else { |
| 798 | return bootstrapDir |
| 799 | } |
| 800 | } |
| 801 | |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 802 | // 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 Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 805 | func packageRoot(ctx blueprint.ModuleContext, config *Config) string { |
| 806 | return filepath.Join(stageDir(config), ctx.ModuleName(), "pkg") |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 807 | } |
| 808 | |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 809 | // 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 Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 812 | func testRoot(ctx blueprint.ModuleContext, config *Config) string { |
| 813 | return filepath.Join(stageDir(config), ctx.ModuleName(), "test") |
Dan Willemsen | 87ba294 | 2015-06-23 17:21:00 -0700 | [diff] [blame] | 814 | } |
| 815 | |
Jamie Gennis | 9e2a4c2 | 2014-11-09 11:52:56 -0800 | [diff] [blame] | 816 | // moduleSrcDir returns the path of the directory that all source file paths are |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 817 | // specified relative to. |
Jamie Gennis | 9e2a4c2 | 2014-11-09 11:52:56 -0800 | [diff] [blame] | 818 | func moduleSrcDir(ctx blueprint.ModuleContext) string { |
| 819 | return filepath.Join("$srcDir", ctx.ModuleDir()) |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 820 | } |
| 821 | |
Jamie Gennis | 9e2a4c2 | 2014-11-09 11:52:56 -0800 | [diff] [blame] | 822 | // moduleObjDir returns the module-specific object directory path. |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 823 | func moduleObjDir(ctx blueprint.ModuleContext, config *Config) string { |
| 824 | return filepath.Join(stageDir(config), ctx.ModuleName(), "obj") |
Jamie Gennis | 1bc967e | 2014-05-27 16:34:41 -0700 | [diff] [blame] | 825 | } |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 826 | |
| 827 | // moduleGenSrcDir returns the module-specific generated sources path. |
Colin Cross | 16fec72 | 2019-10-17 13:41:20 -0700 | [diff] [blame] | 828 | func moduleGenSrcDir(ctx blueprint.ModuleContext, config *Config) string { |
| 829 | return filepath.Join(stageDir(config), ctx.ModuleName(), "gen") |
Dan Willemsen | fdeb724 | 2015-07-24 16:53:27 -0700 | [diff] [blame] | 830 | } |