Home | History | Annotate | Download | only in build
      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