blob: 0ebc96648712eefb018a660d7762f6a5115f5d75 [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
Iliyan Malchev5bb14022016-08-09 15:04:39 -070057static status_t generateSourcesForFile(
58 const FQName &fqName,
59 const char *,
60 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -070061 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070062 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -070063 CHECK(fqName.isFullyQualified());
64
Andreas Huber0fa9e392016-08-31 09:05:44 -070065 AST *ast;
Andreas Huberd29724f2016-09-14 09:33:13 -070066 std::string limitToType;
Andreas Huber0fa9e392016-08-31 09:05:44 -070067
68 if (fqName.name().find("types.") == 0) {
69 CHECK(lang == "java"); // Already verified in validate().
70
Andreas Huberd29724f2016-09-14 09:33:13 -070071 limitToType = fqName.name().substr(strlen("types."));
Andreas Huber0fa9e392016-08-31 09:05:44 -070072
Yifan Hongfece6ec2017-01-12 17:04:04 -080073 FQName typesName = fqName.getTypesForPackage();
Andreas Huber0fa9e392016-08-31 09:05:44 -070074 ast = coordinator->parse(typesName);
75 } else {
76 ast = coordinator->parse(fqName);
77 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -070078
79 if (ast == NULL) {
80 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -070081 "ERROR: Could not parse %s. Aborting.\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -070082 fqName.string().c_str());
83
84 return UNKNOWN_ERROR;
85 }
86
Steven Moreland3b1ce262017-04-21 14:19:59 -070087 if (lang == "check") {
88 return OK; // only parsing, not generating
89 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070090 if (lang == "c++") {
91 return ast->generateCpp(outputDir);
92 }
Steven Moreland1cbf0362017-05-09 14:32:53 -070093 if (lang == "c++-headers") {
94 return ast->generateCppHeaders(outputDir);
95 }
96 if (lang == "c++-sources") {
97 return ast->generateCppSources(outputDir);
98 }
Steven Moreland9c387612016-09-07 09:54:26 -070099 if (lang == "c++-impl") {
100 return ast->generateCppImpl(outputDir);
101 }
Steven Morelandf2a0f5b2017-07-18 20:39:11 -0700102 if (lang == "c++-impl-headers") {
103 return ast->generateStubImplHeader(outputDir);
104 }
105 if (lang == "c++-impl-sources") {
106 return ast->generateStubImplSource(outputDir);
107 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700108 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700109 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700110 }
111 if (lang == "vts") {
112 return ast->generateVts(outputDir);
113 }
114 // Unknown language.
115 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700116}
117
118static status_t generateSourcesForPackage(
119 const FQName &packageFQName,
120 const char *hidl_gen,
121 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700122 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700123 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700124 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700125 !packageFQName.isFullyQualified() &&
126 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700127
128 std::vector<FQName> packageInterfaces;
129
130 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700131 coordinator->appendPackageInterfacesToVector(packageFQName,
132 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700133
134 if (err != OK) {
135 return err;
136 }
137
138 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700139 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700140 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700141 if (err != OK) {
142 return err;
143 }
144 }
145
146 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700147}
148
Steven Morelandbbbbeb82017-05-09 14:20:50 -0700149OutputHandler::GenerationFunction generationFunctionForFileOrPackage(const std::string &language) {
150 return [language](const FQName &fqName,
151 const char *hidl_gen, Coordinator *coordinator,
152 const std::string &outputDir) -> status_t {
153 if (fqName.isFullyQualified()) {
154 return generateSourcesForFile(fqName,
155 hidl_gen,
156 coordinator,
157 outputDir,
158 language);
159 } else {
160 return generateSourcesForPackage(fqName,
161 hidl_gen,
162 coordinator,
163 outputDir,
164 language);
165 }
166 };
167}
168
Andreas Huberd2943e12016-08-05 11:59:31 -0700169static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700170 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700171}
172
Andreas Huberaa573272017-04-13 09:58:06 -0700173static std::string makeJavaLibraryName(const FQName &packageFQName) {
174 std::string out;
175 out = packageFQName.package();
176 out += "-V";
177 out += packageFQName.version();
178 return out;
179}
180
Steven Moreland5715fed2017-01-16 11:06:47 -0800181static void generatePackagePathsSection(
182 Formatter &out,
183 Coordinator *coordinator,
184 const FQName &packageFQName,
185 const std::set<FQName> &importedPackages,
186 bool forMakefiles = false) {
187 std::set<std::string> options{};
188 for (const auto &interface : importedPackages) {
189 options.insert(coordinator->getPackageRootOption(interface));
190 }
191 options.insert(coordinator->getPackageRootOption(packageFQName));
Steven Morelandf7f2a9a2017-07-21 18:05:38 -0700192 options.insert(coordinator->getPackageRootOption(gIBaseFqName));
Steven Moreland5715fed2017-01-16 11:06:47 -0800193 for (const auto &option : options) {
194 out << "-r"
195 << option
196 << " ";
197 if (forMakefiles) {
198 out << "\\\n";
199 }
200 }
201}
202
Dan Willemsen676abdc2016-09-28 19:42:22 -0700203static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700204 Formatter &out,
205 Coordinator *coordinator,
206 const FQName &packageFQName,
207 const FQName &fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800208 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700209 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700210 out << "\n"
211 << "\n#"
212 << "\n# Build " << fqName.name() << ".hal";
213
Dan Willemsen676abdc2016-09-28 19:42:22 -0700214 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700215 out << " (" << typeName << ")";
216 }
217
218 out << "\n#"
219 << "\nGEN := $(intermediates)/"
220 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800221 << coordinator->getPackagePath(packageFQName, true /* relative */,
222 true /* sanitized */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700223 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700224 out << fqName.name() << ".java";
225 } else {
226 out << typeName << ".java";
227 }
228
229 out << "\n$(GEN): $(HIDL)";
230 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
231 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
232 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700233
234 {
235 AST *ast = coordinator->parse(fqName);
236 CHECK(ast != nullptr);
237 const std::set<FQName>& refs = ast->getImportedNames();
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -0700238 for (const auto& depFQName : refs) {
Iliyan Malchevb9819132016-09-07 12:38:31 -0700239 // If the package of depFQName is the same as this fqName's package,
240 // then add it explicitly as a .hal dependency within the same
241 // package.
242 if (fqName.package() == depFQName.package() &&
243 fqName.version() == depFQName.version()) {
244 // PRIVATE_DEPS is not actually being used in the
245 // auto-generated file, but is necessary if the build rule
246 // ever needs to use the dependency information, since the
247 // built-in Make variables are not supported in the Android
248 // build system.
249 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
250 << depFQName.name() << ".hal";
251 // This is the actual dependency.
252 out << "\n$(GEN): $(LOCAL_PATH)/"
253 << depFQName.name() << ".hal";
254 }
255 }
256 }
257
Andreas Huber0fa9e392016-08-31 09:05:44 -0700258 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
259 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
260 out.indent();
261 out.indent();
262 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800263 << "\n-Ljava \\\n";
264
265 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700266
267 out << packageFQName.string()
268 << "::"
269 << fqName.name();
270
Dan Willemsen676abdc2016-09-28 19:42:22 -0700271 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700272 out << "." << typeName;
273 }
274
275 out << "\n";
276
277 out.unindent();
278 out.unindent();
279
280 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
281 out << "\n\t$(transform-generated-source)";
282 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
283}
284
Dan Willemsen676abdc2016-09-28 19:42:22 -0700285static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700286 Formatter &out,
287 Coordinator *coordinator,
288 const FQName &packageFQName,
289 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800290 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700291 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700292 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700293 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700294 CHECK(typesAST != nullptr);
295
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700296 Scope* rootScope = typesAST->getRootScope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700297
Andreas Huberb747bd92016-09-26 15:55:31 -0700298 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
299 std::sort(
300 subTypes.begin(),
301 subTypes.end(),
302 [](const NamedType *a, const NamedType *b) -> bool {
303 return a->fqName() < b->fqName();
304 });
305
306 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700307 if (type->isTypeDef()) {
308 continue;
309 }
310
Dan Willemsen676abdc2016-09-28 19:42:22 -0700311 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700312 out,
313 coordinator,
314 packageFQName,
315 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800316 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700317 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700318 }
319
320 continue;
321 }
322
Dan Willemsen676abdc2016-09-28 19:42:22 -0700323 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700324 out,
325 coordinator,
326 packageFQName,
327 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800328 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700329 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700330 }
331}
332
Andreas Huber75ae95d2016-10-12 16:08:26 -0700333static status_t isPackageJavaCompatible(
334 const FQName &packageFQName,
335 Coordinator *coordinator,
336 bool *compatible) {
337 std::vector<FQName> todo;
338 status_t err =
339 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
340
341 if (err != OK) {
342 return err;
343 }
344
345 std::set<FQName> seen;
346 for (const auto &iface : todo) {
347 seen.insert(iface);
348 }
349
350 // Form the transitive closure of all imported interfaces (and types.hal-s)
351 // If any one of them is not java compatible, this package isn't either.
352 while (!todo.empty()) {
353 const FQName fqName = todo.back();
354 todo.pop_back();
355
356 AST *ast = coordinator->parse(fqName);
357
358 if (ast == nullptr) {
359 return UNKNOWN_ERROR;
360 }
361
362 if (!ast->isJavaCompatible()) {
363 *compatible = false;
364 return OK;
365 }
366
367 std::set<FQName> importedPackages;
368 ast->getImportedPackages(&importedPackages);
369
370 for (const auto &package : importedPackages) {
371 std::vector<FQName> packageInterfaces;
372 status_t err = coordinator->appendPackageInterfacesToVector(
373 package, &packageInterfaces);
374
375 if (err != OK) {
376 return err;
377 }
378
379 for (const auto &iface : packageInterfaces) {
380 if (seen.find(iface) != seen.end()) {
381 continue;
382 }
383
384 todo.push_back(iface);
385 seen.insert(iface);
386 }
387 }
388 }
389
390 *compatible = true;
391 return OK;
392}
393
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700394static bool packageNeedsJavaCode(
395 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
396 // If there is more than just a types.hal file to this package we'll
397 // definitely need to generate Java code.
398 if (packageInterfaces.size() > 1
399 || packageInterfaces[0].name() != "types") {
400 return true;
401 }
402
403 CHECK(typesAST != nullptr);
404
405 // We'll have to generate Java code if types.hal contains any non-typedef
406 // type declarations.
407
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700408 Scope* rootScope = typesAST->getRootScope();
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700409 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
410
411 for (const auto &subType : subTypes) {
412 if (!subType->isTypeDef()) {
413 return true;
414 }
415 }
416
417 return false;
418}
419
Andreas Huber1c507272016-10-05 14:33:21 -0700420static void generateMakefileSectionForJavaConstants(
421 Formatter &out,
422 Coordinator *coordinator,
423 const FQName &packageFQName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800424 const std::vector<FQName> &packageInterfaces,
425 const std::set<FQName> &importedPackages) {
Andreas Huber1c507272016-10-05 14:33:21 -0700426 out << "\n#"
427 << "\nGEN := $(intermediates)/"
428 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800429 << coordinator->getPackagePath(packageFQName, true /* relative */, true /* sanitized */)
Andreas Huber1c507272016-10-05 14:33:21 -0700430 << "Constants.java";
431
432 out << "\n$(GEN): $(HIDL)\n";
433 for (const auto &iface : packageInterfaces) {
434 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
435 }
436 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
437 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
438 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
439 out.indent();
440 out.indent();
441 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800442 << "\n-Ljava-constants \\\n";
443
444 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber1c507272016-10-05 14:33:21 -0700445
446 out << packageFQName.string();
447 out << "\n";
448
449 out.unindent();
450 out.unindent();
451
452 out << "\n$(GEN):";
453 out << "\n\t$(transform-generated-source)";
454 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
455}
456
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700457static status_t generateMakefileForPackage(
458 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700459 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700460 Coordinator *coordinator,
Steven Morelanda171b562017-05-12 15:18:03 -0700461 const std::string &outputPath) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700462
463 CHECK(packageFQName.isValid() &&
464 !packageFQName.isFullyQualified() &&
465 packageFQName.name().empty());
466
Andreas Huberd2943e12016-08-05 11:59:31 -0700467 std::vector<FQName> packageInterfaces;
468
469 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700470 coordinator->appendPackageInterfacesToVector(packageFQName,
471 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700472
473 if (err != OK) {
474 return err;
475 }
476
477 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700478 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700479 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700480
Andreas Huberd2943e12016-08-05 11:59:31 -0700481 for (const auto &fqName : packageInterfaces) {
482 AST *ast = coordinator->parse(fqName);
483
484 if (ast == NULL) {
485 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700486 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700487 fqName.string().c_str());
488
489 return UNKNOWN_ERROR;
490 }
491
Andreas Huber0fa9e392016-08-31 09:05:44 -0700492 if (fqName.name() == "types") {
493 typesAST = ast;
494 }
495
Yifan Hong40a373d2016-11-30 15:16:47 -0800496 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700497 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700498 }
499
Andreas Huber75ae95d2016-10-12 16:08:26 -0700500 bool packageIsJavaCompatible;
501 err = isPackageJavaCompatible(
502 packageFQName, coordinator, &packageIsJavaCompatible);
503
504 if (err != OK) {
505 return err;
506 }
507
Andreas Huber1c507272016-10-05 14:33:21 -0700508 bool haveJavaConstants = !exportedTypes.empty();
509
510 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800511 // TODO(b/33420795)
512 fprintf(stderr,
513 "WARNING: %s is not java compatible. No java makefile created.\n",
514 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700515 return OK;
516 }
517
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700518 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
519 return OK;
520 }
521
Steven Morelanda171b562017-05-12 15:18:03 -0700522 std::string path = outputPath;
Steven Morelandf7fa0682017-05-11 16:14:55 -0700523 path.append(coordinator->getPackagePath(packageFQName, false /* relative */));
Andreas Huberd2943e12016-08-05 11:59:31 -0700524 path.append("Android.mk");
525
526 CHECK(Coordinator::MakeParentHierarchy(path));
527 FILE *file = fopen(path.c_str(), "w");
528
529 if (file == NULL) {
530 return -errno;
531 }
532
Andreas Huberaa573272017-04-13 09:58:06 -0700533 const std::string libraryName = makeJavaLibraryName(packageFQName);
Andreas Huberd2943e12016-08-05 11:59:31 -0700534
535 Formatter out(file);
536
Dan Willemsen676abdc2016-09-28 19:42:22 -0700537 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
538 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700539
Steven Morelandbc7e8312017-08-01 15:33:52 -0700540 if (packageIsJavaCompatible) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700541 out << "\n"
542 << "########################################"
543 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700544
Dan Willemsen676abdc2016-09-28 19:42:22 -0700545 out << "include $(CLEAR_VARS)\n"
546 << "LOCAL_MODULE := "
547 << libraryName
548 << "-java"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700549 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800550 << "intermediates := $(call local-generated-sources-dir, COMMON)"
551 << "\n\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700552 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
553 << hidl_gen
554 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700555
Dan Willemsen676abdc2016-09-28 19:42:22 -0700556 if (!importedPackages.empty()) {
Steven Morelandbc7e8312017-08-01 15:33:52 -0700557 out << "\n\nLOCAL_JAVA_LIBRARIES := \\";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700558
559 out.indent();
560 for (const auto &importedPackage : importedPackages) {
561 out << "\n"
Andreas Huberaa573272017-04-13 09:58:06 -0700562 << makeJavaLibraryName(importedPackage)
Dan Willemsen676abdc2016-09-28 19:42:22 -0700563 << "-java"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700564 << " \\";
565 }
Steven Morelandbc7e8312017-08-01 15:33:52 -0700566
Dan Willemsen676abdc2016-09-28 19:42:22 -0700567 out << "\n";
568 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700569 }
Sundong Ahnc1432c92017-07-13 23:58:27 +0900570 out << "\nLOCAL_NO_STANDARD_LIBRARIES := true";
Steven Morelandbc7e8312017-08-01 15:33:52 -0700571 out << "\nLOCAL_JAVA_LIBRARIES += core-oj hwbinder";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700572
573 generateMakefileSection(
574 out,
575 coordinator,
576 packageFQName,
577 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800578 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700579 typesAST);
580
Steven Morelandbc7e8312017-08-01 15:33:52 -0700581 out << "\ninclude $(BUILD_JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700582 }
583
Andreas Huber1c507272016-10-05 14:33:21 -0700584 if (haveJavaConstants) {
585 out << "\n"
586 << "########################################"
587 << "########################################\n\n";
588
589 out << "include $(CLEAR_VARS)\n"
590 << "LOCAL_MODULE := "
591 << libraryName
592 << "-java-constants"
593 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800594 << "intermediates := $(call local-generated-sources-dir, COMMON)"
595 << "\n\n"
Andreas Huber1c507272016-10-05 14:33:21 -0700596 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
597 << hidl_gen
598 << "$(HOST_EXECUTABLE_SUFFIX)";
599
600 generateMakefileSectionForJavaConstants(
Steven Moreland5715fed2017-01-16 11:06:47 -0800601 out, coordinator, packageFQName, packageInterfaces, importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700602
603 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
604 << "-> framework.jar\n"
605 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
606 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
607 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
608 }
609
Iliyan Malchev8be09552016-09-22 16:20:33 -0700610 out << "\n\n"
611 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
612
Andreas Huberd2943e12016-08-05 11:59:31 -0700613 return OK;
614}
615
Steven Moreland05951b32017-05-12 17:22:22 -0700616bool validateIsPackage(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700617 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700618 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700619 fprintf(stderr, "ERROR: Expecting package name\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700620 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700621 }
622
623 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700624 fprintf(stderr, "ERROR: Expecting package version\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700625 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700626 }
627
628 if (!fqName.name().empty()) {
629 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700630 "ERROR: Expecting only package name and version.\n");
Steven Moreland05951b32017-05-12 17:22:22 -0700631 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700632 }
633
Steven Moreland05951b32017-05-12 17:22:22 -0700634 return true;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700635}
636
Steven Morelandf7f2a9a2017-07-21 18:05:38 -0700637bool isHidlTransportPackage(const FQName& fqName) {
638 return fqName.package() == gIBasePackageFqName.string() ||
639 fqName.package() == gIManagerPackageFqName.string();
Steven Moreland77cf7642017-06-15 14:49:39 -0700640}
641
Steven Morelandc7946c92017-08-08 14:48:32 -0700642bool isSystemProcessSupportedPackage(const FQName& fqName) {
643 // Technically, so is hidl IBase + IServiceManager, but
644 // these are part of libhidltransport.
645 return fqName.string() == "android.hardware.graphics.allocator@2.0" ||
646 fqName.string() == "android.hardware.graphics.common@1.0" ||
647 fqName.string() == "android.hardware.graphics.mapper@2.0" ||
648 fqName.string() == "android.hardware.renderscript@1.0" ||
649 fqName.string() == "android.hidl.memory@1.0";
650}
651
Steven Moreland5edf5282017-07-20 12:56:58 -0700652bool isSystemPackage(const FQName &package) {
653 return package.inPackage("android.hidl") ||
654 package.inPackage("android.system") ||
655 package.inPackage("android.frameworks") ||
656 package.inPackage("android.hardware");
657}
658
Dan Willemsen676abdc2016-09-28 19:42:22 -0700659static void generateAndroidBpGenSection(
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -0700660 Formatter& out,
661 const FQName& packageFQName,
662 const char* hidl_gen,
663 Coordinator* coordinator,
664 const std::string& halFilegroupName,
665 const std::string& genName,
666 const char* language,
667 const std::vector<FQName>& packageInterfaces,
668 const std::set<FQName>& importedPackages,
669 const std::function<void(Formatter&, const FQName)>& outputFn) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700670 out << "genrule {\n";
671 out.indent();
672 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700673 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700674
Colin Crossd5419bd2016-11-04 15:05:54 -0700675 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Steven Moreland5715fed2017-01-16 11:06:47 -0800676 << " -L" << language << " ";
677
678 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages);
679
680 out << packageFQName.string() << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700681
682 out << "srcs: [\n";
683 out.indent();
Tri Vo6a827fa2017-02-08 10:24:42 -0800684 out << "\":" << halFilegroupName << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700685 out.unindent();
686 out << "],\n";
687
688 out << "out: [\n";
689 out.indent();
690 for (const auto &fqName : packageInterfaces) {
691 outputFn(out, fqName);
692 }
693 out.unindent();
694 out << "],\n";
695
696 out.unindent();
697 out << "}\n\n";
698}
699
Steven Moreland5edf5282017-07-20 12:56:58 -0700700static void generateAndroidBpDependencyList(
701 Formatter &out,
702 const std::set<FQName> &importedPackagesHierarchy,
703 bool generateVendor) {
704 for (const auto &importedPackage : importedPackagesHierarchy) {
705 if (isHidlTransportPackage(importedPackage)) {
706 continue;
707 }
708
709 out << "\"" << makeLibraryName(importedPackage);
710 if (generateVendor && !isSystemPackage(importedPackage)) {
711 out << "_vendor";
712 }
713 out << "\",\n";
714 }
715}
716
Steven Moreland77cf7642017-06-15 14:49:39 -0700717static void generateAndroidBpLibSection(
718 Formatter &out,
719 bool generateVendor,
Steven Morelandc7946c92017-08-08 14:48:32 -0700720 const FQName &packageFQName,
Steven Moreland77cf7642017-06-15 14:49:39 -0700721 const std::string &libraryName,
722 const std::string &genSourceName,
723 const std::string &genHeaderName,
724 const std::set<FQName> &importedPackagesHierarchy) {
725
726 // C++ library definition
Steven Moreland02516de2017-07-26 10:09:22 -0700727 out << "cc_library {\n";
Steven Moreland77cf7642017-06-15 14:49:39 -0700728 out.indent();
729 out << "name: \"" << libraryName << (generateVendor ? "_vendor" : "") << "\",\n"
730 << "defaults: [\"hidl-module-defaults\"],\n"
731 << "generated_sources: [\"" << genSourceName << "\"],\n"
732 << "generated_headers: [\"" << genHeaderName << "\"],\n"
733 << "export_generated_headers: [\"" << genHeaderName << "\"],\n";
734
735 if (generateVendor) {
736 out << "vendor: true,\n";
737 } else {
738 out << "vendor_available: true,\n";
Steven Moreland79e700e2017-07-25 18:24:50 -0700739 out << "vndk: ";
740 out.block([&]() {
741 out << "enabled: true,\n";
Steven Morelandc7946c92017-08-08 14:48:32 -0700742 if (isSystemProcessSupportedPackage(packageFQName)) {
743 out << "support_system_process: true,\n";
744 }
Steven Moreland79e700e2017-07-25 18:24:50 -0700745 }) << ",\n";
Steven Moreland77cf7642017-06-15 14:49:39 -0700746 }
747 out << "shared_libs: [\n";
748
749 out.indent();
750 out << "\"libhidlbase\",\n"
751 << "\"libhidltransport\",\n"
752 << "\"libhwbinder\",\n"
753 << "\"liblog\",\n"
754 << "\"libutils\",\n"
755 << "\"libcutils\",\n";
Steven Moreland5edf5282017-07-20 12:56:58 -0700756 generateAndroidBpDependencyList(out, importedPackagesHierarchy, generateVendor);
Steven Moreland77cf7642017-06-15 14:49:39 -0700757 out.unindent();
758
759 out << "],\n";
760
761 out << "export_shared_lib_headers: [\n";
762 out.indent();
763 out << "\"libhidlbase\",\n"
764 << "\"libhidltransport\",\n"
765 << "\"libhwbinder\",\n"
766 << "\"libutils\",\n";
Steven Moreland5edf5282017-07-20 12:56:58 -0700767 generateAndroidBpDependencyList(out, importedPackagesHierarchy, generateVendor);
Steven Moreland77cf7642017-06-15 14:49:39 -0700768 out.unindent();
769 out << "],\n";
770 out.unindent();
771
772 out << "}\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700773}
774
Dan Willemsen676abdc2016-09-28 19:42:22 -0700775static status_t generateAndroidBpForPackage(
776 const FQName &packageFQName,
777 const char *hidl_gen,
778 Coordinator *coordinator,
Steven Morelanda171b562017-05-12 15:18:03 -0700779 const std::string &outputPath) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700780
781 CHECK(packageFQName.isValid() &&
782 !packageFQName.isFullyQualified() &&
783 packageFQName.name().empty());
784
785 std::vector<FQName> packageInterfaces;
786
787 status_t err =
788 coordinator->appendPackageInterfacesToVector(packageFQName,
789 &packageInterfaces);
790
791 if (err != OK) {
792 return err;
793 }
794
Steven Morelandff5262b2017-03-20 06:59:03 -0700795 std::set<FQName> importedPackagesHierarchy;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700796 AST *typesAST = nullptr;
797
798 for (const auto &fqName : packageInterfaces) {
799 AST *ast = coordinator->parse(fqName);
800
801 if (ast == NULL) {
802 fprintf(stderr,
803 "ERROR: Could not parse %s. Aborting.\n",
804 fqName.string().c_str());
805
806 return UNKNOWN_ERROR;
807 }
808
809 if (fqName.name() == "types") {
810 typesAST = ast;
811 }
812
Steven Morelandff5262b2017-03-20 06:59:03 -0700813 ast->getImportedPackagesHierarchy(&importedPackagesHierarchy);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700814 }
815
Steven Morelanda171b562017-05-12 15:18:03 -0700816 std::string path = outputPath;
Steven Morelandf7fa0682017-05-11 16:14:55 -0700817 path.append(coordinator->getPackagePath(packageFQName, false /* relative */));
Dan Willemsen676abdc2016-09-28 19:42:22 -0700818 path.append("Android.bp");
819
820 CHECK(Coordinator::MakeParentHierarchy(path));
821 FILE *file = fopen(path.c_str(), "w");
822
823 if (file == NULL) {
824 return -errno;
825 }
826
827 const std::string libraryName = makeLibraryName(packageFQName);
Tri Vo15052c62017-02-06 10:04:07 -0800828 const std::string halFilegroupName = libraryName + "_hal";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700829 const std::string genSourceName = libraryName + "_genc++";
830 const std::string genHeaderName = libraryName + "_genc++_headers";
831 const std::string pathPrefix =
832 coordinator->convertPackageRootToPath(packageFQName) +
833 coordinator->getPackagePath(packageFQName, true /* relative */);
834
835 Formatter out(file);
836
837 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
838
Tri Vo15052c62017-02-06 10:04:07 -0800839 // Rule to generate .hal filegroup
840 out << "filegroup {\n";
841 out.indent();
842 out << "name: \"" << halFilegroupName << "\",\n";
843 out << "srcs: [\n";
844 out.indent();
845 for (const auto &fqName : packageInterfaces) {
846 out << "\"" << fqName.name() << ".hal\",\n";
847 }
848 out.unindent();
849 out << "],\n";
850 out.unindent();
851 out << "}\n\n";
852
Dan Willemsen676abdc2016-09-28 19:42:22 -0700853 // Rule to generate the C++ source files
854 generateAndroidBpGenSection(
855 out,
856 packageFQName,
857 hidl_gen,
858 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800859 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700860 genSourceName,
Steven Moreland1cbf0362017-05-09 14:32:53 -0700861 "c++-sources",
Dan Willemsen676abdc2016-09-28 19:42:22 -0700862 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700863 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700864 [&pathPrefix](Formatter &out, const FQName &fqName) {
865 if (fqName.name() == "types") {
866 out << "\"" << pathPrefix << "types.cpp\",\n";
867 } else {
868 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
869 }
870 });
871
872 // Rule to generate the C++ header files
873 generateAndroidBpGenSection(
874 out,
875 packageFQName,
876 hidl_gen,
877 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800878 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700879 genHeaderName,
Steven Moreland1cbf0362017-05-09 14:32:53 -0700880 "c++-headers",
Dan Willemsen676abdc2016-09-28 19:42:22 -0700881 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700882 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700883 [&pathPrefix](Formatter &out, const FQName &fqName) {
884 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
885 if (fqName.name() != "types") {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800886 out << "\"" << pathPrefix << fqName.getInterfaceHwName() << ".h\",\n";
887 out << "\"" << pathPrefix << fqName.getInterfaceStubName() << ".h\",\n";
888 out << "\"" << pathPrefix << fqName.getInterfaceProxyName() << ".h\",\n";
889 out << "\"" << pathPrefix << fqName.getInterfacePassthroughName() << ".h\",\n";
Steven Moreland9774d622017-03-24 21:51:45 -0700890 } else {
891 out << "\"" << pathPrefix << "hwtypes.h\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700892 }
893 });
894
Steven Morelandf5f593f2017-05-02 13:13:00 -0700895 if (isHidlTransportPackage(packageFQName)) {
896 out << "// " << packageFQName.string() << " is exported from libhidltransport\n";
Steven Moreland0e875df2017-04-25 13:24:17 -0700897 } else {
Steven Moreland77cf7642017-06-15 14:49:39 -0700898 generateAndroidBpLibSection(
899 out,
900 false /* generateVendor */,
Steven Morelandc7946c92017-08-08 14:48:32 -0700901 packageFQName,
Steven Moreland77cf7642017-06-15 14:49:39 -0700902 libraryName,
903 genSourceName,
904 genHeaderName,
905 importedPackagesHierarchy);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700906
Steven Moreland77cf7642017-06-15 14:49:39 -0700907 // TODO(b/35813011): make all libraries vendor_available
908 // Explicitly create '_vendor' copies of libraries so that
909 // vendor code can link against the extensions. When this is
910 // used, framework code should link against vendor.awesome.foo@1.0
911 // and code on the vendor image should link against
912 // vendor.awesome.foo@1.0_vendor. For libraries with the below extensions,
913 // they will be available even on the generic system image.
914 // Because of this, they should always be referenced without the
915 // '_vendor' name suffix.
Steven Moreland5edf5282017-07-20 12:56:58 -0700916 if (!isSystemPackage(packageFQName)) {
Steven Moreland77cf7642017-06-15 14:49:39 -0700917
918 // Note, not using cc_defaults here since it's already not used and
919 // because generating this libraries will be removed when the VNDK
920 // is enabled (done by the build system itself).
921 out.endl();
922 generateAndroidBpLibSection(
923 out,
924 true /* generateVendor */,
Steven Morelandc7946c92017-08-08 14:48:32 -0700925 packageFQName,
Steven Moreland77cf7642017-06-15 14:49:39 -0700926 libraryName,
927 genSourceName,
928 genHeaderName,
929 importedPackagesHierarchy);
Steven Moreland1b2167b2017-05-01 10:06:21 -0700930 }
Yifan Hongc1f9b8d2016-11-07 14:35:44 -0800931 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700932
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800933 return OK;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700934}
935
Yifan Hong958ee462016-12-06 17:09:51 -0800936static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -0700937 const FQName &packageFQName,
938 const char *,
939 Coordinator *coordinator,
940 const std::string &outputDir) {
941
Iliyan Malchev4923f932016-09-09 13:04:59 -0700942 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700943
944 std::vector<FQName> packageInterfaces;
945
946 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700947 coordinator->appendPackageInterfacesToVector(packageFQName,
948 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700949
950 if (err != OK) {
951 return err;
952 }
953
954 std::set<FQName> importedPackages;
955
956 for (const auto &fqName : packageInterfaces) {
957 AST *ast = coordinator->parse(fqName);
958
959 if (ast == NULL) {
960 fprintf(stderr,
961 "ERROR: Could not parse %s. Aborting.\n",
962 fqName.string().c_str());
963
964 return UNKNOWN_ERROR;
965 }
966
967 ast->getImportedPackages(&importedPackages);
968 }
969
Yifan Hongaafed702016-12-14 12:59:47 -0800970 std::string path = outputDir + "Android.bp";
Steven Moreland197d56c2016-09-09 10:03:58 -0700971
972 CHECK(Coordinator::MakeParentHierarchy(path));
973 FILE *file = fopen(path.c_str(), "w");
974
975 if (file == NULL) {
976 return -errno;
977 }
978
979 Formatter out(file);
980
Yifan Hong958ee462016-12-06 17:09:51 -0800981 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800982 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800983 out << "name: \"" << libraryName << "\",\n"
984 << "relative_install_path: \"hw\",\n"
Steven Morelandf8a22e92017-02-15 18:46:04 -0800985 << "proprietary: true,\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800986 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800987 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800988 for (const auto &fqName : packageInterfaces) {
989 if (fqName.name() == "types") {
990 continue;
991 }
992 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
993 }
994 });
995 out << "],\n"
996 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800997 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800998 out << "\"libhidlbase\",\n"
999 << "\"libhidltransport\",\n"
Yifan Hong958ee462016-12-06 17:09:51 -08001000 << "\"libutils\",\n"
1001 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -07001002
Yifan Hong958ee462016-12-06 17:09:51 -08001003 for (const auto &importedPackage : importedPackages) {
Steven Morelanddadd1842017-05-09 13:24:54 -07001004 if (isHidlTransportPackage(importedPackage)) {
1005 continue;
1006 }
1007
Yifan Hong958ee462016-12-06 17:09:51 -08001008 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
1009 }
1010 });
1011 out << "],\n";
1012 });
1013 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -07001014
1015 return OK;
1016}
1017
Steven Moreland05951b32017-05-12 17:22:22 -07001018bool validateForSource(
Andreas Huber0fa9e392016-08-31 09:05:44 -07001019 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001020 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -07001021 fprintf(stderr, "ERROR: Expecting package name\n");
Steven Moreland05951b32017-05-12 17:22:22 -07001022 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001023 }
1024
1025 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -07001026 fprintf(stderr, "ERROR: Expecting package version\n");
Steven Moreland05951b32017-05-12 17:22:22 -07001027 return false;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001028 }
1029
Andreas Huber0fa9e392016-08-31 09:05:44 -07001030 const std::string &name = fqName.name();
1031 if (!name.empty()) {
1032 if (name.find('.') == std::string::npos) {
Steven Moreland05951b32017-05-12 17:22:22 -07001033 return true;
Andreas Huber0fa9e392016-08-31 09:05:44 -07001034 }
1035
1036 if (language != "java" || name.find("types.") != 0) {
1037 // When generating java sources for "types.hal", output can be
1038 // constrained to just one of the top-level types declared
1039 // by using the extended syntax
1040 // android.hardware.Foo@1.0::types.TopLevelTypeName.
1041 // In all other cases (different language, not 'types') the dot
1042 // notation in the name is illegal in this context.
Steven Moreland05951b32017-05-12 17:22:22 -07001043 return false;
Andreas Huber0fa9e392016-08-31 09:05:44 -07001044 }
1045
Steven Moreland05951b32017-05-12 17:22:22 -07001046 return true;
Andreas Huber0fa9e392016-08-31 09:05:44 -07001047 }
1048
Steven Moreland05951b32017-05-12 17:22:22 -07001049 return true;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001050}
1051
Steven Morelandf47912d2017-05-12 16:25:44 -07001052OutputHandler::GenerationFunction generateExportHeaderForPackage(bool forJava) {
1053 return [forJava](const FQName &packageFQName,
1054 const char * /* hidl_gen */,
1055 Coordinator *coordinator,
1056 const std::string &outputPath) -> status_t {
1057 CHECK(packageFQName.isValid()
1058 && !packageFQName.package().empty()
1059 && !packageFQName.version().empty()
1060 && packageFQName.name().empty());
Andreas Huber019d21d2016-10-03 12:59:47 -07001061
Steven Morelandf47912d2017-05-12 16:25:44 -07001062 std::vector<FQName> packageInterfaces;
Andreas Huber019d21d2016-10-03 12:59:47 -07001063
Steven Morelandf47912d2017-05-12 16:25:44 -07001064 status_t err = coordinator->appendPackageInterfacesToVector(
1065 packageFQName, &packageInterfaces);
Andreas Huber019d21d2016-10-03 12:59:47 -07001066
Steven Morelandf47912d2017-05-12 16:25:44 -07001067 if (err != OK) {
1068 return err;
Andreas Huber019d21d2016-10-03 12:59:47 -07001069 }
1070
Steven Morelandf47912d2017-05-12 16:25:44 -07001071 std::vector<const Type *> exportedTypes;
Andreas Huber019d21d2016-10-03 12:59:47 -07001072
Steven Morelandf47912d2017-05-12 16:25:44 -07001073 for (const auto &fqName : packageInterfaces) {
1074 AST *ast = coordinator->parse(fqName);
1075
1076 if (ast == NULL) {
1077 fprintf(stderr,
1078 "ERROR: Could not parse %s. Aborting.\n",
1079 fqName.string().c_str());
1080
1081 return UNKNOWN_ERROR;
1082 }
1083
1084 ast->appendToExportedTypesVector(&exportedTypes);
1085 }
1086
1087 if (exportedTypes.empty()) {
1088 return OK;
1089 }
1090
1091 std::string path = outputPath;
1092
1093 if (forJava) {
1094 path.append(coordinator->convertPackageRootToPath(packageFQName));
1095
1096 path.append(coordinator->getPackagePath(
1097 packageFQName, true /* relative */, true /* sanitized */));
1098
1099 path.append("Constants.java");
1100 }
1101
1102 CHECK(Coordinator::MakeParentHierarchy(path));
1103 FILE *file = fopen(path.c_str(), "w");
1104
1105 if (file == nullptr) {
1106 return -errno;
1107 }
1108
1109 Formatter out(file);
1110
1111 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
1112 << "// Source: " << packageFQName.string() << "\n"
1113 << "// Root: " << coordinator->getPackageRootOption(packageFQName) << "\n\n";
1114
1115 std::string guard;
1116 if (forJava) {
1117 out << "package " << packageFQName.javaPackage() << ";\n\n";
1118 out << "public class Constants {\n";
1119 out.indent();
1120 } else {
1121 guard = "HIDL_GENERATED_";
1122 guard += StringHelper::Uppercase(packageFQName.tokenName());
1123 guard += "_";
1124 guard += "EXPORTED_CONSTANTS_H_";
1125
1126 out << "#ifndef "
1127 << guard
1128 << "\n#define "
1129 << guard
1130 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
1131 }
1132
1133 for (const auto &type : exportedTypes) {
1134 type->emitExportedHeader(out, forJava);
1135 }
1136
1137 if (forJava) {
1138 out.unindent();
1139 out << "}\n";
1140 } else {
1141 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
1142 << guard
1143 << "\n";
1144 }
1145
Andreas Huber019d21d2016-10-03 12:59:47 -07001146 return OK;
Steven Morelandf47912d2017-05-12 16:25:44 -07001147 };
Andreas Huber019d21d2016-10-03 12:59:47 -07001148}
1149
Steven Morelandf2e44692017-04-18 20:19:09 -07001150static status_t generateHashOutput(const FQName &fqName,
1151 const char* /*hidl_gen*/,
1152 Coordinator *coordinator,
1153 const std::string & /*outputDir*/) {
1154
1155 status_t err;
1156 std::vector<FQName> packageInterfaces;
1157
1158 if (fqName.isFullyQualified()) {
1159 packageInterfaces = {fqName};
1160 } else {
1161 err = coordinator->appendPackageInterfacesToVector(
1162 fqName, &packageInterfaces);
1163 if (err != OK) {
1164 return err;
1165 }
1166 }
1167
1168 for (const auto &currentFqName : packageInterfaces) {
Steven Morelandc59326e2017-06-20 15:19:30 -07001169 AST* ast = coordinator->parse(currentFqName, {} /* parsed */,
1170 Coordinator::Enforce::NO_HASH /* enforcement */);
Steven Morelandf2e44692017-04-18 20:19:09 -07001171
1172 if (ast == NULL) {
1173 fprintf(stderr,
1174 "ERROR: Could not parse %s. Aborting.\n",
1175 currentFqName.string().c_str());
1176
1177 return UNKNOWN_ERROR;
1178 }
1179
1180 printf("%s %s\n",
1181 Hash::getHash(ast->getFilename()).hexString().c_str(),
1182 currentFqName.string().c_str());
1183 }
1184
1185 return OK;
1186}
1187
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001188static std::vector<OutputHandler> formats = {
Steven Moreland3b1ce262017-04-21 14:19:59 -07001189 {"check",
Steven Moreland97e52332017-05-12 16:47:19 -07001190 "Parses the interface to see if valid but doesn't write any files.",
Steven Moreland3b1ce262017-04-21 14:19:59 -07001191 OutputHandler::NOT_NEEDED /* mOutputMode */,
1192 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001193 generationFunctionForFileOrPackage("check")
Steven Moreland3b1ce262017-04-21 14:19:59 -07001194 },
1195
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001196 {"c++",
Steven Moreland97e52332017-05-12 16:47:19 -07001197 "(internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001198 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001199 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001200 generationFunctionForFileOrPackage("c++")
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001201 },
1202
Steven Moreland1cbf0362017-05-09 14:32:53 -07001203 {"c++-headers",
Steven Moreland97e52332017-05-12 16:47:19 -07001204 "(internal) Generates C++ headers for interface files for talking to HIDL interfaces.",
Steven Moreland1cbf0362017-05-09 14:32:53 -07001205 OutputHandler::NEEDS_DIR /* mOutputMode */,
1206 validateForSource,
1207 generationFunctionForFileOrPackage("c++-headers")
1208 },
1209
1210 {"c++-sources",
Steven Moreland97e52332017-05-12 16:47:19 -07001211 "(internal) Generates C++ sources for interface files for talking to HIDL interfaces.",
Steven Moreland1cbf0362017-05-09 14:32:53 -07001212 OutputHandler::NEEDS_DIR /* mOutputMode */,
1213 validateForSource,
1214 generationFunctionForFileOrPackage("c++-sources")
1215 },
1216
Andreas Huber019d21d2016-10-03 12:59:47 -07001217 {"export-header",
Steven Moreland97e52332017-05-12 16:47:19 -07001218 "Generates a header file from @export enumerations to help maintain legacy code.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001219 OutputHandler::NEEDS_FILE /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -07001220 validateIsPackage,
Steven Morelandf47912d2017-05-12 16:25:44 -07001221 generateExportHeaderForPackage(false /* forJava */)
Andreas Huber019d21d2016-10-03 12:59:47 -07001222 },
1223
Steven Moreland9c387612016-09-07 09:54:26 -07001224 {"c++-impl",
Steven Moreland97e52332017-05-12 16:47:19 -07001225 "Generates boilerplate implementation of a hidl interface in C++ (for convenience).",
Andreas Huber019d21d2016-10-03 12:59:47 -07001226 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001227 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001228 generationFunctionForFileOrPackage("c++-impl")
Steven Moreland9c387612016-09-07 09:54:26 -07001229 },
Steven Morelandf2a0f5b2017-07-18 20:39:11 -07001230 {"c++-impl-headers",
1231 "c++-impl but headers only",
1232 OutputHandler::NEEDS_DIR /* mOutputMode */,
1233 validateForSource,
1234 generationFunctionForFileOrPackage("c++-impl-headers")
1235 },
1236 {"c++-impl-sources",
1237 "c++-impl but sources only",
1238 OutputHandler::NEEDS_DIR /* mOutputMode */,
1239 validateForSource,
1240 generationFunctionForFileOrPackage("c++-impl-sources")
1241 },
Steven Moreland9c387612016-09-07 09:54:26 -07001242
Andreas Huber2831d512016-08-15 09:33:47 -07001243 {"java",
Steven Moreland97e52332017-05-12 16:47:19 -07001244 "(internal) Generates Java library for talking to HIDL interfaces in Java.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001245 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001246 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001247 generationFunctionForFileOrPackage("java")
Andreas Huber2831d512016-08-15 09:33:47 -07001248 },
1249
Andreas Huber1c507272016-10-05 14:33:21 -07001250 {"java-constants",
Steven Moreland97e52332017-05-12 16:47:19 -07001251 "(internal) Like export-header but for Java (always created by -Lmakefile if @export exists).",
Andreas Huber1c507272016-10-05 14:33:21 -07001252 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -07001253 validateIsPackage,
Steven Morelandf47912d2017-05-12 16:25:44 -07001254 generateExportHeaderForPackage(true /* forJava */)
Andreas Huber1c507272016-10-05 14:33:21 -07001255 },
1256
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001257 {"vts",
Steven Moreland97e52332017-05-12 16:47:19 -07001258 "(internal) Generates vts proto files for use in vtsd.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001259 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001260 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001261 generationFunctionForFileOrPackage("vts")
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001262 },
1263
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001264 {"makefile",
Steven Moreland97e52332017-05-12 16:47:19 -07001265 "(internal) Generates makefiles for -Ljava and -Ljava-constants.",
Steven Morelanda171b562017-05-12 15:18:03 -07001266 OutputHandler::NEEDS_SRC /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -07001267 validateIsPackage,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001268 generateMakefileForPackage,
1269 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001270
Dan Willemsen676abdc2016-09-28 19:42:22 -07001271 {"androidbp",
Steven Moreland97e52332017-05-12 16:47:19 -07001272 "(internal) Generates Soong bp files for -Lc++-headers and -Lc++-sources.",
Steven Morelanda171b562017-05-12 15:18:03 -07001273 OutputHandler::NEEDS_SRC /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -07001274 validateIsPackage,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001275 generateAndroidBpForPackage,
1276 },
1277
Yifan Hong958ee462016-12-06 17:09:51 -08001278 {"androidbp-impl",
Steven Moreland97e52332017-05-12 16:47:19 -07001279 "Generates boilerplate bp files for implementation created with -Lc++-impl.",
Yifan Hong94bcea02016-10-06 13:51:31 -07001280 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland05951b32017-05-12 17:22:22 -07001281 validateIsPackage,
Yifan Hong958ee462016-12-06 17:09:51 -08001282 generateAndroidBpImplForPackage,
Steven Morelandf2e44692017-04-18 20:19:09 -07001283 },
1284
1285 {"hash",
Steven Moreland97e52332017-05-12 16:47:19 -07001286 "Prints hashes of interface in `current.txt` format to standard out.",
Steven Morelandf2e44692017-04-18 20:19:09 -07001287 OutputHandler::NOT_NEEDED /* mOutputMode */,
1288 validateForSource,
1289 generateHashOutput,
1290 },
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001291};
1292
1293static void usage(const char *me) {
1294 fprintf(stderr,
Steven Moreland97e52332017-05-12 16:47:19 -07001295 "usage: %s [-p <root path>] -o <output path> -L <language> (-r <interface root>)+ fqname+\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001296 me);
1297
Steven Moreland97e52332017-05-12 16:47:19 -07001298 fprintf(stderr, " -h: Prints this menu.\n");
1299 fprintf(stderr, " -L <language>: The following options are available:\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001300 for (auto &e : formats) {
Steven Moreland97e52332017-05-12 16:47:19 -07001301 fprintf(stderr, " %-16s: %s\n", e.name().c_str(), e.description().c_str());
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001302 }
Steven Moreland97e52332017-05-12 16:47:19 -07001303 fprintf(stderr, " -o <output path>: Location to output files.\n");
1304 fprintf(stderr, " -p <root path>: Android build root, defaults to $ANDROID_BUILD_TOP or pwd.\n");
1305 fprintf(stderr, " -r <package:path root>: E.g., android.hardware:hardware/interfaces.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001306}
1307
Andreas Gampec4ce9262017-04-27 21:03:20 -07001308// hidl is intentionally leaky. Turn off LeakSanitizer by default.
Vishwath Mohancec4a702017-08-10 12:30:12 -07001309// Also disable container overflow detection to prevent false
1310// positives (b/64564544)
Andreas Gampec4ce9262017-04-27 21:03:20 -07001311extern "C" const char *__asan_default_options() {
Vishwath Mohancec4a702017-08-10 12:30:12 -07001312 return "detect_leaks=0:detect_container_overflow=0";
Andreas Gampec4ce9262017-04-27 21:03:20 -07001313}
1314
Andreas Huberb82318c2016-08-02 14:45:54 -07001315int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001316 std::string outputPath;
Steven Morelandf7fa0682017-05-11 16:14:55 -07001317 std::string rootPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001318 std::vector<std::string> packageRootPaths;
1319 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001320
Andreas Huber737080b2016-08-02 15:38:04 -07001321 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001322 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001323
Steven Moreland3db99f22017-05-11 16:21:46 -07001324 if (argc == 1) {
1325 usage(me);
1326 exit(1);
1327 }
1328
Andreas Huberb82318c2016-08-02 14:45:54 -07001329 int res;
Steven Morelandf7fa0682017-05-11 16:14:55 -07001330 while ((res = getopt(argc, argv, "hp:o:r:L:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001331 switch (res) {
Steven Morelandf7fa0682017-05-11 16:14:55 -07001332 case 'p':
1333 {
1334 rootPath = optarg;
1335 break;
1336 }
1337
Andreas Huberb82318c2016-08-02 14:45:54 -07001338 case 'o':
1339 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001340 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001341 break;
1342 }
1343
Andreas Huberdca261f2016-08-04 13:47:51 -07001344 case 'r':
1345 {
1346 std::string val(optarg);
1347 auto index = val.find_first_of(':');
Steven Moreland4ff74202017-04-21 14:24:47 -07001348 if (index == std::string::npos) {
1349 fprintf(stderr, "ERROR: -r option must contain ':': %s\n", val.c_str());
1350 exit(1);
1351 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001352
1353 auto package = val.substr(0, index);
1354 auto path = val.substr(index + 1);
1355 packageRootPaths.push_back(path);
1356 packageRoots.push_back(package);
1357 break;
1358 }
1359
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001360 case 'L':
1361 {
Steven Morelanddd583842017-04-19 13:09:57 -07001362 if (outputFormat != nullptr) {
1363 fprintf(stderr,
1364 "ERROR: only one -L option allowed. \"%s\" already specified.\n",
1365 outputFormat->name().c_str());
1366 exit(1);
1367 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001368 for (auto &e : formats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001369 if (e.name() == optarg) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001370 outputFormat = &e;
1371 break;
1372 }
1373 }
Steven Morelanddd583842017-04-19 13:09:57 -07001374 if (outputFormat == nullptr) {
1375 fprintf(stderr,
1376 "ERROR: unrecognized -L option: \"%s\".\n",
1377 optarg);
1378 exit(1);
1379 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001380 break;
1381 }
1382
Andreas Huberb82318c2016-08-02 14:45:54 -07001383 case '?':
1384 case 'h':
1385 default:
1386 {
Andreas Huber737080b2016-08-02 15:38:04 -07001387 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001388 exit(1);
1389 break;
1390 }
1391 }
1392 }
1393
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001394 if (outputFormat == nullptr) {
Steven Morelanddd583842017-04-19 13:09:57 -07001395 fprintf(stderr,
1396 "ERROR: no -L option provided.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001397 exit(1);
1398 }
1399
Andreas Huberb82318c2016-08-02 14:45:54 -07001400 argc -= optind;
1401 argv += optind;
1402
Steven Moreland3effa832017-06-16 16:17:41 -07001403 if (argc == 0) {
1404 fprintf(stderr, "ERROR: no fqname specified.\n");
1405 usage(me);
1406 exit(1);
1407 }
1408
Steven Morelandf7fa0682017-05-11 16:14:55 -07001409 if (rootPath.empty()) {
1410 const char *ANDROID_BUILD_TOP = getenv("ANDROID_BUILD_TOP");
1411
1412 if (ANDROID_BUILD_TOP != nullptr) {
1413 rootPath = ANDROID_BUILD_TOP;
1414 }
1415
1416 // else default to pwd
1417 }
1418
1419 if (!rootPath.empty() && !StringHelper::EndsWith(rootPath, "/")) {
1420 rootPath += "/";
1421 }
1422
Andreas Huber737080b2016-08-02 15:38:04 -07001423 // Valid options are now in argv[0] .. argv[argc - 1].
1424
Andreas Huber019d21d2016-10-03 12:59:47 -07001425 switch (outputFormat->mOutputMode) {
1426 case OutputHandler::NEEDS_DIR:
1427 case OutputHandler::NEEDS_FILE:
1428 {
1429 if (outputPath.empty()) {
1430 usage(me);
1431 exit(1);
1432 }
1433
1434 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
1435 const size_t len = outputPath.size();
1436 if (outputPath[len - 1] != '/') {
1437 outputPath += "/";
1438 }
1439 }
1440 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001441 }
Steven Morelanda171b562017-05-12 15:18:03 -07001442 case OutputHandler::NEEDS_SRC:
1443 {
1444 if (outputPath.empty()) {
1445 outputPath = rootPath;
1446 }
1447
1448 break;
1449 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001450
1451 default:
1452 outputPath.clear(); // Unused.
1453 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001454 }
1455
Steven Morelandf7fa0682017-05-11 16:14:55 -07001456 Coordinator coordinator(packageRootPaths, packageRoots, rootPath);
Steven Moreland25c81662017-05-12 14:57:36 -07001457 coordinator.addDefaultPackagePath("android.hardware", "hardware/interfaces");
1458 coordinator.addDefaultPackagePath("android.hidl", "system/libhidl/transport");
1459 coordinator.addDefaultPackagePath("android.frameworks", "frameworks/hardware/interfaces");
1460 coordinator.addDefaultPackagePath("android.system", "system/hardware/interfaces");
Andreas Huber5345ec22016-07-29 13:33:27 -07001461
Andreas Huber737080b2016-08-02 15:38:04 -07001462 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001463 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001464
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001465 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001466 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001467 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001468 exit(1);
1469 }
Andreas Huber881227d2016-08-02 14:20:21 -07001470
Steven Moreland05951b32017-05-12 17:22:22 -07001471 if (!outputFormat->validate(fqName, outputFormat->name())) {
Steven Morelandf2e44692017-04-18 20:19:09 -07001472 fprintf(stderr,
1473 "ERROR: output handler failed.\n");
Andreas Hubere61e3f72016-08-03 10:22:03 -07001474 exit(1);
1475 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001476
1477 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001478 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001479
1480 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001481 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001482 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001483 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001484
Andreas Huberd2943e12016-08-05 11:59:31 -07001485 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001486}