blob: 598e342dc39bf0f7b93094f18d7ad9d27b7c573d [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 Willemsen02781d52017-05-12 19:28:13 -070021 "strings"
Dan Willemsen1e704462016-08-21 15:17:17 -070022 "text/template"
23)
24
25// Ensures the out directory exists, and has the proper files to prevent kati
26// from recursing into it.
27func SetupOutDir(ctx Context, config Config) {
28 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "Android.mk"))
29 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "CleanSpec.mk"))
30 ensureEmptyFileExists(ctx, filepath.Join(config.SoongOutDir(), ".soong.in_make"))
31 // The ninja_build file is used by our buildbots to understand that the output
32 // can be parsed as ninja output.
33 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "ninja_build"))
34}
35
36var combinedBuildNinjaTemplate = template.Must(template.New("combined").Parse(`
37builddir = {{.OutDir}}
38include {{.KatiNinjaFile}}
39include {{.SoongNinjaFile}}
40build {{.CombinedNinjaFile}}: phony {{.SoongNinjaFile}}
41`))
42
43func createCombinedBuildNinjaFile(ctx Context, config Config) {
44 file, err := os.Create(config.CombinedNinjaFile())
45 if err != nil {
46 ctx.Fatalln("Failed to create combined ninja file:", err)
47 }
48 defer file.Close()
49
50 if err := combinedBuildNinjaTemplate.Execute(file, config); err != nil {
51 ctx.Fatalln("Failed to write combined ninja file:", err)
52 }
53}
54
55const (
56 BuildNone = iota
57 BuildProductConfig = 1 << iota
58 BuildSoong = 1 << iota
59 BuildKati = 1 << iota
60 BuildNinja = 1 << iota
61 BuildAll = BuildProductConfig | BuildSoong | BuildKati | BuildNinja
62)
63
Dan Willemsendb8457c2017-05-12 16:38:17 -070064func checkCaseSensitivity(ctx Context, config Config) {
65 outDir := config.OutDir()
66 lowerCase := filepath.Join(outDir, "casecheck.txt")
67 upperCase := filepath.Join(outDir, "CaseCheck.txt")
68 lowerData := "a"
69 upperData := "B"
70
71 err := ioutil.WriteFile(lowerCase, []byte(lowerData), 0777)
72 if err != nil {
73 ctx.Fatalln("Failed to check case sensitivity:", err)
74 }
75
76 err = ioutil.WriteFile(upperCase, []byte(upperData), 0777)
77 if err != nil {
78 ctx.Fatalln("Failed to check case sensitivity:", err)
79 }
80
81 res, err := ioutil.ReadFile(lowerCase)
82 if err != nil {
83 ctx.Fatalln("Failed to check case sensitivity:", err)
84 }
85
86 if string(res) != lowerData {
87 ctx.Println("************************************************************")
88 ctx.Println("You are building on a case-insensitive filesystem.")
89 ctx.Println("Please move your source tree to a case-sensitive filesystem.")
90 ctx.Println("************************************************************")
91 ctx.Fatalln("Case-insensitive filesystems not supported")
92 }
93}
94
Dan Willemsen02781d52017-05-12 19:28:13 -070095// Since products and build variants (unfortunately) shared the same
96// PRODUCT_OUT staging directory, things can get out of sync if different
97// build configurations are built in the same tree. This function will
98// notice when the configuration has changed and call installclean to
99// remove the files necessary to keep things consistent.
100func installcleanIfNecessary(ctx Context, config Config) {
101 if inList("installclean", config.Arguments()) {
102 return
103 }
104
105 configFile := config.DevicePreviousProductConfig()
106 prefix := "PREVIOUS_BUILD_CONFIG := "
107 suffix := "\n"
108 currentProduct := prefix + config.TargetProduct() + "-" + config.TargetBuildVariant() + suffix
109
110 writeConfig := func() {
111 err := ioutil.WriteFile(configFile, []byte(currentProduct), 0777)
112 if err != nil {
113 ctx.Fatalln("Failed to write product config:", err)
114 }
115 }
116
117 prev, err := ioutil.ReadFile(configFile)
118 if err != nil {
119 if os.IsNotExist(err) {
120 writeConfig()
121 return
122 } else {
123 ctx.Fatalln("Failed to read previous product config:", err)
124 }
125 } else if string(prev) == currentProduct {
126 return
127 }
128
129 if disable, _ := config.Environment().Get("DISABLE_AUTO_INSTALLCLEAN"); disable == "true" {
130 ctx.Println("DISABLE_AUTO_INSTALLCLEAN is set; skipping auto-clean. Your tree may be in an inconsistent state.")
131 return
132 }
133
134 ctx.BeginTrace("installclean")
135 defer ctx.EndTrace()
136
137 prevConfig := strings.TrimPrefix(strings.TrimSuffix(string(prev), suffix), prefix)
138 currentConfig := strings.TrimPrefix(strings.TrimSuffix(currentProduct, suffix), prefix)
139
140 ctx.Printf("Build configuration changed: %q -> %q, forcing installclean\n", prevConfig, currentConfig)
141
142 cleanConfig := CopyConfig(ctx, config, "installclean")
143 cleanConfig.SetKatiArgs([]string{"installclean"})
144 cleanConfig.SetNinjaArgs([]string{"installclean"})
145
146 Build(ctx, cleanConfig, BuildKati|BuildNinja)
147
148 writeConfig()
149}
150
Dan Willemsen1e704462016-08-21 15:17:17 -0700151// Build the tree. The 'what' argument can be used to chose which components of
152// the build to run.
153func Build(ctx Context, config Config, what int) {
154 ctx.Verboseln("Starting build with args:", config.Arguments())
155 ctx.Verboseln("Environment:", config.Environment().Environ())
156
157 if inList("help", config.Arguments()) {
Dan Willemsen269a8c72017-05-03 17:15:47 -0700158 cmd := Command(ctx, config, "make",
159 "make", "-f", "build/core/help.mk")
160 cmd.Sandbox = makeSandbox
Dan Willemsen1e704462016-08-21 15:17:17 -0700161 cmd.Stdout = ctx.Stdout()
162 cmd.Stderr = ctx.Stderr()
Dan Willemsen269a8c72017-05-03 17:15:47 -0700163 cmd.RunOrFatal()
Dan Willemsen1e704462016-08-21 15:17:17 -0700164 return
Dan Willemsen0b73b4b2017-05-12 19:28:13 -0700165 } else if inList("clean", config.Arguments()) || inList("clobber", config.Arguments()) {
166 // We can't use os.RemoveAll, since we don't want to remove the
167 // output directory itself, in case it's a symlink. So just do
168 // exactly what make used to do.
169 cmd := Command(ctx, config, "rm -rf $OUT_DIR/*",
170 "/bin/bash", "-c", "rm -rf "+config.OutDir()+"/*")
171 cmd.Stdout = ctx.Stdout()
172 cmd.Stderr = ctx.Stderr()
173 cmd.RunOrFatal()
174 ctx.Println("Entire build directory removed.")
175 return
Dan Willemsen1e704462016-08-21 15:17:17 -0700176 }
177
Dan Willemsendb8457c2017-05-12 16:38:17 -0700178 // Start getting java version as early as possible
179 getJavaVersions(ctx, config)
180
Dan Willemsen1e704462016-08-21 15:17:17 -0700181 SetupOutDir(ctx, config)
182
Dan Willemsendb8457c2017-05-12 16:38:17 -0700183 checkCaseSensitivity(ctx, config)
184
Dan Willemsen1e704462016-08-21 15:17:17 -0700185 if what&BuildProductConfig != 0 {
186 // Run make for product config
187 runMakeProductConfig(ctx, config)
188 }
189
190 if what&BuildSoong != 0 {
191 // Run Soong
192 runSoongBootstrap(ctx, config)
193 runSoong(ctx, config)
194 }
195
Dan Willemsendb8457c2017-05-12 16:38:17 -0700196 // Check the java versions we read earlier
197 checkJavaVersion(ctx, config)
198
Dan Willemsen1e704462016-08-21 15:17:17 -0700199 if what&BuildKati != 0 {
200 // Run ckati
201 runKati(ctx, config)
202 }
203
204 if what&BuildNinja != 0 {
Dan Willemsen02781d52017-05-12 19:28:13 -0700205 installcleanIfNecessary(ctx, config)
206
Dan Willemsen1e704462016-08-21 15:17:17 -0700207 // Write combined ninja file
208 createCombinedBuildNinjaFile(ctx, config)
209
210 // Run ninja
211 runNinja(ctx, config)
212 }
213}