blob: 58805095bad49eb2ea72b71e878f21cbb3da93b1 [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) {
38 cmd := exec.CommandContext(ctx.Context,
39 "make",
40 "--no-print-directory",
41 "-f", "build/core/config.mk",
42 "dump-many-vars",
43 "CALLED_FROM_SETUP=true",
44 "BUILD_SYSTEM=build/core",
45 "MAKECMDGOALS="+strings.Join(goals, " "),
46 "DUMP_MANY_VARS="+strings.Join(vars, " "),
47 "OUT_DIR="+config.OutDir())
48 cmd.Env = config.Environment().Environ()
49 cmd.Args = append(cmd.Args, extra_targets...)
50 // TODO: error out when Stderr contains any content
51 cmd.Stderr = ctx.Stderr()
52 ctx.Verboseln(cmd.Path, cmd.Args)
53 output, err := cmd.Output()
54 if err != nil {
55 return nil, err
56 }
57
58 ret := make(map[string]string, len(vars))
59 for _, line := range strings.Split(string(output), "\n") {
60 if len(line) == 0 {
61 continue
62 }
63
64 if key, value, ok := decodeKeyValue(line); ok {
65 if value, ok = singleUnquote(value); ok {
66 ret[key] = value
67 ctx.Verboseln(key, value)
68 } else {
69 return nil, fmt.Errorf("Failed to parse make line: %q", line)
70 }
71 } else {
72 return nil, fmt.Errorf("Failed to parse make line: %q", line)
73 }
74 }
75
76 return ret, nil
77}
78
79func runMakeProductConfig(ctx Context, config Config) {
80 // Variables to export into the environment of Kati/Ninja
81 exportEnvVars := []string{
82 // So that we can use the correct TARGET_PRODUCT if it's been
83 // modified by PRODUCT-* arguments
84 "TARGET_PRODUCT",
85
86 // compiler wrappers set up by make
87 "CC_WRAPPER",
88 "CXX_WRAPPER",
89
90 // ccache settings
91 "CCACHE_COMPILERCHECK",
92 "CCACHE_SLOPPINESS",
93 "CCACHE_BASEDIR",
94 "CCACHE_CPP2",
95 }
96
97 // Variables to print out in the top banner
98 bannerVars := []string{
99 "PLATFORM_VERSION_CODENAME",
100 "PLATFORM_VERSION",
101 "TARGET_PRODUCT",
102 "TARGET_BUILD_VARIANT",
103 "TARGET_BUILD_TYPE",
104 "TARGET_BUILD_APPS",
105 "TARGET_ARCH",
106 "TARGET_ARCH_VARIANT",
107 "TARGET_CPU_VARIANT",
108 "TARGET_2ND_ARCH",
109 "TARGET_2ND_ARCH_VARIANT",
110 "TARGET_2ND_CPU_VARIANT",
111 "HOST_ARCH",
112 "HOST_2ND_ARCH",
113 "HOST_OS",
114 "HOST_OS_EXTRA",
115 "HOST_CROSS_OS",
116 "HOST_CROSS_ARCH",
117 "HOST_CROSS_2ND_ARCH",
118 "HOST_BUILD_TYPE",
119 "BUILD_ID",
120 "OUT_DIR",
121 "AUX_OS_VARIANT_LIST",
122 "TARGET_BUILD_PDK",
123 "PDK_FUSION_PLATFORM_ZIP",
124 }
125
126 allVars := append(append([]string{
127 // Used to execute Kati and Ninja
128 "NINJA_GOALS",
129 "KATI_GOALS",
130 }, exportEnvVars...), bannerVars...)
131
132 make_vars, err := DumpMakeVars(ctx, config, config.Arguments(), []string{
133 filepath.Join(config.SoongOutDir(), "soong.variables"),
134 }, allVars)
135 if err != nil {
136 ctx.Fatalln("Error dumping make vars:", err)
137 }
138
139 // Print the banner like make does
140 fmt.Fprintln(ctx.Stdout(), "============================================")
141 for _, name := range bannerVars {
142 if make_vars[name] != "" {
143 fmt.Fprintf(ctx.Stdout(), "%s=%s\n", name, make_vars[name])
144 }
145 }
146 fmt.Fprintln(ctx.Stdout(), "============================================")
147
148 // Populate the environment
149 env := config.Environment()
150 for _, name := range exportEnvVars {
151 if make_vars[name] == "" {
152 env.Unset(name)
153 } else {
154 env.Set(name, make_vars[name])
155 }
156 }
157
158 config.SetKatiArgs(strings.Fields(make_vars["KATI_GOALS"]))
159 config.SetNinjaArgs(strings.Fields(make_vars["NINJA_GOALS"]))
160}