blob: 60b5687bb313104fa00fd7af37bc65413c061d70 [file] [log] [blame]
Joe Onorato0578cbc2016-10-19 17:03:06 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "make.h"
18
19#include "command.h"
20#include "print.h"
21#include "util.h"
22
23#include <json/reader.h>
24#include <json/value.h>
25
26#include <fstream>
27#include <string>
28#include <map>
29
30#include <sys/types.h>
31#include <dirent.h>
32#include <string.h>
33
34using namespace std;
35
36map<string,string> g_buildVars;
37
38string
39get_build_var(const string& buildTop, const string& name, bool quiet)
40{
41 int err;
42
43 map<string,string>::iterator it = g_buildVars.find(name);
44 if (it == g_buildVars.end()) {
45 Command cmd("make");
46 cmd.AddArg("--no-print-directory");
47 cmd.AddArg("-C");
48 cmd.AddArg(buildTop);
49 cmd.AddArg("-f");
50 cmd.AddArg("build/core/config.mk");
51 cmd.AddArg(string("dumpvar-") + name);
52 cmd.AddEnv("CALLED_FROM_SETUP", "true");
53 cmd.AddEnv("BUILD_SYSTEM", "build/core");
54
55 string output = trim(get_command_output(cmd, &err, quiet));
56 if (err == 0) {
57 g_buildVars[name] = output;
58 return output;
59 } else {
60 return string();
61 }
62 } else {
63 return it->second;
64 }
65}
66
67string
68sniff_device_name(const string& buildOut, const string& product)
69{
70 string match("ro.build.product=" + product);
71
72 string base(buildOut + "/target/product");
73 DIR* dir = opendir(base.c_str());
74 if (dir == NULL) {
75 return string();
76 }
77
78 dirent* entry;
79 while ((entry = readdir(dir)) != NULL) {
80 if (entry->d_name[0] == '.') {
81 continue;
82 }
83 if (entry->d_type == DT_DIR) {
84 string filename(base + "/" + entry->d_name + "/system/build.prop");
85 vector<string> lines;
86 split_lines(&lines, read_file(filename));
87 for (size_t i=0; i<lines.size(); i++) {
88 if (lines[i] == match) {
89 return entry->d_name;
90 }
91 }
92 }
93 }
94
95 closedir(dir);
96 return string();
97}
98
99void
100json_error(const string& filename, const char* error, bool quiet)
101{
102 if (!quiet) {
103 print_error("Unable to parse module info file (%s): %s", error, filename.c_str());
104 print_error("Have you done a full build?");
105 }
106 exit(1);
107}
108
109static void
110get_values(const Json::Value& json, const string& name, vector<string>* result)
111{
112 Json::Value nullValue;
113
114 const Json::Value& value = json.get(name, nullValue);
115 if (!value.isArray()) {
116 return;
117 }
118
119 const int N = value.size();
120 for (int i=0; i<N; i++) {
121 const Json::Value& child = value[i];
122 if (child.isString()) {
123 result->push_back(child.asString());
124 }
125 }
126}
127
128void
129read_modules(const string& buildOut, const string& device, map<string,Module>* result, bool quiet)
130{
131 string filename(string(buildOut + "/target/product/") + device + "/module-info.json");
132 std::ifstream stream(filename, std::ifstream::binary);
133
134 if (stream.fail()) {
135 if (!quiet) {
136 print_error("Unable to open module info file: %s", filename.c_str());
137 print_error("Have you done a full build?");
138 }
139 exit(1);
140 }
141
142 Json::Value json;
143 Json::Reader reader;
144 if (!reader.parse(stream, json)) {
145 json_error(filename, "can't parse json format", quiet);
146 return;
147 }
148
149 if (!json.isObject()) {
150 json_error(filename, "root element not an object", quiet);
151 return;
152 }
153
154 vector<string> names = json.getMemberNames();
155 const int N = names.size();
156 for (int i=0; i<N; i++) {
157 const string& name = names[i];
158
159 const Json::Value& value = json[name];
160 if (!value.isObject()) {
161 continue;
162 }
163
164 Module module;
165
166 module.name = name;
167 get_values(value, "class", &module.classes);
168 get_values(value, "path", &module.paths);
169 get_values(value, "installed", &module.installed);
170
171 // Only keep classes we can handle
172 for (ssize_t i = module.classes.size() - 1; i >= 0; i--) {
173 string cl = module.classes[i];
174 if (!(cl == "JAVA_LIBRARIES" || cl == "EXECUTABLES" || cl == "SHARED_LIBRARIES"
175 || cl == "APPS")) {
176 module.classes.erase(module.classes.begin() + i);
177 }
178 }
179 if (module.classes.size() == 0) {
180 continue;
181 }
182
183 // Only target modules (not host)
184 for (ssize_t i = module.installed.size() - 1; i >= 0; i--) {
185 string fn = module.installed[i];
186 if (!starts_with(fn, buildOut + "/target/")) {
187 module.installed.erase(module.installed.begin() + i);
188 }
189 }
190 if (module.installed.size() == 0) {
191 continue;
192 }
193
194 (*result)[name] = module;
195 }
196}
197
198int
199build_goals(const vector<string>& goals)
200{
201 Command cmd("make");
202 cmd.AddArg("-f");
203 cmd.AddArg("build/core/main.mk");
204 for (size_t i=0; i<goals.size(); i++) {
205 cmd.AddArg(goals[i]);
206 }
207
208 return run_command(cmd);
209}
210