blob: f3feac2bef6bb66e6fbc1708a3d3bb77e4b155a8 [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"
21 "text/template"
Colin Cross74cda722020-01-16 15:25:50 -080022
23 "android/soong/ui/metrics"
Dan Willemsen1e704462016-08-21 15:17:17 -070024)
25
26// Ensures the out directory exists, and has the proper files to prevent kati
27// from recursing into it.
28func SetupOutDir(ctx Context, config Config) {
29 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "Android.mk"))
30 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "CleanSpec.mk"))
Dan Willemsene0879fc2017-08-04 15:06:27 -070031 if !config.SkipMake() {
32 ensureEmptyFileExists(ctx, filepath.Join(config.SoongOutDir(), ".soong.in_make"))
33 }
Dan Willemsen1e704462016-08-21 15:17:17 -070034 // The ninja_build file is used by our buildbots to understand that the output
35 // can be parsed as ninja output.
36 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "ninja_build"))
Jeff Gastonb64fc1c2017-08-04 12:30:12 -070037 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), ".out-dir"))
Colin Cross28f527c2019-11-26 16:19:04 -080038
39 if buildDateTimeFile, ok := config.environ.Get("BUILD_DATETIME_FILE"); ok {
40 err := ioutil.WriteFile(buildDateTimeFile, []byte(config.buildDateTime), 0777)
41 if err != nil {
42 ctx.Fatalln("Failed to write BUILD_DATETIME to file:", err)
43 }
44 } else {
45 ctx.Fatalln("Missing BUILD_DATETIME_FILE")
46 }
Dan Willemsen1e704462016-08-21 15:17:17 -070047}
48
49var combinedBuildNinjaTemplate = template.Must(template.New("combined").Parse(`
50builddir = {{.OutDir}}
Colin Cross8b8bec32019-11-15 13:18:43 -080051{{if .UseRemoteBuild }}pool local_pool
Dan Willemsen29971232018-09-26 14:58:30 -070052 depth = {{.Parallel}}
Colin Cross8b8bec32019-11-15 13:18:43 -080053{{end -}}
54pool highmem_pool
55 depth = {{.HighmemParallel}}
Dan Willemsen29971232018-09-26 14:58:30 -070056build _kati_always_build_: phony
Dan Willemsenfb1271a2018-09-26 15:00:42 -070057{{if .HasKatiSuffix}}subninja {{.KatiBuildNinjaFile}}
58subninja {{.KatiPackageNinjaFile}}
Dan Willemsene0879fc2017-08-04 15:06:27 -070059{{end -}}
Dan Willemsenfb1271a2018-09-26 15:00:42 -070060subninja {{.SoongNinjaFile}}
Dan Willemsen1e704462016-08-21 15:17:17 -070061`))
62
63func createCombinedBuildNinjaFile(ctx Context, config Config) {
Dan Willemsene0879fc2017-08-04 15:06:27 -070064 // If we're in SkipMake mode, skip creating this file if it already exists
65 if config.SkipMake() {
66 if _, err := os.Stat(config.CombinedNinjaFile()); err == nil || !os.IsNotExist(err) {
67 return
68 }
69 }
70
Dan Willemsen1e704462016-08-21 15:17:17 -070071 file, err := os.Create(config.CombinedNinjaFile())
72 if err != nil {
73 ctx.Fatalln("Failed to create combined ninja file:", err)
74 }
75 defer file.Close()
76
77 if err := combinedBuildNinjaTemplate.Execute(file, config); err != nil {
78 ctx.Fatalln("Failed to write combined ninja file:", err)
79 }
80}
81
82const (
83 BuildNone = iota
84 BuildProductConfig = 1 << iota
85 BuildSoong = 1 << iota
86 BuildKati = 1 << iota
87 BuildNinja = 1 << iota
Colin Cross37193492017-11-16 17:55:00 -080088 RunBuildTests = 1 << iota
Dan Willemsen1e704462016-08-21 15:17:17 -070089 BuildAll = BuildProductConfig | BuildSoong | BuildKati | BuildNinja
90)
91
Anton Hanssonecf0f102018-09-19 22:14:17 +010092func checkProblematicFiles(ctx Context) {
93 files := []string{"Android.mk", "CleanSpec.mk"}
94 for _, file := range files {
95 if _, err := os.Stat(file); !os.IsNotExist(err) {
96 absolute := absPath(ctx, file)
97 ctx.Printf("Found %s in tree root. This file needs to be removed to build.\n", file)
98 ctx.Fatalf(" rm %s\n", absolute)
99 }
100 }
101}
102
Dan Willemsendb8457c2017-05-12 16:38:17 -0700103func checkCaseSensitivity(ctx Context, config Config) {
104 outDir := config.OutDir()
105 lowerCase := filepath.Join(outDir, "casecheck.txt")
106 upperCase := filepath.Join(outDir, "CaseCheck.txt")
107 lowerData := "a"
108 upperData := "B"
109
110 err := ioutil.WriteFile(lowerCase, []byte(lowerData), 0777)
111 if err != nil {
112 ctx.Fatalln("Failed to check case sensitivity:", err)
113 }
114
115 err = ioutil.WriteFile(upperCase, []byte(upperData), 0777)
116 if err != nil {
117 ctx.Fatalln("Failed to check case sensitivity:", err)
118 }
119
120 res, err := ioutil.ReadFile(lowerCase)
121 if err != nil {
122 ctx.Fatalln("Failed to check case sensitivity:", err)
123 }
124
125 if string(res) != lowerData {
126 ctx.Println("************************************************************")
127 ctx.Println("You are building on a case-insensitive filesystem.")
128 ctx.Println("Please move your source tree to a case-sensitive filesystem.")
129 ctx.Println("************************************************************")
130 ctx.Fatalln("Case-insensitive filesystems not supported")
131 }
132}
133
Dan Willemsenf052f782017-05-18 15:29:04 -0700134func help(ctx Context, config Config, what int) {
Jeff Gastondf4a0812017-05-30 20:11:20 -0700135 cmd := Command(ctx, config, "help.sh", "build/make/help.sh")
Dan Willemsenb2e6c2e2017-07-13 17:24:44 -0700136 cmd.Sandbox = dumpvarsSandbox
Dan Willemsenb82471a2018-05-17 16:37:09 -0700137 cmd.RunAndPrintOrFatal()
Dan Willemsen02781d52017-05-12 19:28:13 -0700138}
139
Dan Willemsen1e704462016-08-21 15:17:17 -0700140// Build the tree. The 'what' argument can be used to chose which components of
141// the build to run.
142func Build(ctx Context, config Config, what int) {
143 ctx.Verboseln("Starting build with args:", config.Arguments())
144 ctx.Verboseln("Environment:", config.Environment().Environ())
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800145 ctx.Verbosef("Total RAM: %dGB", config.TotalRAM()/1024/1024/1024)
Dan Willemsen1e704462016-08-21 15:17:17 -0700146
Colin Cross74cda722020-01-16 15:25:50 -0800147 ctx.BeginTrace(metrics.Total, "total")
148 defer ctx.EndTrace()
149
Dan Willemsene0879fc2017-08-04 15:06:27 -0700150 if config.SkipMake() {
151 ctx.Verboseln("Skipping Make/Kati as requested")
152 what = what & (BuildSoong | BuildNinja)
153 }
154
Dan Willemsen1e704462016-08-21 15:17:17 -0700155 if inList("help", config.Arguments()) {
Dan Willemsenf052f782017-05-18 15:29:04 -0700156 help(ctx, config, what)
Dan Willemsen1e704462016-08-21 15:17:17 -0700157 return
Dan Willemsen0b73b4b2017-05-12 19:28:13 -0700158 } else if inList("clean", config.Arguments()) || inList("clobber", config.Arguments()) {
Dan Willemsenf052f782017-05-18 15:29:04 -0700159 clean(ctx, config, what)
Dan Willemsen0b73b4b2017-05-12 19:28:13 -0700160 return
Dan Willemsen1e704462016-08-21 15:17:17 -0700161 }
162
Jeff Gaston3615fe82017-05-24 13:14:34 -0700163 // Make sure that no other Soong process is running with the same output directory
164 buildLock := BecomeSingletonOrFail(ctx, config)
165 defer buildLock.Unlock()
166
Anton Hanssonecf0f102018-09-19 22:14:17 +0100167 checkProblematicFiles(ctx)
168
Dan Willemsen1e704462016-08-21 15:17:17 -0700169 SetupOutDir(ctx, config)
170
Dan Willemsendb8457c2017-05-12 16:38:17 -0700171 checkCaseSensitivity(ctx, config)
172
Jeff Gastonefc1b412017-03-29 17:29:06 -0700173 ensureEmptyDirectoriesExist(ctx, config.TempDir())
174
Dan Willemsen18490112018-05-25 16:30:04 -0700175 SetupPath(ctx, config)
176
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +0900177 if config.StartGoma() {
178 // Ensure start Goma compiler_proxy
179 startGoma(ctx, config)
180 }
181
Ramy Medhatbbf25672019-07-17 12:30:04 +0000182 if config.StartRBE() {
183 // Ensure RBE proxy is started
184 startRBE(ctx, config)
185 }
186
Dan Willemsen1e704462016-08-21 15:17:17 -0700187 if what&BuildProductConfig != 0 {
188 // Run make for product config
189 runMakeProductConfig(ctx, config)
190 }
191
Colin Cross806fd942019-05-03 13:35:58 -0700192 if inList("installclean", config.Arguments()) ||
193 inList("install-clean", config.Arguments()) {
Dan Willemsenf052f782017-05-18 15:29:04 -0700194 installClean(ctx, config, what)
195 ctx.Println("Deleted images and staging directories.")
196 return
Colin Cross806fd942019-05-03 13:35:58 -0700197 } else if inList("dataclean", config.Arguments()) ||
198 inList("data-clean", config.Arguments()) {
Dan Willemsenf052f782017-05-18 15:29:04 -0700199 dataClean(ctx, config, what)
200 ctx.Println("Deleted data files.")
201 return
202 }
203
Dan Willemsen1e704462016-08-21 15:17:17 -0700204 if what&BuildSoong != 0 {
205 // Run Soong
Dan Willemsen1e704462016-08-21 15:17:17 -0700206 runSoong(ctx, config)
207 }
208
Dan Willemsen1e704462016-08-21 15:17:17 -0700209 if what&BuildKati != 0 {
210 // Run ckati
Dan Willemsen29971232018-09-26 14:58:30 -0700211 genKatiSuffix(ctx, config)
212 runKatiCleanSpec(ctx, config)
213 runKatiBuild(ctx, config)
Dan Willemsenfb1271a2018-09-26 15:00:42 -0700214 runKatiPackage(ctx, config)
Dan Willemsene0879fc2017-08-04 15:06:27 -0700215
216 ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0777)
217 } else {
218 // Load last Kati Suffix if it exists
219 if katiSuffix, err := ioutil.ReadFile(config.LastKatiSuffixFile()); err == nil {
220 ctx.Verboseln("Loaded previous kati config:", string(katiSuffix))
221 config.SetKatiSuffix(string(katiSuffix))
222 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700223 }
224
Colin Cross37193492017-11-16 17:55:00 -0800225 // Write combined ninja file
226 createCombinedBuildNinjaFile(ctx, config)
227
228 if what&RunBuildTests != 0 {
229 testForDanglingRules(ctx, config)
230 }
231
Dan Willemsen1e704462016-08-21 15:17:17 -0700232 if what&BuildNinja != 0 {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700233 if !config.SkipMake() {
234 installCleanIfNecessary(ctx, config)
235 }
Dan Willemsen02781d52017-05-12 19:28:13 -0700236
Dan Willemsen1e704462016-08-21 15:17:17 -0700237 // Run ninja
238 runNinja(ctx, config)
239 }
240}