blob: 3969b11d90531ae6dc68dd7b0b193c698eea3cea [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
Steven Moreland5bdfa702017-04-18 23:20:39 -070021#include <hidl-hash/Hash.h>
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070022#include <hidl-util/Formatter.h>
Steven Moreland7ae3d542017-01-18 16:46:01 -080023#include <hidl-util/FQName.h>
Steven Morelandd177b122016-12-12 09:15:37 -080024#include <hidl-util/StringHelper.h>
Andreas Huber68f24592016-07-29 14:53:48 -070025#include <android-base/logging.h>
Iliyan Malchev5bb14022016-08-09 15:04:39 -070026#include <set>
Andreas Huberc9410c72016-07-28 12:18:40 -070027#include <stdio.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070028#include <string>
Andreas Huberb82318c2016-08-02 14:45:54 -070029#include <unistd.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070030#include <vector>
Andreas Huberc9410c72016-07-28 12:18:40 -070031
32using namespace android;
33
Iliyan Malchev5bb14022016-08-09 15:04:39 -070034struct OutputHandler {
35 std::string mKey;
Steven Moreland97e52332017-05-12 16:47:19 -070036 std::string mDescription;
Andreas Huber019d21d2016-10-03 12:59:47 -070037 enum OutputMode {
38 NEEDS_DIR,
39 NEEDS_FILE,
Steven Morelanda171b562017-05-12 15:18:03 -070040 NEEDS_SRC, // for changes inside the source tree itself
Andreas Huber019d21d2016-10-03 12:59:47 -070041 NOT_NEEDED
42 } mOutputMode;
43
Steven Morelanddd583842017-04-19 13:09:57 -070044 const std::string& name() { return mKey; }
Steven Moreland97e52332017-05-12 16:47:19 -070045 const std::string& description() { return mDescription; }
Steven Morelandbbbbeb82017-05-09 14:20:50 -070046
Steven Moreland05951b32017-05-12 17:22:22 -070047 using ValidationFunction = std::function<bool(const FQName &, const std::string &language)>;
Steven Morelandbbbbeb82017-05-09 14:20:50 -070048 using GenerationFunction = std::function<status_t(const FQName &fqName,
49 const char *hidl_gen,
50 Coordinator *coordinator,
51 const std::string &outputDir)>;
52
53 ValidationFunction validate;
54 GenerationFunction generate;
Iliyan Malchev5bb14022016-08-09 15:04:39 -070055};
Andreas Huberdca261f2016-08-04 13:47:51 -070056
Jiyong Park37283252017-08-29 14:11:48 +090057static bool generateForTest = false;
58
Iliyan Malchev5bb14022016-08-09 15:04:39 -070059static status_t generateSourcesForFile(
60 const FQName &fqName,
61 const char *,
62 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -070063 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070064 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -070065 CHECK(fqName.isFullyQualified());
66
Andreas Huber0fa9e392016-08-31 09:05:44 -070067 AST *ast;
Andreas Huberd29724f2016-09-14 09:33:13 -070068 std::string limitToType;
Andreas Huber0fa9e392016-08-31 09:05:44 -070069
70 if (fqName.name().find("types.") == 0) {
71 CHECK(lang == "java"); // Already verified in validate().
72
Andreas Huberd29724f2016-09-14 09:33:13 -070073 limitToType = fqName.name().substr(strlen("types."));
Andreas Huber0fa9e392016-08-31 09:05:44 -070074
Yifan Hongfece6ec2017-01-12 17:04:04 -080075 FQName typesName = fqName.getTypesForPackage();
Andreas Huber0fa9e392016-08-31 09:05:44 -070076 ast = coordinator->parse(typesName);
77 } else {
78 ast = coordinator->parse(fqName);
79 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -070080
81 if (ast == NULL) {
82 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -070083 "ERROR: Could not parse %s. Aborting.\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -070084 fqName.string().c_str());
85
86 return UNKNOWN_ERROR;
87 }
88
Steven Moreland3b1ce262017-04-21 14:19:59 -070089 if (lang == "check") {
90 return OK; // only parsing, not generating
91 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070092 if (lang == "c++") {
93 return ast->generateCpp(outputDir);
94 }
Steven Moreland1cbf0362017-05-09 14:32:53 -070095 if (lang == "c++-headers") {
96 return ast->generateCppHeaders(outputDir);
97 }
98 if (lang == "c++-sources") {
99 return ast->generateCppSources(outputDir);
100 }
Steven Moreland9c387612016-09-07 09:54:26 -0700101 if (lang == "c++-impl") {
102 return ast->generateCppImpl(outputDir);
103 }
Steven Morelandf2a0f5b2017-07-18 20:39:11 -0700104 if (lang == "c++-impl-headers") {
Steven Moreland6d688552017-09-15 11:03:02 -0700105 return ast->generateCppImplHeader(outputDir);
Steven Morelandf2a0f5b2017-07-18 20:39:11 -0700106 }
107 if (lang == "c++-impl-sources") {
Steven Moreland6d688552017-09-15 11:03:02 -0700108 return ast->generateCppImplSource(outputDir);
Steven Morelandf2a0f5b2017-07-18 20:39:11 -0700109 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700110 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700111 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700112 }
113 if (lang == "vts") {
114 return ast->generateVts(outputDir);
115 }
116 // Unknown language.
117 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700118}
119
120static status_t generateSourcesForPackage(
121 const FQName &packageFQName,
122 const char *hidl_gen,
123 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700124 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700125 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700126 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700127 !packageFQName.isFullyQualified() &&
128 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700129
130 std::vector<FQName> packageInterfaces;
131
132 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700133 coordinator->appendPackageInterfacesToVector(packageFQName,
134 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700135
136 if (err != OK) {
137 return err;
138 }
139
140 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700141 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700142 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700143 if (err != OK) {
144 return err;
145 }
146 }
147
148 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700149}
150
Steven Morelandbbbbeb82017-05-09 14:20:50 -0700151OutputHandler::GenerationFunction generationFunctionForFileOrPackage(const std::string &language) {
152 return [language](const FQName &fqName,
153 const char *hidl_gen, Coordinator *coordinator,
154 const std::string &outputDir) -> status_t {
155 if (fqName.isFullyQualified()) {
156 return generateSourcesForFile(fqName,
157 hidl_gen,
158 coordinator,
159 outputDir,
160 language);
161 } else {
162 return generateSourcesForPackage(fqName,
163 hidl_gen,
164 coordinator,
165 outputDir,
166 language);
167 }
168 };
169}
170
Andreas Huberd2943e12016-08-05 11:59:31 -0700171static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700172 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700173}
174
Andreas Huberaa573272017-04-13 09:58:06 -0700175static std::string makeJavaLibraryName(const FQName &packageFQName) {
176 std::string out;
177 out = packageFQName.package();
178 out += "-V";
179 out += packageFQName.version();
180 return out;
181}
182
Steven Moreland5715fed2017-01-16 11:06:47 -0800183static void generatePackagePathsSection(
184 Formatter &out,
185 Coordinator *coordinator,
186 const FQName &packageFQName,
187 const std::set<FQName> &importedPackages,
188 bool forMakefiles = false) {
189 std::set<std::string> options{};
190 for (const auto &interface : importedPackages) {
191 options.insert(coordinator->getPackageRootOption(interface));
192 }
193 options.insert(coordinator->getPackageRootOption(packageFQName));
Steven Morelandf7f2a9a2017-07-21 18:05:38 -0700194 options.insert(coordinator->getPackageRootOption(gIBaseFqName));
Steven Moreland5715fed2017-01-16 11:06:47 -0800195 for (const auto &option : options) {
196 out << "-r"
197 << option
198 << " ";
199 if (forMakefiles) {
200 out << "\\\n";
201 }
202 }
203}
204
Dan Willemsen676abdc2016-09-28 19:42:22 -0700205static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700206 Formatter &out,
207 Coordinator *coordinator,
208 const FQName &packageFQName,
209 const FQName &fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800210 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700211 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700212 out << "\n"
213 << "\n#"
214 << "\n# Build " << fqName.name() << ".hal";
215
Dan Willemsen676abdc2016-09-28 19:42:22 -0700216 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700217 out << " (" << typeName << ")";
218 }
219
220 out << "\n#"
221 << "\nGEN := $(intermediates)/"
222 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800223 << coordinator->getPackagePath(packageFQName, true /* relative */,
224 true /* sanitized */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700225 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700226 out << fqName.name() << ".java";
227 } else {
228 out << typeName << ".java";
229 }
230
231 out << "\n$(GEN): $(HIDL)";
232 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
233 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
234 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700235
236 {
237 AST *ast = coordinator->parse(fqName);
238 CHECK(ast != nullptr);
239 const std::set<FQName>& refs = ast->getImportedNames();
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -0700240 for (const auto& depFQName : refs) {
Iliyan Malchevb9819132016-09-07 12:38:31 -0700241 // If the package of depFQName is the same as this fqName's package,
242 // then add it explicitly as a .hal dependency within the same
243 // package.
244 if (fqName.package() == depFQName.package() &&
245 fqName.version() == depFQName.version()) {
246 // PRIVATE_DEPS is not actually being used in the
247 // auto-generated file, but is necessary if the build rule
248 // ever needs to use the dependency information, since the
249 // built-in Make variables are not supported in the Android
250 // build system.
251 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
252 << depFQName.name() << ".hal";
253 // This is the actual dependency.
254 out << "\n$(GEN): $(LOCAL_PATH)/"
255 << depFQName.name() << ".hal";
256 }
257 }
258 }
259
Andreas Huber0fa9e392016-08-31 09:05:44 -0700260 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
261 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
262 out.indent();
263 out.indent();
264 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800265 << "\n-Ljava \\\n";
266
267 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700268
269 out << packageFQName.string()
270 << "::"
271 << fqName.name();
272
Dan Willemsen676abdc2016-09-28 19:42:22 -0700273 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700274 out << "." << typeName;
275 }
276
277 out << "\n";
278
279 out.unindent();
280 out.unindent();
281
282 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
283 out << "\n\t$(transform-generated-source)";
284 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
285}
286
Dan Willemsen676abdc2016-09-28 19:42:22 -0700287static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700288 Formatter &out,
289 Coordinator *coordinator,
290 const FQName &packageFQName,
291 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800292 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700293 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700294 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700295 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700296 CHECK(typesAST != nullptr);
297
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700298 Scope* rootScope = typesAST->getRootScope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700299
Andreas Huberb747bd92016-09-26 15:55:31 -0700300 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
301 std::sort(
302 subTypes.begin(),
303 subTypes.end(),
304 [](const NamedType *a, const NamedType *b) -> bool {
305 return a->fqName() < b->fqName();
306 });
307
308 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700309 if (type->isTypeDef()) {
310 continue;
311 }
312
Dan Willemsen676abdc2016-09-28 19:42:22 -0700313 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700314 out,
315 coordinator,
316 packageFQName,
317 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800318 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700319 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700320 }
321
322 continue;
323 }
324
Dan Willemsen676abdc2016-09-28 19:42:22 -0700325 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700326 out,
327 coordinator,
328 packageFQName,
329 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800330 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700331 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700332 }
333}
334
Andreas Huber75ae95d2016-10-12 16:08:26 -0700335static status_t isPackageJavaCompatible(
336 const FQName &packageFQName,
337 Coordinator *coordinator,
338 bool *compatible) {
339 std::vector<FQName> todo;
340 status_t err =
341 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
342
343 if (err != OK) {
344 return err;
345 }
346
347 std::set<FQName> seen;
348 for (const auto &iface : todo) {
349 seen.insert(iface);
350 }
351
352 // Form the transitive closure of all imported interfaces (and types.hal-s)
353 // If any one of them is not java compatible, this package isn't either.
354 while (!todo.empty()) {
355 const FQName fqName = todo.back();
356 todo.pop_back();
357
358 AST *ast = coordinator->parse(fqName);
359
360 if (ast == nullptr) {
361 return UNKNOWN_ERROR;
362 }
363
364 if (!ast->isJavaCompatible()) {
365 *compatible = false;
366 return OK;
367 }
368
369 std::set<FQName> importedPackages;
370 ast->getImportedPackages(&importedPackages);
371
372 for (const auto &package : importedPackages) {
373 std::vector<FQName> packageInterfaces;
374 status_t err = coordinator->appendPackageInterfacesToVector(
375 package, &packageInterfaces);
376
377 if (err != OK) {
378 return err;
379 }
380
381 for (const auto &iface : packageInterfaces) {
382 if (seen.find(iface) != seen.end()) {
383 continue;
384 }
385
386 todo.push_back(iface);
387 seen.insert(iface);
388 }
389 }
390 }
391
392 *compatible = true;
393 return OK;
394}
395
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700396static bool packageNeedsJavaCode(
397 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
398 // If there is more than just a types.hal file to this package we'll
399 // definitely need to generate Java code.
400 if (packageInterfaces.size() > 1
401 || packageInterfaces[0].name() != "types") {
402 return true;
403 }
404
405 CHECK(typesAST != nullptr);
406
407 // We'll have to generate Java code if types.hal contains any non-typedef
408 // type declarations.
409
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700410 Scope* rootScope = typesAST->getRootScope();
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700411 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
412
413 for (const auto &subType : subTypes) {
414 if (!subType->isTypeDef()) {
415 return true;
416 }
417 }
418
419 return false;
420}
421
Andreas Huber1c507272016-10-05 14:33:21 -0700422static void generateMakefileSectionForJavaConstants(
423 Formatter &out,
424 Coordinator *coordinator,
425 const FQName &packageFQName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800426 const std::vector<FQName> &packageInterfaces,
427 const std::set<FQName> &importedPackages) {
Andreas Huber1c507272016-10-05 14:33:21 -0700428 out << "\n#"
429 << "\nGEN := $(intermediates)/"
430 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800431 << coordinator->getPackagePath(packageFQName, true /* relative */, true /* sanitized */)
Andreas Huber1c507272016-10-05 14:33:21 -0700432 << "Constants.java";
433
434 out << "\n$(GEN): $(HIDL)\n";
435 for (const auto &iface : packageInterfaces) {
436 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
437 }
438 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
439 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
440 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
441 out.indent();
442 out.indent();
443 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800444 << "\n-Ljava-constants \\\n";
445
446 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber1c507272016-10-05 14:33:21 -0700447
448 out << packageFQName.string();
449 out << "\n";
450
451 out.unindent();
452 out.unindent();
453
454 out << "\n$(GEN):";
455 out << "\n\t$(transform-generated-source)";
456 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
457}
458
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700459static status_t generateMakefileForPackage(
460 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700461 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700462 Coordinator *coordinator,
Steven Morelanda171b562017-05-12 15:18:03 -0700463 const std::string &outputPath) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700464
465 CHECK(packageFQName.isValid() &&
466 !packageFQName.isFullyQualified() &&
467 packageFQName.name().empty());
468
Andreas Huberd2943e12016-08-05 11:59:31 -0700469 std::vector<FQName> packageInterfaces;
470
471 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700472 coordinator->appendPackageInterfacesToVector(packageFQName,
473 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700474
475 if (err != OK) {
476 return err;
477 }
478
479 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700480 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700481 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700482
Andreas Huberd2943e12016-08-05 11:59:31 -0700483 for (const auto &fqName : packageInterfaces) {
484 AST *ast = coordinator->parse(fqName);
485
486 if (ast == NULL) {
487 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700488 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700489 fqName.string().c_str());
490
491 return UNKNOWN_ERROR;
492 }
493
Andreas Huber0fa9e392016-08-31 09:05:44 -0700494 if (fqName.name() == "types") {
495 typesAST = ast;
496 }
497
Yifan Hong40a373d2016-11-30 15:16:47 -0800498 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700499 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700500 }
501
Andreas Huber75ae95d2016-10-12 16:08:26 -0700502 bool packageIsJavaCompatible;
503 err = isPackageJavaCompatible(
504 packageFQName, coordinator, &packageIsJavaCompatible);
505
506 if (err != OK) {
507 return err;
508 }
509
Andreas Huber1c507272016-10-05 14:33:21 -0700510 bool haveJavaConstants = !exportedTypes.empty();
511
512 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800513 // TODO(b/33420795)
514 fprintf(stderr,
515 "WARNING: %s is not java compatible. No java makefile created.\n",
516 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700517 return OK;
518 }
519
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700520 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
521 return OK;
522 }
523
Steven Morelanda171b562017-05-12 15:18:03 -0700524 std::string path = outputPath;
Steven Morelandf7fa0682017-05-11 16:14:55 -0700525 path.append(coordinator->getPackagePath(packageFQName, false /* relative */));
Andreas Huberd2943e12016-08-05 11:59:31 -0700526 path.append("Android.mk");
527
528 CHECK(Coordinator::MakeParentHierarchy(path));
529 FILE *file = fopen(path.c_str(), "w");
530
531 if (file == NULL) {
532 return -errno;
533 }
534
Andreas Huberaa573272017-04-13 09:58:06 -0700535 const std::string libraryName = makeJavaLibraryName(packageFQName);
Andreas Huberd2943e12016-08-05 11:59:31 -0700536
537 Formatter out(file);
538
Dan Willemsen676abdc2016-09-28 19:42:22 -0700539 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
540 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700541
Steven Morelandbc7e8312017-08-01 15:33:52 -0700542 if (packageIsJavaCompatible) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700543 out << "\n"
544 << "########################################"
545 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700546
Dan Willemsen676abdc2016-09-28 19:42:22 -0700547 out << "include $(CLEAR_VARS)\n"
548 << "LOCAL_MODULE := "
549 << libraryName
550 << "-java"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700551 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800552 << "intermediates := $(call local-generated-sources-dir, COMMON)"
553 << "\n\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700554 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
555 << hidl_gen
556 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700557
Dan Willemsen676abdc2016-09-28 19:42:22 -0700558 if (!importedPackages.empty()) {
Steven Morelandbc7e8312017-08-01 15:33:52 -0700559 out << "\n\nLOCAL_JAVA_LIBRARIES := \\";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700560
561 out.indent();
562 for (const auto &importedPackage : importedPackages) {
563 out << "\n"
Andreas Huberaa573272017-04-13 09:58:06 -0700564 << makeJavaLibraryName(importedPackage)
Dan Willemsen676abdc2016-09-28 19:42:22 -0700565 << "-java"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700566 << " \\";
567 }
Steven Morelandbc7e8312017-08-01 15:33:52 -0700568
Dan Willemsen676abdc2016-09-28 19:42:22 -0700569 out << "\n";
570 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700571 }
Sundong Ahnc1432c92017-07-13 23:58:27 +0900572 out << "\nLOCAL_NO_STANDARD_LIBRARIES := true";
Steven Morelandbc7e8312017-08-01 15:33:52 -0700573 out << "\nLOCAL_JAVA_LIBRARIES += core-oj hwbinder";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700574
575 generateMakefileSection(
576 out,
577 coordinator,
578 packageFQName,
579 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800580 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700581 typesAST);
582
Steven Morelandbc7e8312017-08-01 15:33:52 -0700583 out << "\ninclude $(BUILD_JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700584 }
585
Andreas Huber1c507272016-10-05 14:33:21 -0700586 if (haveJavaConstants) {
587 out << "\n"
588 << "########################################"
589 << "########################################\n\n";
590
591 out << "include $(CLEAR_VARS)\n"
592 << "LOCAL_MODULE := "
593 << libraryName
594 << "-java-constants"
595 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800596 << "intermediates := $(call local-generated-sources-dir, COMMON)"
597 << "\n\n"
Andreas Huber1c507272016-10-05 14:33:21 -0700598 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
599 << hidl_gen
600 << "$(HOST_EXECUTABLE_SUFFIX)";
601
602 generateMakefileSectionForJavaConstants(
Steven Moreland5715fed2017-01-16 11:06:47 -0800603 out, coordinator, packageFQName, packageInterfaces, importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700604
605 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
606 << "-> framework.jar\n"
607 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
608 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
609 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
610 }
611
Iliyan Malchev8be09552016-09-22 16:20:33 -0700612 out << "\n\n"
613 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
614
Andreas Huberd2943e12016-08-05 11:59:31 -0700615 return OK;
616}
617
Steven Moreland05951b32017-05-12 17:22:22 -0700618bool validateIsPackage(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700619 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700620 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700621 fprintf(stderr, "ERROR: Expecting package name\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700622 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700623 }
624
625 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700626 fprintf(stderr, "ERROR: Expecting package version\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700627 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700628 }
629
630 if (!fqName.name().empty()) {
631 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700632 "ERROR: Expecting only package name and version.\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700633 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700634 }
635
Steven Moreland05951b32017-05-12 17:22:22 -0700636 return true;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700637}
638
Steven Morelandf7f2a9a2017-07-21 18:05:38 -0700639bool isHidlTransportPackage(const FQName& fqName) {
640 return fqName.package() == gIBasePackageFqName.string() ||
641 fqName.package() == gIManagerPackageFqName.string();
Steven Moreland77cf7642017-06-15 14:49:39 -0700642}
643
Steven Morelandc7946c92017-08-08 14:48:32 -0700644bool isSystemProcessSupportedPackage(const FQName& fqName) {
645 // Technically, so is hidl IBase + IServiceManager, but
646 // these are part of libhidltransport.
647 return fqName.string() == "android.hardware.graphics.allocator@2.0" ||
648 fqName.string() == "android.hardware.graphics.common@1.0" ||
649 fqName.string() == "android.hardware.graphics.mapper@2.0" ||
650 fqName.string() == "android.hardware.renderscript@1.0" ||
651 fqName.string() == "android.hidl.memory@1.0";
652}
653
Steven Moreland5edf5282017-07-20 12:56:58 -0700654bool isSystemPackage(const FQName &package) {
655 return package.inPackage("android.hidl") ||
656 package.inPackage("android.system") ||
657 package.inPackage("android.frameworks") ||
658 package.inPackage("android.hardware");
659}
660
Dan Willemsen676abdc2016-09-28 19:42:22 -0700661static void generateAndroidBpGenSection(
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -0700662 Formatter& out,
663 const FQName& packageFQName,
664 const char* hidl_gen,
665 Coordinator* coordinator,
666 const std::string& halFilegroupName,
667 const std::string& genName,
668 const char* language,
669 const std::vector<FQName>& packageInterfaces,
670 const std::set<FQName>& importedPackages,
671 const std::function<void(Formatter&, const FQName)>& outputFn) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700672 out << "genrule {\n";
673 out.indent();
674 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700675 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700676
Colin Crossd5419bd2016-11-04 15:05:54 -0700677 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Steven Moreland5715fed2017-01-16 11:06:47 -0800678 << " -L" << language << " ";
679
680 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages);
681
682 out << packageFQName.string() << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700683
684 out << "srcs: [\n";
685 out.indent();
Tri Vo6a827fa2017-02-08 10:24:42 -0800686 out << "\":" << halFilegroupName << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700687 out.unindent();
688 out << "],\n";
689
690 out << "out: [\n";
691 out.indent();
692 for (const auto &fqName : packageInterfaces) {
693 outputFn(out, fqName);
694 }
695 out.unindent();
696 out << "],\n";
697
698 out.unindent();
699 out << "}\n\n";
700}
701
Steven Moreland5edf5282017-07-20 12:56:58 -0700702static void generateAndroidBpDependencyList(
703 Formatter &out,
704 const std::set<FQName> &importedPackagesHierarchy,
705 bool generateVendor) {
706 for (const auto &importedPackage : importedPackagesHierarchy) {
707 if (isHidlTransportPackage(importedPackage)) {
708 continue;
709 }
710
711 out << "\"" << makeLibraryName(importedPackage);
712 if (generateVendor && !isSystemPackage(importedPackage)) {
713 out << "_vendor";
714 }
715 out << "\",\n";
716 }
717}
718
Steven Moreland77cf7642017-06-15 14:49:39 -0700719static void generateAndroidBpLibSection(
720 Formatter &out,
721 bool generateVendor,
Steven Morelandc7946c92017-08-08 14:48:32 -0700722 const FQName &packageFQName,
Steven Moreland77cf7642017-06-15 14:49:39 -0700723 const std::string &libraryName,
724 const std::string &genSourceName,
725 const std::string &genHeaderName,
726 const std::set<FQName> &importedPackagesHierarchy) {
727
728 // C++ library definition
Steven Moreland02516de2017-07-26 10:09:22 -0700729 out << "cc_library {\n";
Steven Moreland77cf7642017-06-15 14:49:39 -0700730 out.indent();
731 out << "name: \"" << libraryName << (generateVendor ? "_vendor" : "") << "\",\n"
732 << "defaults: [\"hidl-module-defaults\"],\n"
733 << "generated_sources: [\"" << genSourceName << "\"],\n"
734 << "generated_headers: [\"" << genHeaderName << "\"],\n"
735 << "export_generated_headers: [\"" << genHeaderName << "\"],\n";
736
737 if (generateVendor) {
738 out << "vendor: true,\n";
739 } else {
740 out << "vendor_available: true,\n";
Jiyong Park37283252017-08-29 14:11:48 +0900741 if (!generateForTest) {
742 out << "vndk: ";
743 out.block([&]() {
744 out << "enabled: true,\n";
745 if (isSystemProcessSupportedPackage(packageFQName)) {
746 out << "support_system_process: true,\n";
747 }
748 }) << ",\n";
749 }
Steven Moreland77cf7642017-06-15 14:49:39 -0700750 }
751 out << "shared_libs: [\n";
752
753 out.indent();
754 out << "\"libhidlbase\",\n"
755 << "\"libhidltransport\",\n"
756 << "\"libhwbinder\",\n"
757 << "\"liblog\",\n"
758 << "\"libutils\",\n"
759 << "\"libcutils\",\n";
Steven Moreland5edf5282017-07-20 12:56:58 -0700760 generateAndroidBpDependencyList(out, importedPackagesHierarchy, generateVendor);
Steven Moreland77cf7642017-06-15 14:49:39 -0700761 out.unindent();
762
763 out << "],\n";
764
765 out << "export_shared_lib_headers: [\n";
766 out.indent();
767 out << "\"libhidlbase\",\n"
768 << "\"libhidltransport\",\n"
769 << "\"libhwbinder\",\n"
770 << "\"libutils\",\n";
Steven Moreland5edf5282017-07-20 12:56:58 -0700771 generateAndroidBpDependencyList(out, importedPackagesHierarchy, generateVendor);
Steven Moreland77cf7642017-06-15 14:49:39 -0700772 out.unindent();
773 out << "],\n";
774 out.unindent();
775
776 out << "}\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700777}
778
Dan Willemsen676abdc2016-09-28 19:42:22 -0700779static status_t generateAndroidBpForPackage(
780 const FQName &packageFQName,
781 const char *hidl_gen,
782 Coordinator *coordinator,
Steven Morelanda171b562017-05-12 15:18:03 -0700783 const std::string &outputPath) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700784
785 CHECK(packageFQName.isValid() &&
786 !packageFQName.isFullyQualified() &&
787 packageFQName.name().empty());
788
789 std::vector<FQName> packageInterfaces;
790
791 status_t err =
792 coordinator->appendPackageInterfacesToVector(packageFQName,
793 &packageInterfaces);
794
795 if (err != OK) {
796 return err;
797 }
798
Steven Morelandff5262b2017-03-20 06:59:03 -0700799 std::set<FQName> importedPackagesHierarchy;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700800 AST *typesAST = nullptr;
801
802 for (const auto &fqName : packageInterfaces) {
803 AST *ast = coordinator->parse(fqName);
804
805 if (ast == NULL) {
806 fprintf(stderr,
807 "ERROR: Could not parse %s. Aborting.\n",
808 fqName.string().c_str());
809
810 return UNKNOWN_ERROR;
811 }
812
813 if (fqName.name() == "types") {
814 typesAST = ast;
815 }
816
Steven Morelandff5262b2017-03-20 06:59:03 -0700817 ast->getImportedPackagesHierarchy(&importedPackagesHierarchy);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700818 }
819
Steven Morelanda171b562017-05-12 15:18:03 -0700820 std::string path = outputPath;
Steven Morelandf7fa0682017-05-11 16:14:55 -0700821 path.append(coordinator->getPackagePath(packageFQName, false /* relative */));
Dan Willemsen676abdc2016-09-28 19:42:22 -0700822 path.append("Android.bp");
823
824 CHECK(Coordinator::MakeParentHierarchy(path));
825 FILE *file = fopen(path.c_str(), "w");
826
827 if (file == NULL) {
828 return -errno;
829 }
830
831 const std::string libraryName = makeLibraryName(packageFQName);
Tri Vo15052c62017-02-06 10:04:07 -0800832 const std::string halFilegroupName = libraryName + "_hal";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700833 const std::string genSourceName = libraryName + "_genc++";
834 const std::string genHeaderName = libraryName + "_genc++_headers";
835 const std::string pathPrefix =
836 coordinator->convertPackageRootToPath(packageFQName) +
837 coordinator->getPackagePath(packageFQName, true /* relative */);
838
839 Formatter out(file);
840
841 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
842
Tri Vo15052c62017-02-06 10:04:07 -0800843 // Rule to generate .hal filegroup
844 out << "filegroup {\n";
845 out.indent();
846 out << "name: \"" << halFilegroupName << "\",\n";
847 out << "srcs: [\n";
848 out.indent();
849 for (const auto &fqName : packageInterfaces) {
850 out << "\"" << fqName.name() << ".hal\",\n";
851 }
852 out.unindent();
853 out << "],\n";
854 out.unindent();
855 out << "}\n\n";
856
Dan Willemsen676abdc2016-09-28 19:42:22 -0700857 // Rule to generate the C++ source files
858 generateAndroidBpGenSection(
859 out,
860 packageFQName,
861 hidl_gen,
862 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800863 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700864 genSourceName,
Steven Moreland1cbf0362017-05-09 14:32:53 -0700865 "c++-sources",
Dan Willemsen676abdc2016-09-28 19:42:22 -0700866 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700867 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700868 [&pathPrefix](Formatter &out, const FQName &fqName) {
869 if (fqName.name() == "types") {
870 out << "\"" << pathPrefix << "types.cpp\",\n";
871 } else {
872 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
873 }
874 });
875
876 // Rule to generate the C++ header files
877 generateAndroidBpGenSection(
878 out,
879 packageFQName,
880 hidl_gen,
881 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800882 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700883 genHeaderName,
Steven Moreland1cbf0362017-05-09 14:32:53 -0700884 "c++-headers",
Dan Willemsen676abdc2016-09-28 19:42:22 -0700885 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700886 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700887 [&pathPrefix](Formatter &out, const FQName &fqName) {
888 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
889 if (fqName.name() != "types") {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800890 out << "\"" << pathPrefix << fqName.getInterfaceHwName() << ".h\",\n";
891 out << "\"" << pathPrefix << fqName.getInterfaceStubName() << ".h\",\n";
892 out << "\"" << pathPrefix << fqName.getInterfaceProxyName() << ".h\",\n";
893 out << "\"" << pathPrefix << fqName.getInterfacePassthroughName() << ".h\",\n";
Steven Moreland9774d622017-03-24 21:51:45 -0700894 } else {
895 out << "\"" << pathPrefix << "hwtypes.h\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700896 }
897 });
898
Steven Morelandf5f593f2017-05-02 13:13:00 -0700899 if (isHidlTransportPackage(packageFQName)) {
900 out << "// " << packageFQName.string() << " is exported from libhidltransport\n";
Steven Moreland0e875df2017-04-25 13:24:17 -0700901 } else {
Steven Moreland77cf7642017-06-15 14:49:39 -0700902 generateAndroidBpLibSection(
903 out,
904 false /* generateVendor */,
Steven Morelandc7946c92017-08-08 14:48:32 -0700905 packageFQName,
Steven Moreland77cf7642017-06-15 14:49:39 -0700906 libraryName,
907 genSourceName,
908 genHeaderName,
909 importedPackagesHierarchy);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700910
Steven Moreland77cf7642017-06-15 14:49:39 -0700911 // TODO(b/35813011): make all libraries vendor_available
912 // Explicitly create '_vendor' copies of libraries so that
913 // vendor code can link against the extensions. When this is
914 // used, framework code should link against vendor.awesome.foo@1.0
915 // and code on the vendor image should link against
916 // vendor.awesome.foo@1.0_vendor. For libraries with the below extensions,
917 // they will be available even on the generic system image.
918 // Because of this, they should always be referenced without the
919 // '_vendor' name suffix.
Steven Moreland5edf5282017-07-20 12:56:58 -0700920 if (!isSystemPackage(packageFQName)) {
Steven Moreland77cf7642017-06-15 14:49:39 -0700921
922 // Note, not using cc_defaults here since it's already not used and
923 // because generating this libraries will be removed when the VNDK
924 // is enabled (done by the build system itself).
925 out.endl();
926 generateAndroidBpLibSection(
927 out,
928 true /* generateVendor */,
Steven Morelandc7946c92017-08-08 14:48:32 -0700929 packageFQName,
Steven Moreland77cf7642017-06-15 14:49:39 -0700930 libraryName,
931 genSourceName,
932 genHeaderName,
933 importedPackagesHierarchy);
Steven Moreland1b2167b2017-05-01 10:06:21 -0700934 }
Yifan Hongc1f9b8d2016-11-07 14:35:44 -0800935 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700936
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800937 return OK;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700938}
939
Yifan Hong958ee462016-12-06 17:09:51 -0800940static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -0700941 const FQName &packageFQName,
942 const char *,
943 Coordinator *coordinator,
944 const std::string &outputDir) {
945
Iliyan Malchev4923f932016-09-09 13:04:59 -0700946 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700947
948 std::vector<FQName> packageInterfaces;
949
950 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700951 coordinator->appendPackageInterfacesToVector(packageFQName,
952 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700953
954 if (err != OK) {
955 return err;
956 }
957
958 std::set<FQName> importedPackages;
959
960 for (const auto &fqName : packageInterfaces) {
961 AST *ast = coordinator->parse(fqName);
962
963 if (ast == NULL) {
964 fprintf(stderr,
965 "ERROR: Could not parse %s. Aborting.\n",
966 fqName.string().c_str());
967
968 return UNKNOWN_ERROR;
969 }
970
971 ast->getImportedPackages(&importedPackages);
972 }
973
Yifan Hongaafed702016-12-14 12:59:47 -0800974 std::string path = outputDir + "Android.bp";
Steven Moreland197d56c2016-09-09 10:03:58 -0700975
976 CHECK(Coordinator::MakeParentHierarchy(path));
977 FILE *file = fopen(path.c_str(), "w");
978
979 if (file == NULL) {
980 return -errno;
981 }
982
983 Formatter out(file);
984
Yifan Hong958ee462016-12-06 17:09:51 -0800985 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800986 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800987 out << "name: \"" << libraryName << "\",\n"
988 << "relative_install_path: \"hw\",\n"
Steven Morelandf8a22e92017-02-15 18:46:04 -0800989 << "proprietary: true,\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800990 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800991 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800992 for (const auto &fqName : packageInterfaces) {
993 if (fqName.name() == "types") {
994 continue;
995 }
996 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
997 }
998 });
999 out << "],\n"
1000 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001001 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -08001002 out << "\"libhidlbase\",\n"
1003 << "\"libhidltransport\",\n"
Yifan Hong958ee462016-12-06 17:09:51 -08001004 << "\"libutils\",\n"
1005 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -07001006
Yifan Hong958ee462016-12-06 17:09:51 -08001007 for (const auto &importedPackage : importedPackages) {
Steven Morelanddadd1842017-05-09 13:24:54 -07001008 if (isHidlTransportPackage(importedPackage)) {
1009 continue;
1010 }
1011
Yifan Hong958ee462016-12-06 17:09:51 -08001012 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
1013 }
1014 });
1015 out << "],\n";
1016 });
1017 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -07001018
1019 return OK;
1020}
1021
Steven Moreland05951b32017-05-12 17:22:22 -07001022bool validateForSource(
Andreas Huber0fa9e392016-08-31 09:05:44 -07001023 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001024 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -07001025 fprintf(stderr, "ERROR: Expecting package name\n");
Steven Moreland05951b32017-05-12 17:22:22 -07001026 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001027 }
1028
1029 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -07001030 fprintf(stderr, "ERROR: Expecting package version\n");
Steven Moreland05951b32017-05-12 17:22:22 -07001031 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001032 }
1033
Andreas Huber0fa9e392016-08-31 09:05:44 -07001034 const std::string &name = fqName.name();
1035 if (!name.empty()) {
1036 if (name.find('.') == std::string::npos) {
Steven Moreland05951b32017-05-12 17:22:22 -07001037 return true;
Andreas Huber0fa9e392016-08-31 09:05:44 -07001038 }
1039
1040 if (language != "java" || name.find("types.") != 0) {
1041 // When generating java sources for "types.hal", output can be
1042 // constrained to just one of the top-level types declared
1043 // by using the extended syntax
1044 // android.hardware.Foo@1.0::types.TopLevelTypeName.
1045 // In all other cases (different language, not 'types') the dot
1046 // notation in the name is illegal in this context.
Steven Moreland05951b32017-05-12 17:22:22 -07001047 return false;
Andreas Huber0fa9e392016-08-31 09:05:44 -07001048 }
1049
Steven Moreland05951b32017-05-12 17:22:22 -07001050 return true;
Andreas Huber0fa9e392016-08-31 09:05:44 -07001051 }
1052
Steven Moreland05951b32017-05-12 17:22:22 -07001053 return true;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001054}
1055
Steven Morelandf47912d2017-05-12 16:25:44 -07001056OutputHandler::GenerationFunction generateExportHeaderForPackage(bool forJava) {
1057 return [forJava](const FQName &packageFQName,
1058 const char * /* hidl_gen */,
1059 Coordinator *coordinator,
1060 const std::string &outputPath) -> status_t {
1061 CHECK(packageFQName.isValid()
1062 && !packageFQName.package().empty()
1063 && !packageFQName.version().empty()
1064 && packageFQName.name().empty());
Andreas Huber019d21d2016-10-03 12:59:47 -07001065
Steven Morelandf47912d2017-05-12 16:25:44 -07001066 std::vector<FQName> packageInterfaces;
Andreas Huber019d21d2016-10-03 12:59:47 -07001067
Steven Morelandf47912d2017-05-12 16:25:44 -07001068 status_t err = coordinator->appendPackageInterfacesToVector(
1069 packageFQName, &packageInterfaces);
Andreas Huber019d21d2016-10-03 12:59:47 -07001070
Steven Morelandf47912d2017-05-12 16:25:44 -07001071 if (err != OK) {
1072 return err;
Andreas Huber019d21d2016-10-03 12:59:47 -07001073 }
1074
Steven Morelandf47912d2017-05-12 16:25:44 -07001075 std::vector<const Type *> exportedTypes;
Andreas Huber019d21d2016-10-03 12:59:47 -07001076
Steven Morelandf47912d2017-05-12 16:25:44 -07001077 for (const auto &fqName : packageInterfaces) {
1078 AST *ast = coordinator->parse(fqName);
1079
1080 if (ast == NULL) {
1081 fprintf(stderr,
1082 "ERROR: Could not parse %s. Aborting.\n",
1083 fqName.string().c_str());
1084
1085 return UNKNOWN_ERROR;
1086 }
1087
1088 ast->appendToExportedTypesVector(&exportedTypes);
1089 }
1090
1091 if (exportedTypes.empty()) {
1092 return OK;
1093 }
1094
1095 std::string path = outputPath;
1096
1097 if (forJava) {
1098 path.append(coordinator->convertPackageRootToPath(packageFQName));
1099
1100 path.append(coordinator->getPackagePath(
1101 packageFQName, true /* relative */, true /* sanitized */));
1102
1103 path.append("Constants.java");
1104 }
1105
1106 CHECK(Coordinator::MakeParentHierarchy(path));
1107 FILE *file = fopen(path.c_str(), "w");
1108
1109 if (file == nullptr) {
1110 return -errno;
1111 }
1112
1113 Formatter out(file);
1114
1115 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
1116 << "// Source: " << packageFQName.string() << "\n"
1117 << "// Root: " << coordinator->getPackageRootOption(packageFQName) << "\n\n";
1118
1119 std::string guard;
1120 if (forJava) {
1121 out << "package " << packageFQName.javaPackage() << ";\n\n";
1122 out << "public class Constants {\n";
1123 out.indent();
1124 } else {
1125 guard = "HIDL_GENERATED_";
1126 guard += StringHelper::Uppercase(packageFQName.tokenName());
1127 guard += "_";
1128 guard += "EXPORTED_CONSTANTS_H_";
1129
1130 out << "#ifndef "
1131 << guard
1132 << "\n#define "
1133 << guard
1134 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
1135 }
1136
1137 for (const auto &type : exportedTypes) {
1138 type->emitExportedHeader(out, forJava);
1139 }
1140
1141 if (forJava) {
1142 out.unindent();
1143 out << "}\n";
1144 } else {
1145 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
1146 << guard
1147 << "\n";
1148 }
1149
Andreas Huber019d21d2016-10-03 12:59:47 -07001150 return OK;
Steven Morelandf47912d2017-05-12 16:25:44 -07001151 };
Andreas Huber019d21d2016-10-03 12:59:47 -07001152}
1153
Steven Morelandf2e44692017-04-18 20:19:09 -07001154static status_t generateHashOutput(const FQName &fqName,
1155 const char* /*hidl_gen*/,
1156 Coordinator *coordinator,
1157 const std::string & /*outputDir*/) {
1158
1159 status_t err;
1160 std::vector<FQName> packageInterfaces;
1161
1162 if (fqName.isFullyQualified()) {
1163 packageInterfaces = {fqName};
1164 } else {
1165 err = coordinator->appendPackageInterfacesToVector(
1166 fqName, &packageInterfaces);
1167 if (err != OK) {
1168 return err;
1169 }
1170 }
1171
1172 for (const auto &currentFqName : packageInterfaces) {
Steven Morelandc59326e2017-06-20 15:19:30 -07001173 AST* ast = coordinator->parse(currentFqName, {} /* parsed */,
1174 Coordinator::Enforce::NO_HASH /* enforcement */);
Steven Morelandf2e44692017-04-18 20:19:09 -07001175
1176 if (ast == NULL) {
1177 fprintf(stderr,
1178 "ERROR: Could not parse %s. Aborting.\n",
1179 currentFqName.string().c_str());
1180
1181 return UNKNOWN_ERROR;
1182 }
1183
1184 printf("%s %s\n",
1185 Hash::getHash(ast->getFilename()).hexString().c_str(),
1186 currentFqName.string().c_str());
1187 }
1188
1189 return OK;
1190}
1191
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001192static std::vector<OutputHandler> formats = {
Steven Moreland3b1ce262017-04-21 14:19:59 -07001193 {"check",
Steven Moreland97e52332017-05-12 16:47:19 -07001194 "Parses the interface to see if valid but doesn't write any files.",
Steven Moreland3b1ce262017-04-21 14:19:59 -07001195 OutputHandler::NOT_NEEDED /* mOutputMode */,
1196 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001197 generationFunctionForFileOrPackage("check")
Steven Moreland3b1ce262017-04-21 14:19:59 -07001198 },
1199
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001200 {"c++",
Steven Moreland97e52332017-05-12 16:47:19 -07001201 "(internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001202 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001203 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001204 generationFunctionForFileOrPackage("c++")
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001205 },
1206
Steven Moreland1cbf0362017-05-09 14:32:53 -07001207 {"c++-headers",
Steven Moreland97e52332017-05-12 16:47:19 -07001208 "(internal) Generates C++ headers for interface files for talking to HIDL interfaces.",
Steven Moreland1cbf0362017-05-09 14:32:53 -07001209 OutputHandler::NEEDS_DIR /* mOutputMode */,
1210 validateForSource,
1211 generationFunctionForFileOrPackage("c++-headers")
1212 },
1213
1214 {"c++-sources",
Steven Moreland97e52332017-05-12 16:47:19 -07001215 "(internal) Generates C++ sources for interface files for talking to HIDL interfaces.",
Steven Moreland1cbf0362017-05-09 14:32:53 -07001216 OutputHandler::NEEDS_DIR /* mOutputMode */,
1217 validateForSource,
1218 generationFunctionForFileOrPackage("c++-sources")
1219 },
1220
Andreas Huber019d21d2016-10-03 12:59:47 -07001221 {"export-header",
Steven Moreland97e52332017-05-12 16:47:19 -07001222 "Generates a header file from @export enumerations to help maintain legacy code.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001223 OutputHandler::NEEDS_FILE /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -07001224 validateIsPackage,
Steven Morelandf47912d2017-05-12 16:25:44 -07001225 generateExportHeaderForPackage(false /* forJava */)
Andreas Huber019d21d2016-10-03 12:59:47 -07001226 },
1227
Steven Moreland9c387612016-09-07 09:54:26 -07001228 {"c++-impl",
Steven Moreland97e52332017-05-12 16:47:19 -07001229 "Generates boilerplate implementation of a hidl interface in C++ (for convenience).",
Andreas Huber019d21d2016-10-03 12:59:47 -07001230 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001231 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001232 generationFunctionForFileOrPackage("c++-impl")
Steven Moreland9c387612016-09-07 09:54:26 -07001233 },
Steven Morelandf2a0f5b2017-07-18 20:39:11 -07001234 {"c++-impl-headers",
1235 "c++-impl but headers only",
1236 OutputHandler::NEEDS_DIR /* mOutputMode */,
1237 validateForSource,
1238 generationFunctionForFileOrPackage("c++-impl-headers")
1239 },
1240 {"c++-impl-sources",
1241 "c++-impl but sources only",
1242 OutputHandler::NEEDS_DIR /* mOutputMode */,
1243 validateForSource,
1244 generationFunctionForFileOrPackage("c++-impl-sources")
1245 },
Steven Moreland9c387612016-09-07 09:54:26 -07001246
Andreas Huber2831d512016-08-15 09:33:47 -07001247 {"java",
Steven Moreland97e52332017-05-12 16:47:19 -07001248 "(internal) Generates Java library for talking to HIDL interfaces in Java.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001249 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001250 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001251 generationFunctionForFileOrPackage("java")
Andreas Huber2831d512016-08-15 09:33:47 -07001252 },
1253
Andreas Huber1c507272016-10-05 14:33:21 -07001254 {"java-constants",
Steven Moreland97e52332017-05-12 16:47:19 -07001255 "(internal) Like export-header but for Java (always created by -Lmakefile if @export exists).",
Andreas Huber1c507272016-10-05 14:33:21 -07001256 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -07001257 validateIsPackage,
Steven Morelandf47912d2017-05-12 16:25:44 -07001258 generateExportHeaderForPackage(true /* forJava */)
Andreas Huber1c507272016-10-05 14:33:21 -07001259 },
1260
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001261 {"vts",
Steven Moreland97e52332017-05-12 16:47:19 -07001262 "(internal) Generates vts proto files for use in vtsd.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001263 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001264 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001265 generationFunctionForFileOrPackage("vts")
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001266 },
1267
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001268 {"makefile",
Steven Moreland97e52332017-05-12 16:47:19 -07001269 "(internal) Generates makefiles for -Ljava and -Ljava-constants.",
Steven Morelanda171b562017-05-12 15:18:03 -07001270 OutputHandler::NEEDS_SRC /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -07001271 validateIsPackage,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001272 generateMakefileForPackage,
1273 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001274
Dan Willemsen676abdc2016-09-28 19:42:22 -07001275 {"androidbp",
Steven Moreland97e52332017-05-12 16:47:19 -07001276 "(internal) Generates Soong bp files for -Lc++-headers and -Lc++-sources.",
Steven Morelanda171b562017-05-12 15:18:03 -07001277 OutputHandler::NEEDS_SRC /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -07001278 validateIsPackage,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001279 generateAndroidBpForPackage,
1280 },
1281
Yifan Hong958ee462016-12-06 17:09:51 -08001282 {"androidbp-impl",
Steven Moreland97e52332017-05-12 16:47:19 -07001283 "Generates boilerplate bp files for implementation created with -Lc++-impl.",
Yifan Hong94bcea02016-10-06 13:51:31 -07001284 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -07001285 validateIsPackage,
Yifan Hong958ee462016-12-06 17:09:51 -08001286 generateAndroidBpImplForPackage,
Steven Morelandf2e44692017-04-18 20:19:09 -07001287 },
1288
1289 {"hash",
Steven Moreland97e52332017-05-12 16:47:19 -07001290 "Prints hashes of interface in `current.txt` format to standard out.",
Steven Morelandf2e44692017-04-18 20:19:09 -07001291 OutputHandler::NOT_NEEDED /* mOutputMode */,
1292 validateForSource,
1293 generateHashOutput,
1294 },
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001295};
1296
1297static void usage(const char *me) {
1298 fprintf(stderr,
Jiyong Park37283252017-08-29 14:11:48 +09001299 "usage: %s [-p <root path>] -o <output path> -L <language> (-r <interface root>)+ [-t] "
1300 "fqname+\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001301 me);
1302
Steven Moreland97e52332017-05-12 16:47:19 -07001303 fprintf(stderr, " -h: Prints this menu.\n");
1304 fprintf(stderr, " -L <language>: The following options are available:\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001305 for (auto &e : formats) {
Steven Moreland97e52332017-05-12 16:47:19 -07001306 fprintf(stderr, " %-16s: %s\n", e.name().c_str(), e.description().c_str());
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001307 }
Steven Moreland97e52332017-05-12 16:47:19 -07001308 fprintf(stderr, " -o <output path>: Location to output files.\n");
1309 fprintf(stderr, " -p <root path>: Android build root, defaults to $ANDROID_BUILD_TOP or pwd.\n");
1310 fprintf(stderr, " -r <package:path root>: E.g., android.hardware:hardware/interfaces.\n");
Jiyong Park37283252017-08-29 14:11:48 +09001311 fprintf(stderr, " -t: generate build scripts (Android.bp) for tests.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001312}
1313
Andreas Gampec4ce9262017-04-27 21:03:20 -07001314// hidl is intentionally leaky. Turn off LeakSanitizer by default.
1315extern "C" const char *__asan_default_options() {
Evgenii Stepanova3ee97c2017-08-16 14:59:29 -07001316 return "detect_leaks=0";
Andreas Gampec4ce9262017-04-27 21:03:20 -07001317}
1318
Andreas Huberb82318c2016-08-02 14:45:54 -07001319int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001320 std::string outputPath;
Steven Morelandf7fa0682017-05-11 16:14:55 -07001321 std::string rootPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001322 std::vector<std::string> packageRootPaths;
1323 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001324
Andreas Huber737080b2016-08-02 15:38:04 -07001325 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001326 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001327
Steven Moreland3db99f22017-05-11 16:21:46 -07001328 if (argc == 1) {
1329 usage(me);
1330 exit(1);
1331 }
1332
Andreas Huberb82318c2016-08-02 14:45:54 -07001333 int res;
Jiyong Park37283252017-08-29 14:11:48 +09001334 while ((res = getopt(argc, argv, "hp:o:r:L:t")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001335 switch (res) {
Steven Morelandf7fa0682017-05-11 16:14:55 -07001336 case 'p':
1337 {
1338 rootPath = optarg;
1339 break;
1340 }
1341
Andreas Huberb82318c2016-08-02 14:45:54 -07001342 case 'o':
1343 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001344 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001345 break;
1346 }
1347
Andreas Huberdca261f2016-08-04 13:47:51 -07001348 case 'r':
1349 {
1350 std::string val(optarg);
1351 auto index = val.find_first_of(':');
Steven Moreland4ff74202017-04-21 14:24:47 -07001352 if (index == std::string::npos) {
1353 fprintf(stderr, "ERROR: -r option must contain ':': %s\n", val.c_str());
1354 exit(1);
1355 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001356
1357 auto package = val.substr(0, index);
1358 auto path = val.substr(index + 1);
1359 packageRootPaths.push_back(path);
1360 packageRoots.push_back(package);
1361 break;
1362 }
1363
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001364 case 'L':
1365 {
Steven Morelanddd583842017-04-19 13:09:57 -07001366 if (outputFormat != nullptr) {
1367 fprintf(stderr,
1368 "ERROR: only one -L option allowed. \"%s\" already specified.\n",
1369 outputFormat->name().c_str());
1370 exit(1);
1371 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001372 for (auto &e : formats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001373 if (e.name() == optarg) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001374 outputFormat = &e;
1375 break;
1376 }
1377 }
Steven Morelanddd583842017-04-19 13:09:57 -07001378 if (outputFormat == nullptr) {
1379 fprintf(stderr,
1380 "ERROR: unrecognized -L option: \"%s\".\n",
1381 optarg);
1382 exit(1);
1383 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001384 break;
1385 }
1386
Jiyong Park37283252017-08-29 14:11:48 +09001387 case 't': {
1388 generateForTest = true;
1389 break;
1390 }
1391
Andreas Huberb82318c2016-08-02 14:45:54 -07001392 case '?':
1393 case 'h':
1394 default:
1395 {
Andreas Huber737080b2016-08-02 15:38:04 -07001396 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001397 exit(1);
1398 break;
1399 }
1400 }
1401 }
1402
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001403 if (outputFormat == nullptr) {
Steven Morelanddd583842017-04-19 13:09:57 -07001404 fprintf(stderr,
1405 "ERROR: no -L option provided.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001406 exit(1);
1407 }
1408
Jiyong Park37283252017-08-29 14:11:48 +09001409 if (generateForTest && outputFormat->name() != "androidbp") {
1410 fprintf(stderr, "ERROR: -t option is for -Landroidbp only.\n");
1411 exit(1);
1412 }
1413
Andreas Huberb82318c2016-08-02 14:45:54 -07001414 argc -= optind;
1415 argv += optind;
1416
Steven Moreland3effa832017-06-16 16:17:41 -07001417 if (argc == 0) {
1418 fprintf(stderr, "ERROR: no fqname specified.\n");
1419 usage(me);
1420 exit(1);
1421 }
1422
Steven Morelandf7fa0682017-05-11 16:14:55 -07001423 if (rootPath.empty()) {
1424 const char *ANDROID_BUILD_TOP = getenv("ANDROID_BUILD_TOP");
1425
1426 if (ANDROID_BUILD_TOP != nullptr) {
1427 rootPath = ANDROID_BUILD_TOP;
1428 }
1429
1430 // else default to pwd
1431 }
1432
1433 if (!rootPath.empty() && !StringHelper::EndsWith(rootPath, "/")) {
1434 rootPath += "/";
1435 }
1436
Andreas Huber737080b2016-08-02 15:38:04 -07001437 // Valid options are now in argv[0] .. argv[argc - 1].
1438
Andreas Huber019d21d2016-10-03 12:59:47 -07001439 switch (outputFormat->mOutputMode) {
1440 case OutputHandler::NEEDS_DIR:
1441 case OutputHandler::NEEDS_FILE:
1442 {
1443 if (outputPath.empty()) {
1444 usage(me);
1445 exit(1);
1446 }
1447
1448 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
Howard Chen30f6b492017-08-24 16:50:12 +08001449 if (outputPath.back() != '/') {
Andreas Huber019d21d2016-10-03 12:59:47 -07001450 outputPath += "/";
1451 }
1452 }
1453 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001454 }
Steven Morelanda171b562017-05-12 15:18:03 -07001455 case OutputHandler::NEEDS_SRC:
1456 {
1457 if (outputPath.empty()) {
1458 outputPath = rootPath;
1459 }
Howard Chen30f6b492017-08-24 16:50:12 +08001460 if (outputPath.back() != '/') {
1461 outputPath += "/";
1462 }
Steven Morelanda171b562017-05-12 15:18:03 -07001463
1464 break;
1465 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001466
1467 default:
1468 outputPath.clear(); // Unused.
1469 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001470 }
1471
Steven Morelandf7fa0682017-05-11 16:14:55 -07001472 Coordinator coordinator(packageRootPaths, packageRoots, rootPath);
Steven Moreland25c81662017-05-12 14:57:36 -07001473 coordinator.addDefaultPackagePath("android.hardware", "hardware/interfaces");
1474 coordinator.addDefaultPackagePath("android.hidl", "system/libhidl/transport");
1475 coordinator.addDefaultPackagePath("android.frameworks", "frameworks/hardware/interfaces");
1476 coordinator.addDefaultPackagePath("android.system", "system/hardware/interfaces");
Andreas Huber5345ec22016-07-29 13:33:27 -07001477
Andreas Huber737080b2016-08-02 15:38:04 -07001478 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001479 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001480
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001481 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001482 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001483 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001484 exit(1);
1485 }
Andreas Huber881227d2016-08-02 14:20:21 -07001486
Steven Moreland05951b32017-05-12 17:22:22 -07001487 if (!outputFormat->validate(fqName, outputFormat->name())) {
Steven Morelandf2e44692017-04-18 20:19:09 -07001488 fprintf(stderr,
1489 "ERROR: output handler failed.\n");
Andreas Hubere61e3f72016-08-03 10:22:03 -07001490 exit(1);
1491 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001492
1493 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001494 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001495
1496 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001497 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001498 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001499 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001500
Andreas Huberd2943e12016-08-05 11:59:31 -07001501 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001502}