blob: 4777559440ee712198fc2f391070fdfc58567fac [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -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
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "AST.h"
Andreas Huber5345ec22016-07-29 13:33:27 -070018#include "Coordinator.h"
Andreas Huber0fa9e392016-08-31 09:05:44 -070019#include "Scope.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070020
Andreas Huber308d8a22017-11-06 14:46:52 -080021#include <android-base/logging.h>
Steven Moreland5bdfa702017-04-18 23:20:39 -070022#include <hidl-hash/Hash.h>
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070023#include <hidl-util/Formatter.h>
Steven Moreland7ae3d542017-01-18 16:46:01 -080024#include <hidl-util/FQName.h>
Steven Morelandd177b122016-12-12 09:15:37 -080025#include <hidl-util/StringHelper.h>
Andreas Huber308d8a22017-11-06 14:46:52 -080026#include <iostream>
Iliyan Malchev5bb14022016-08-09 15:04:39 -070027#include <set>
Andreas Huberc9410c72016-07-28 12:18:40 -070028#include <stdio.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070029#include <string>
Andreas Huberb82318c2016-08-02 14:45:54 -070030#include <unistd.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070031#include <vector>
Andreas Huberc9410c72016-07-28 12:18:40 -070032
33using namespace android;
34
Iliyan Malchev5bb14022016-08-09 15:04:39 -070035struct OutputHandler {
36 std::string mKey;
Steven Moreland97e52332017-05-12 16:47:19 -070037 std::string mDescription;
Andreas Huber019d21d2016-10-03 12:59:47 -070038 enum OutputMode {
39 NEEDS_DIR,
40 NEEDS_FILE,
Steven Morelanda171b562017-05-12 15:18:03 -070041 NEEDS_SRC, // for changes inside the source tree itself
Andreas Huber019d21d2016-10-03 12:59:47 -070042 NOT_NEEDED
43 } mOutputMode;
44
Steven Morelanddd583842017-04-19 13:09:57 -070045 const std::string& name() { return mKey; }
Steven Moreland97e52332017-05-12 16:47:19 -070046 const std::string& description() { return mDescription; }
Steven Morelandbbbbeb82017-05-09 14:20:50 -070047
Steven Moreland05951b32017-05-12 17:22:22 -070048 using ValidationFunction = std::function<bool(const FQName &, const std::string &language)>;
Steven Morelandbbbbeb82017-05-09 14:20:50 -070049 using GenerationFunction = std::function<status_t(const FQName &fqName,
50 const char *hidl_gen,
51 Coordinator *coordinator,
52 const std::string &outputDir)>;
53
54 ValidationFunction validate;
55 GenerationFunction generate;
Iliyan Malchev5bb14022016-08-09 15:04:39 -070056};
Andreas Huberdca261f2016-08-04 13:47:51 -070057
Jiyong Park37283252017-08-29 14:11:48 +090058static bool generateForTest = false;
59
Iliyan Malchev5bb14022016-08-09 15:04:39 -070060static status_t generateSourcesForFile(
61 const FQName &fqName,
62 const char *,
63 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -070064 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070065 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -070066 CHECK(fqName.isFullyQualified());
67
Andreas Huber0fa9e392016-08-31 09:05:44 -070068 AST *ast;
Andreas Huberd29724f2016-09-14 09:33:13 -070069 std::string limitToType;
Andreas Huber0fa9e392016-08-31 09:05:44 -070070
71 if (fqName.name().find("types.") == 0) {
72 CHECK(lang == "java"); // Already verified in validate().
73
Andreas Huberd29724f2016-09-14 09:33:13 -070074 limitToType = fqName.name().substr(strlen("types."));
Andreas Huber0fa9e392016-08-31 09:05:44 -070075
Yifan Hongfece6ec2017-01-12 17:04:04 -080076 FQName typesName = fqName.getTypesForPackage();
Andreas Huber0fa9e392016-08-31 09:05:44 -070077 ast = coordinator->parse(typesName);
78 } else {
79 ast = coordinator->parse(fqName);
80 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -070081
82 if (ast == NULL) {
83 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -070084 "ERROR: Could not parse %s. Aborting.\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -070085 fqName.string().c_str());
86
87 return UNKNOWN_ERROR;
88 }
89
Steven Moreland3b1ce262017-04-21 14:19:59 -070090 if (lang == "check") {
91 return OK; // only parsing, not generating
92 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070093 if (lang == "c++") {
94 return ast->generateCpp(outputDir);
95 }
Steven Moreland1cbf0362017-05-09 14:32:53 -070096 if (lang == "c++-headers") {
97 return ast->generateCppHeaders(outputDir);
98 }
99 if (lang == "c++-sources") {
100 return ast->generateCppSources(outputDir);
101 }
Steven Moreland9c387612016-09-07 09:54:26 -0700102 if (lang == "c++-impl") {
103 return ast->generateCppImpl(outputDir);
104 }
Steven Morelandf2a0f5b2017-07-18 20:39:11 -0700105 if (lang == "c++-impl-headers") {
Steven Moreland6d688552017-09-15 11:03:02 -0700106 return ast->generateCppImplHeader(outputDir);
Steven Morelandf2a0f5b2017-07-18 20:39:11 -0700107 }
108 if (lang == "c++-impl-sources") {
Steven Moreland6d688552017-09-15 11:03:02 -0700109 return ast->generateCppImplSource(outputDir);
Steven Morelandf2a0f5b2017-07-18 20:39:11 -0700110 }
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700111 if (lang == "c++-adapter") {
112 return ast->generateCppAdapter(outputDir);
113 }
114 if (lang == "c++-adapter-headers") {
115 return ast->generateCppAdapterHeader(outputDir);
116 }
117 if (lang == "c++-adapter-sources") {
118 return ast->generateCppAdapterSource(outputDir);
119 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700120 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700121 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700122 }
123 if (lang == "vts") {
124 return ast->generateVts(outputDir);
125 }
126 // Unknown language.
127 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700128}
129
Andreas Huber308d8a22017-11-06 14:46:52 -0800130static status_t dumpDefinedButUnreferencedTypeNames(
131 const std::vector<FQName> &packageInterfaces,
132 Coordinator *coordinator) {
133 std::set<FQName> packageDefinedTypes;
134 std::set<FQName> packageReferencedTypes;
Andreas Huber4f4b3822017-11-15 13:18:50 -0800135 std::set<FQName> packageImportedTypes;
Andreas Huber308d8a22017-11-06 14:46:52 -0800136 for (const auto &fqName : packageInterfaces) {
137 AST *ast = coordinator->parse(fqName);
138 if (!ast) {
139 std::cerr
140 << "ERROR: Could not parse " << fqName.string() << ". Aborting."
141 << std::endl;
142
143 return UNKNOWN_ERROR;
144 }
145
146 ast->addDefinedTypes(&packageDefinedTypes);
147 ast->addReferencedTypes(&packageReferencedTypes);
Andreas Huber4f4b3822017-11-15 13:18:50 -0800148 ast->getAllImportedNames(&packageImportedTypes);
Andreas Huber308d8a22017-11-06 14:46:52 -0800149 }
150
Andreas Huber4f4b3822017-11-15 13:18:50 -0800151 // Expand each "types" FQName into its constituent types, i.e.
152 // "android.hardware.foo@1.0::types" might expand into the set
153 // { android.hardware.foo@1.0::FirstType, android.hardware.foo@1.0::SecondType }.
154 std::set<FQName> expandedTypes;
155 for (const auto &importedFQName : packageImportedTypes) {
156 if (importedFQName.name() == "types") {
157 AST *ast = coordinator->parse(
158 importedFQName,
159 nullptr /* parsedASTs */,
160 Coordinator::Enforce::NONE);
161
162 ast->addDefinedTypes(&expandedTypes);
163 }
164 }
165
166 // Now remove all "types" FQNames.
167 for (auto it = packageImportedTypes.begin();
168 it != packageImportedTypes.end();) {
169 if (it->name() == "types") {
170 it = packageImportedTypes.erase(it);
171 } else {
172 ++it;
173 }
174 }
175
176 // And merge the sets. (set<T>::merge not available until C++17)
177 std::for_each(
178 expandedTypes.begin(),
179 expandedTypes.end(),
180 [&packageImportedTypes](const auto &fqName) {
181 packageImportedTypes.insert(fqName);
182 });
Andreas Huber308d8a22017-11-06 14:46:52 -0800183#if 0
184 for (const auto &fqName : packageDefinedTypes) {
185 std::cout << "DEFINED: " << fqName.string() << std::endl;
186 }
187
Andreas Huber4f4b3822017-11-15 13:18:50 -0800188 for (const auto &fqName : packageImportedTypes) {
189 std::cout << "IMPORTED: " << fqName.string() << std::endl;
190 }
191
Andreas Huber308d8a22017-11-06 14:46:52 -0800192 for (const auto &fqName : packageReferencedTypes) {
193 std::cout << "REFERENCED: " << fqName.string() << std::endl;
194 }
195#endif
196
197 for (const auto &fqName : packageReferencedTypes) {
198 packageDefinedTypes.erase(fqName);
Andreas Huber4f4b3822017-11-15 13:18:50 -0800199 packageImportedTypes.erase(fqName);
200 }
201
202 // A package implicitly imports its own types, only track them in one set.
203 for (const auto &fqName : packageDefinedTypes) {
204 packageImportedTypes.erase(fqName);
Andreas Huber308d8a22017-11-06 14:46:52 -0800205 }
206
207 for (const auto &fqName : packageDefinedTypes) {
208 std::cerr
209 << "VERBOSE: DEFINED-BUT-NOT-REFERENCED "
210 << fqName.string()
211 << std::endl;
212 }
213
Andreas Huber4f4b3822017-11-15 13:18:50 -0800214 for (const auto &fqName : packageImportedTypes) {
215 std::cerr
216 << "VERBOSE: IMPORTED-BUT-NOT-REFERENCED "
217 << fqName.string()
218 << std::endl;
219 }
220
Andreas Huber308d8a22017-11-06 14:46:52 -0800221 return OK;
222}
223
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700224static status_t generateSourcesForPackage(
225 const FQName &packageFQName,
226 const char *hidl_gen,
227 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700228 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700229 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700230 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700231 !packageFQName.isFullyQualified() &&
232 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700233
234 std::vector<FQName> packageInterfaces;
235
236 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700237 coordinator->appendPackageInterfacesToVector(packageFQName,
238 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700239
240 if (err != OK) {
241 return err;
242 }
243
Andreas Huber308d8a22017-11-06 14:46:52 -0800244 if (coordinator->isVerbose()) {
245 err = dumpDefinedButUnreferencedTypeNames(
246 packageInterfaces, coordinator);
247
248 if (err != OK) {
249 return err;
250 }
251 }
252
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700253 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700254 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700255 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700256 if (err != OK) {
257 return err;
258 }
259 }
260
261 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700262}
263
Steven Morelandbbbbeb82017-05-09 14:20:50 -0700264OutputHandler::GenerationFunction generationFunctionForFileOrPackage(const std::string &language) {
265 return [language](const FQName &fqName,
266 const char *hidl_gen, Coordinator *coordinator,
267 const std::string &outputDir) -> status_t {
268 if (fqName.isFullyQualified()) {
269 return generateSourcesForFile(fqName,
270 hidl_gen,
271 coordinator,
272 outputDir,
273 language);
274 } else {
275 return generateSourcesForPackage(fqName,
276 hidl_gen,
277 coordinator,
278 outputDir,
279 language);
280 }
281 };
282}
283
Andreas Huberd2943e12016-08-05 11:59:31 -0700284static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700285 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700286}
Steven Moreland5715fed2017-01-16 11:06:47 -0800287
Andreas Huber75ae95d2016-10-12 16:08:26 -0700288static status_t isPackageJavaCompatible(
289 const FQName &packageFQName,
290 Coordinator *coordinator,
291 bool *compatible) {
292 std::vector<FQName> todo;
293 status_t err =
294 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
295
296 if (err != OK) {
297 return err;
298 }
299
300 std::set<FQName> seen;
301 for (const auto &iface : todo) {
302 seen.insert(iface);
303 }
304
305 // Form the transitive closure of all imported interfaces (and types.hal-s)
306 // If any one of them is not java compatible, this package isn't either.
307 while (!todo.empty()) {
308 const FQName fqName = todo.back();
309 todo.pop_back();
310
311 AST *ast = coordinator->parse(fqName);
312
313 if (ast == nullptr) {
314 return UNKNOWN_ERROR;
315 }
316
317 if (!ast->isJavaCompatible()) {
318 *compatible = false;
319 return OK;
320 }
321
322 std::set<FQName> importedPackages;
323 ast->getImportedPackages(&importedPackages);
324
325 for (const auto &package : importedPackages) {
326 std::vector<FQName> packageInterfaces;
327 status_t err = coordinator->appendPackageInterfacesToVector(
328 package, &packageInterfaces);
329
330 if (err != OK) {
331 return err;
332 }
333
334 for (const auto &iface : packageInterfaces) {
335 if (seen.find(iface) != seen.end()) {
336 continue;
337 }
338
339 todo.push_back(iface);
340 seen.insert(iface);
341 }
342 }
343 }
344
345 *compatible = true;
346 return OK;
347}
348
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700349static bool packageNeedsJavaCode(
350 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
Steven Morelandadc25022017-10-11 12:42:19 -0700351 if (packageInterfaces.size() == 0) {
352 return false;
353 }
354
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700355 // If there is more than just a types.hal file to this package we'll
356 // definitely need to generate Java code.
357 if (packageInterfaces.size() > 1
358 || packageInterfaces[0].name() != "types") {
359 return true;
360 }
361
362 CHECK(typesAST != nullptr);
363
364 // We'll have to generate Java code if types.hal contains any non-typedef
365 // type declarations.
366
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700367 Scope* rootScope = typesAST->getRootScope();
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700368 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
369
370 for (const auto &subType : subTypes) {
371 if (!subType->isTypeDef()) {
372 return true;
373 }
374 }
375
376 return false;
377}
378
Steven Moreland05951b32017-05-12 17:22:22 -0700379bool validateIsPackage(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700380 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700381 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700382 fprintf(stderr, "ERROR: Expecting package name\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700383 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700384 }
385
386 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700387 fprintf(stderr, "ERROR: Expecting package version\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700388 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700389 }
390
391 if (!fqName.name().empty()) {
392 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700393 "ERROR: Expecting only package name and version.\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700394 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700395 }
396
Steven Moreland05951b32017-05-12 17:22:22 -0700397 return true;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700398}
399
Steven Morelandf7f2a9a2017-07-21 18:05:38 -0700400bool isHidlTransportPackage(const FQName& fqName) {
401 return fqName.package() == gIBasePackageFqName.string() ||
402 fqName.package() == gIManagerPackageFqName.string();
Steven Moreland77cf7642017-06-15 14:49:39 -0700403}
404
Steven Morelandc7946c92017-08-08 14:48:32 -0700405bool isSystemProcessSupportedPackage(const FQName& fqName) {
406 // Technically, so is hidl IBase + IServiceManager, but
407 // these are part of libhidltransport.
408 return fqName.string() == "android.hardware.graphics.allocator@2.0" ||
409 fqName.string() == "android.hardware.graphics.common@1.0" ||
410 fqName.string() == "android.hardware.graphics.mapper@2.0" ||
Chia-I Wu620cc392017-09-28 15:33:21 -0700411 fqName.string() == "android.hardware.graphics.mapper@2.1" ||
Steven Morelandc7946c92017-08-08 14:48:32 -0700412 fqName.string() == "android.hardware.renderscript@1.0" ||
413 fqName.string() == "android.hidl.memory@1.0";
414}
415
Steven Moreland5edf5282017-07-20 12:56:58 -0700416bool isSystemPackage(const FQName &package) {
417 return package.inPackage("android.hidl") ||
418 package.inPackage("android.system") ||
419 package.inPackage("android.frameworks") ||
420 package.inPackage("android.hardware");
421}
422
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700423static status_t generateAdapterMainSource(
424 const FQName & packageFQName,
425 const char* /* hidl_gen */,
426 Coordinator* coordinator,
427 const std::string &outputPath) {
Steven Morelanda885d252017-09-25 18:44:43 -0700428 Formatter out = coordinator->getFormatter(outputPath, packageFQName,
429 Coordinator::Location::DIRECT, "main.cpp");
430
431 if (!out.isValid()) {
432 return UNKNOWN_ERROR;
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700433 }
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700434
435 std::vector<FQName> packageInterfaces;
436 status_t err =
437 coordinator->appendPackageInterfacesToVector(packageFQName,
438 &packageInterfaces);
439 if (err != OK) {
440 return err;
441 }
442
443 out << "#include <hidladapter/HidlBinderAdapter.h>\n";
444
445 for (auto &interface : packageInterfaces) {
446 if (interface.name() == "types") {
447 continue;
448 }
449 AST::generateCppPackageInclude(out, interface, interface.getInterfaceAdapterName());
450 }
451
452 out << "int main(int argc, char** argv) ";
453 out.block([&] {
454 out << "return ::android::hardware::adapterMain<\n";
455 out.indent();
456 for (auto &interface : packageInterfaces) {
457 if (interface.name() == "types") {
458 continue;
459 }
460 out << interface.getInterfaceAdapterFqName().cppName();
461
462 if (&interface != &packageInterfaces.back()) {
463 out << ",\n";
464 }
465 }
466 out << ">(\"" << packageFQName.string() << "\", argc, argv);\n";
467 out.unindent();
468 }).endl();
469 return OK;
470}
471
Steven Moreland313a0132017-11-03 14:23:14 -0700472static status_t generateAndroidBpForPackage(const FQName& packageFQName, const char* /* hidl_gen */,
Steven Moreland40069d52017-10-03 09:36:51 -0700473 Coordinator* coordinator,
474 const std::string& outputPath) {
475 CHECK(packageFQName.isValid() && !packageFQName.isFullyQualified() &&
476 packageFQName.name().empty());
477
478 std::vector<FQName> packageInterfaces;
479
480 status_t err = coordinator->appendPackageInterfacesToVector(packageFQName, &packageInterfaces);
481
482 if (err != OK) {
483 return err;
484 }
485
486 std::set<FQName> importedPackagesHierarchy;
Steven Moreland887b84c2017-10-09 18:40:58 -0700487 std::vector<const Type *> exportedTypes;
Steven Moreland40069d52017-10-03 09:36:51 -0700488 AST* typesAST = nullptr;
489
490 for (const auto& fqName : packageInterfaces) {
491 AST* ast = coordinator->parse(fqName);
492
493 if (ast == NULL) {
494 fprintf(stderr, "ERROR: Could not parse %s. Aborting.\n", fqName.string().c_str());
495
496 return UNKNOWN_ERROR;
497 }
498
499 if (fqName.name() == "types") {
500 typesAST = ast;
501 }
502
503 ast->getImportedPackagesHierarchy(&importedPackagesHierarchy);
Steven Moreland887b84c2017-10-09 18:40:58 -0700504 ast->appendToExportedTypesVector(&exportedTypes);
Steven Moreland40069d52017-10-03 09:36:51 -0700505 }
506
Steven Moreland313a0132017-11-03 14:23:14 -0700507 bool needsJavaCode = packageNeedsJavaCode(packageInterfaces, typesAST);
508
509 bool genJavaConstants = needsJavaCode && !exportedTypes.empty();
Steven Moreland887b84c2017-10-09 18:40:58 -0700510
511 bool isJavaCompatible;
512 err = isPackageJavaCompatible(packageFQName, coordinator, &isJavaCompatible);
513 if (err != OK) return err;
Steven Moreland313a0132017-11-03 14:23:14 -0700514 bool genJavaLibrary = needsJavaCode && isJavaCompatible;
515
516 bool isVndk = !generateForTest && isSystemPackage(packageFQName);
517 bool isVndkSp = isVndk && isSystemProcessSupportedPackage(packageFQName);
Steven Moreland887b84c2017-10-09 18:40:58 -0700518
Steven Moreland40069d52017-10-03 09:36:51 -0700519 Formatter out = coordinator->getFormatter(outputPath, packageFQName,
520 Coordinator::Location::PACKAGE_ROOT, "Android.bp");
521
522 if (!out.isValid()) {
523 return UNKNOWN_ERROR;
524 }
525
Steven Moreland313a0132017-11-03 14:23:14 -0700526 out << "// This file is autogenerated by hidl-gen -Landroidbp.\n\n";
Steven Moreland40069d52017-10-03 09:36:51 -0700527
Steven Moreland313a0132017-11-03 14:23:14 -0700528
529 out << "hidl_interface ";
Steven Moreland40069d52017-10-03 09:36:51 -0700530 out.block([&] {
Steven Moreland313a0132017-11-03 14:23:14 -0700531 out << "name: \"" << makeLibraryName(packageFQName) << "\",\n";
532 out << "root: \"" << coordinator->getPackageRoot(packageFQName) << "\",\n";
533 if (isHidlTransportPackage(packageFQName)) {
534 out << "core_interface: true,\n";
535 }
536 if (isVndk) {
537 out << "vndk: ";
538 out.block([&]() {
539 out << "enabled: true,\n";
540 if (isVndkSp) {
541 out << "support_system_process: true,\n";
542 }
543 }) << ",\n";
544 }
545 (out << "srcs: [\n").indent([&] {
Steven Moreland40069d52017-10-03 09:36:51 -0700546 for (const auto& fqName : packageInterfaces) {
547 out << "\"" << fqName.name() << ".hal\",\n";
548 }
Steven Moreland313a0132017-11-03 14:23:14 -0700549 }) << "],\n";
550 if (!importedPackagesHierarchy.empty()) {
551 (out << "interfaces: [\n").indent([&] {
552 for (const auto& fqName : importedPackagesHierarchy) {
553 out << "\"" << fqName.string() << "\",\n";
554 }
555 }) << "],\n";
556 }
557 if (typesAST != nullptr) {
558 (out << "types: [\n").indent([&] {
559 std::vector<NamedType *> subTypes = typesAST->getRootScope()->getSubTypes();
560 std::sort(
561 subTypes.begin(),
562 subTypes.end(),
563 [](const NamedType *a, const NamedType *b) -> bool {
564 return a->fqName() < b->fqName();
565 });
566
567 for (const auto &type : subTypes) {
568 if (type->isTypeDef()) {
569 continue;
570 }
571
572 out << "\"" << type->localName() << "\",\n";
573 }
574 }) << "],\n";
575 }
576 // Explicity call this out for developers.
577 out << "gen_java: " << (genJavaLibrary ? "true" : "false") << ",\n";
578 if (genJavaConstants) {
579 out << "gen_java_constants: true,\n";
580 }
Steven Moreland40069d52017-10-03 09:36:51 -0700581 }).endl().endl();
582
Steven Moreland40069d52017-10-03 09:36:51 -0700583 return OK;
584}
585
Steven Morelanda885d252017-09-25 18:44:43 -0700586static status_t generateAndroidBpImplForPackage(const FQName& packageFQName, const char*,
587 Coordinator* coordinator,
588 const std::string& outputPath) {
Iliyan Malchev4923f932016-09-09 13:04:59 -0700589 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700590
591 std::vector<FQName> packageInterfaces;
592
593 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700594 coordinator->appendPackageInterfacesToVector(packageFQName,
595 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700596
597 if (err != OK) {
598 return err;
599 }
600
601 std::set<FQName> importedPackages;
602
603 for (const auto &fqName : packageInterfaces) {
604 AST *ast = coordinator->parse(fqName);
605
606 if (ast == NULL) {
607 fprintf(stderr,
608 "ERROR: Could not parse %s. Aborting.\n",
609 fqName.string().c_str());
610
611 return UNKNOWN_ERROR;
612 }
613
614 ast->getImportedPackages(&importedPackages);
615 }
616
Steven Morelanda885d252017-09-25 18:44:43 -0700617 Formatter out = coordinator->getFormatter(outputPath, packageFQName,
618 Coordinator::Location::DIRECT, "Android.bp");
Steven Moreland197d56c2016-09-09 10:03:58 -0700619
Steven Morelanda885d252017-09-25 18:44:43 -0700620 if (!out.isValid()) {
621 return UNKNOWN_ERROR;
Steven Moreland197d56c2016-09-09 10:03:58 -0700622 }
623
Yifan Hong958ee462016-12-06 17:09:51 -0800624 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800625 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800626 out << "name: \"" << libraryName << "\",\n"
627 << "relative_install_path: \"hw\",\n"
Steven Morelandf8a22e92017-02-15 18:46:04 -0800628 << "proprietary: true,\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800629 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800630 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800631 for (const auto &fqName : packageInterfaces) {
632 if (fqName.name() == "types") {
633 continue;
634 }
635 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
636 }
637 });
638 out << "],\n"
639 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800640 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800641 out << "\"libhidlbase\",\n"
642 << "\"libhidltransport\",\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800643 << "\"libutils\",\n"
644 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -0700645
Yifan Hong958ee462016-12-06 17:09:51 -0800646 for (const auto &importedPackage : importedPackages) {
Steven Morelanddadd1842017-05-09 13:24:54 -0700647 if (isHidlTransportPackage(importedPackage)) {
648 continue;
649 }
650
Yifan Hong958ee462016-12-06 17:09:51 -0800651 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
652 }
653 });
654 out << "],\n";
655 });
656 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -0700657
658 return OK;
659}
660
Steven Moreland05951b32017-05-12 17:22:22 -0700661bool validateForSource(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700662 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700663 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700664 fprintf(stderr, "ERROR: Expecting package name\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700665 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700666 }
667
668 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700669 fprintf(stderr, "ERROR: Expecting package version\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700670 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700671 }
672
Andreas Huber0fa9e392016-08-31 09:05:44 -0700673 const std::string &name = fqName.name();
674 if (!name.empty()) {
675 if (name.find('.') == std::string::npos) {
Steven Moreland05951b32017-05-12 17:22:22 -0700676 return true;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700677 }
678
679 if (language != "java" || name.find("types.") != 0) {
680 // When generating java sources for "types.hal", output can be
681 // constrained to just one of the top-level types declared
682 // by using the extended syntax
683 // android.hardware.Foo@1.0::types.TopLevelTypeName.
684 // In all other cases (different language, not 'types') the dot
685 // notation in the name is illegal in this context.
Steven Moreland05951b32017-05-12 17:22:22 -0700686 return false;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700687 }
688
Steven Moreland05951b32017-05-12 17:22:22 -0700689 return true;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700690 }
691
Steven Moreland05951b32017-05-12 17:22:22 -0700692 return true;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700693}
694
Steven Morelandf47912d2017-05-12 16:25:44 -0700695OutputHandler::GenerationFunction generateExportHeaderForPackage(bool forJava) {
696 return [forJava](const FQName &packageFQName,
697 const char * /* hidl_gen */,
698 Coordinator *coordinator,
699 const std::string &outputPath) -> status_t {
700 CHECK(packageFQName.isValid()
701 && !packageFQName.package().empty()
702 && !packageFQName.version().empty()
703 && packageFQName.name().empty());
Andreas Huber019d21d2016-10-03 12:59:47 -0700704
Steven Morelandf47912d2017-05-12 16:25:44 -0700705 std::vector<FQName> packageInterfaces;
Andreas Huber019d21d2016-10-03 12:59:47 -0700706
Steven Morelandf47912d2017-05-12 16:25:44 -0700707 status_t err = coordinator->appendPackageInterfacesToVector(
708 packageFQName, &packageInterfaces);
Andreas Huber019d21d2016-10-03 12:59:47 -0700709
Steven Morelandf47912d2017-05-12 16:25:44 -0700710 if (err != OK) {
711 return err;
Andreas Huber019d21d2016-10-03 12:59:47 -0700712 }
713
Steven Morelandf47912d2017-05-12 16:25:44 -0700714 std::vector<const Type *> exportedTypes;
Andreas Huber019d21d2016-10-03 12:59:47 -0700715
Steven Morelandf47912d2017-05-12 16:25:44 -0700716 for (const auto &fqName : packageInterfaces) {
717 AST *ast = coordinator->parse(fqName);
718
719 if (ast == NULL) {
720 fprintf(stderr,
721 "ERROR: Could not parse %s. Aborting.\n",
722 fqName.string().c_str());
723
724 return UNKNOWN_ERROR;
725 }
726
727 ast->appendToExportedTypesVector(&exportedTypes);
728 }
729
730 if (exportedTypes.empty()) {
731 return OK;
732 }
733
Steven Morelanda885d252017-09-25 18:44:43 -0700734 // C++ filename is specified in output path
735 const std::string filename = forJava ? "Constants.java" : "";
736 const Coordinator::Location location =
737 forJava ? Coordinator::Location::GEN_SANITIZED : Coordinator::Location::DIRECT;
Steven Morelandf47912d2017-05-12 16:25:44 -0700738
Steven Morelanda885d252017-09-25 18:44:43 -0700739 Formatter out = coordinator->getFormatter(outputPath, packageFQName, location, filename);
Steven Morelandf47912d2017-05-12 16:25:44 -0700740
Steven Morelanda885d252017-09-25 18:44:43 -0700741 if (!out.isValid()) {
742 return UNKNOWN_ERROR;
Steven Morelandf47912d2017-05-12 16:25:44 -0700743 }
744
Steven Morelandf47912d2017-05-12 16:25:44 -0700745 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
746 << "// Source: " << packageFQName.string() << "\n"
747 << "// Root: " << coordinator->getPackageRootOption(packageFQName) << "\n\n";
748
749 std::string guard;
750 if (forJava) {
751 out << "package " << packageFQName.javaPackage() << ";\n\n";
752 out << "public class Constants {\n";
753 out.indent();
754 } else {
755 guard = "HIDL_GENERATED_";
756 guard += StringHelper::Uppercase(packageFQName.tokenName());
757 guard += "_";
758 guard += "EXPORTED_CONSTANTS_H_";
759
760 out << "#ifndef "
761 << guard
762 << "\n#define "
763 << guard
764 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
765 }
766
767 for (const auto &type : exportedTypes) {
768 type->emitExportedHeader(out, forJava);
769 }
770
771 if (forJava) {
772 out.unindent();
773 out << "}\n";
774 } else {
775 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
776 << guard
777 << "\n";
778 }
779
Andreas Huber019d21d2016-10-03 12:59:47 -0700780 return OK;
Steven Morelandf47912d2017-05-12 16:25:44 -0700781 };
Andreas Huber019d21d2016-10-03 12:59:47 -0700782}
783
Steven Morelandf2e44692017-04-18 20:19:09 -0700784static status_t generateHashOutput(const FQName &fqName,
785 const char* /*hidl_gen*/,
786 Coordinator *coordinator,
787 const std::string & /*outputDir*/) {
788
789 status_t err;
790 std::vector<FQName> packageInterfaces;
791
792 if (fqName.isFullyQualified()) {
793 packageInterfaces = {fqName};
794 } else {
795 err = coordinator->appendPackageInterfacesToVector(
796 fqName, &packageInterfaces);
797 if (err != OK) {
798 return err;
799 }
800 }
801
802 for (const auto &currentFqName : packageInterfaces) {
Steven Morelandc59326e2017-06-20 15:19:30 -0700803 AST* ast = coordinator->parse(currentFqName, {} /* parsed */,
804 Coordinator::Enforce::NO_HASH /* enforcement */);
Steven Morelandf2e44692017-04-18 20:19:09 -0700805
806 if (ast == NULL) {
807 fprintf(stderr,
808 "ERROR: Could not parse %s. Aborting.\n",
809 currentFqName.string().c_str());
810
811 return UNKNOWN_ERROR;
812 }
813
814 printf("%s %s\n",
815 Hash::getHash(ast->getFilename()).hexString().c_str(),
816 currentFqName.string().c_str());
817 }
818
819 return OK;
820}
821
Steven Moreland0241a842017-10-06 10:26:07 -0700822// clang-format off
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700823static std::vector<OutputHandler> formats = {
Steven Moreland3b1ce262017-04-21 14:19:59 -0700824 {"check",
Steven Moreland97e52332017-05-12 16:47:19 -0700825 "Parses the interface to see if valid but doesn't write any files.",
Steven Moreland3b1ce262017-04-21 14:19:59 -0700826 OutputHandler::NOT_NEEDED /* mOutputMode */,
827 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -0700828 generationFunctionForFileOrPackage("check")
Steven Moreland3b1ce262017-04-21 14:19:59 -0700829 },
830
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700831 {"c++",
Steven Moreland97e52332017-05-12 16:47:19 -0700832 "(internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.",
Andreas Huber019d21d2016-10-03 12:59:47 -0700833 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700834 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -0700835 generationFunctionForFileOrPackage("c++")
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700836 },
Steven Moreland1cbf0362017-05-09 14:32:53 -0700837 {"c++-headers",
Steven Moreland97e52332017-05-12 16:47:19 -0700838 "(internal) Generates C++ headers for interface files for talking to HIDL interfaces.",
Steven Moreland1cbf0362017-05-09 14:32:53 -0700839 OutputHandler::NEEDS_DIR /* mOutputMode */,
840 validateForSource,
841 generationFunctionForFileOrPackage("c++-headers")
842 },
Steven Moreland1cbf0362017-05-09 14:32:53 -0700843 {"c++-sources",
Steven Moreland97e52332017-05-12 16:47:19 -0700844 "(internal) Generates C++ sources for interface files for talking to HIDL interfaces.",
Steven Moreland1cbf0362017-05-09 14:32:53 -0700845 OutputHandler::NEEDS_DIR /* mOutputMode */,
846 validateForSource,
847 generationFunctionForFileOrPackage("c++-sources")
848 },
849
Andreas Huber019d21d2016-10-03 12:59:47 -0700850 {"export-header",
Steven Moreland97e52332017-05-12 16:47:19 -0700851 "Generates a header file from @export enumerations to help maintain legacy code.",
Andreas Huber019d21d2016-10-03 12:59:47 -0700852 OutputHandler::NEEDS_FILE /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -0700853 validateIsPackage,
Steven Morelandf47912d2017-05-12 16:25:44 -0700854 generateExportHeaderForPackage(false /* forJava */)
Andreas Huber019d21d2016-10-03 12:59:47 -0700855 },
856
Steven Moreland9c387612016-09-07 09:54:26 -0700857 {"c++-impl",
Steven Moreland97e52332017-05-12 16:47:19 -0700858 "Generates boilerplate implementation of a hidl interface in C++ (for convenience).",
Andreas Huber019d21d2016-10-03 12:59:47 -0700859 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -0700860 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -0700861 generationFunctionForFileOrPackage("c++-impl")
Steven Moreland9c387612016-09-07 09:54:26 -0700862 },
Steven Morelandf2a0f5b2017-07-18 20:39:11 -0700863 {"c++-impl-headers",
864 "c++-impl but headers only",
865 OutputHandler::NEEDS_DIR /* mOutputMode */,
866 validateForSource,
867 generationFunctionForFileOrPackage("c++-impl-headers")
868 },
869 {"c++-impl-sources",
870 "c++-impl but sources only",
871 OutputHandler::NEEDS_DIR /* mOutputMode */,
872 validateForSource,
873 generationFunctionForFileOrPackage("c++-impl-sources")
874 },
Steven Moreland9c387612016-09-07 09:54:26 -0700875
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700876 {"c++-adapter",
877 "Takes a x.(y+n) interface and mocks an x.y interface.",
878 OutputHandler::NEEDS_DIR /* mOutputMode */,
879 validateForSource,
880 generationFunctionForFileOrPackage("c++-adapter")
881 },
882 {"c++-adapter-headers",
Steven Morelandb9a94922017-10-10 15:16:35 -0700883 "c++-adapter but helper headers only",
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700884 OutputHandler::NEEDS_DIR /* mOutputMode */,
885 validateForSource,
886 generationFunctionForFileOrPackage("c++-adapter-headers")
887 },
888 {"c++-adapter-sources",
Steven Morelandb9a94922017-10-10 15:16:35 -0700889 "c++-adapter but helper sources only",
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700890 OutputHandler::NEEDS_DIR /* mOutputMode */,
891 validateForSource,
892 generationFunctionForFileOrPackage("c++-adapter-sources")
893 },
894 {"c++-adapter-main",
Steven Morelandb9a94922017-10-10 15:16:35 -0700895 "c++-adapter but the adapter binary source only",
Steven Moreland9a6da7a2017-09-15 16:21:24 -0700896 OutputHandler::NEEDS_DIR /* mOutputMode */,
897 validateIsPackage,
898 generateAdapterMainSource,
899 },
900
Andreas Huber2831d512016-08-15 09:33:47 -0700901 {"java",
Steven Moreland97e52332017-05-12 16:47:19 -0700902 "(internal) Generates Java library for talking to HIDL interfaces in Java.",
Andreas Huber019d21d2016-10-03 12:59:47 -0700903 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700904 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -0700905 generationFunctionForFileOrPackage("java")
Andreas Huber2831d512016-08-15 09:33:47 -0700906 },
907
Andreas Huber1c507272016-10-05 14:33:21 -0700908 {"java-constants",
Steven Moreland97e52332017-05-12 16:47:19 -0700909 "(internal) Like export-header but for Java (always created by -Lmakefile if @export exists).",
Andreas Huber1c507272016-10-05 14:33:21 -0700910 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -0700911 validateIsPackage,
Steven Morelandf47912d2017-05-12 16:25:44 -0700912 generateExportHeaderForPackage(true /* forJava */)
Andreas Huber1c507272016-10-05 14:33:21 -0700913 },
914
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700915 {"vts",
Steven Moreland97e52332017-05-12 16:47:19 -0700916 "(internal) Generates vts proto files for use in vtsd.",
Andreas Huber019d21d2016-10-03 12:59:47 -0700917 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700918 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -0700919 generationFunctionForFileOrPackage("vts")
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700920 },
921
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700922 {"makefile",
Steven Moreland887b84c2017-10-09 18:40:58 -0700923 "(removed) Used to generate makefiles for -Ljava and -Ljava-constants.",
Steven Morelanda171b562017-05-12 15:18:03 -0700924 OutputHandler::NEEDS_SRC /* mOutputMode */,
Steven Moreland887b84c2017-10-09 18:40:58 -0700925 [](const FQName &, const std::string &) {
926 fprintf(stderr, "ERROR: makefile output is not supported. Use -Landroidbp for all build file generation.\n");
927 return false;
928 },
929 nullptr,
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700930 },
Steven Moreland197d56c2016-09-09 10:03:58 -0700931
Dan Willemsen676abdc2016-09-28 19:42:22 -0700932 {"androidbp",
Steven Moreland887b84c2017-10-09 18:40:58 -0700933 "(internal) Generates Soong bp files for -Lc++-headers, -Lc++-sources, -Ljava, -Ljava-constants, and -Lc++-adapter.",
Steven Morelanda171b562017-05-12 15:18:03 -0700934 OutputHandler::NEEDS_SRC /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -0700935 validateIsPackage,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700936 generateAndroidBpForPackage,
937 },
938
Yifan Hong958ee462016-12-06 17:09:51 -0800939 {"androidbp-impl",
Steven Moreland97e52332017-05-12 16:47:19 -0700940 "Generates boilerplate bp files for implementation created with -Lc++-impl.",
Yifan Hong94bcea02016-10-06 13:51:31 -0700941 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -0700942 validateIsPackage,
Yifan Hong958ee462016-12-06 17:09:51 -0800943 generateAndroidBpImplForPackage,
Steven Morelandf2e44692017-04-18 20:19:09 -0700944 },
945
946 {"hash",
Steven Moreland97e52332017-05-12 16:47:19 -0700947 "Prints hashes of interface in `current.txt` format to standard out.",
Steven Morelandf2e44692017-04-18 20:19:09 -0700948 OutputHandler::NOT_NEEDED /* mOutputMode */,
949 validateForSource,
950 generateHashOutput,
951 },
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700952};
Steven Moreland0241a842017-10-06 10:26:07 -0700953// clang-format on
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700954
955static void usage(const char *me) {
956 fprintf(stderr,
Steven Moreland37c57ee2017-09-25 19:08:56 -0700957 "usage: %s [-p <root path>] -o <output path> -L <language> (-r <interface root>)+ [-t] [-v]"
Jiyong Park37283252017-08-29 14:11:48 +0900958 "fqname+\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700959 me);
960
Steven Moreland97e52332017-05-12 16:47:19 -0700961 fprintf(stderr, " -h: Prints this menu.\n");
962 fprintf(stderr, " -L <language>: The following options are available:\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700963 for (auto &e : formats) {
Steven Moreland97e52332017-05-12 16:47:19 -0700964 fprintf(stderr, " %-16s: %s\n", e.name().c_str(), e.description().c_str());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700965 }
Steven Moreland97e52332017-05-12 16:47:19 -0700966 fprintf(stderr, " -o <output path>: Location to output files.\n");
967 fprintf(stderr, " -p <root path>: Android build root, defaults to $ANDROID_BUILD_TOP or pwd.\n");
968 fprintf(stderr, " -r <package:path root>: E.g., android.hardware:hardware/interfaces.\n");
Jiyong Park37283252017-08-29 14:11:48 +0900969 fprintf(stderr, " -t: generate build scripts (Android.bp) for tests.\n");
Steven Moreland37c57ee2017-09-25 19:08:56 -0700970 fprintf(stderr, " -v: verbose output (locations of touched files).\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700971}
972
Andreas Gampec4ce9262017-04-27 21:03:20 -0700973// hidl is intentionally leaky. Turn off LeakSanitizer by default.
974extern "C" const char *__asan_default_options() {
Evgenii Stepanova3ee97c2017-08-16 14:59:29 -0700975 return "detect_leaks=0";
Andreas Gampec4ce9262017-04-27 21:03:20 -0700976}
977
Andreas Huberb82318c2016-08-02 14:45:54 -0700978int main(int argc, char **argv) {
Andreas Huber737080b2016-08-02 15:38:04 -0700979 const char *me = argv[0];
Steven Moreland3db99f22017-05-11 16:21:46 -0700980 if (argc == 1) {
981 usage(me);
982 exit(1);
983 }
984
Steven Moreland47792c42017-09-20 10:03:20 -0700985 OutputHandler *outputFormat = nullptr;
986 Coordinator coordinator;
987 std::string outputPath;
988
989 const char *ANDROID_BUILD_TOP = getenv("ANDROID_BUILD_TOP");
990 if (ANDROID_BUILD_TOP != nullptr) {
991 coordinator.setRootPath(ANDROID_BUILD_TOP);
992 }
993
Andreas Huberb82318c2016-08-02 14:45:54 -0700994 int res;
Steven Moreland37c57ee2017-09-25 19:08:56 -0700995 while ((res = getopt(argc, argv, "hp:o:r:L:tv")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -0700996 switch (res) {
Steven Morelandf7fa0682017-05-11 16:14:55 -0700997 case 'p':
998 {
Steven Moreland47792c42017-09-20 10:03:20 -0700999 coordinator.setRootPath(optarg);
Steven Morelandf7fa0682017-05-11 16:14:55 -07001000 break;
1001 }
1002
Steven Moreland37c57ee2017-09-25 19:08:56 -07001003 case 'v':
1004 {
1005 coordinator.setVerbose(true);
1006 break;
1007 }
1008
Andreas Huberb82318c2016-08-02 14:45:54 -07001009 case 'o':
1010 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001011 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001012 break;
1013 }
1014
Andreas Huberdca261f2016-08-04 13:47:51 -07001015 case 'r':
1016 {
1017 std::string val(optarg);
1018 auto index = val.find_first_of(':');
Steven Moreland4ff74202017-04-21 14:24:47 -07001019 if (index == std::string::npos) {
1020 fprintf(stderr, "ERROR: -r option must contain ':': %s\n", val.c_str());
1021 exit(1);
1022 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001023
Steven Moreland13594d12017-09-28 23:27:50 +00001024 auto root = val.substr(0, index);
1025 auto path = val.substr(index + 1);
Steven Moreland47792c42017-09-20 10:03:20 -07001026
1027 std::string error;
1028 status_t err = coordinator.addPackagePath(root, path, &error);
1029 if (err != OK) {
1030 fprintf(stderr, "%s\n", error.c_str());
1031 exit(1);
1032 }
1033
Andreas Huberdca261f2016-08-04 13:47:51 -07001034 break;
1035 }
1036
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001037 case 'L':
1038 {
Steven Morelanddd583842017-04-19 13:09:57 -07001039 if (outputFormat != nullptr) {
1040 fprintf(stderr,
1041 "ERROR: only one -L option allowed. \"%s\" already specified.\n",
1042 outputFormat->name().c_str());
1043 exit(1);
1044 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001045 for (auto &e : formats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001046 if (e.name() == optarg) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001047 outputFormat = &e;
1048 break;
1049 }
1050 }
Steven Morelanddd583842017-04-19 13:09:57 -07001051 if (outputFormat == nullptr) {
1052 fprintf(stderr,
1053 "ERROR: unrecognized -L option: \"%s\".\n",
1054 optarg);
1055 exit(1);
1056 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001057 break;
1058 }
1059
Jiyong Park37283252017-08-29 14:11:48 +09001060 case 't': {
1061 generateForTest = true;
1062 break;
1063 }
1064
Andreas Huberb82318c2016-08-02 14:45:54 -07001065 case '?':
1066 case 'h':
1067 default:
1068 {
Andreas Huber737080b2016-08-02 15:38:04 -07001069 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001070 exit(1);
1071 break;
1072 }
1073 }
1074 }
1075
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001076 if (outputFormat == nullptr) {
Steven Morelanddd583842017-04-19 13:09:57 -07001077 fprintf(stderr,
1078 "ERROR: no -L option provided.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001079 exit(1);
1080 }
1081
Jiyong Park37283252017-08-29 14:11:48 +09001082 if (generateForTest && outputFormat->name() != "androidbp") {
1083 fprintf(stderr, "ERROR: -t option is for -Landroidbp only.\n");
1084 exit(1);
1085 }
1086
Andreas Huberb82318c2016-08-02 14:45:54 -07001087 argc -= optind;
1088 argv += optind;
1089
Steven Moreland3effa832017-06-16 16:17:41 -07001090 if (argc == 0) {
1091 fprintf(stderr, "ERROR: no fqname specified.\n");
1092 usage(me);
1093 exit(1);
1094 }
1095
Andreas Huber737080b2016-08-02 15:38:04 -07001096 // Valid options are now in argv[0] .. argv[argc - 1].
1097
Andreas Huber019d21d2016-10-03 12:59:47 -07001098 switch (outputFormat->mOutputMode) {
1099 case OutputHandler::NEEDS_DIR:
1100 case OutputHandler::NEEDS_FILE:
1101 {
1102 if (outputPath.empty()) {
1103 usage(me);
1104 exit(1);
1105 }
1106
1107 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
Howard Chen30f6b492017-08-24 16:50:12 +08001108 if (outputPath.back() != '/') {
Andreas Huber019d21d2016-10-03 12:59:47 -07001109 outputPath += "/";
1110 }
1111 }
1112 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001113 }
Steven Morelanda171b562017-05-12 15:18:03 -07001114 case OutputHandler::NEEDS_SRC:
1115 {
1116 if (outputPath.empty()) {
Steven Moreland47792c42017-09-20 10:03:20 -07001117 outputPath = coordinator.getRootPath();
Steven Morelanda171b562017-05-12 15:18:03 -07001118 }
Howard Chen30f6b492017-08-24 16:50:12 +08001119 if (outputPath.back() != '/') {
1120 outputPath += "/";
1121 }
Steven Morelanda171b562017-05-12 15:18:03 -07001122
1123 break;
1124 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001125
1126 default:
1127 outputPath.clear(); // Unused.
1128 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001129 }
1130
Steven Moreland25c81662017-05-12 14:57:36 -07001131 coordinator.addDefaultPackagePath("android.hardware", "hardware/interfaces");
1132 coordinator.addDefaultPackagePath("android.hidl", "system/libhidl/transport");
1133 coordinator.addDefaultPackagePath("android.frameworks", "frameworks/hardware/interfaces");
1134 coordinator.addDefaultPackagePath("android.system", "system/hardware/interfaces");
Andreas Huber5345ec22016-07-29 13:33:27 -07001135
Andreas Huber737080b2016-08-02 15:38:04 -07001136 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001137 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001138
Steven Morelandbf714212017-10-27 18:29:01 -07001139 // TODO(b/65200821): remove
1140 gCurrentCompileName = "_" + StringHelper::Uppercase(fqName.tokenName());
1141
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001142 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001143 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001144 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001145 exit(1);
1146 }
Andreas Huber881227d2016-08-02 14:20:21 -07001147
Steven Moreland05951b32017-05-12 17:22:22 -07001148 if (!outputFormat->validate(fqName, outputFormat->name())) {
Steven Morelandf2e44692017-04-18 20:19:09 -07001149 fprintf(stderr,
1150 "ERROR: output handler failed.\n");
Andreas Hubere61e3f72016-08-03 10:22:03 -07001151 exit(1);
1152 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001153
1154 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001155 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001156
1157 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001158 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001159 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001160 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001161
Andreas Huberd2943e12016-08-05 11:59:31 -07001162 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001163}