blob: f7a2d7b18f594016248683aedd22dbd45ff97aeb [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
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000113// 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 +0100114func checkProblematicFiles(ctx Context) {
115 files := []string{"Android.mk", "CleanSpec.mk"}
116 for _, file := range files {
117 if _, err := os.Stat(file); !os.IsNotExist(err) {
118 absolute := absPath(ctx, file)
119 ctx.Printf("Found %s in tree root. This file needs to be removed to build.\n", file)
120 ctx.Fatalf(" rm %s\n", absolute)
121 }
122 }
123}
124
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000125// checkCaseSensitivity issues a warning if a case-insensitive file system is being used.
Dan Willemsendb8457c2017-05-12 16:38:17 -0700126func checkCaseSensitivity(ctx Context, config Config) {
127 outDir := config.OutDir()
128 lowerCase := filepath.Join(outDir, "casecheck.txt")
129 upperCase := filepath.Join(outDir, "CaseCheck.txt")
130 lowerData := "a"
131 upperData := "B"
132
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000133 if err := ioutil.WriteFile(lowerCase, []byte(lowerData), 0666); err != nil { // a+rw
Dan Willemsendb8457c2017-05-12 16:38:17 -0700134 ctx.Fatalln("Failed to check case sensitivity:", err)
135 }
136
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000137 if err := ioutil.WriteFile(upperCase, []byte(upperData), 0666); err != nil { // a+rw
Dan Willemsendb8457c2017-05-12 16:38:17 -0700138 ctx.Fatalln("Failed to check case sensitivity:", err)
139 }
140
141 res, err := ioutil.ReadFile(lowerCase)
142 if err != nil {
143 ctx.Fatalln("Failed to check case sensitivity:", err)
144 }
145
146 if string(res) != lowerData {
147 ctx.Println("************************************************************")
148 ctx.Println("You are building on a case-insensitive filesystem.")
149 ctx.Println("Please move your source tree to a case-sensitive filesystem.")
150 ctx.Println("************************************************************")
151 ctx.Fatalln("Case-insensitive filesystems not supported")
152 }
153}
154
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000155// help prints a help/usage message, via the build/make/help.sh script.
156func help(ctx Context, config Config) {
Jeff Gastondf4a0812017-05-30 20:11:20 -0700157 cmd := Command(ctx, config, "help.sh", "build/make/help.sh")
Dan Willemsenb2e6c2e2017-07-13 17:24:44 -0700158 cmd.Sandbox = dumpvarsSandbox
Dan Willemsenb82471a2018-05-17 16:37:09 -0700159 cmd.RunAndPrintOrFatal()
Dan Willemsen02781d52017-05-12 19:28:13 -0700160}
161
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000162// checkRAM warns if there probably isn't enough RAM to complete a build.
163func checkRAM(ctx Context, config Config) {
Dan Willemsen570a2922020-05-26 23:02:29 -0700164 if totalRAM := config.TotalRAM(); totalRAM != 0 {
165 ram := float32(totalRAM) / (1024 * 1024 * 1024)
166 ctx.Verbosef("Total RAM: %.3vGB", ram)
167
168 if ram <= 16 {
169 ctx.Println("************************************************************")
170 ctx.Printf("You are building on a machine with %.3vGB of RAM\n", ram)
171 ctx.Println("")
172 ctx.Println("The minimum required amount of free memory is around 16GB,")
173 ctx.Println("and even with that, some configurations may not work.")
174 ctx.Println("")
175 ctx.Println("If you run into segfaults or other errors, try reducing your")
176 ctx.Println("-j value.")
177 ctx.Println("************************************************************")
178 } else if ram <= float32(config.Parallel()) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000179 // Want at least 1GB of RAM per job.
Dan Willemsen570a2922020-05-26 23:02:29 -0700180 ctx.Printf("Warning: high -j%d count compared to %.3vGB of RAM", config.Parallel(), ram)
181 ctx.Println("If you run into segfaults or other errors, try a lower -j value")
182 }
183 }
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000184}
185
Usta Shresthadb46a9b2022-07-11 11:29:56 -0400186// Build the tree. Various flags in `config` govern which components of
187// the build to run.
Anton Hansson5a7861a2021-06-04 10:09:01 +0100188func Build(ctx Context, config Config) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000189 ctx.Verboseln("Starting build with args:", config.Arguments())
190 ctx.Verboseln("Environment:", config.Environment().Environ())
Dan Willemsen1e704462016-08-21 15:17:17 -0700191
Colin Cross74cda722020-01-16 15:25:50 -0800192 ctx.BeginTrace(metrics.Total, "total")
193 defer ctx.EndTrace()
194
Dan Willemsen1e704462016-08-21 15:17:17 -0700195 if inList("help", config.Arguments()) {
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000196 help(ctx, config)
Dan Willemsen0b73b4b2017-05-12 19:28:13 -0700197 return
Dan Willemsen1e704462016-08-21 15:17:17 -0700198 }
199
Jeff Gaston3615fe82017-05-24 13:14:34 -0700200 // Make sure that no other Soong process is running with the same output directory
201 buildLock := BecomeSingletonOrFail(ctx, config)
202 defer buildLock.Unlock()
203
Usta Shrestha675564d2022-08-09 18:03:23 -0400204 logArgsOtherThan := func(specialTargets ...string) {
205 var ignored []string
206 for _, a := range config.Arguments() {
207 if !inList(a, specialTargets) {
208 ignored = append(ignored, a)
209 }
210 }
211 if len(ignored) > 0 {
212 ctx.Printf("ignoring arguments %q", ignored)
213 }
214 }
215
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000216 if inList("clean", config.Arguments()) || inList("clobber", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400217 logArgsOtherThan("clean", "clobber")
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000218 clean(ctx, config)
219 return
220 }
221
Dan Willemsen80d72612022-04-20 21:45:00 -0700222 defer waitForDist(ctx)
223
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000224 // 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 +0100225 checkProblematicFiles(ctx)
226
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000227 checkRAM(ctx, config)
228
Dan Willemsen1e704462016-08-21 15:17:17 -0700229 SetupOutDir(ctx, config)
230
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000231 // checkCaseSensitivity issues a warning if a case-insensitive file system is being used.
Dan Willemsendb8457c2017-05-12 16:38:17 -0700232 checkCaseSensitivity(ctx, config)
233
Jeff Gastonefc1b412017-03-29 17:29:06 -0700234 ensureEmptyDirectoriesExist(ctx, config.TempDir())
235
Dan Willemsen18490112018-05-25 16:30:04 -0700236 SetupPath(ctx, config)
237
Anton Hansson5a7861a2021-06-04 10:09:01 +0100238 what := RunAll
239 if config.UseBazel() {
240 what = RunAllWithBazel
241 }
242 if config.Checkbuild() {
243 what |= RunBuildTests
244 }
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000245 if config.SkipConfig() {
246 ctx.Verboseln("Skipping Config as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100247 what = what &^ RunProductConfig
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000248 }
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000249 if config.SkipKati() {
250 ctx.Verboseln("Skipping Kati as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100251 what = what &^ RunKati
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000252 }
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100253 if config.SkipKatiNinja() {
254 ctx.Verboseln("Skipping use of Kati ninja as requested")
255 what = what &^ RunKatiNinja
256 }
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200257 if config.SkipSoong() {
258 ctx.Verboseln("Skipping use of Soong as requested")
259 what = what &^ RunSoong
260 }
261
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100262 if config.SkipNinja() {
263 ctx.Verboseln("Skipping Ninja as requested")
Anton Hansson5a7861a2021-06-04 10:09:01 +0100264 what = what &^ RunNinja
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100265 }
266
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200267 if !config.SoongBuildInvocationNeeded() {
268 // This means that the output of soong_build is not needed and thus it would
269 // run unnecessarily. In addition, if this code wasn't there invocations
270 // with only special-cased target names like "m bp2build" would result in
271 // passing Ninja the empty target list and it would then build the default
272 // targets which is not what the user asked for.
273 what = what &^ RunNinja
274 what = what &^ RunKati
275 }
276
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +0900277 if config.StartGoma() {
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +0900278 startGoma(ctx, config)
279 }
280
Ramy Medhatbbf25672019-07-17 12:30:04 +0000281 if config.StartRBE() {
Kousik Kumar4c180ad2022-05-27 07:48:37 -0400282 cleanupRBELogsDir(ctx, config)
Ramy Medhatbbf25672019-07-17 12:30:04 +0000283 startRBE(ctx, config)
Kousik Kumara1d8fa92022-03-18 02:50:31 -0400284 defer DumpRBEMetrics(ctx, config, filepath.Join(config.LogsDir(), "rbe_metrics.pb"))
Ramy Medhatbbf25672019-07-17 12:30:04 +0000285 }
286
Anton Hansson5a7861a2021-06-04 10:09:01 +0100287 if what&RunProductConfig != 0 {
Dan Willemsen1e704462016-08-21 15:17:17 -0700288 runMakeProductConfig(ctx, config)
289 }
290
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000291 // Everything below here depends on product config.
292
Colin Cross806fd942019-05-03 13:35:58 -0700293 if inList("installclean", config.Arguments()) ||
294 inList("install-clean", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400295 logArgsOtherThan("installclean", "install-clean")
Rupert Shuttleworth1f304e62020-11-24 14:13:41 +0000296 installClean(ctx, config)
Dan Willemsenf052f782017-05-18 15:29:04 -0700297 ctx.Println("Deleted images and staging directories.")
298 return
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000299 }
300
301 if inList("dataclean", config.Arguments()) ||
Colin Cross806fd942019-05-03 13:35:58 -0700302 inList("data-clean", config.Arguments()) {
Usta Shrestha675564d2022-08-09 18:03:23 -0400303 logArgsOtherThan("dataclean", "data-clean")
Rupert Shuttleworth1f304e62020-11-24 14:13:41 +0000304 dataClean(ctx, config)
Dan Willemsenf052f782017-05-18 15:29:04 -0700305 ctx.Println("Deleted data files.")
306 return
307 }
308
Anton Hansson5a7861a2021-06-04 10:09:01 +0100309 if what&RunSoong != 0 {
Dan Willemsen1e704462016-08-21 15:17:17 -0700310 runSoong(ctx, config)
311 }
312
Anton Hansson5a7861a2021-06-04 10:09:01 +0100313 if what&RunKati != 0 {
Dan Willemsen29971232018-09-26 14:58:30 -0700314 genKatiSuffix(ctx, config)
315 runKatiCleanSpec(ctx, config)
316 runKatiBuild(ctx, config)
Dan Willemsenfb1271a2018-09-26 15:00:42 -0700317 runKatiPackage(ctx, config)
Dan Willemsene0879fc2017-08-04 15:06:27 -0700318
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000319 ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0666) // a+rw
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100320 } else if what&RunKatiNinja != 0 {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700321 // Load last Kati Suffix if it exists
322 if katiSuffix, err := ioutil.ReadFile(config.LastKatiSuffixFile()); err == nil {
323 ctx.Verboseln("Loaded previous kati config:", string(katiSuffix))
324 config.SetKatiSuffix(string(katiSuffix))
325 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700326 }
327
Colin Cross37193492017-11-16 17:55:00 -0800328 // Write combined ninja file
329 createCombinedBuildNinjaFile(ctx, config)
330
Colin Cross8ba7d472020-06-25 11:27:52 -0700331 distGzipFile(ctx, config, config.CombinedNinjaFile())
332
Colin Cross37193492017-11-16 17:55:00 -0800333 if what&RunBuildTests != 0 {
334 testForDanglingRules(ctx, config)
335 }
336
Anton Hansson5a7861a2021-06-04 10:09:01 +0100337 if what&RunNinja != 0 {
338 if what&RunKati != 0 {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700339 installCleanIfNecessary(ctx, config)
340 }
Dan Willemsen02781d52017-05-12 19:28:13 -0700341
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100342 runNinjaForBuild(ctx, config)
Dan Willemsen1e704462016-08-21 15:17:17 -0700343 }
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000344
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000345 // Currently, using Bazel requires Kati and Soong to run first, so check whether to run Bazel last.
Anton Hansson5a7861a2021-06-04 10:09:01 +0100346 if what&RunBazel != 0 {
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000347 runBazel(ctx, config)
348 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700349}
Colin Cross8ba7d472020-06-25 11:27:52 -0700350
Dan Willemsen80d72612022-04-20 21:45:00 -0700351var distWaitGroup sync.WaitGroup
352
353// waitForDist waits for all backgrounded distGzipFile and distFile writes to finish
354func waitForDist(ctx Context) {
355 ctx.BeginTrace("soong_ui", "dist")
356 defer ctx.EndTrace()
357
358 distWaitGroup.Wait()
359}
360
Colin Cross8ba7d472020-06-25 11:27:52 -0700361// distGzipFile writes a compressed copy of src to the distDir if dist is enabled. Failures
Dan Willemsen80d72612022-04-20 21:45:00 -0700362// are printed but non-fatal. Uses the distWaitGroup func for backgrounding (optimization).
Colin Cross8ba7d472020-06-25 11:27:52 -0700363func distGzipFile(ctx Context, config Config, src string, subDirs ...string) {
364 if !config.Dist() {
365 return
366 }
367
368 subDir := filepath.Join(subDirs...)
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000369 destDir := filepath.Join(config.RealDistDir(), "soong_ui", subDir)
Colin Cross8ba7d472020-06-25 11:27:52 -0700370
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000371 if err := os.MkdirAll(destDir, 0777); err != nil { // a+rwx
Colin Cross8ba7d472020-06-25 11:27:52 -0700372 ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
Colin Cross8ba7d472020-06-25 11:27:52 -0700373 }
374
Dan Willemsen80d72612022-04-20 21:45:00 -0700375 distWaitGroup.Add(1)
376 go func() {
377 defer distWaitGroup.Done()
378 if err := gzipFileToDir(src, destDir); err != nil {
379 ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
380 }
381 }()
Colin Cross8ba7d472020-06-25 11:27:52 -0700382}
383
384// distFile writes a copy of src to the distDir if dist is enabled. Failures are printed but
Dan Willemsen80d72612022-04-20 21:45:00 -0700385// non-fatal. Uses the distWaitGroup func for backgrounding (optimization).
Colin Cross8ba7d472020-06-25 11:27:52 -0700386func distFile(ctx Context, config Config, src string, subDirs ...string) {
387 if !config.Dist() {
388 return
389 }
390
391 subDir := filepath.Join(subDirs...)
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000392 destDir := filepath.Join(config.RealDistDir(), "soong_ui", subDir)
Colin Cross8ba7d472020-06-25 11:27:52 -0700393
Rupert Shuttlewortheeb5caa2020-11-25 07:13:54 +0000394 if err := os.MkdirAll(destDir, 0777); err != nil { // a+rwx
Colin Cross8ba7d472020-06-25 11:27:52 -0700395 ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
Colin Cross8ba7d472020-06-25 11:27:52 -0700396 }
397
Dan Willemsen80d72612022-04-20 21:45:00 -0700398 distWaitGroup.Add(1)
399 go func() {
400 defer distWaitGroup.Done()
401 if _, err := copyFile(src, filepath.Join(destDir, filepath.Base(src))); err != nil {
402 ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
403 }
404 }()
Colin Cross8ba7d472020-06-25 11:27:52 -0700405}