blob: ecf11ccd658fb55b716d520b4f1fd8567b9b51e0 [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.
Chris Parsons19ab9a42022-08-30 13:15:04 -0400107 RunBazel = 1 << iota
108 RunBuildTests = 1 << iota
109 RunAll = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunNinja
Dan Willemsen1e704462016-08-21 15:17:17 -0700110)
111
Chris Parsonsef615e52022-08-18 22:04:11 -0400112// checkBazelMode fails the build if there are conflicting arguments for which bazel
113// build mode to use.
114func checkBazelMode(ctx Context, config Config) {
115 // TODO(cparsons): Remove USE_BAZEL_ANALYSIS handling.
116 if config.Environment().IsEnvTrue("USE_BAZEL_ANALYSIS") {
117 if config.bazelProdMode || config.bazelDevMode {
118 ctx.Fatalf("USE_BAZEL_ANALYSIS is deprecated.\n" +
119 "Unset USE_BAZEL_ANALYSIS when using --bazel-mode or --bazel-mode-dev.")
120 } else {
121 config.bazelDevMode = true
122 }
123 }
124 if config.bazelProdMode && config.bazelDevMode {
125 ctx.Fatalf("Conflicting bazel mode.\n" +
126 "Do not specify both --bazel-mode and --bazel-mode-dev")
127 }
128}
129
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000130// 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 +0100131func checkProblematicFiles(ctx Context) {
132 files := []string{"Android.mk", "CleanSpec.mk"}
133 for _, file := range files {
134 if _, err := os.Stat(file); !os.IsNotExist(err) {
135 absolute := absPath(ctx, file)
136 ctx.Printf("Found %s in tree root. This file needs to be removed to build.\n", file)
137 ctx.Fatalf(" rm %s\n", absolute)
138 }
139 }
140}
141
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000142// checkCaseSensitivity issues a warning if a case-insensitive file system is being used.
Dan Willemsendb8457c2017-05-12 16:38:17 -0700143func checkCaseSensitivity(ctx Context, config Config) {
144 outDir := config.OutDir()
145 lowerCase := filepath.Join(outDir, "casecheck.txt")
146 upperCase := filepath.Join(outDir, "CaseCheck.txt")
147 lowerData := "a"
148 upperData := "B"
149
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000150 if err := ioutil.WriteFile(lowerCase, []byte(lowerData), 0666); err != nil { // a+rw
Dan Willemsendb8457c2017-05-12 16:38:17 -0700151 ctx.Fatalln("Failed to check case sensitivity:", err)
152 }
153
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000154 if err := ioutil.WriteFile(upperCase, []byte(upperData), 0666); err != nil { // a+rw
Dan Willemsendb8457c2017-05-12 16:38:17 -0700155 ctx.Fatalln("Failed to check case sensitivity:", err)
156 }
157
158 res, err := ioutil.ReadFile(lowerCase)
159 if err != nil {
160 ctx.Fatalln("Failed to check case sensitivity:", err)
161 }
162
163 if string(res) != lowerData {
164 ctx.Println("************************************************************")
165 ctx.Println("You are building on a case-insensitive filesystem.")
166 ctx.Println("Please move your source tree to a case-sensitive filesystem.")
167 ctx.Println("************************************************************")
168 ctx.Fatalln("Case-insensitive filesystems not supported")
169 }
170}
171
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000172// help prints a help/usage message, via the build/make/help.sh script.
173func help(ctx Context, config Config) {
Jeff Gastondf4a0812017-05-30 20:11:20 -0700174 cmd := Command(ctx, config, "help.sh", "build/make/help.sh")
Dan Willemsenb2e6c2e2017-07-13 17:24:44 -0700175 cmd.Sandbox = dumpvarsSandbox
Dan Willemsenb82471a2018-05-17 16:37:09 -0700176 cmd.RunAndPrintOrFatal()
Dan Willemsen02781d52017-05-12 19:28:13 -0700177}
178
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000179// checkRAM warns if there probably isn't enough RAM to complete a build.
180func checkRAM(ctx Context, config Config) {
Dan Willemsen570a2922020-05-26 23:02:29 -0700181 if totalRAM := config.TotalRAM(); totalRAM != 0 {
182 ram := float32(totalRAM) / (1024 * 1024 * 1024)
183 ctx.Verbosef("Total RAM: %.3vGB", ram)
184
185 if ram <= 16 {
186 ctx.Println("************************************************************")
187 ctx.Printf("You are building on a machine with %.3vGB of RAM\n", ram)
188 ctx.Println("")
189 ctx.Println("The minimum required amount of free memory is around 16GB,")
190 ctx.Println("and even with that, some configurations may not work.")
191 ctx.Println("")
192 ctx.Println("If you run into segfaults or other errors, try reducing your")
193 ctx.Println("-j value.")
194 ctx.Println("************************************************************")
195 } else if ram <= float32(config.Parallel()) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000196 // Want at least 1GB of RAM per job.
Dan Willemsen570a2922020-05-26 23:02:29 -0700197 ctx.Printf("Warning: high -j%d count compared to %.3vGB of RAM", config.Parallel(), ram)
198 ctx.Println("If you run into segfaults or other errors, try a lower -j value")
199 }
200 }
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000201}
202
Usta Shresthadb46a9b2022-07-11 11:29:56 -0400203// Build the tree. Various flags in `config` govern which components of
204// the build to run.
Anton Hansson5a7861a2021-06-04 10:09:01 +0100205func Build(ctx Context, config Config) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000206 ctx.Verboseln("Starting build with args:", config.Arguments())
207 ctx.Verboseln("Environment:", config.Environment().Environ())
Dan Willemsen1e704462016-08-21 15:17:17 -0700208
Colin Cross74cda722020-01-16 15:25:50 -0800209 ctx.BeginTrace(metrics.Total, "total")
210 defer ctx.EndTrace()
211
Dan Willemsen1e704462016-08-21 15:17:17 -0700212 if inList("help", config.Arguments()) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000213 help(ctx, config)
Dan Willemsen0b73b4b2017-05-12 19:28:13 -0700214 return
Dan Willemsen1e704462016-08-21 15:17:17 -0700215 }
216
Jeff Gaston3615fe82017-05-24 13:14:34 -0700217 // Make sure that no other Soong process is running with the same output directory
218 buildLock := BecomeSingletonOrFail(ctx, config)
219 defer buildLock.Unlock()
220
Usta Shrestha675564d2022-08-09 18:03:23 -0400221 logArgsOtherThan := func(specialTargets ...string) {
222 var ignored []string
223 for _, a := range config.Arguments() {
224 if !inList(a, specialTargets) {
225 ignored = append(ignored, a)
226 }
227 }
228 if len(ignored) > 0 {
229 ctx.Printf("ignoring arguments %q", ignored)
230 }
231 }
232
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000233 if inList("clean", config.Arguments()) || inList("clobber", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400234 logArgsOtherThan("clean", "clobber")
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000235 clean(ctx, config)
236 return
237 }
238
Dan Willemsen80d72612022-04-20 21:45:00 -0700239 defer waitForDist(ctx)
240
Chris Parsonsef615e52022-08-18 22:04:11 -0400241 checkBazelMode(ctx, config)
242
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000243 // 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 +0100244 checkProblematicFiles(ctx)
245
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000246 checkRAM(ctx, config)
247
Dan Willemsen1e704462016-08-21 15:17:17 -0700248 SetupOutDir(ctx, config)
249
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000250 // checkCaseSensitivity issues a warning if a case-insensitive file system is being used.
Dan Willemsendb8457c2017-05-12 16:38:17 -0700251 checkCaseSensitivity(ctx, config)
252
Jeff Gastonefc1b412017-03-29 17:29:06 -0700253 ensureEmptyDirectoriesExist(ctx, config.TempDir())
254
Dan Willemsen18490112018-05-25 16:30:04 -0700255 SetupPath(ctx, config)
256
Anton Hansson5a7861a2021-06-04 10:09:01 +0100257 what := RunAll
Anton Hansson5a7861a2021-06-04 10:09:01 +0100258 if config.Checkbuild() {
259 what |= RunBuildTests
260 }
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000261 if config.SkipConfig() {
262 ctx.Verboseln("Skipping Config as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100263 what = what &^ RunProductConfig
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000264 }
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000265 if config.SkipKati() {
266 ctx.Verboseln("Skipping Kati as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100267 what = what &^ RunKati
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000268 }
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100269 if config.SkipKatiNinja() {
270 ctx.Verboseln("Skipping use of Kati ninja as requested")
271 what = what &^ RunKatiNinja
272 }
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200273 if config.SkipSoong() {
274 ctx.Verboseln("Skipping use of Soong as requested")
275 what = what &^ RunSoong
276 }
277
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100278 if config.SkipNinja() {
279 ctx.Verboseln("Skipping Ninja as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100280 what = what &^ RunNinja
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100281 }
282
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200283 if !config.SoongBuildInvocationNeeded() {
284 // This means that the output of soong_build is not needed and thus it would
285 // run unnecessarily. In addition, if this code wasn't there invocations
286 // with only special-cased target names like "m bp2build" would result in
287 // passing Ninja the empty target list and it would then build the default
288 // targets which is not what the user asked for.
289 what = what &^ RunNinja
290 what = what &^ RunKati
291 }
292
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +0900293 if config.StartGoma() {
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +0900294 startGoma(ctx, config)
295 }
296
Ramy Medhatbbf25672019-07-17 12:30:04 +0000297 if config.StartRBE() {
Kousik Kumar4c180ad2022-05-27 07:48:37 -0400298 cleanupRBELogsDir(ctx, config)
Ramy Medhatbbf25672019-07-17 12:30:04 +0000299 startRBE(ctx, config)
Kousik Kumara1d8fa92022-03-18 02:50:31 -0400300 defer DumpRBEMetrics(ctx, config, filepath.Join(config.LogsDir(), "rbe_metrics.pb"))
Ramy Medhatbbf25672019-07-17 12:30:04 +0000301 }
302
Anton Hansson5a7861a2021-06-04 10:09:01 +0100303 if what&RunProductConfig != 0 {
Dan Willemsen1e704462016-08-21 15:17:17 -0700304 runMakeProductConfig(ctx, config)
305 }
306
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000307 // Everything below here depends on product config.
308
Colin Cross806fd942019-05-03 13:35:58 -0700309 if inList("installclean", config.Arguments()) ||
310 inList("install-clean", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400311 logArgsOtherThan("installclean", "install-clean")
Rupert Shuttleworth1f304e62020-11-24 14:13:41 +0000312 installClean(ctx, config)
Dan Willemsenf052f782017-05-18 15:29:04 -0700313 ctx.Println("Deleted images and staging directories.")
314 return
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000315 }
316
317 if inList("dataclean", config.Arguments()) ||
Colin Cross806fd942019-05-03 13:35:58 -0700318 inList("data-clean", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400319 logArgsOtherThan("dataclean", "data-clean")
Rupert Shuttleworth1f304e62020-11-24 14:13:41 +0000320 dataClean(ctx, config)
Dan Willemsenf052f782017-05-18 15:29:04 -0700321 ctx.Println("Deleted data files.")
322 return
323 }
324
Anton Hansson5a7861a2021-06-04 10:09:01 +0100325 if what&RunSoong != 0 {
Dan Willemsen1e704462016-08-21 15:17:17 -0700326 runSoong(ctx, config)
327 }
328
Anton Hansson5a7861a2021-06-04 10:09:01 +0100329 if what&RunKati != 0 {
Dan Willemsen29971232018-09-26 14:58:30 -0700330 genKatiSuffix(ctx, config)
331 runKatiCleanSpec(ctx, config)
332 runKatiBuild(ctx, config)
Dan Willemsenfb1271a2018-09-26 15:00:42 -0700333 runKatiPackage(ctx, config)
Dan Willemsene0879fc2017-08-04 15:06:27 -0700334
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000335 ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0666) // a+rw
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100336 } else if what&RunKatiNinja != 0 {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700337 // Load last Kati Suffix if it exists
338 if katiSuffix, err := ioutil.ReadFile(config.LastKatiSuffixFile()); err == nil {
339 ctx.Verboseln("Loaded previous kati config:", string(katiSuffix))
340 config.SetKatiSuffix(string(katiSuffix))
341 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700342 }
343
Colin Cross37193492017-11-16 17:55:00 -0800344 // Write combined ninja file
345 createCombinedBuildNinjaFile(ctx, config)
346
Colin Cross8ba7d472020-06-25 11:27:52 -0700347 distGzipFile(ctx, config, config.CombinedNinjaFile())
348
Colin Cross37193492017-11-16 17:55:00 -0800349 if what&RunBuildTests != 0 {
350 testForDanglingRules(ctx, config)
351 }
352
Anton Hansson5a7861a2021-06-04 10:09:01 +0100353 if what&RunNinja != 0 {
354 if what&RunKati != 0 {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700355 installCleanIfNecessary(ctx, config)
356 }
Dan Willemsen02781d52017-05-12 19:28:13 -0700357
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100358 runNinjaForBuild(ctx, config)
Dan Willemsen1e704462016-08-21 15:17:17 -0700359 }
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000360
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000361 // Currently, using Bazel requires Kati and Soong to run first, so check whether to run Bazel last.
Anton Hansson5a7861a2021-06-04 10:09:01 +0100362 if what&RunBazel != 0 {
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000363 runBazel(ctx, config)
364 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700365}
Colin Cross8ba7d472020-06-25 11:27:52 -0700366
Dan Willemsen80d72612022-04-20 21:45:00 -0700367var distWaitGroup sync.WaitGroup
368
369// waitForDist waits for all backgrounded distGzipFile and distFile writes to finish
370func waitForDist(ctx Context) {
371 ctx.BeginTrace("soong_ui", "dist")
372 defer ctx.EndTrace()
373
374 distWaitGroup.Wait()
375}
376
Colin Cross8ba7d472020-06-25 11:27:52 -0700377// distGzipFile writes a compressed copy of src to the distDir if dist is enabled. Failures
Dan Willemsen80d72612022-04-20 21:45:00 -0700378// are printed but non-fatal. Uses the distWaitGroup func for backgrounding (optimization).
Colin Cross8ba7d472020-06-25 11:27:52 -0700379func distGzipFile(ctx Context, config Config, src string, subDirs ...string) {
380 if !config.Dist() {
381 return
382 }
383
384 subDir := filepath.Join(subDirs...)
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000385 destDir := filepath.Join(config.RealDistDir(), "soong_ui", subDir)
Colin Cross8ba7d472020-06-25 11:27:52 -0700386
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000387 if err := os.MkdirAll(destDir, 0777); err != nil { // a+rwx
Colin Cross8ba7d472020-06-25 11:27:52 -0700388 ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
Colin Cross8ba7d472020-06-25 11:27:52 -0700389 }
390
Dan Willemsen80d72612022-04-20 21:45:00 -0700391 distWaitGroup.Add(1)
392 go func() {
393 defer distWaitGroup.Done()
394 if err := gzipFileToDir(src, destDir); err != nil {
395 ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
396 }
397 }()
Colin Cross8ba7d472020-06-25 11:27:52 -0700398}
399
400// distFile writes a copy of src to the distDir if dist is enabled. Failures are printed but
Dan Willemsen80d72612022-04-20 21:45:00 -0700401// non-fatal. Uses the distWaitGroup func for backgrounding (optimization).
Colin Cross8ba7d472020-06-25 11:27:52 -0700402func distFile(ctx Context, config Config, src string, subDirs ...string) {
403 if !config.Dist() {
404 return
405 }
406
407 subDir := filepath.Join(subDirs...)
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000408 destDir := filepath.Join(config.RealDistDir(), "soong_ui", subDir)
Colin Cross8ba7d472020-06-25 11:27:52 -0700409
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000410 if err := os.MkdirAll(destDir, 0777); err != nil { // a+rwx
Colin Cross8ba7d472020-06-25 11:27:52 -0700411 ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
Colin Cross8ba7d472020-06-25 11:27:52 -0700412 }
413
Dan Willemsen80d72612022-04-20 21:45:00 -0700414 distWaitGroup.Add(1)
415 go func() {
416 defer distWaitGroup.Done()
417 if _, err := copyFile(src, filepath.Join(destDir, filepath.Base(src))); err != nil {
418 ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
419 }
420 }()
Colin Cross8ba7d472020-06-25 11:27:52 -0700421}