blob: ff2d5f28d7e42a6d627672d27d11139764128866 [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) {
Chris Parsonsef615e52022-08-18 22:04:11 -0400115 if config.Environment().IsEnvTrue("USE_BAZEL_ANALYSIS") {
Chris Parsons1bb58da2022-08-30 13:37:57 -0400116 ctx.Fatalln("USE_BAZEL_ANALYSIS is deprecated. Unset USE_BAZEL_ANALYSIS.\n" +
117 "Use --bazel-mode-dev instead. For example: `m --bazel-mode-dev nothing`")
Chris Parsonsef615e52022-08-18 22:04:11 -0400118 }
119 if config.bazelProdMode && config.bazelDevMode {
Chris Parsons1bb58da2022-08-30 13:37:57 -0400120 ctx.Fatalln("Conflicting bazel mode.\n" +
Chris Parsonsef615e52022-08-18 22:04:11 -0400121 "Do not specify both --bazel-mode and --bazel-mode-dev")
122 }
123}
124
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000125// 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 +0100126func checkProblematicFiles(ctx Context) {
127 files := []string{"Android.mk", "CleanSpec.mk"}
128 for _, file := range files {
129 if _, err := os.Stat(file); !os.IsNotExist(err) {
130 absolute := absPath(ctx, file)
131 ctx.Printf("Found %s in tree root. This file needs to be removed to build.\n", file)
132 ctx.Fatalf(" rm %s\n", absolute)
133 }
134 }
135}
136
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000137// checkCaseSensitivity issues a warning if a case-insensitive file system is being used.
Dan Willemsendb8457c2017-05-12 16:38:17 -0700138func checkCaseSensitivity(ctx Context, config Config) {
139 outDir := config.OutDir()
140 lowerCase := filepath.Join(outDir, "casecheck.txt")
141 upperCase := filepath.Join(outDir, "CaseCheck.txt")
142 lowerData := "a"
143 upperData := "B"
144
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000145 if err := ioutil.WriteFile(lowerCase, []byte(lowerData), 0666); err != nil { // a+rw
Dan Willemsendb8457c2017-05-12 16:38:17 -0700146 ctx.Fatalln("Failed to check case sensitivity:", err)
147 }
148
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000149 if err := ioutil.WriteFile(upperCase, []byte(upperData), 0666); err != nil { // a+rw
Dan Willemsendb8457c2017-05-12 16:38:17 -0700150 ctx.Fatalln("Failed to check case sensitivity:", err)
151 }
152
153 res, err := ioutil.ReadFile(lowerCase)
154 if err != nil {
155 ctx.Fatalln("Failed to check case sensitivity:", err)
156 }
157
158 if string(res) != lowerData {
159 ctx.Println("************************************************************")
160 ctx.Println("You are building on a case-insensitive filesystem.")
161 ctx.Println("Please move your source tree to a case-sensitive filesystem.")
162 ctx.Println("************************************************************")
163 ctx.Fatalln("Case-insensitive filesystems not supported")
164 }
165}
166
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000167// help prints a help/usage message, via the build/make/help.sh script.
168func help(ctx Context, config Config) {
Jeff Gastondf4a0812017-05-30 20:11:20 -0700169 cmd := Command(ctx, config, "help.sh", "build/make/help.sh")
Dan Willemsenb2e6c2e2017-07-13 17:24:44 -0700170 cmd.Sandbox = dumpvarsSandbox
Dan Willemsenb82471a2018-05-17 16:37:09 -0700171 cmd.RunAndPrintOrFatal()
Dan Willemsen02781d52017-05-12 19:28:13 -0700172}
173
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000174// checkRAM warns if there probably isn't enough RAM to complete a build.
175func checkRAM(ctx Context, config Config) {
Dan Willemsen570a2922020-05-26 23:02:29 -0700176 if totalRAM := config.TotalRAM(); totalRAM != 0 {
177 ram := float32(totalRAM) / (1024 * 1024 * 1024)
178 ctx.Verbosef("Total RAM: %.3vGB", ram)
179
180 if ram <= 16 {
181 ctx.Println("************************************************************")
182 ctx.Printf("You are building on a machine with %.3vGB of RAM\n", ram)
183 ctx.Println("")
184 ctx.Println("The minimum required amount of free memory is around 16GB,")
185 ctx.Println("and even with that, some configurations may not work.")
186 ctx.Println("")
187 ctx.Println("If you run into segfaults or other errors, try reducing your")
188 ctx.Println("-j value.")
189 ctx.Println("************************************************************")
190 } else if ram <= float32(config.Parallel()) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000191 // Want at least 1GB of RAM per job.
Dan Willemsen570a2922020-05-26 23:02:29 -0700192 ctx.Printf("Warning: high -j%d count compared to %.3vGB of RAM", config.Parallel(), ram)
193 ctx.Println("If you run into segfaults or other errors, try a lower -j value")
194 }
195 }
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000196}
197
Usta Shresthadb46a9b2022-07-11 11:29:56 -0400198// Build the tree. Various flags in `config` govern which components of
199// the build to run.
Anton Hansson5a7861a2021-06-04 10:09:01 +0100200func Build(ctx Context, config Config) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000201 ctx.Verboseln("Starting build with args:", config.Arguments())
202 ctx.Verboseln("Environment:", config.Environment().Environ())
Dan Willemsen1e704462016-08-21 15:17:17 -0700203
Colin Cross74cda722020-01-16 15:25:50 -0800204 ctx.BeginTrace(metrics.Total, "total")
205 defer ctx.EndTrace()
206
Dan Willemsen1e704462016-08-21 15:17:17 -0700207 if inList("help", config.Arguments()) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000208 help(ctx, config)
Dan Willemsen0b73b4b2017-05-12 19:28:13 -0700209 return
Dan Willemsen1e704462016-08-21 15:17:17 -0700210 }
211
Jeff Gaston3615fe82017-05-24 13:14:34 -0700212 // Make sure that no other Soong process is running with the same output directory
213 buildLock := BecomeSingletonOrFail(ctx, config)
214 defer buildLock.Unlock()
215
Usta Shrestha675564d2022-08-09 18:03:23 -0400216 logArgsOtherThan := func(specialTargets ...string) {
217 var ignored []string
218 for _, a := range config.Arguments() {
219 if !inList(a, specialTargets) {
220 ignored = append(ignored, a)
221 }
222 }
223 if len(ignored) > 0 {
224 ctx.Printf("ignoring arguments %q", ignored)
225 }
226 }
227
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000228 if inList("clean", config.Arguments()) || inList("clobber", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400229 logArgsOtherThan("clean", "clobber")
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000230 clean(ctx, config)
231 return
232 }
233
Dan Willemsen80d72612022-04-20 21:45:00 -0700234 defer waitForDist(ctx)
235
Chris Parsonsef615e52022-08-18 22:04:11 -0400236 checkBazelMode(ctx, config)
237
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000238 // 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 +0100239 checkProblematicFiles(ctx)
240
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000241 checkRAM(ctx, config)
242
Dan Willemsen1e704462016-08-21 15:17:17 -0700243 SetupOutDir(ctx, config)
244
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000245 // checkCaseSensitivity issues a warning if a case-insensitive file system is being used.
Dan Willemsendb8457c2017-05-12 16:38:17 -0700246 checkCaseSensitivity(ctx, config)
247
Jeff Gastonefc1b412017-03-29 17:29:06 -0700248 ensureEmptyDirectoriesExist(ctx, config.TempDir())
249
Dan Willemsen18490112018-05-25 16:30:04 -0700250 SetupPath(ctx, config)
251
Anton Hansson5a7861a2021-06-04 10:09:01 +0100252 what := RunAll
Anton Hansson5a7861a2021-06-04 10:09:01 +0100253 if config.Checkbuild() {
254 what |= RunBuildTests
255 }
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000256 if config.SkipConfig() {
257 ctx.Verboseln("Skipping Config as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100258 what = what &^ RunProductConfig
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000259 }
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000260 if config.SkipKati() {
261 ctx.Verboseln("Skipping Kati as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100262 what = what &^ RunKati
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000263 }
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100264 if config.SkipKatiNinja() {
265 ctx.Verboseln("Skipping use of Kati ninja as requested")
266 what = what &^ RunKatiNinja
267 }
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200268 if config.SkipSoong() {
269 ctx.Verboseln("Skipping use of Soong as requested")
270 what = what &^ RunSoong
271 }
272
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100273 if config.SkipNinja() {
274 ctx.Verboseln("Skipping Ninja as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100275 what = what &^ RunNinja
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100276 }
277
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200278 if !config.SoongBuildInvocationNeeded() {
279 // This means that the output of soong_build is not needed and thus it would
280 // run unnecessarily. In addition, if this code wasn't there invocations
281 // with only special-cased target names like "m bp2build" would result in
282 // passing Ninja the empty target list and it would then build the default
283 // targets which is not what the user asked for.
284 what = what &^ RunNinja
285 what = what &^ RunKati
286 }
287
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +0900288 if config.StartGoma() {
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +0900289 startGoma(ctx, config)
290 }
291
Ramy Medhatbbf25672019-07-17 12:30:04 +0000292 if config.StartRBE() {
Kousik Kumar4c180ad2022-05-27 07:48:37 -0400293 cleanupRBELogsDir(ctx, config)
Ramy Medhatbbf25672019-07-17 12:30:04 +0000294 startRBE(ctx, config)
Kousik Kumara1d8fa92022-03-18 02:50:31 -0400295 defer DumpRBEMetrics(ctx, config, filepath.Join(config.LogsDir(), "rbe_metrics.pb"))
Ramy Medhatbbf25672019-07-17 12:30:04 +0000296 }
297
Anton Hansson5a7861a2021-06-04 10:09:01 +0100298 if what&RunProductConfig != 0 {
Dan Willemsen1e704462016-08-21 15:17:17 -0700299 runMakeProductConfig(ctx, config)
300 }
301
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000302 // Everything below here depends on product config.
303
Colin Cross806fd942019-05-03 13:35:58 -0700304 if inList("installclean", config.Arguments()) ||
305 inList("install-clean", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400306 logArgsOtherThan("installclean", "install-clean")
Rupert Shuttleworth1f304e62020-11-24 14:13:41 +0000307 installClean(ctx, config)
Dan Willemsenf052f782017-05-18 15:29:04 -0700308 ctx.Println("Deleted images and staging directories.")
309 return
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000310 }
311
312 if inList("dataclean", config.Arguments()) ||
Colin Cross806fd942019-05-03 13:35:58 -0700313 inList("data-clean", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400314 logArgsOtherThan("dataclean", "data-clean")
Rupert Shuttleworth1f304e62020-11-24 14:13:41 +0000315 dataClean(ctx, config)
Dan Willemsenf052f782017-05-18 15:29:04 -0700316 ctx.Println("Deleted data files.")
317 return
318 }
319
Anton Hansson5a7861a2021-06-04 10:09:01 +0100320 if what&RunSoong != 0 {
Dan Willemsen1e704462016-08-21 15:17:17 -0700321 runSoong(ctx, config)
322 }
323
Anton Hansson5a7861a2021-06-04 10:09:01 +0100324 if what&RunKati != 0 {
Dan Willemsen29971232018-09-26 14:58:30 -0700325 genKatiSuffix(ctx, config)
326 runKatiCleanSpec(ctx, config)
327 runKatiBuild(ctx, config)
Dan Willemsenfb1271a2018-09-26 15:00:42 -0700328 runKatiPackage(ctx, config)
Dan Willemsene0879fc2017-08-04 15:06:27 -0700329
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000330 ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0666) // a+rw
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100331 } else if what&RunKatiNinja != 0 {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700332 // Load last Kati Suffix if it exists
333 if katiSuffix, err := ioutil.ReadFile(config.LastKatiSuffixFile()); err == nil {
334 ctx.Verboseln("Loaded previous kati config:", string(katiSuffix))
335 config.SetKatiSuffix(string(katiSuffix))
336 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700337 }
338
Colin Cross37193492017-11-16 17:55:00 -0800339 // Write combined ninja file
340 createCombinedBuildNinjaFile(ctx, config)
341
Colin Cross8ba7d472020-06-25 11:27:52 -0700342 distGzipFile(ctx, config, config.CombinedNinjaFile())
343
Colin Cross37193492017-11-16 17:55:00 -0800344 if what&RunBuildTests != 0 {
345 testForDanglingRules(ctx, config)
346 }
347
Anton Hansson5a7861a2021-06-04 10:09:01 +0100348 if what&RunNinja != 0 {
349 if what&RunKati != 0 {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700350 installCleanIfNecessary(ctx, config)
351 }
Dan Willemsen02781d52017-05-12 19:28:13 -0700352
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100353 runNinjaForBuild(ctx, config)
Dan Willemsen1e704462016-08-21 15:17:17 -0700354 }
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000355
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000356 // Currently, using Bazel requires Kati and Soong to run first, so check whether to run Bazel last.
Anton Hansson5a7861a2021-06-04 10:09:01 +0100357 if what&RunBazel != 0 {
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000358 runBazel(ctx, config)
359 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700360}
Colin Cross8ba7d472020-06-25 11:27:52 -0700361
Dan Willemsen80d72612022-04-20 21:45:00 -0700362var distWaitGroup sync.WaitGroup
363
364// waitForDist waits for all backgrounded distGzipFile and distFile writes to finish
365func waitForDist(ctx Context) {
366 ctx.BeginTrace("soong_ui", "dist")
367 defer ctx.EndTrace()
368
369 distWaitGroup.Wait()
370}
371
Colin Cross8ba7d472020-06-25 11:27:52 -0700372// distGzipFile writes a compressed copy of src to the distDir if dist is enabled. Failures
Dan Willemsen80d72612022-04-20 21:45:00 -0700373// are printed but non-fatal. Uses the distWaitGroup func for backgrounding (optimization).
Colin Cross8ba7d472020-06-25 11:27:52 -0700374func distGzipFile(ctx Context, config Config, src string, subDirs ...string) {
375 if !config.Dist() {
376 return
377 }
378
379 subDir := filepath.Join(subDirs...)
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000380 destDir := filepath.Join(config.RealDistDir(), "soong_ui", subDir)
Colin Cross8ba7d472020-06-25 11:27:52 -0700381
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000382 if err := os.MkdirAll(destDir, 0777); err != nil { // a+rwx
Colin Cross8ba7d472020-06-25 11:27:52 -0700383 ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
Colin Cross8ba7d472020-06-25 11:27:52 -0700384 }
385
Dan Willemsen80d72612022-04-20 21:45:00 -0700386 distWaitGroup.Add(1)
387 go func() {
388 defer distWaitGroup.Done()
389 if err := gzipFileToDir(src, destDir); err != nil {
390 ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
391 }
392 }()
Colin Cross8ba7d472020-06-25 11:27:52 -0700393}
394
395// distFile writes a copy of src to the distDir if dist is enabled. Failures are printed but
Dan Willemsen80d72612022-04-20 21:45:00 -0700396// non-fatal. Uses the distWaitGroup func for backgrounding (optimization).
Colin Cross8ba7d472020-06-25 11:27:52 -0700397func distFile(ctx Context, config Config, src string, subDirs ...string) {
398 if !config.Dist() {
399 return
400 }
401
402 subDir := filepath.Join(subDirs...)
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000403 destDir := filepath.Join(config.RealDistDir(), "soong_ui", subDir)
Colin Cross8ba7d472020-06-25 11:27:52 -0700404
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000405 if err := os.MkdirAll(destDir, 0777); err != nil { // a+rwx
Colin Cross8ba7d472020-06-25 11:27:52 -0700406 ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
Colin Cross8ba7d472020-06-25 11:27:52 -0700407 }
408
Dan Willemsen80d72612022-04-20 21:45:00 -0700409 distWaitGroup.Add(1)
410 go func() {
411 defer distWaitGroup.Done()
412 if _, err := copyFile(src, filepath.Join(destDir, filepath.Base(src))); err != nil {
413 ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
414 }
415 }()
Colin Cross8ba7d472020-06-25 11:27:52 -0700416}