blob: 89e03f7468ee640c216662ca6c49c9c047eacbe6 [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 (
18 "fmt"
19 "os/exec"
20 "path/filepath"
21 "strings"
22)
23
24// DumpMakeVars can be used to extract the values of Make variables after the
25// product configurations are loaded. This is roughly equivalent to the
26// `get_build_var` bash function.
27//
28// goals can be used to set MAKECMDGOALS, which emulates passing arguments to
29// Make without actually building them. So all the variables based on
30// MAKECMDGOALS can be read.
31//
32// extra_targets adds real arguments to the make command, in case other targets
33// actually need to be run (like the Soong config generator).
34//
35// vars is the list of variables to read. The values will be put in the
36// returned map.
37func DumpMakeVars(ctx Context, config Config, goals, extra_targets, vars []string) (map[string]string, error) {
Dan Willemsend9f6fa22016-08-21 15:17:17 -070038 ctx.BeginTrace("dumpvars")
39 defer ctx.EndTrace()
40
Dan Willemsen1e704462016-08-21 15:17:17 -070041 cmd := exec.CommandContext(ctx.Context,
42 "make",
43 "--no-print-directory",
44 "-f", "build/core/config.mk",
45 "dump-many-vars",
46 "CALLED_FROM_SETUP=true",
47 "BUILD_SYSTEM=build/core",
48 "MAKECMDGOALS="+strings.Join(goals, " "),
49 "DUMP_MANY_VARS="+strings.Join(vars, " "),
50 "OUT_DIR="+config.OutDir())
51 cmd.Env = config.Environment().Environ()
52 cmd.Args = append(cmd.Args, extra_targets...)
53 // TODO: error out when Stderr contains any content
54 cmd.Stderr = ctx.Stderr()
55 ctx.Verboseln(cmd.Path, cmd.Args)
56 output, err := cmd.Output()
57 if err != nil {
58 return nil, err
59 }
60
61 ret := make(map[string]string, len(vars))
62 for _, line := range strings.Split(string(output), "\n") {
63 if len(line) == 0 {
64 continue
65 }
66
67 if key, value, ok := decodeKeyValue(line); ok {
68 if value, ok = singleUnquote(value); ok {
69 ret[key] = value
70 ctx.Verboseln(key, value)
71 } else {
72 return nil, fmt.Errorf("Failed to parse make line: %q", line)
73 }
74 } else {
75 return nil, fmt.Errorf("Failed to parse make line: %q", line)
76 }
77 }
78
79 return ret, nil
80}
81
82func runMakeProductConfig(ctx Context, config Config) {
83 // Variables to export into the environment of Kati/Ninja
84 exportEnvVars := []string{
85 // So that we can use the correct TARGET_PRODUCT if it's been
86 // modified by PRODUCT-* arguments
87 "TARGET_PRODUCT",
88
89 // compiler wrappers set up by make
90 "CC_WRAPPER",
91 "CXX_WRAPPER",
92
93 // ccache settings
94 "CCACHE_COMPILERCHECK",
95 "CCACHE_SLOPPINESS",
96 "CCACHE_BASEDIR",
97 "CCACHE_CPP2",
98 }
99
100 // Variables to print out in the top banner
101 bannerVars := []string{
102 "PLATFORM_VERSION_CODENAME",
103 "PLATFORM_VERSION",
104 "TARGET_PRODUCT",
105 "TARGET_BUILD_VARIANT",
106 "TARGET_BUILD_TYPE",
107 "TARGET_BUILD_APPS",
108 "TARGET_ARCH",
109 "TARGET_ARCH_VARIANT",
110 "TARGET_CPU_VARIANT",
111 "TARGET_2ND_ARCH",
112 "TARGET_2ND_ARCH_VARIANT",
113 "TARGET_2ND_CPU_VARIANT",
114 "HOST_ARCH",
115 "HOST_2ND_ARCH",
116 "HOST_OS",
117 "HOST_OS_EXTRA",
118 "HOST_CROSS_OS",
119 "HOST_CROSS_ARCH",
120 "HOST_CROSS_2ND_ARCH",
121 "HOST_BUILD_TYPE",
122 "BUILD_ID",
123 "OUT_DIR",
124 "AUX_OS_VARIANT_LIST",
125 "TARGET_BUILD_PDK",
126 "PDK_FUSION_PLATFORM_ZIP",
127 }
128
129 allVars := append(append([]string{
130 // Used to execute Kati and Ninja
131 "NINJA_GOALS",
132 "KATI_GOALS",
133 }, exportEnvVars...), bannerVars...)
134
135 make_vars, err := DumpMakeVars(ctx, config, config.Arguments(), []string{
136 filepath.Join(config.SoongOutDir(), "soong.variables"),
137 }, allVars)
138 if err != nil {
139 ctx.Fatalln("Error dumping make vars:", err)
140 }
141
142 // Print the banner like make does
143 fmt.Fprintln(ctx.Stdout(), "============================================")
144 for _, name := range bannerVars {
145 if make_vars[name] != "" {
146 fmt.Fprintf(ctx.Stdout(), "%s=%s\n", name, make_vars[name])
147 }
148 }
149 fmt.Fprintln(ctx.Stdout(), "============================================")
150
151 // Populate the environment
152 env := config.Environment()
153 for _, name := range exportEnvVars {
154 if make_vars[name] == "" {
155 env.Unset(name)
156 } else {
157 env.Set(name, make_vars[name])
158 }
159 }
160
161 config.SetKatiArgs(strings.Fields(make_vars["KATI_GOALS"]))
162 config.SetNinjaArgs(strings.Fields(make_vars["NINJA_GOALS"]))
163}