blob: 9650eaa20bd7173fb050005703bde5914ec7d572 [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"
22)
23
24// Ensures the out directory exists, and has the proper files to prevent kati
25// from recursing into it.
26func SetupOutDir(ctx Context, config Config) {
27 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "Android.mk"))
28 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "CleanSpec.mk"))
Dan Willemsene0879fc2017-08-04 15:06:27 -070029 if !config.SkipMake() {
30 ensureEmptyFileExists(ctx, filepath.Join(config.SoongOutDir(), ".soong.in_make"))
31 }
Dan Willemsen1e704462016-08-21 15:17:17 -070032 // The ninja_build file is used by our buildbots to understand that the output
33 // can be parsed as ninja output.
34 ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "ninja_build"))
35}
36
37var combinedBuildNinjaTemplate = template.Must(template.New("combined").Parse(`
38builddir = {{.OutDir}}
Dan Willemsene0879fc2017-08-04 15:06:27 -070039{{if .HasKatiSuffix}}include {{.KatiNinjaFile}}
40{{end -}}
Dan Willemsen1e704462016-08-21 15:17:17 -070041include {{.SoongNinjaFile}}
42build {{.CombinedNinjaFile}}: phony {{.SoongNinjaFile}}
43`))
44
45func createCombinedBuildNinjaFile(ctx Context, config Config) {
Dan Willemsene0879fc2017-08-04 15:06:27 -070046 // If we're in SkipMake mode, skip creating this file if it already exists
47 if config.SkipMake() {
48 if _, err := os.Stat(config.CombinedNinjaFile()); err == nil || !os.IsNotExist(err) {
49 return
50 }
51 }
52
Dan Willemsen1e704462016-08-21 15:17:17 -070053 file, err := os.Create(config.CombinedNinjaFile())
54 if err != nil {
55 ctx.Fatalln("Failed to create combined ninja file:", err)
56 }
57 defer file.Close()
58
59 if err := combinedBuildNinjaTemplate.Execute(file, config); err != nil {
60 ctx.Fatalln("Failed to write combined ninja file:", err)
61 }
62}
63
64const (
65 BuildNone = iota
66 BuildProductConfig = 1 << iota
67 BuildSoong = 1 << iota
68 BuildKati = 1 << iota
69 BuildNinja = 1 << iota
70 BuildAll = BuildProductConfig | BuildSoong | BuildKati | BuildNinja
71)
72
Dan Willemsendb8457c2017-05-12 16:38:17 -070073func checkCaseSensitivity(ctx Context, config Config) {
74 outDir := config.OutDir()
75 lowerCase := filepath.Join(outDir, "casecheck.txt")
76 upperCase := filepath.Join(outDir, "CaseCheck.txt")
77 lowerData := "a"
78 upperData := "B"
79
80 err := ioutil.WriteFile(lowerCase, []byte(lowerData), 0777)
81 if err != nil {
82 ctx.Fatalln("Failed to check case sensitivity:", err)
83 }
84
85 err = ioutil.WriteFile(upperCase, []byte(upperData), 0777)
86 if err != nil {
87 ctx.Fatalln("Failed to check case sensitivity:", err)
88 }
89
90 res, err := ioutil.ReadFile(lowerCase)
91 if err != nil {
92 ctx.Fatalln("Failed to check case sensitivity:", err)
93 }
94
95 if string(res) != lowerData {
96 ctx.Println("************************************************************")
97 ctx.Println("You are building on a case-insensitive filesystem.")
98 ctx.Println("Please move your source tree to a case-sensitive filesystem.")
99 ctx.Println("************************************************************")
100 ctx.Fatalln("Case-insensitive filesystems not supported")
101 }
102}
103
Dan Willemsenf052f782017-05-18 15:29:04 -0700104func help(ctx Context, config Config, what int) {
Jeff Gastondf4a0812017-05-30 20:11:20 -0700105 cmd := Command(ctx, config, "help.sh", "build/make/help.sh")
Dan Willemsenf052f782017-05-18 15:29:04 -0700106 cmd.Sandbox = makeSandbox
107 cmd.Stdout = ctx.Stdout()
108 cmd.Stderr = ctx.Stderr()
109 cmd.RunOrFatal()
Dan Willemsen02781d52017-05-12 19:28:13 -0700110}
111
Dan Willemsen1e704462016-08-21 15:17:17 -0700112// Build the tree. The 'what' argument can be used to chose which components of
113// the build to run.
114func Build(ctx Context, config Config, what int) {
115 ctx.Verboseln("Starting build with args:", config.Arguments())
116 ctx.Verboseln("Environment:", config.Environment().Environ())
117
Dan Willemsene0879fc2017-08-04 15:06:27 -0700118 if config.SkipMake() {
119 ctx.Verboseln("Skipping Make/Kati as requested")
120 what = what & (BuildSoong | BuildNinja)
121 }
122
Dan Willemsen1e704462016-08-21 15:17:17 -0700123 if inList("help", config.Arguments()) {
Dan Willemsenf052f782017-05-18 15:29:04 -0700124 help(ctx, config, what)
Dan Willemsen1e704462016-08-21 15:17:17 -0700125 return
Dan Willemsen0b73b4b2017-05-12 19:28:13 -0700126 } else if inList("clean", config.Arguments()) || inList("clobber", config.Arguments()) {
Dan Willemsenf052f782017-05-18 15:29:04 -0700127 clean(ctx, config, what)
Dan Willemsen0b73b4b2017-05-12 19:28:13 -0700128 return
Dan Willemsen1e704462016-08-21 15:17:17 -0700129 }
130
Jeff Gaston3615fe82017-05-24 13:14:34 -0700131 // Make sure that no other Soong process is running with the same output directory
132 buildLock := BecomeSingletonOrFail(ctx, config)
133 defer buildLock.Unlock()
134
Dan Willemsen1e704462016-08-21 15:17:17 -0700135 SetupOutDir(ctx, config)
136
Dan Willemsendb8457c2017-05-12 16:38:17 -0700137 checkCaseSensitivity(ctx, config)
138
Jeff Gastonefc1b412017-03-29 17:29:06 -0700139 ensureEmptyDirectoriesExist(ctx, config.TempDir())
140
Dan Willemsen1e704462016-08-21 15:17:17 -0700141 if what&BuildProductConfig != 0 {
142 // Run make for product config
143 runMakeProductConfig(ctx, config)
144 }
145
Dan Willemsenf052f782017-05-18 15:29:04 -0700146 if inList("installclean", config.Arguments()) {
147 installClean(ctx, config, what)
148 ctx.Println("Deleted images and staging directories.")
149 return
150 } else if inList("dataclean", config.Arguments()) {
151 dataClean(ctx, config, what)
152 ctx.Println("Deleted data files.")
153 return
154 }
155
Dan Willemsen1e704462016-08-21 15:17:17 -0700156 if what&BuildSoong != 0 {
157 // Run Soong
158 runSoongBootstrap(ctx, config)
159 runSoong(ctx, config)
160 }
161
Dan Willemsen1e704462016-08-21 15:17:17 -0700162 if what&BuildKati != 0 {
163 // Run ckati
164 runKati(ctx, config)
Dan Willemsene0879fc2017-08-04 15:06:27 -0700165
166 ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0777)
167 } else {
168 // Load last Kati Suffix if it exists
169 if katiSuffix, err := ioutil.ReadFile(config.LastKatiSuffixFile()); err == nil {
170 ctx.Verboseln("Loaded previous kati config:", string(katiSuffix))
171 config.SetKatiSuffix(string(katiSuffix))
172 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700173 }
174
175 if what&BuildNinja != 0 {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700176 if !config.SkipMake() {
177 installCleanIfNecessary(ctx, config)
178 }
Dan Willemsen02781d52017-05-12 19:28:13 -0700179
Dan Willemsen1e704462016-08-21 15:17:17 -0700180 // Write combined ninja file
181 createCombinedBuildNinjaFile(ctx, config)
182
183 // Run ninja
184 runNinja(ctx, config)
185 }
186}