blob: a8d4483bc300ea713b286afe7492eb9fc51756a8 [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",
Yoshisato Yanagisawa13fd3ff2017-04-05 11:05:31 +090092 "JAVAC_WRAPPER",
Dan Willemsen1e704462016-08-21 15:17:17 -070093
94 // ccache settings
95 "CCACHE_COMPILERCHECK",
96 "CCACHE_SLOPPINESS",
97 "CCACHE_BASEDIR",
98 "CCACHE_CPP2",
99 }
100
101 // Variables to print out in the top banner
102 bannerVars := []string{
103 "PLATFORM_VERSION_CODENAME",
104 "PLATFORM_VERSION",
105 "TARGET_PRODUCT",
106 "TARGET_BUILD_VARIANT",
107 "TARGET_BUILD_TYPE",
108 "TARGET_BUILD_APPS",
109 "TARGET_ARCH",
110 "TARGET_ARCH_VARIANT",
111 "TARGET_CPU_VARIANT",
112 "TARGET_2ND_ARCH",
113 "TARGET_2ND_ARCH_VARIANT",
114 "TARGET_2ND_CPU_VARIANT",
115 "HOST_ARCH",
116 "HOST_2ND_ARCH",
117 "HOST_OS",
118 "HOST_OS_EXTRA",
119 "HOST_CROSS_OS",
120 "HOST_CROSS_ARCH",
121 "HOST_CROSS_2ND_ARCH",
122 "HOST_BUILD_TYPE",
123 "BUILD_ID",
124 "OUT_DIR",
125 "AUX_OS_VARIANT_LIST",
126 "TARGET_BUILD_PDK",
127 "PDK_FUSION_PLATFORM_ZIP",
128 }
129
130 allVars := append(append([]string{
131 // Used to execute Kati and Ninja
132 "NINJA_GOALS",
133 "KATI_GOALS",
134 }, exportEnvVars...), bannerVars...)
135
136 make_vars, err := DumpMakeVars(ctx, config, config.Arguments(), []string{
137 filepath.Join(config.SoongOutDir(), "soong.variables"),
138 }, allVars)
139 if err != nil {
140 ctx.Fatalln("Error dumping make vars:", err)
141 }
142
143 // Print the banner like make does
144 fmt.Fprintln(ctx.Stdout(), "============================================")
145 for _, name := range bannerVars {
146 if make_vars[name] != "" {
147 fmt.Fprintf(ctx.Stdout(), "%s=%s\n", name, make_vars[name])
148 }
149 }
150 fmt.Fprintln(ctx.Stdout(), "============================================")
151
152 // Populate the environment
153 env := config.Environment()
154 for _, name := range exportEnvVars {
155 if make_vars[name] == "" {
156 env.Unset(name)
157 } else {
158 env.Set(name, make_vars[name])
159 }
160 }
161
162 config.SetKatiArgs(strings.Fields(make_vars["KATI_GOALS"]))
163 config.SetNinjaArgs(strings.Fields(make_vars["NINJA_GOALS"]))
164}