blob: c61baa13549b61648d2f7946e6af618314b3bca0 [file] [log] [blame]
Dan Willemsen1e704462016-08-21 15:17:17 -07001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package build
16
17import (
Dan Willemsendb8457c2017-05-12 16:38:17 -070018 "io/ioutil"
Dan Willemsen1e704462016-08-21 15:17:17 -070019 "os"
Dan Willemsen1e704462016-08-21 15:17:17 -070020 "path/filepath"
Dan Willemsen80d72612022-04-20 21:45:00 -070021 "sync"
Dan Willemsen1e704462016-08-21 15:17:17 -070022 "text/template"
Colin Cross74cda722020-01-16 15:25:50 -080023
24 "android/soong/ui/metrics"
Dan Willemsen1e704462016-08-21 15:17:17 -070025)
26
Jingwen Chencda22c92020-11-23 00:22:30 -050027// SetupOutDir ensures the out directory exists, and has the proper files to
28// prevent kati from recursing into it.
Dan Willemsen1e704462016-08-21 15:17:17 -070029func SetupOutDir(ctx Context, config Config) {
30 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "Android.mk"))
31 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "CleanSpec.mk"))
Anton Hansson17fc5a02021-06-18 16:37:14 +010032
33 // Potentially write a marker file for whether kati is enabled. This is used by soong_build to
34 // potentially run the AndroidMk singleton and postinstall commands.
35 // Note that the absence of the file does not not preclude running Kati for product
36 // configuration purposes.
37 katiEnabledMarker := filepath.Join(config.SoongOutDir(), ".soong.kati_enabled")
38 if config.SkipKatiNinja() {
39 os.Remove(katiEnabledMarker)
40 // Note that we can not remove the file for SkipKati builds yet -- some continuous builds
41 // --skip-make builds rely on kati targets being defined.
42 } else if !config.SkipKati() {
43 ensureEmptyFileExists(ctx, katiEnabledMarker)
Dan Willemsene0879fc2017-08-04 15:06:27 -070044 }
Anton Hansson17fc5a02021-06-18 16:37:14 +010045
Dan Willemsen1e704462016-08-21 15:17:17 -070046 // The ninja_build file is used by our buildbots to understand that the output
47 // can be parsed as ninja output.
48 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "ninja_build"))
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070049 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), ".out-dir"))
Colin Cross28f527c2019-11-26 16:19:04 -080050
51 if buildDateTimeFile, ok := config.environ.Get("BUILD_DATETIME_FILE"); ok {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +000052 err := ioutil.WriteFile(buildDateTimeFile, []byte(config.buildDateTime), 0666) // a+rw
Colin Cross28f527c2019-11-26 16:19:04 -080053 if err != nil {
54 ctx.Fatalln("Failed to write BUILD_DATETIME to file:", err)
55 }
56 } else {
57 ctx.Fatalln("Missing BUILD_DATETIME_FILE")
58 }
Dan Willemsen1e704462016-08-21 15:17:17 -070059}
60
61var combinedBuildNinjaTemplate = template.Must(template.New("combined").Parse(`
62builddir = {{.OutDir}}
Colin Cross8b8bec32019-11-15 13:18:43 -080063{{if .UseRemoteBuild }}pool local_pool
Dan Willemsen29971232018-09-26 14:58:30 -070064 depth = {{.Parallel}}
Colin Cross8b8bec32019-11-15 13:18:43 -080065{{end -}}
66pool highmem_pool
67 depth = {{.HighmemParallel}}
Anton Hansson0b55bdb2021-06-04 10:08:08 +010068{{if and (not .SkipKatiNinja) .HasKatiSuffix}}subninja {{.KatiBuildNinjaFile}}
Dan Willemsenfb1271a2018-09-26 15:00:42 -070069subninja {{.KatiPackageNinjaFile}}
Dan Willemsene0879fc2017-08-04 15:06:27 -070070{{end -}}
Dan Willemsenfb1271a2018-09-26 15:00:42 -070071subninja {{.SoongNinjaFile}}
Dan Willemsen1e704462016-08-21 15:17:17 -070072`))
73
74func createCombinedBuildNinjaFile(ctx Context, config Config) {
Anton Hansson0b55bdb2021-06-04 10:08:08 +010075 // If we're in SkipKati mode but want to run kati ninja, skip creating this file if it already exists
76 if config.SkipKati() && !config.SkipKatiNinja() {
Dan Willemsene0879fc2017-08-04 15:06:27 -070077 if _, err := os.Stat(config.CombinedNinjaFile()); err == nil || !os.IsNotExist(err) {
78 return
79 }
80 }
81
Dan Willemsen1e704462016-08-21 15:17:17 -070082 file, err := os.Create(config.CombinedNinjaFile())
83 if err != nil {
84 ctx.Fatalln("Failed to create combined ninja file:", err)
85 }
86 defer file.Close()
87
88 if err := combinedBuildNinjaTemplate.Execute(file, config); err != nil {
89 ctx.Fatalln("Failed to write combined ninja file:", err)
90 }
91}
92
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +000093// These are bitmasks which can be used to check whether various flags are set e.g. whether to use Bazel.
Dan Willemsen1e704462016-08-21 15:17:17 -070094const (
Anton Hansson5a7861a2021-06-04 10:09:01 +010095 _ = iota
96 // Whether to run the kati config step.
97 RunProductConfig = 1 << iota
98 // Whether to run soong to generate a ninja file.
99 RunSoong = 1 << iota
100 // Whether to run kati to generate a ninja file.
101 RunKati = 1 << iota
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100102 // Whether to include the kati-generated ninja file in the combined ninja.
103 RunKatiNinja = 1 << iota
Anton Hansson5a7861a2021-06-04 10:09:01 +0100104 // Whether to run ninja on the combined ninja.
105 RunNinja = 1 << iota
106 // Whether to run bazel on the combined ninja.
107 RunBazel = 1 << iota
108 RunBuildTests = 1 << iota
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100109 RunAll = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunNinja
110 RunAllWithBazel = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunBazel
Dan Willemsen1e704462016-08-21 15:17:17 -0700111)
112
Chris Parsonsef615e52022-08-18 22:04:11 -0400113// checkBazelMode fails the build if there are conflicting arguments for which bazel
114// build mode to use.
115func checkBazelMode(ctx Context, config Config) {
116 // TODO(cparsons): Remove USE_BAZEL_ANALYSIS handling.
117 if config.Environment().IsEnvTrue("USE_BAZEL_ANALYSIS") {
118 if config.bazelProdMode || config.bazelDevMode {
119 ctx.Fatalf("USE_BAZEL_ANALYSIS is deprecated.\n" +
120 "Unset USE_BAZEL_ANALYSIS when using --bazel-mode or --bazel-mode-dev.")
121 } else {
122 config.bazelDevMode = true
123 }
124 }
125 if config.bazelProdMode && config.bazelDevMode {
126 ctx.Fatalf("Conflicting bazel mode.\n" +
127 "Do not specify both --bazel-mode and --bazel-mode-dev")
128 }
129}
130
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000131// checkProblematicFiles fails the build if existing Android.mk or CleanSpec.mk files are found at the root of the tree.
Anton Hanssonecf0f102018-09-19 22:14:17 +0100132func checkProblematicFiles(ctx Context) {
133 files := []string{"Android.mk", "CleanSpec.mk"}
134 for _, file := range files {
135 if _, err := os.Stat(file); !os.IsNotExist(err) {
136 absolute := absPath(ctx, file)
137 ctx.Printf("Found %s in tree root. This file needs to be removed to build.\n", file)
138 ctx.Fatalf(" rm %s\n", absolute)
139 }
140 }
141}
142
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000143// checkCaseSensitivity issues a warning if a case-insensitive file system is being used.
Dan Willemsendb8457c2017-05-12 16:38:17 -0700144func checkCaseSensitivity(ctx Context, config Config) {
145 outDir := config.OutDir()
146 lowerCase := filepath.Join(outDir, "casecheck.txt")
147 upperCase := filepath.Join(outDir, "CaseCheck.txt")
148 lowerData := "a"
149 upperData := "B"
150
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000151 if err := ioutil.WriteFile(lowerCase, []byte(lowerData), 0666); err != nil { // a+rw
Dan Willemsendb8457c2017-05-12 16:38:17 -0700152 ctx.Fatalln("Failed to check case sensitivity:", err)
153 }
154
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000155 if err := ioutil.WriteFile(upperCase, []byte(upperData), 0666); err != nil { // a+rw
Dan Willemsendb8457c2017-05-12 16:38:17 -0700156 ctx.Fatalln("Failed to check case sensitivity:", err)
157 }
158
159 res, err := ioutil.ReadFile(lowerCase)
160 if err != nil {
161 ctx.Fatalln("Failed to check case sensitivity:", err)
162 }
163
164 if string(res) != lowerData {
165 ctx.Println("************************************************************")
166 ctx.Println("You are building on a case-insensitive filesystem.")
167 ctx.Println("Please move your source tree to a case-sensitive filesystem.")
168 ctx.Println("************************************************************")
169 ctx.Fatalln("Case-insensitive filesystems not supported")
170 }
171}
172
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000173// help prints a help/usage message, via the build/make/help.sh script.
174func help(ctx Context, config Config) {
Jeff Gastondf4a0812017-05-30 20:11:20 -0700175 cmd := Command(ctx, config, "help.sh", "build/make/help.sh")
Dan Willemsenb2e6c2e2017-07-13 17:24:44 -0700176 cmd.Sandbox = dumpvarsSandbox
Dan Willemsenb82471a2018-05-17 16:37:09 -0700177 cmd.RunAndPrintOrFatal()
Dan Willemsen02781d52017-05-12 19:28:13 -0700178}
179
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000180// checkRAM warns if there probably isn't enough RAM to complete a build.
181func checkRAM(ctx Context, config Config) {
Dan Willemsen570a2922020-05-26 23:02:29 -0700182 if totalRAM := config.TotalRAM(); totalRAM != 0 {
183 ram := float32(totalRAM) / (1024 * 1024 * 1024)
184 ctx.Verbosef("Total RAM: %.3vGB", ram)
185
186 if ram <= 16 {
187 ctx.Println("************************************************************")
188 ctx.Printf("You are building on a machine with %.3vGB of RAM\n", ram)
189 ctx.Println("")
190 ctx.Println("The minimum required amount of free memory is around 16GB,")
191 ctx.Println("and even with that, some configurations may not work.")
192 ctx.Println("")
193 ctx.Println("If you run into segfaults or other errors, try reducing your")
194 ctx.Println("-j value.")
195 ctx.Println("************************************************************")
196 } else if ram <= float32(config.Parallel()) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000197 // Want at least 1GB of RAM per job.
Dan Willemsen570a2922020-05-26 23:02:29 -0700198 ctx.Printf("Warning: high -j%d count compared to %.3vGB of RAM", config.Parallel(), ram)
199 ctx.Println("If you run into segfaults or other errors, try a lower -j value")
200 }
201 }
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000202}
203
Usta Shresthadb46a9b2022-07-11 11:29:56 -0400204// Build the tree. Various flags in `config` govern which components of
205// the build to run.
Anton Hansson5a7861a2021-06-04 10:09:01 +0100206func Build(ctx Context, config Config) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000207 ctx.Verboseln("Starting build with args:", config.Arguments())
208 ctx.Verboseln("Environment:", config.Environment().Environ())
Dan Willemsen1e704462016-08-21 15:17:17 -0700209
Colin Cross74cda722020-01-16 15:25:50 -0800210 ctx.BeginTrace(metrics.Total, "total")
211 defer ctx.EndTrace()
212
Dan Willemsen1e704462016-08-21 15:17:17 -0700213 if inList("help", config.Arguments()) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000214 help(ctx, config)
Dan Willemsen0b73b4b2017-05-12 19:28:13 -0700215 return
Dan Willemsen1e704462016-08-21 15:17:17 -0700216 }
217
Jeff Gaston3615fe82017-05-24 13:14:34 -0700218 // Make sure that no other Soong process is running with the same output directory
219 buildLock := BecomeSingletonOrFail(ctx, config)
220 defer buildLock.Unlock()
221
Usta Shrestha675564d2022-08-09 18:03:23 -0400222 logArgsOtherThan := func(specialTargets ...string) {
223 var ignored []string
224 for _, a := range config.Arguments() {
225 if !inList(a, specialTargets) {
226 ignored = append(ignored, a)
227 }
228 }
229 if len(ignored) > 0 {
230 ctx.Printf("ignoring arguments %q", ignored)
231 }
232 }
233
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000234 if inList("clean", config.Arguments()) || inList("clobber", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400235 logArgsOtherThan("clean", "clobber")
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000236 clean(ctx, config)
237 return
238 }
239
Dan Willemsen80d72612022-04-20 21:45:00 -0700240 defer waitForDist(ctx)
241
Chris Parsonsef615e52022-08-18 22:04:11 -0400242 checkBazelMode(ctx, config)
243
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000244 // checkProblematicFiles aborts the build if Android.mk or CleanSpec.mk are found at the root of the tree.
Anton Hanssonecf0f102018-09-19 22:14:17 +0100245 checkProblematicFiles(ctx)
246
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000247 checkRAM(ctx, config)
248
Dan Willemsen1e704462016-08-21 15:17:17 -0700249 SetupOutDir(ctx, config)
250
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000251 // checkCaseSensitivity issues a warning if a case-insensitive file system is being used.
Dan Willemsendb8457c2017-05-12 16:38:17 -0700252 checkCaseSensitivity(ctx, config)
253
Jeff Gastonefc1b412017-03-29 17:29:06 -0700254 ensureEmptyDirectoriesExist(ctx, config.TempDir())
255
Dan Willemsen18490112018-05-25 16:30:04 -0700256 SetupPath(ctx, config)
257
Anton Hansson5a7861a2021-06-04 10:09:01 +0100258 what := RunAll
259 if config.UseBazel() {
260 what = RunAllWithBazel
261 }
262 if config.Checkbuild() {
263 what |= RunBuildTests
264 }
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000265 if config.SkipConfig() {
266 ctx.Verboseln("Skipping Config as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100267 what = what &^ RunProductConfig
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000268 }
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000269 if config.SkipKati() {
270 ctx.Verboseln("Skipping Kati as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100271 what = what &^ RunKati
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000272 }
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100273 if config.SkipKatiNinja() {
274 ctx.Verboseln("Skipping use of Kati ninja as requested")
275 what = what &^ RunKatiNinja
276 }
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200277 if config.SkipSoong() {
278 ctx.Verboseln("Skipping use of Soong as requested")
279 what = what &^ RunSoong
280 }
281
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100282 if config.SkipNinja() {
283 ctx.Verboseln("Skipping Ninja as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100284 what = what &^ RunNinja
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100285 }
286
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200287 if !config.SoongBuildInvocationNeeded() {
288 // This means that the output of soong_build is not needed and thus it would
289 // run unnecessarily. In addition, if this code wasn't there invocations
290 // with only special-cased target names like "m bp2build" would result in
291 // passing Ninja the empty target list and it would then build the default
292 // targets which is not what the user asked for.
293 what = what &^ RunNinja
294 what = what &^ RunKati
295 }
296
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +0900297 if config.StartGoma() {
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +0900298 startGoma(ctx, config)
299 }
300
Ramy Medhatbbf25672019-07-17 12:30:04 +0000301 if config.StartRBE() {
Kousik Kumar4c180ad2022-05-27 07:48:37 -0400302 cleanupRBELogsDir(ctx, config)
Ramy Medhatbbf25672019-07-17 12:30:04 +0000303 startRBE(ctx, config)
Kousik Kumara1d8fa92022-03-18 02:50:31 -0400304 defer DumpRBEMetrics(ctx, config, filepath.Join(config.LogsDir(), "rbe_metrics.pb"))
Ramy Medhatbbf25672019-07-17 12:30:04 +0000305 }
306
Anton Hansson5a7861a2021-06-04 10:09:01 +0100307 if what&RunProductConfig != 0 {
Dan Willemsen1e704462016-08-21 15:17:17 -0700308 runMakeProductConfig(ctx, config)
309 }
310
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000311 // Everything below here depends on product config.
312
Colin Cross806fd942019-05-03 13:35:58 -0700313 if inList("installclean", config.Arguments()) ||
314 inList("install-clean", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400315 logArgsOtherThan("installclean", "install-clean")
Rupert Shuttleworth1f304e62020-11-24 14:13:41 +0000316 installClean(ctx, config)
Dan Willemsenf052f782017-05-18 15:29:04 -0700317 ctx.Println("Deleted images and staging directories.")
318 return
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000319 }
320
321 if inList("dataclean", config.Arguments()) ||
Colin Cross806fd942019-05-03 13:35:58 -0700322 inList("data-clean", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400323 logArgsOtherThan("dataclean", "data-clean")
Rupert Shuttleworth1f304e62020-11-24 14:13:41 +0000324 dataClean(ctx, config)
Dan Willemsenf052f782017-05-18 15:29:04 -0700325 ctx.Println("Deleted data files.")
326 return
327 }
328
Anton Hansson5a7861a2021-06-04 10:09:01 +0100329 if what&RunSoong != 0 {
Dan Willemsen1e704462016-08-21 15:17:17 -0700330 runSoong(ctx, config)
331 }
332
Anton Hansson5a7861a2021-06-04 10:09:01 +0100333 if what&RunKati != 0 {
Dan Willemsen29971232018-09-26 14:58:30 -0700334 genKatiSuffix(ctx, config)
335 runKatiCleanSpec(ctx, config)
336 runKatiBuild(ctx, config)
Dan Willemsenfb1271a2018-09-26 15:00:42 -0700337 runKatiPackage(ctx, config)
Dan Willemsene0879fc2017-08-04 15:06:27 -0700338
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000339 ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0666) // a+rw
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100340 } else if what&RunKatiNinja != 0 {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700341 // Load last Kati Suffix if it exists
342 if katiSuffix, err := ioutil.ReadFile(config.LastKatiSuffixFile()); err == nil {
343 ctx.Verboseln("Loaded previous kati config:", string(katiSuffix))
344 config.SetKatiSuffix(string(katiSuffix))
345 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700346 }
347
Colin Cross37193492017-11-16 17:55:00 -0800348 // Write combined ninja file
349 createCombinedBuildNinjaFile(ctx, config)
350
Colin Cross8ba7d472020-06-25 11:27:52 -0700351 distGzipFile(ctx, config, config.CombinedNinjaFile())
352
Colin Cross37193492017-11-16 17:55:00 -0800353 if what&RunBuildTests != 0 {
354 testForDanglingRules(ctx, config)
355 }
356
Anton Hansson5a7861a2021-06-04 10:09:01 +0100357 if what&RunNinja != 0 {
358 if what&RunKati != 0 {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700359 installCleanIfNecessary(ctx, config)
360 }
Dan Willemsen02781d52017-05-12 19:28:13 -0700361
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100362 runNinjaForBuild(ctx, config)
Dan Willemsen1e704462016-08-21 15:17:17 -0700363 }
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000364
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000365 // Currently, using Bazel requires Kati and Soong to run first, so check whether to run Bazel last.
Anton Hansson5a7861a2021-06-04 10:09:01 +0100366 if what&RunBazel != 0 {
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000367 runBazel(ctx, config)
368 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700369}
Colin Cross8ba7d472020-06-25 11:27:52 -0700370
Dan Willemsen80d72612022-04-20 21:45:00 -0700371var distWaitGroup sync.WaitGroup
372
373// waitForDist waits for all backgrounded distGzipFile and distFile writes to finish
374func waitForDist(ctx Context) {
375 ctx.BeginTrace("soong_ui", "dist")
376 defer ctx.EndTrace()
377
378 distWaitGroup.Wait()
379}
380
Colin Cross8ba7d472020-06-25 11:27:52 -0700381// distGzipFile writes a compressed copy of src to the distDir if dist is enabled. Failures
Dan Willemsen80d72612022-04-20 21:45:00 -0700382// are printed but non-fatal. Uses the distWaitGroup func for backgrounding (optimization).
Colin Cross8ba7d472020-06-25 11:27:52 -0700383func distGzipFile(ctx Context, config Config, src string, subDirs ...string) {
384 if !config.Dist() {
385 return
386 }
387
388 subDir := filepath.Join(subDirs...)
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000389 destDir := filepath.Join(config.RealDistDir(), "soong_ui", subDir)
Colin Cross8ba7d472020-06-25 11:27:52 -0700390
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000391 if err := os.MkdirAll(destDir, 0777); err != nil { // a+rwx
Colin Cross8ba7d472020-06-25 11:27:52 -0700392 ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
Colin Cross8ba7d472020-06-25 11:27:52 -0700393 }
394
Dan Willemsen80d72612022-04-20 21:45:00 -0700395 distWaitGroup.Add(1)
396 go func() {
397 defer distWaitGroup.Done()
398 if err := gzipFileToDir(src, destDir); err != nil {
399 ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
400 }
401 }()
Colin Cross8ba7d472020-06-25 11:27:52 -0700402}
403
404// distFile writes a copy of src to the distDir if dist is enabled. Failures are printed but
Dan Willemsen80d72612022-04-20 21:45:00 -0700405// non-fatal. Uses the distWaitGroup func for backgrounding (optimization).
Colin Cross8ba7d472020-06-25 11:27:52 -0700406func distFile(ctx Context, config Config, src string, subDirs ...string) {
407 if !config.Dist() {
408 return
409 }
410
411 subDir := filepath.Join(subDirs...)
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000412 destDir := filepath.Join(config.RealDistDir(), "soong_ui", subDir)
Colin Cross8ba7d472020-06-25 11:27:52 -0700413
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000414 if err := os.MkdirAll(destDir, 0777); err != nil { // a+rwx
Colin Cross8ba7d472020-06-25 11:27:52 -0700415 ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
Colin Cross8ba7d472020-06-25 11:27:52 -0700416 }
417
Dan Willemsen80d72612022-04-20 21:45:00 -0700418 distWaitGroup.Add(1)
419 go func() {
420 defer distWaitGroup.Done()
421 if _, err := copyFile(src, filepath.Join(destDir, filepath.Base(src))); err != nil {
422 ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
423 }
424 }()
Colin Cross8ba7d472020-06-25 11:27:52 -0700425}