| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 1 | // 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 |  | 
 | 15 | package build | 
 | 16 |  | 
 | 17 | import ( | 
| Cole Faust | 583dfb4 | 2023-09-28 13:56:30 -0700 | [diff] [blame] | 18 | 	"android/soong/ui/metrics" | 
 | 19 | 	"android/soong/ui/status" | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 20 | 	"crypto/md5" | 
 | 21 | 	"fmt" | 
 | 22 | 	"io/ioutil" | 
| Dan Willemsen | 71edc8b | 2019-01-02 12:21:18 -0800 | [diff] [blame] | 23 | 	"os" | 
 | 24 | 	"os/user" | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 25 | 	"path/filepath" | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 26 | 	"strings" | 
 | 27 | ) | 
 | 28 |  | 
 | 29 | var spaceSlashReplacer = strings.NewReplacer("/", "_", " ", "_") | 
 | 30 |  | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 31 | const katiBuildSuffix = "" | 
 | 32 | const katiCleanspecSuffix = "-cleanspec" | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 33 | const katiPackageSuffix = "-package" | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 34 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 35 | // genKatiSuffix creates a filename suffix for kati-generated files so that we | 
 | 36 | // can cache them based on their inputs. Such files include the generated Ninja | 
 | 37 | // files and env.sh environment variable setup files. | 
 | 38 | // | 
 | 39 | // The filename suffix should encode all common changes to Kati inputs. | 
 | 40 | // Currently that includes the TARGET_PRODUCT and kati-processed command line | 
 | 41 | // arguments. | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 42 | func genKatiSuffix(ctx Context, config Config) { | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 43 | 	// Construct the base suffix. | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 44 | 	katiSuffix := "-" + config.TargetProduct() | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 45 |  | 
 | 46 | 	// Append kati arguments to the suffix. | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 47 | 	if args := config.KatiArgs(); len(args) > 0 { | 
 | 48 | 		katiSuffix += "-" + spaceSlashReplacer.Replace(strings.Join(args, "_")) | 
 | 49 | 	} | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 50 |  | 
 | 51 | 	// If the suffix is too long, replace it with a md5 hash and write a | 
 | 52 | 	// file that contains the original suffix. | 
 | 53 | 	if len(katiSuffix) > 64 { | 
 | 54 | 		shortSuffix := "-" + fmt.Sprintf("%x", md5.Sum([]byte(katiSuffix))) | 
 | 55 | 		config.SetKatiSuffix(shortSuffix) | 
 | 56 |  | 
 | 57 | 		ctx.Verbosef("Kati ninja suffix too long: %q", katiSuffix) | 
 | 58 | 		ctx.Verbosef("Replacing with: %q", shortSuffix) | 
 | 59 |  | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 60 | 		if err := ioutil.WriteFile(strings.TrimSuffix(config.KatiBuildNinjaFile(), "ninja")+"suf", []byte(katiSuffix), 0777); err != nil { | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 61 | 			ctx.Println("Error writing suffix file:", err) | 
 | 62 | 		} | 
 | 63 | 	} else { | 
 | 64 | 		config.SetKatiSuffix(katiSuffix) | 
 | 65 | 	} | 
 | 66 | } | 
 | 67 |  | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 68 | func writeValueIfChanged(ctx Context, config Config, dir string, filename string, value string) { | 
 | 69 | 	filePath := filepath.Join(dir, filename) | 
 | 70 | 	previousValue := "" | 
 | 71 | 	rawPreviousValue, err := ioutil.ReadFile(filePath) | 
 | 72 | 	if err == nil { | 
 | 73 | 		previousValue = string(rawPreviousValue) | 
 | 74 | 	} | 
 | 75 |  | 
 | 76 | 	if previousValue != value { | 
 | 77 | 		if err = ioutil.WriteFile(filePath, []byte(value), 0666); err != nil { | 
 | 78 | 			ctx.Fatalf("Failed to write: %v", err) | 
 | 79 | 		} | 
 | 80 | 	} | 
 | 81 | } | 
 | 82 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 83 | // Base function to construct and run the Kati command line with additional | 
 | 84 | // arguments, and a custom function closure to mutate the environment Kati runs | 
 | 85 | // in. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 86 | func runKati(ctx Context, config Config, extraSuffix string, args []string, envFunc func(*Environment)) { | 
| Dan Willemsen | f173d59 | 2017-04-27 14:28:00 -0700 | [diff] [blame] | 87 | 	executable := config.PrebuiltBuildTool("ckati") | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 88 | 	// cKati arguments. | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 89 | 	args = append([]string{ | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 90 | 		// Instead of executing commands directly, generate a Ninja file. | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 91 | 		"--ninja", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 92 | 		// Generate Ninja files in the output directory. | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 93 | 		"--ninja_dir=" + config.OutDir(), | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 94 | 		// Filename suffix of the generated Ninja file. | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 95 | 		"--ninja_suffix=" + config.KatiSuffix() + extraSuffix, | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 96 | 		// Remove common parts at the beginning of a Ninja file, like build_dir, | 
 | 97 | 		// local_pool and _kati_always_build_. Allows Kati to be run multiple | 
 | 98 | 		// times, with generated Ninja files combined in a single invocation | 
 | 99 | 		// using 'include'. | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 100 | 		"--no_ninja_prelude", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 101 | 		// Support declaring phony outputs in AOSP Ninja. | 
| Dan Willemsen | 6587bed | 2020-04-18 20:25:59 -0700 | [diff] [blame] | 102 | 		"--use_ninja_phony_output", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 103 | 		// Support declaring symlink outputs in AOSP Ninja. | 
| Jingwen Chen | ce679d2 | 2020-09-23 04:30:02 +0000 | [diff] [blame] | 104 | 		"--use_ninja_symlink_outputs", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 105 | 		// Regenerate the Ninja file if environment inputs have changed. e.g. | 
 | 106 | 		// CLI flags, .mk file timestamps, env vars, $(wildcard ..) and some | 
 | 107 | 		// $(shell ..) results. | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 108 | 		"--regen", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 109 | 		// Skip '-include' directives starting with the specified path. Used to | 
 | 110 | 		// ignore generated .mk files. | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 111 | 		"--ignore_optional_include=" + filepath.Join(config.OutDir(), "%.P"), | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 112 | 		// Detect the use of $(shell echo ...). | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 113 | 		"--detect_android_echo", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 114 | 		// Colorful ANSI-based warning and error messages. | 
| Dan Willemsen | c38d366 | 2017-02-24 10:53:23 -0800 | [diff] [blame] | 115 | 		"--color_warnings", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 116 | 		// Generate all targets, not just the top level requested ones. | 
| Dan Willemsen | c38d366 | 2017-02-24 10:53:23 -0800 | [diff] [blame] | 117 | 		"--gen_all_targets", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 118 | 		// Use the built-in emulator of GNU find for better file finding | 
 | 119 | 		// performance. Used with $(shell find ...). | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 120 | 		"--use_find_emulator", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 121 | 		// Fail when the find emulator encounters problems. | 
| Dan Willemsen | 418420e | 2017-05-30 14:07:45 -0700 | [diff] [blame] | 122 | 		"--werror_find_emulator", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 123 | 		// Do not provide any built-in rules. | 
| Dan Willemsen | d368d6f | 2018-06-15 21:53:18 -0700 | [diff] [blame] | 124 | 		"--no_builtin_rules", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 125 | 		// Fail when suffix rules are used. | 
| Dan Willemsen | d368d6f | 2018-06-15 21:53:18 -0700 | [diff] [blame] | 126 | 		"--werror_suffix_rules", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 127 | 		// Fail when a real target depends on a phony target. | 
| Dan Willemsen | 6097746 | 2019-04-18 09:40:15 -0700 | [diff] [blame] | 128 | 		"--werror_real_to_phony", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 129 | 		// Makes real_to_phony checks assume that any top-level or leaf | 
 | 130 | 		// dependencies that does *not* have a '/' in it is a phony target. | 
| Dan Willemsen | cc62890 | 2019-01-24 15:53:06 -0800 | [diff] [blame] | 131 | 		"--top_level_phony", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 132 | 		// Fail when a phony target contains slashes. | 
 | 133 | 		"--werror_phony_looks_real", | 
 | 134 | 		// Fail when writing to a read-only directory. | 
 | 135 | 		"--werror_writable", | 
 | 136 | 		// Print Kati's internal statistics, such as the number of variables, | 
 | 137 | 		// implicit/explicit/suffix rules, and so on. | 
| Dan Willemsen | 75d2c17 | 2017-10-12 20:46:34 -0700 | [diff] [blame] | 138 | 		"--kati_stats", | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 139 | 	}, args...) | 
 | 140 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 141 | 	// Generate a minimal Ninja file. | 
 | 142 | 	// | 
 | 143 | 	// Used for build_test and multiproduct_kati, which runs Kati several | 
 | 144 | 	// hundred times for different configurations to test file generation logic. | 
 | 145 | 	// These can result in generating Ninja files reaching ~1GB or more, | 
 | 146 | 	// resulting in ~hundreds of GBs of writes. | 
 | 147 | 	// | 
 | 148 | 	// Since we don't care about executing the Ninja files in these test cases, | 
 | 149 | 	// generating the Ninja file content wastes time, so skip writing any | 
 | 150 | 	// information out with --empty_ninja_file. | 
 | 151 | 	// | 
 | 152 | 	// From https://github.com/google/kati/commit/87b8da7af2c8bea28b1d8ab17679453d859f96e5 | 
| Colin Cross | f3bdbcb | 2021-06-01 11:43:55 -0700 | [diff] [blame] | 153 | 	if config.EmptyNinjaFile() { | 
| Dan Willemsen | f99915f | 2018-10-25 22:04:42 -0700 | [diff] [blame] | 154 | 		args = append(args, "--empty_ninja_file") | 
 | 155 | 	} | 
 | 156 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 157 | 	// Apply 'local_pool' to to all rules that don't specify a pool. | 
| Colin Cross | 9016b91 | 2019-11-11 14:57:42 -0800 | [diff] [blame] | 158 | 	if config.UseRemoteBuild() { | 
 | 159 | 		args = append(args, "--default_pool=local_pool") | 
 | 160 | 	} | 
 | 161 |  | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 162 | 	cmd := Command(ctx, config, "ckati", executable, args...) | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 163 |  | 
 | 164 | 	// Set up the nsjail sandbox. | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 165 | 	cmd.Sandbox = katiSandbox | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 166 |  | 
 | 167 | 	// Set up stdout and stderr. | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 168 | 	pipe, err := cmd.StdoutPipe() | 
 | 169 | 	if err != nil { | 
 | 170 | 		ctx.Fatalln("Error getting output pipe for ckati:", err) | 
 | 171 | 	} | 
 | 172 | 	cmd.Stderr = cmd.Stdout | 
 | 173 |  | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 174 | 	var username string | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 175 | 	// Pass on various build environment metadata to Kati. | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 176 | 	if usernameFromEnv, ok := cmd.Environment.Get("BUILD_USERNAME"); !ok { | 
 | 177 | 		username = "unknown" | 
| Dan Willemsen | a17ac96 | 2020-03-10 15:38:57 -0700 | [diff] [blame] | 178 | 		if u, err := user.Current(); err == nil { | 
 | 179 | 			username = u.Username | 
 | 180 | 		} else { | 
 | 181 | 			ctx.Println("Failed to get current user:", err) | 
| Dan Willemsen | 71edc8b | 2019-01-02 12:21:18 -0800 | [diff] [blame] | 182 | 		} | 
| Dan Willemsen | a17ac96 | 2020-03-10 15:38:57 -0700 | [diff] [blame] | 183 | 		cmd.Environment.Set("BUILD_USERNAME", username) | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 184 | 	} else { | 
 | 185 | 		username = usernameFromEnv | 
| Dan Willemsen | 71edc8b | 2019-01-02 12:21:18 -0800 | [diff] [blame] | 186 | 	} | 
 | 187 |  | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 188 | 	hostname, ok := cmd.Environment.Get("BUILD_HOSTNAME") | 
| Jeongik Cha | f2af38d | 2023-05-23 06:59:39 +0900 | [diff] [blame] | 189 | 	// Unset BUILD_HOSTNAME during kati run to avoid kati rerun, kati will use BUILD_HOSTNAME from a file. | 
 | 190 | 	cmd.Environment.Unset("BUILD_HOSTNAME") | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 191 | 	if !ok { | 
 | 192 | 		hostname, err = os.Hostname() | 
| Dan Willemsen | 71edc8b | 2019-01-02 12:21:18 -0800 | [diff] [blame] | 193 | 		if err != nil { | 
| Dan Willemsen | a17ac96 | 2020-03-10 15:38:57 -0700 | [diff] [blame] | 194 | 			ctx.Println("Failed to read hostname:", err) | 
 | 195 | 			hostname = "unknown" | 
| Dan Willemsen | 71edc8b | 2019-01-02 12:21:18 -0800 | [diff] [blame] | 196 | 		} | 
| Dan Willemsen | 71edc8b | 2019-01-02 12:21:18 -0800 | [diff] [blame] | 197 | 	} | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 198 | 	writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_hostname.txt", hostname) | 
| Cole Faust | 583dfb4 | 2023-09-28 13:56:30 -0700 | [diff] [blame] | 199 | 	_, ok = cmd.Environment.Get("BUILD_NUMBER") | 
| Jeongik Cha | f2af38d | 2023-05-23 06:59:39 +0900 | [diff] [blame] | 200 | 	// Unset BUILD_NUMBER during kati run to avoid kati rerun, kati will use BUILD_NUMBER from a file. | 
 | 201 | 	cmd.Environment.Unset("BUILD_NUMBER") | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 202 | 	if ok { | 
 | 203 | 		cmd.Environment.Set("HAS_BUILD_NUMBER", "true") | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 204 | 	} else { | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 205 | 		cmd.Environment.Set("HAS_BUILD_NUMBER", "false") | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 206 | 	} | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 207 |  | 
 | 208 | 	// Apply the caller's function closure to mutate the environment variables. | 
 | 209 | 	envFunc(cmd.Environment) | 
| Dan Willemsen | 71edc8b | 2019-01-02 12:21:18 -0800 | [diff] [blame] | 210 |  | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 211 | 	cmd.StartOrFatal() | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 212 | 	// Set up the ToolStatus command line reader for Kati for a consistent UI | 
 | 213 | 	// for the user. | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 214 | 	status.KatiReader(ctx.Status.StartTool(), pipe) | 
 | 215 | 	cmd.WaitOrFatal() | 
 | 216 | } | 
 | 217 |  | 
 | 218 | func runKatiBuild(ctx Context, config Config) { | 
| Nan Zhang | 17f2767 | 2018-12-12 16:01:49 -0800 | [diff] [blame] | 219 | 	ctx.BeginTrace(metrics.RunKati, "kati build") | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 220 | 	defer ctx.EndTrace() | 
 | 221 |  | 
 | 222 | 	args := []string{ | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 223 | 		// Mark the output directory as writable. | 
| Dan Willemsen | 25a5618 | 2018-08-31 20:25:32 -0700 | [diff] [blame] | 224 | 		"--writable", config.OutDir() + "/", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 225 | 		// Fail when encountering implicit rules. e.g. | 
 | 226 | 		// %.foo: %.bar | 
 | 227 | 		//   cp $< $@ | 
| Dan Willemsen | 9f43597 | 2020-05-28 15:28:00 -0700 | [diff] [blame] | 228 | 		"--werror_implicit_rules", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 229 | 		// Entry point for the Kati Ninja file generation. | 
| Dan Willemsen | b2e6c2e | 2017-07-13 17:24:44 -0700 | [diff] [blame] | 230 | 		"-f", "build/make/core/main.mk", | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 231 | 	} | 
 | 232 |  | 
| Dan Willemsen | 3d60b11 | 2018-04-04 22:25:56 -0700 | [diff] [blame] | 233 | 	if !config.BuildBrokenDupRules() { | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 234 | 		// Fail when redefining / duplicating a target. | 
| Dan Willemsen | 3d60b11 | 2018-04-04 22:25:56 -0700 | [diff] [blame] | 235 | 		args = append(args, "--werror_overriding_commands") | 
 | 236 | 	} | 
 | 237 |  | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 238 | 	args = append(args, config.KatiArgs()...) | 
 | 239 |  | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 240 | 	args = append(args, | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 241 | 		// Location of the Make vars .mk file generated by Soong. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 242 | 		"SOONG_MAKEVARS_MK="+config.SoongMakeVarsMk(), | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 243 | 		// Location of the Android.mk file generated by Soong. This | 
 | 244 | 		// file contains Soong modules represented as Kati modules, | 
 | 245 | 		// allowing Kati modules to depend on Soong modules. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 246 | 		"SOONG_ANDROID_MK="+config.SoongAndroidMk(), | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 247 | 		// Directory containing outputs for the target device. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 248 | 		"TARGET_DEVICE_DIR="+config.TargetDeviceDir(), | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 249 | 		// Directory containing .mk files for packaging purposes, such as | 
 | 250 | 		// the dist.mk file, containing dist-for-goals data. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 251 | 		"KATI_PACKAGE_MK_DIR="+config.KatiPackageMkDir()) | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 252 |  | 
| Dan Willemsen | 2d31a44 | 2018-10-20 21:33:41 -0700 | [diff] [blame] | 253 | 	runKati(ctx, config, katiBuildSuffix, args, func(env *Environment) {}) | 
| Dan Willemsen | 7842826 | 2019-12-13 18:50:24 -0800 | [diff] [blame] | 254 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 255 | 	// compress and dist the main build ninja file. | 
| Colin Cross | 8ba7d47 | 2020-06-25 11:27:52 -0700 | [diff] [blame] | 256 | 	distGzipFile(ctx, config, config.KatiBuildNinjaFile()) | 
 | 257 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 258 | 	// Cleanup steps. | 
| Dan Willemsen | 7842826 | 2019-12-13 18:50:24 -0800 | [diff] [blame] | 259 | 	cleanCopyHeaders(ctx, config) | 
| Colin Cross | 41ad6b6 | 2021-03-09 12:02:15 -0800 | [diff] [blame] | 260 | 	cleanOldInstalledFiles(ctx, config) | 
| Dan Willemsen | 7842826 | 2019-12-13 18:50:24 -0800 | [diff] [blame] | 261 | } | 
 | 262 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 263 | // Clean out obsolete header files on the disk that were *not copied* during the | 
 | 264 | // build with BUILD_COPY_HEADERS and LOCAL_COPY_HEADERS. | 
 | 265 | // | 
 | 266 | // These should be increasingly uncommon, as it's a deprecated feature and there | 
 | 267 | // isn't an equivalent feature in Soong. | 
| Dan Willemsen | 7842826 | 2019-12-13 18:50:24 -0800 | [diff] [blame] | 268 | func cleanCopyHeaders(ctx Context, config Config) { | 
 | 269 | 	ctx.BeginTrace("clean", "clean copy headers") | 
 | 270 | 	defer ctx.EndTrace() | 
 | 271 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 272 | 	// Read and parse the list of copied headers from a file in the product | 
 | 273 | 	// output directory. | 
| Dan Willemsen | 7842826 | 2019-12-13 18:50:24 -0800 | [diff] [blame] | 274 | 	data, err := ioutil.ReadFile(filepath.Join(config.ProductOut(), ".copied_headers_list")) | 
 | 275 | 	if err != nil { | 
 | 276 | 		if os.IsNotExist(err) { | 
 | 277 | 			return | 
 | 278 | 		} | 
 | 279 | 		ctx.Fatalf("Failed to read copied headers list: %v", err) | 
 | 280 | 	} | 
 | 281 |  | 
 | 282 | 	headers := strings.Fields(string(data)) | 
 | 283 | 	if len(headers) < 1 { | 
 | 284 | 		ctx.Fatal("Failed to parse copied headers list: %q", string(data)) | 
 | 285 | 	} | 
 | 286 | 	headerDir := headers[0] | 
 | 287 | 	headers = headers[1:] | 
 | 288 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 289 | 	// Walk the tree and remove any headers that are not in the list of copied | 
 | 290 | 	// headers in the current build. | 
| Dan Willemsen | 7842826 | 2019-12-13 18:50:24 -0800 | [diff] [blame] | 291 | 	filepath.Walk(headerDir, | 
 | 292 | 		func(path string, info os.FileInfo, err error) error { | 
 | 293 | 			if err != nil { | 
 | 294 | 				return nil | 
 | 295 | 			} | 
 | 296 | 			if info.IsDir() { | 
 | 297 | 				return nil | 
 | 298 | 			} | 
 | 299 | 			if !inList(path, headers) { | 
 | 300 | 				ctx.Printf("Removing obsolete header %q", path) | 
 | 301 | 				if err := os.Remove(path); err != nil { | 
 | 302 | 					ctx.Fatalf("Failed to remove obsolete header %q: %v", path, err) | 
 | 303 | 				} | 
 | 304 | 			} | 
 | 305 | 			return nil | 
 | 306 | 		}) | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 307 | } | 
 | 308 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 309 | // Clean out any previously installed files from the disk that are not installed | 
 | 310 | // in the current build. | 
| Dan Willemsen | 1e775d7 | 2020-01-03 13:40:45 -0800 | [diff] [blame] | 311 | func cleanOldInstalledFiles(ctx Context, config Config) { | 
 | 312 | 	ctx.BeginTrace("clean", "clean old installed files") | 
 | 313 | 	defer ctx.EndTrace() | 
 | 314 |  | 
 | 315 | 	// We shouldn't be removing files from one side of the two-step asan builds | 
 | 316 | 	var suffix string | 
 | 317 | 	if v, ok := config.Environment().Get("SANITIZE_TARGET"); ok { | 
 | 318 | 		if sanitize := strings.Fields(v); inList("address", sanitize) { | 
 | 319 | 			suffix = "_asan" | 
 | 320 | 		} | 
 | 321 | 	} | 
 | 322 |  | 
 | 323 | 	cleanOldFiles(ctx, config.ProductOut(), ".installable_files"+suffix) | 
 | 324 |  | 
 | 325 | 	cleanOldFiles(ctx, config.HostOut(), ".installable_test_files") | 
 | 326 | } | 
 | 327 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 328 | // Generate the Ninja file containing the packaging command lines for the dist | 
 | 329 | // dir. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 330 | func runKatiPackage(ctx Context, config Config) { | 
| Nan Zhang | 17f2767 | 2018-12-12 16:01:49 -0800 | [diff] [blame] | 331 | 	ctx.BeginTrace(metrics.RunKati, "kati package") | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 332 | 	defer ctx.EndTrace() | 
 | 333 |  | 
 | 334 | 	args := []string{ | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 335 | 		// Mark the dist dir as writable. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 336 | 		"--writable", config.DistDir() + "/", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 337 | 		// Fail when encountering implicit rules. e.g. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 338 | 		"--werror_implicit_rules", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 339 | 		// Fail when redefining / duplicating a target. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 340 | 		"--werror_overriding_commands", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 341 | 		// Entry point. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 342 | 		"-f", "build/make/packaging/main.mk", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 343 | 		// Directory containing .mk files for packaging purposes, such as | 
 | 344 | 		// the dist.mk file, containing dist-for-goals data. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 345 | 		"KATI_PACKAGE_MK_DIR=" + config.KatiPackageMkDir(), | 
 | 346 | 	} | 
 | 347 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 348 | 	// Run Kati against a restricted set of environment variables. | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 349 | 	runKati(ctx, config, katiPackageSuffix, args, func(env *Environment) { | 
 | 350 | 		env.Allow([]string{ | 
 | 351 | 			// Some generic basics | 
 | 352 | 			"LANG", | 
 | 353 | 			"LC_MESSAGES", | 
 | 354 | 			"PATH", | 
 | 355 | 			"PWD", | 
 | 356 | 			"TMPDIR", | 
 | 357 |  | 
 | 358 | 			// Tool configs | 
| Dan Willemsen | 70c1ff8 | 2019-08-21 14:56:13 -0700 | [diff] [blame] | 359 | 			"ASAN_SYMBOLIZER_PATH", | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 360 | 			"JAVA_HOME", | 
 | 361 | 			"PYTHONDONTWRITEBYTECODE", | 
 | 362 |  | 
 | 363 | 			// Build configuration | 
 | 364 | 			"ANDROID_BUILD_SHELL", | 
 | 365 | 			"DIST_DIR", | 
 | 366 | 			"OUT_DIR", | 
| Jeongik Cha | 4e49bbd | 2023-04-26 21:06:24 +0900 | [diff] [blame] | 367 | 			"FILE_NAME_TAG", | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 368 | 		}...) | 
 | 369 |  | 
 | 370 | 		if config.Dist() { | 
 | 371 | 			env.Set("DIST", "true") | 
| Dan Willemsen | 2d31a44 | 2018-10-20 21:33:41 -0700 | [diff] [blame] | 372 | 			env.Set("DIST_DIR", config.DistDir()) | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 373 | 		} | 
 | 374 | 	}) | 
| Colin Cross | 8ba7d47 | 2020-06-25 11:27:52 -0700 | [diff] [blame] | 375 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 376 | 	// Compress and dist the packaging Ninja file. | 
| Colin Cross | 8ba7d47 | 2020-06-25 11:27:52 -0700 | [diff] [blame] | 377 | 	distGzipFile(ctx, config, config.KatiPackageNinjaFile()) | 
| Dan Willemsen | 1e70446 | 2016-08-21 15:17:17 -0700 | [diff] [blame] | 378 | } | 
| Dan Willemsen | 29f8827 | 2017-02-18 18:12:41 -0800 | [diff] [blame] | 379 |  | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 380 | // Run Kati on the cleanspec files to clean the build. | 
| Dan Willemsen | 59fdf96 | 2017-07-24 22:26:54 -0700 | [diff] [blame] | 381 | func runKatiCleanSpec(ctx Context, config Config) { | 
| Nan Zhang | 17f2767 | 2018-12-12 16:01:49 -0800 | [diff] [blame] | 382 | 	ctx.BeginTrace(metrics.RunKati, "kati cleanspec") | 
| Dan Willemsen | 59fdf96 | 2017-07-24 22:26:54 -0700 | [diff] [blame] | 383 | 	defer ctx.EndTrace() | 
 | 384 |  | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 385 | 	runKati(ctx, config, katiCleanspecSuffix, []string{ | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 386 | 		// Fail when encountering implicit rules. e.g. | 
| Dan Willemsen | 2997123 | 2018-09-26 14:58:30 -0700 | [diff] [blame] | 387 | 		"--werror_implicit_rules", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 388 | 		// Fail when redefining / duplicating a target. | 
| Dan Willemsen | 3d60b11 | 2018-04-04 22:25:56 -0700 | [diff] [blame] | 389 | 		"--werror_overriding_commands", | 
| Jingwen Chen | b1d30d6 | 2020-11-18 02:43:19 -0500 | [diff] [blame] | 390 | 		// Entry point. | 
| Dan Willemsen | 59fdf96 | 2017-07-24 22:26:54 -0700 | [diff] [blame] | 391 | 		"-f", "build/make/core/cleanbuild.mk", | 
| Dan Willemsen | fb1271a | 2018-09-26 15:00:42 -0700 | [diff] [blame] | 392 | 		"SOONG_MAKEVARS_MK=" + config.SoongMakeVarsMk(), | 
 | 393 | 		"TARGET_DEVICE_DIR=" + config.TargetDeviceDir(), | 
| Dan Willemsen | 2d31a44 | 2018-10-20 21:33:41 -0700 | [diff] [blame] | 394 | 	}, func(env *Environment) {}) | 
| Dan Willemsen | 59fdf96 | 2017-07-24 22:26:54 -0700 | [diff] [blame] | 395 | } |