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 ( 18 "bytes" 19 "fmt" 20 "strings" 21 ) 22 23 // DumpMakeVars can be used to extract the values of Make variables after the 24 // product configurations are loaded. This is roughly equivalent to the 25 // `get_build_var` bash function. 26 // 27 // goals can be used to set MAKECMDGOALS, which emulates passing arguments to 28 // Make without actually building them. So all the variables based on 29 // MAKECMDGOALS can be read. 30 // 31 // vars is the list of variables to read. The values will be put in the 32 // returned map. 33 func DumpMakeVars(ctx Context, config Config, goals, vars []string) (map[string]string, error) { 34 return dumpMakeVars(ctx, config, goals, vars, false) 35 } 36 37 func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool) (map[string]string, error) { 38 ctx.BeginTrace("dumpvars") 39 defer ctx.EndTrace() 40 41 cmd := Command(ctx, config, "dumpvars", 42 config.PrebuiltBuildTool("ckati"), 43 "-f", "build/make/core/config.mk", 44 "--color_warnings", 45 "--kati_stats", 46 "dump-many-vars", 47 "MAKECMDGOALS="+strings.Join(goals, " ")) 48 cmd.Environment.Set("CALLED_FROM_SETUP", "true") 49 cmd.Environment.Set("BUILD_SYSTEM", "build/make/core") 50 if write_soong_vars { 51 cmd.Environment.Set("WRITE_SOONG_VARIABLES", "true") 52 } 53 cmd.Environment.Set("DUMP_MANY_VARS", strings.Join(vars, " ")) 54 cmd.Sandbox = dumpvarsSandbox 55 output := bytes.Buffer{} 56 cmd.Stdout = &output 57 pipe, err := cmd.StderrPipe() 58 if err != nil { 59 ctx.Fatalln("Error getting output pipe for ckati:", err) 60 } 61 cmd.StartOrFatal() 62 // TODO: error out when Stderr contains any content 63 katiRewriteOutput(ctx, pipe) 64 cmd.WaitOrFatal() 65 66 ret := make(map[string]string, len(vars)) 67 for _, line := range strings.Split(output.String(), "\n") { 68 if len(line) == 0 { 69 continue 70 } 71 72 if key, value, ok := decodeKeyValue(line); ok { 73 if value, ok = singleUnquote(value); ok { 74 ret[key] = value 75 ctx.Verboseln(key, value) 76 } else { 77 return nil, fmt.Errorf("Failed to parse make line: %q", line) 78 } 79 } else { 80 return nil, fmt.Errorf("Failed to parse make line: %q", line) 81 } 82 } 83 84 return ret, nil 85 } 86 87 // Variables to print out in the top banner 88 var BannerVars = []string{ 89 "PLATFORM_VERSION_CODENAME", 90 "PLATFORM_VERSION", 91 "TARGET_PRODUCT", 92 "TARGET_BUILD_VARIANT", 93 "TARGET_BUILD_TYPE", 94 "TARGET_BUILD_APPS", 95 "TARGET_ARCH", 96 "TARGET_ARCH_VARIANT", 97 "TARGET_CPU_VARIANT", 98 "TARGET_2ND_ARCH", 99 "TARGET_2ND_ARCH_VARIANT", 100 "TARGET_2ND_CPU_VARIANT", 101 "HOST_ARCH", 102 "HOST_2ND_ARCH", 103 "HOST_OS", 104 "HOST_OS_EXTRA", 105 "HOST_CROSS_OS", 106 "HOST_CROSS_ARCH", 107 "HOST_CROSS_2ND_ARCH", 108 "HOST_BUILD_TYPE", 109 "BUILD_ID", 110 "OUT_DIR", 111 "AUX_OS_VARIANT_LIST", 112 "TARGET_BUILD_PDK", 113 "PDK_FUSION_PLATFORM_ZIP", 114 "PRODUCT_SOONG_NAMESPACES", 115 } 116 117 func Banner(make_vars map[string]string) string { 118 b := &bytes.Buffer{} 119 120 fmt.Fprintln(b, "============================================") 121 for _, name := range BannerVars { 122 if make_vars[name] != "" { 123 fmt.Fprintf(b, "%s=%s\n", name, make_vars[name]) 124 } 125 } 126 fmt.Fprint(b, "============================================") 127 128 return b.String() 129 } 130 131 func runMakeProductConfig(ctx Context, config Config) { 132 // Variables to export into the environment of Kati/Ninja 133 exportEnvVars := []string{ 134 // So that we can use the correct TARGET_PRODUCT if it's been 135 // modified by PRODUCT-*/APP-* arguments 136 "TARGET_PRODUCT", 137 "TARGET_BUILD_VARIANT", 138 "TARGET_BUILD_APPS", 139 140 // compiler wrappers set up by make 141 "CC_WRAPPER", 142 "CXX_WRAPPER", 143 "JAVAC_WRAPPER", 144 145 // ccache settings 146 "CCACHE_COMPILERCHECK", 147 "CCACHE_SLOPPINESS", 148 "CCACHE_BASEDIR", 149 "CCACHE_CPP2", 150 } 151 152 allVars := append(append([]string{ 153 // Used to execute Kati and Ninja 154 "NINJA_GOALS", 155 "KATI_GOALS", 156 157 // To find target/product/<DEVICE> 158 "TARGET_DEVICE", 159 }, exportEnvVars...), BannerVars...) 160 161 make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true) 162 if err != nil { 163 ctx.Fatalln("Error dumping make vars:", err) 164 } 165 166 // Print the banner like make does 167 fmt.Fprintln(ctx.Stdout(), Banner(make_vars)) 168 169 // Populate the environment 170 env := config.Environment() 171 for _, name := range exportEnvVars { 172 if make_vars[name] == "" { 173 env.Unset(name) 174 } else { 175 env.Set(name, make_vars[name]) 176 } 177 } 178 179 config.SetKatiArgs(strings.Fields(make_vars["KATI_GOALS"])) 180 config.SetNinjaArgs(strings.Fields(make_vars["NINJA_GOALS"])) 181 config.SetTargetDevice(make_vars["TARGET_DEVICE"]) 182 } 183