blob: 0118ece9840235bb4a736b378d04aaf1e0c4a64a [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;
Andreas Huber019d21d2016-10-03 12:59:47 -070036 enum OutputMode {
37 NEEDS_DIR,
38 NEEDS_FILE,
39 NOT_NEEDED
40 } mOutputMode;
41
Iliyan Malchev5bb14022016-08-09 15:04:39 -070042 enum ValRes {
43 FAILED,
44 PASS_PACKAGE,
45 PASS_FULL
46 };
Steven Morelanddd583842017-04-19 13:09:57 -070047 const std::string& name() { return mKey; }
Andreas Huber0fa9e392016-08-31 09:05:44 -070048 ValRes (*validate)(const FQName &, const std::string &language);
Iliyan Malchev5bb14022016-08-09 15:04:39 -070049 status_t (*generate)(const FQName &fqName,
50 const char *hidl_gen,
51 Coordinator *coordinator,
52 const std::string &outputDir);
53};
Andreas Huberdca261f2016-08-04 13:47:51 -070054
Iliyan Malchev5bb14022016-08-09 15:04:39 -070055static status_t generateSourcesForFile(
56 const FQName &fqName,
57 const char *,
58 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -070059 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070060 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -070061 CHECK(fqName.isFullyQualified());
62
Andreas Huber0fa9e392016-08-31 09:05:44 -070063 AST *ast;
Andreas Huberd29724f2016-09-14 09:33:13 -070064 std::string limitToType;
Andreas Huber0fa9e392016-08-31 09:05:44 -070065
66 if (fqName.name().find("types.") == 0) {
67 CHECK(lang == "java"); // Already verified in validate().
68
Andreas Huberd29724f2016-09-14 09:33:13 -070069 limitToType = fqName.name().substr(strlen("types."));
Andreas Huber0fa9e392016-08-31 09:05:44 -070070
Yifan Hongfece6ec2017-01-12 17:04:04 -080071 FQName typesName = fqName.getTypesForPackage();
Andreas Huber0fa9e392016-08-31 09:05:44 -070072 ast = coordinator->parse(typesName);
73 } else {
74 ast = coordinator->parse(fqName);
75 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -070076
77 if (ast == NULL) {
78 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -070079 "ERROR: Could not parse %s. Aborting.\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -070080 fqName.string().c_str());
81
82 return UNKNOWN_ERROR;
83 }
84
Steven Moreland3b1ce262017-04-21 14:19:59 -070085 if (lang == "check") {
86 return OK; // only parsing, not generating
87 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070088 if (lang == "c++") {
89 return ast->generateCpp(outputDir);
90 }
Steven Moreland1cbf0362017-05-09 14:32:53 -070091 if (lang == "c++-headers") {
92 return ast->generateCppHeaders(outputDir);
93 }
94 if (lang == "c++-sources") {
95 return ast->generateCppSources(outputDir);
96 }
Steven Moreland9c387612016-09-07 09:54:26 -070097 if (lang == "c++-impl") {
98 return ast->generateCppImpl(outputDir);
99 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700100 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700101 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700102 }
103 if (lang == "vts") {
104 return ast->generateVts(outputDir);
105 }
106 // Unknown language.
107 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700108}
109
110static status_t generateSourcesForPackage(
111 const FQName &packageFQName,
112 const char *hidl_gen,
113 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700114 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700115 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700116 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700117 !packageFQName.isFullyQualified() &&
118 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700119
120 std::vector<FQName> packageInterfaces;
121
122 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700123 coordinator->appendPackageInterfacesToVector(packageFQName,
124 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700125
126 if (err != OK) {
127 return err;
128 }
129
130 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700131 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700132 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700133 if (err != OK) {
134 return err;
135 }
136 }
137
138 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700139}
140
Andreas Huberd2943e12016-08-05 11:59:31 -0700141static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700142 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700143}
144
Andreas Huberaa573272017-04-13 09:58:06 -0700145static std::string makeJavaLibraryName(const FQName &packageFQName) {
146 std::string out;
147 out = packageFQName.package();
148 out += "-V";
149 out += packageFQName.version();
150 return out;
151}
152
Steven Moreland5715fed2017-01-16 11:06:47 -0800153static void generatePackagePathsSection(
154 Formatter &out,
155 Coordinator *coordinator,
156 const FQName &packageFQName,
157 const std::set<FQName> &importedPackages,
158 bool forMakefiles = false) {
159 std::set<std::string> options{};
160 for (const auto &interface : importedPackages) {
161 options.insert(coordinator->getPackageRootOption(interface));
162 }
163 options.insert(coordinator->getPackageRootOption(packageFQName));
164 options.insert(coordinator->getPackageRootOption(gIBasePackageFqName));
165 for (const auto &option : options) {
166 out << "-r"
167 << option
168 << " ";
169 if (forMakefiles) {
170 out << "\\\n";
171 }
172 }
173}
174
Dan Willemsen676abdc2016-09-28 19:42:22 -0700175static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700176 Formatter &out,
177 Coordinator *coordinator,
178 const FQName &packageFQName,
179 const FQName &fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800180 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700181 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700182 out << "\n"
183 << "\n#"
184 << "\n# Build " << fqName.name() << ".hal";
185
Dan Willemsen676abdc2016-09-28 19:42:22 -0700186 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700187 out << " (" << typeName << ")";
188 }
189
190 out << "\n#"
191 << "\nGEN := $(intermediates)/"
192 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800193 << coordinator->getPackagePath(packageFQName, true /* relative */,
194 true /* sanitized */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700195 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700196 out << fqName.name() << ".java";
197 } else {
198 out << typeName << ".java";
199 }
200
201 out << "\n$(GEN): $(HIDL)";
202 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
203 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
204 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700205
206 {
207 AST *ast = coordinator->parse(fqName);
208 CHECK(ast != nullptr);
209 const std::set<FQName>& refs = ast->getImportedNames();
210 for (auto depFQName : refs) {
211 // If the package of depFQName is the same as this fqName's package,
212 // then add it explicitly as a .hal dependency within the same
213 // package.
214 if (fqName.package() == depFQName.package() &&
215 fqName.version() == depFQName.version()) {
216 // PRIVATE_DEPS is not actually being used in the
217 // auto-generated file, but is necessary if the build rule
218 // ever needs to use the dependency information, since the
219 // built-in Make variables are not supported in the Android
220 // build system.
221 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
222 << depFQName.name() << ".hal";
223 // This is the actual dependency.
224 out << "\n$(GEN): $(LOCAL_PATH)/"
225 << depFQName.name() << ".hal";
226 }
227 }
228 }
229
Andreas Huber0fa9e392016-08-31 09:05:44 -0700230 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
231 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
232 out.indent();
233 out.indent();
234 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800235 << "\n-Ljava \\\n";
236
237 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700238
239 out << packageFQName.string()
240 << "::"
241 << fqName.name();
242
Dan Willemsen676abdc2016-09-28 19:42:22 -0700243 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700244 out << "." << typeName;
245 }
246
247 out << "\n";
248
249 out.unindent();
250 out.unindent();
251
252 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
253 out << "\n\t$(transform-generated-source)";
254 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
255}
256
Dan Willemsen676abdc2016-09-28 19:42:22 -0700257static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700258 Formatter &out,
259 Coordinator *coordinator,
260 const FQName &packageFQName,
261 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800262 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700263 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700264 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700265 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700266 CHECK(typesAST != nullptr);
267
268 Scope *rootScope = typesAST->scope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700269
Andreas Huberb747bd92016-09-26 15:55:31 -0700270 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
271 std::sort(
272 subTypes.begin(),
273 subTypes.end(),
274 [](const NamedType *a, const NamedType *b) -> bool {
275 return a->fqName() < b->fqName();
276 });
277
278 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700279 if (type->isTypeDef()) {
280 continue;
281 }
282
Dan Willemsen676abdc2016-09-28 19:42:22 -0700283 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700284 out,
285 coordinator,
286 packageFQName,
287 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800288 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700289 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700290 }
291
292 continue;
293 }
294
Dan Willemsen676abdc2016-09-28 19:42:22 -0700295 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700296 out,
297 coordinator,
298 packageFQName,
299 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800300 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700301 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700302 }
303}
304
Andreas Huber75ae95d2016-10-12 16:08:26 -0700305static status_t isPackageJavaCompatible(
306 const FQName &packageFQName,
307 Coordinator *coordinator,
308 bool *compatible) {
309 std::vector<FQName> todo;
310 status_t err =
311 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
312
313 if (err != OK) {
314 return err;
315 }
316
317 std::set<FQName> seen;
318 for (const auto &iface : todo) {
319 seen.insert(iface);
320 }
321
322 // Form the transitive closure of all imported interfaces (and types.hal-s)
323 // If any one of them is not java compatible, this package isn't either.
324 while (!todo.empty()) {
325 const FQName fqName = todo.back();
326 todo.pop_back();
327
328 AST *ast = coordinator->parse(fqName);
329
330 if (ast == nullptr) {
331 return UNKNOWN_ERROR;
332 }
333
334 if (!ast->isJavaCompatible()) {
335 *compatible = false;
336 return OK;
337 }
338
339 std::set<FQName> importedPackages;
340 ast->getImportedPackages(&importedPackages);
341
342 for (const auto &package : importedPackages) {
343 std::vector<FQName> packageInterfaces;
344 status_t err = coordinator->appendPackageInterfacesToVector(
345 package, &packageInterfaces);
346
347 if (err != OK) {
348 return err;
349 }
350
351 for (const auto &iface : packageInterfaces) {
352 if (seen.find(iface) != seen.end()) {
353 continue;
354 }
355
356 todo.push_back(iface);
357 seen.insert(iface);
358 }
359 }
360 }
361
362 *compatible = true;
363 return OK;
364}
365
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700366static bool packageNeedsJavaCode(
367 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
368 // If there is more than just a types.hal file to this package we'll
369 // definitely need to generate Java code.
370 if (packageInterfaces.size() > 1
371 || packageInterfaces[0].name() != "types") {
372 return true;
373 }
374
375 CHECK(typesAST != nullptr);
376
377 // We'll have to generate Java code if types.hal contains any non-typedef
378 // type declarations.
379
380 Scope *rootScope = typesAST->scope();
381 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
382
383 for (const auto &subType : subTypes) {
384 if (!subType->isTypeDef()) {
385 return true;
386 }
387 }
388
389 return false;
390}
391
Andreas Huber1c507272016-10-05 14:33:21 -0700392static void generateMakefileSectionForJavaConstants(
393 Formatter &out,
394 Coordinator *coordinator,
395 const FQName &packageFQName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800396 const std::vector<FQName> &packageInterfaces,
397 const std::set<FQName> &importedPackages) {
Andreas Huber1c507272016-10-05 14:33:21 -0700398 out << "\n#"
399 << "\nGEN := $(intermediates)/"
400 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800401 << coordinator->getPackagePath(packageFQName, true /* relative */, true /* sanitized */)
Andreas Huber1c507272016-10-05 14:33:21 -0700402 << "Constants.java";
403
404 out << "\n$(GEN): $(HIDL)\n";
405 for (const auto &iface : packageInterfaces) {
406 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
407 }
408 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
409 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
410 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
411 out.indent();
412 out.indent();
413 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800414 << "\n-Ljava-constants \\\n";
415
416 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber1c507272016-10-05 14:33:21 -0700417
418 out << packageFQName.string();
419 out << "\n";
420
421 out.unindent();
422 out.unindent();
423
424 out << "\n$(GEN):";
425 out << "\n\t$(transform-generated-source)";
426 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
427}
428
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700429static status_t generateMakefileForPackage(
430 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700431 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700432 Coordinator *coordinator,
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700433 const std::string &) {
434
435 CHECK(packageFQName.isValid() &&
436 !packageFQName.isFullyQualified() &&
437 packageFQName.name().empty());
438
Andreas Huberd2943e12016-08-05 11:59:31 -0700439 std::vector<FQName> packageInterfaces;
440
441 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700442 coordinator->appendPackageInterfacesToVector(packageFQName,
443 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700444
445 if (err != OK) {
446 return err;
447 }
448
449 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700450 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700451 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700452
Andreas Huberd2943e12016-08-05 11:59:31 -0700453 for (const auto &fqName : packageInterfaces) {
454 AST *ast = coordinator->parse(fqName);
455
456 if (ast == NULL) {
457 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700458 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700459 fqName.string().c_str());
460
461 return UNKNOWN_ERROR;
462 }
463
Andreas Huber0fa9e392016-08-31 09:05:44 -0700464 if (fqName.name() == "types") {
465 typesAST = ast;
466 }
467
Yifan Hong40a373d2016-11-30 15:16:47 -0800468 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700469 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700470 }
471
Andreas Huber75ae95d2016-10-12 16:08:26 -0700472 bool packageIsJavaCompatible;
473 err = isPackageJavaCompatible(
474 packageFQName, coordinator, &packageIsJavaCompatible);
475
476 if (err != OK) {
477 return err;
478 }
479
Andreas Huber1c507272016-10-05 14:33:21 -0700480 bool haveJavaConstants = !exportedTypes.empty();
481
482 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800483 // TODO(b/33420795)
484 fprintf(stderr,
485 "WARNING: %s is not java compatible. No java makefile created.\n",
486 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700487 return OK;
488 }
489
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700490 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
491 return OK;
492 }
493
Andreas Huberd2943e12016-08-05 11:59:31 -0700494 std::string path =
495 coordinator->getPackagePath(packageFQName, false /* relative */);
496
497 path.append("Android.mk");
498
499 CHECK(Coordinator::MakeParentHierarchy(path));
500 FILE *file = fopen(path.c_str(), "w");
501
502 if (file == NULL) {
503 return -errno;
504 }
505
Andreas Huberaa573272017-04-13 09:58:06 -0700506 const std::string libraryName = makeJavaLibraryName(packageFQName);
Andreas Huberd2943e12016-08-05 11:59:31 -0700507
508 Formatter out(file);
509
Dan Willemsen676abdc2016-09-28 19:42:22 -0700510 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
511 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700512
Dan Willemsen676abdc2016-09-28 19:42:22 -0700513 enum LibraryStyle {
514 LIBRARY_STYLE_REGULAR,
515 LIBRARY_STYLE_STATIC,
516 LIBRARY_STYLE_END,
517 };
Andreas Huberd2943e12016-08-05 11:59:31 -0700518
Andreas Huber1c507272016-10-05 14:33:21 -0700519 for (int style = LIBRARY_STYLE_REGULAR;
520 (packageIsJavaCompatible && style != LIBRARY_STYLE_END);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700521 ++style) {
522 const std::string staticSuffix =
523 (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700524
Dan Willemsen676abdc2016-09-28 19:42:22 -0700525 out << "\n"
526 << "########################################"
527 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700528
Dan Willemsen676abdc2016-09-28 19:42:22 -0700529 out << "include $(CLEAR_VARS)\n"
530 << "LOCAL_MODULE := "
531 << libraryName
532 << "-java"
533 << staticSuffix
534 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800535 << "intermediates := $(call local-generated-sources-dir, COMMON)"
536 << "\n\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700537 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
538 << hidl_gen
539 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700540
Dan Willemsen676abdc2016-09-28 19:42:22 -0700541 if (!importedPackages.empty()) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700542 out << "\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700543 << "\nLOCAL_"
Andreas Huber782d45e2016-09-22 13:25:14 -0700544 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
Dan Willemsen676abdc2016-09-28 19:42:22 -0700545 << "JAVA_LIBRARIES := \\";
546
547 out.indent();
548 for (const auto &importedPackage : importedPackages) {
549 out << "\n"
Andreas Huberaa573272017-04-13 09:58:06 -0700550 << makeJavaLibraryName(importedPackage)
Dan Willemsen676abdc2016-09-28 19:42:22 -0700551 << "-java"
552 << staticSuffix
553 << " \\";
554 }
555 out << "\n";
556 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700557 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700558
559 generateMakefileSection(
560 out,
561 coordinator,
562 packageFQName,
563 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800564 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700565 typesAST);
566
567 out << "\ninclude $(BUILD_"
568 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
569 << "JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700570 }
571
Andreas Huber1c507272016-10-05 14:33:21 -0700572 if (haveJavaConstants) {
573 out << "\n"
574 << "########################################"
575 << "########################################\n\n";
576
577 out << "include $(CLEAR_VARS)\n"
578 << "LOCAL_MODULE := "
579 << libraryName
580 << "-java-constants"
581 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800582 << "intermediates := $(call local-generated-sources-dir, COMMON)"
583 << "\n\n"
Andreas Huber1c507272016-10-05 14:33:21 -0700584 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
585 << hidl_gen
586 << "$(HOST_EXECUTABLE_SUFFIX)";
587
588 generateMakefileSectionForJavaConstants(
Steven Moreland5715fed2017-01-16 11:06:47 -0800589 out, coordinator, packageFQName, packageInterfaces, importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700590
591 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
592 << "-> framework.jar\n"
593 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
594 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
595 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
596 }
597
Iliyan Malchev8be09552016-09-22 16:20:33 -0700598 out << "\n\n"
599 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
600
Andreas Huberd2943e12016-08-05 11:59:31 -0700601 return OK;
602}
603
Andreas Huber0fa9e392016-08-31 09:05:44 -0700604OutputHandler::ValRes validateForMakefile(
605 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700606 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700607 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700608 return OutputHandler::FAILED;
609 }
610
611 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700612 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700613 return OutputHandler::FAILED;
614 }
615
616 if (!fqName.name().empty()) {
617 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700618 "ERROR: Expecting only package name and version.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700619 return OutputHandler::FAILED;
620 }
621
622 return OutputHandler::PASS_PACKAGE;
623}
624
Dan Willemsen676abdc2016-09-28 19:42:22 -0700625static void generateAndroidBpGenSection(
626 Formatter &out,
627 const FQName &packageFQName,
628 const char *hidl_gen,
629 Coordinator *coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800630 const std::string &halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700631 const std::string &genName,
632 const char *language,
633 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800634 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700635 const std::function<void(Formatter&, const FQName)> outputFn) {
636
637 out << "genrule {\n";
638 out.indent();
639 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700640 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700641
Colin Crossd5419bd2016-11-04 15:05:54 -0700642 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Steven Moreland5715fed2017-01-16 11:06:47 -0800643 << " -L" << language << " ";
644
645 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages);
646
647 out << packageFQName.string() << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700648
649 out << "srcs: [\n";
650 out.indent();
Tri Vo6a827fa2017-02-08 10:24:42 -0800651 out << "\":" << halFilegroupName << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700652 out.unindent();
653 out << "],\n";
654
655 out << "out: [\n";
656 out.indent();
657 for (const auto &fqName : packageInterfaces) {
658 outputFn(out, fqName);
659 }
660 out.unindent();
661 out << "],\n";
662
663 out.unindent();
664 out << "}\n\n";
665}
666
Steven Moreland1b2167b2017-05-01 10:06:21 -0700667bool isHidlTransportPackage(const FQName &package) {
668 return package == gIBasePackageFqName ||
669 package == gIManagerPackageFqName;
670}
671
Dan Willemsen676abdc2016-09-28 19:42:22 -0700672static status_t generateAndroidBpForPackage(
673 const FQName &packageFQName,
674 const char *hidl_gen,
675 Coordinator *coordinator,
676 const std::string &) {
677
678 CHECK(packageFQName.isValid() &&
679 !packageFQName.isFullyQualified() &&
680 packageFQName.name().empty());
681
682 std::vector<FQName> packageInterfaces;
683
684 status_t err =
685 coordinator->appendPackageInterfacesToVector(packageFQName,
686 &packageInterfaces);
687
688 if (err != OK) {
689 return err;
690 }
691
Steven Morelandff5262b2017-03-20 06:59:03 -0700692 std::set<FQName> importedPackagesHierarchy;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700693 AST *typesAST = nullptr;
694
695 for (const auto &fqName : packageInterfaces) {
696 AST *ast = coordinator->parse(fqName);
697
698 if (ast == NULL) {
699 fprintf(stderr,
700 "ERROR: Could not parse %s. Aborting.\n",
701 fqName.string().c_str());
702
703 return UNKNOWN_ERROR;
704 }
705
706 if (fqName.name() == "types") {
707 typesAST = ast;
708 }
709
Steven Morelandff5262b2017-03-20 06:59:03 -0700710 ast->getImportedPackagesHierarchy(&importedPackagesHierarchy);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700711 }
712
713 std::string path =
714 coordinator->getPackagePath(packageFQName, false /* relative */);
715
716 path.append("Android.bp");
717
718 CHECK(Coordinator::MakeParentHierarchy(path));
719 FILE *file = fopen(path.c_str(), "w");
720
721 if (file == NULL) {
722 return -errno;
723 }
724
725 const std::string libraryName = makeLibraryName(packageFQName);
Tri Vo15052c62017-02-06 10:04:07 -0800726 const std::string halFilegroupName = libraryName + "_hal";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700727 const std::string genSourceName = libraryName + "_genc++";
728 const std::string genHeaderName = libraryName + "_genc++_headers";
729 const std::string pathPrefix =
730 coordinator->convertPackageRootToPath(packageFQName) +
731 coordinator->getPackagePath(packageFQName, true /* relative */);
732
733 Formatter out(file);
734
735 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
736
Tri Vo15052c62017-02-06 10:04:07 -0800737 // Rule to generate .hal filegroup
738 out << "filegroup {\n";
739 out.indent();
740 out << "name: \"" << halFilegroupName << "\",\n";
741 out << "srcs: [\n";
742 out.indent();
743 for (const auto &fqName : packageInterfaces) {
744 out << "\"" << fqName.name() << ".hal\",\n";
745 }
746 out.unindent();
747 out << "],\n";
748 out.unindent();
749 out << "}\n\n";
750
Dan Willemsen676abdc2016-09-28 19:42:22 -0700751 // Rule to generate the C++ source files
752 generateAndroidBpGenSection(
753 out,
754 packageFQName,
755 hidl_gen,
756 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800757 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700758 genSourceName,
Steven Moreland1cbf0362017-05-09 14:32:53 -0700759 "c++-sources",
Dan Willemsen676abdc2016-09-28 19:42:22 -0700760 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700761 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700762 [&pathPrefix](Formatter &out, const FQName &fqName) {
763 if (fqName.name() == "types") {
764 out << "\"" << pathPrefix << "types.cpp\",\n";
765 } else {
766 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
767 }
768 });
769
770 // Rule to generate the C++ header files
771 generateAndroidBpGenSection(
772 out,
773 packageFQName,
774 hidl_gen,
775 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800776 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700777 genHeaderName,
Steven Moreland1cbf0362017-05-09 14:32:53 -0700778 "c++-headers",
Dan Willemsen676abdc2016-09-28 19:42:22 -0700779 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700780 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700781 [&pathPrefix](Formatter &out, const FQName &fqName) {
782 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
783 if (fqName.name() != "types") {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800784 out << "\"" << pathPrefix << fqName.getInterfaceHwName() << ".h\",\n";
785 out << "\"" << pathPrefix << fqName.getInterfaceStubName() << ".h\",\n";
786 out << "\"" << pathPrefix << fqName.getInterfaceProxyName() << ".h\",\n";
787 out << "\"" << pathPrefix << fqName.getInterfacePassthroughName() << ".h\",\n";
Steven Moreland9774d622017-03-24 21:51:45 -0700788 } else {
789 out << "\"" << pathPrefix << "hwtypes.h\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700790 }
791 });
792
Steven Morelandf5f593f2017-05-02 13:13:00 -0700793 if (isHidlTransportPackage(packageFQName)) {
794 out << "// " << packageFQName.string() << " is exported from libhidltransport\n";
Steven Moreland0e875df2017-04-25 13:24:17 -0700795 } else {
Steven Morelandf5f593f2017-05-02 13:13:00 -0700796 // C++ library definition
797 out << "cc_library_shared {\n";
798 out.indent();
799 out << "name: \"" << libraryName << "\",\n"
800 << "generated_sources: [\"" << genSourceName << "\"],\n"
801 << "generated_headers: [\"" << genHeaderName << "\"],\n"
802 << "export_generated_headers: [\"" << genHeaderName << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700803
Steven Morelandf5f593f2017-05-02 13:13:00 -0700804 // TODO(b/35813011): make always vendor_available
805 // Explicitly mark libraries vendor until BOARD_VNDK_VERSION can
806 // be enabled.
807 if (packageFQName.inPackage("android.hidl") ||
808 packageFQName.inPackage("android.system") ||
809 packageFQName.inPackage("android.frameworks") ||
810 packageFQName.inPackage("android.hardware")) {
811 out << "vendor_available: true,\n";
812 } else {
813 out << "vendor: true,\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700814 }
Steven Morelandf5f593f2017-05-02 13:13:00 -0700815 out << "shared_libs: [\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700816
Steven Morelandf5f593f2017-05-02 13:13:00 -0700817 out.indent();
818 out << "\"libhidlbase\",\n"
819 << "\"libhidltransport\",\n"
820 << "\"libhwbinder\",\n"
821 << "\"liblog\",\n"
822 << "\"libutils\",\n"
823 << "\"libcutils\",\n";
824 for (const auto &importedPackage : importedPackagesHierarchy) {
825 if (isHidlTransportPackage(importedPackage)) {
826 continue;
827 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700828
Steven Morelandf5f593f2017-05-02 13:13:00 -0700829 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700830 }
Steven Morelandf5f593f2017-05-02 13:13:00 -0700831 out.unindent();
Steven Moreland1b2167b2017-05-01 10:06:21 -0700832
Steven Morelandf5f593f2017-05-02 13:13:00 -0700833 out << "],\n";
834
835 out << "export_shared_lib_headers: [\n";
836 out.indent();
837 out << "\"libhidlbase\",\n"
838 << "\"libhidltransport\",\n"
839 << "\"libhwbinder\",\n"
840 << "\"libutils\",\n";
841 for (const auto &importedPackage : importedPackagesHierarchy) {
842 if (isHidlTransportPackage(importedPackage)) {
843 continue;
844 }
845
846 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
847 }
848 out.unindent();
849 out << "],\n";
850 out.unindent();
851
852 out << "}\n";
Yifan Hongc1f9b8d2016-11-07 14:35:44 -0800853 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700854
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800855 return OK;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700856}
857
Yifan Hong958ee462016-12-06 17:09:51 -0800858static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -0700859 const FQName &packageFQName,
860 const char *,
861 Coordinator *coordinator,
862 const std::string &outputDir) {
863
Iliyan Malchev4923f932016-09-09 13:04:59 -0700864 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700865
866 std::vector<FQName> packageInterfaces;
867
868 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700869 coordinator->appendPackageInterfacesToVector(packageFQName,
870 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700871
872 if (err != OK) {
873 return err;
874 }
875
876 std::set<FQName> importedPackages;
877
878 for (const auto &fqName : packageInterfaces) {
879 AST *ast = coordinator->parse(fqName);
880
881 if (ast == NULL) {
882 fprintf(stderr,
883 "ERROR: Could not parse %s. Aborting.\n",
884 fqName.string().c_str());
885
886 return UNKNOWN_ERROR;
887 }
888
889 ast->getImportedPackages(&importedPackages);
890 }
891
Yifan Hongaafed702016-12-14 12:59:47 -0800892 std::string path = outputDir + "Android.bp";
Steven Moreland197d56c2016-09-09 10:03:58 -0700893
894 CHECK(Coordinator::MakeParentHierarchy(path));
895 FILE *file = fopen(path.c_str(), "w");
896
897 if (file == NULL) {
898 return -errno;
899 }
900
901 Formatter out(file);
902
Yifan Hong958ee462016-12-06 17:09:51 -0800903 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800904 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800905 out << "name: \"" << libraryName << "\",\n"
906 << "relative_install_path: \"hw\",\n"
Steven Morelandf8a22e92017-02-15 18:46:04 -0800907 << "proprietary: true,\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800908 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800909 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800910 for (const auto &fqName : packageInterfaces) {
911 if (fqName.name() == "types") {
912 continue;
913 }
914 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
915 }
916 });
917 out << "],\n"
918 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800919 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800920 out << "\"libhidlbase\",\n"
921 << "\"libhidltransport\",\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800922 << "\"libutils\",\n"
923 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -0700924
Yifan Hong958ee462016-12-06 17:09:51 -0800925 for (const auto &importedPackage : importedPackages) {
Steven Morelanddadd1842017-05-09 13:24:54 -0700926 if (isHidlTransportPackage(importedPackage)) {
927 continue;
928 }
929
Yifan Hong958ee462016-12-06 17:09:51 -0800930 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
931 }
932 });
933 out << "],\n";
934 });
935 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -0700936
937 return OK;
938}
939
Andreas Huber0fa9e392016-08-31 09:05:44 -0700940OutputHandler::ValRes validateForSource(
941 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700942 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700943 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700944 return OutputHandler::FAILED;
945 }
946
947 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700948 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700949 return OutputHandler::FAILED;
950 }
951
Andreas Huber0fa9e392016-08-31 09:05:44 -0700952 const std::string &name = fqName.name();
953 if (!name.empty()) {
954 if (name.find('.') == std::string::npos) {
955 return OutputHandler::PASS_FULL;
956 }
957
958 if (language != "java" || name.find("types.") != 0) {
959 // When generating java sources for "types.hal", output can be
960 // constrained to just one of the top-level types declared
961 // by using the extended syntax
962 // android.hardware.Foo@1.0::types.TopLevelTypeName.
963 // In all other cases (different language, not 'types') the dot
964 // notation in the name is illegal in this context.
965 return OutputHandler::FAILED;
966 }
967
968 return OutputHandler::PASS_FULL;
969 }
970
971 return OutputHandler::PASS_PACKAGE;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700972}
973
Andreas Huber019d21d2016-10-03 12:59:47 -0700974OutputHandler::ValRes validateForExportHeader(
975 const FQName &fqName, const std::string & /* language */) {
976 if (fqName.package().empty()) {
977 fprintf(stderr, "ERROR: Expecting package name\n");
978 return OutputHandler::FAILED;
979 }
980
981 if (fqName.version().empty()) {
982 fprintf(stderr, "ERROR: Expecting package version\n");
983 return OutputHandler::FAILED;
984 }
985
986 if (!fqName.name().empty()) {
987 fprintf(stderr,
988 "ERROR: Expecting only package name and version.\n");
989 return OutputHandler::FAILED;
990 }
991
992 return OutputHandler::PASS_PACKAGE;
993}
994
995
996static status_t generateExportHeaderForPackage(
997 const FQName &packageFQName,
998 const char * /* hidl_gen */,
999 Coordinator *coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001000 const std::string &outputPath,
1001 bool forJava) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001002
1003 CHECK(packageFQName.isValid()
1004 && !packageFQName.isFullyQualified()
1005 && packageFQName.name().empty());
1006
1007 std::vector<FQName> packageInterfaces;
1008
1009 status_t err = coordinator->appendPackageInterfacesToVector(
1010 packageFQName, &packageInterfaces);
1011
1012 if (err != OK) {
1013 return err;
1014 }
1015
1016 std::vector<const Type *> exportedTypes;
1017
1018 for (const auto &fqName : packageInterfaces) {
1019 AST *ast = coordinator->parse(fqName);
1020
1021 if (ast == NULL) {
1022 fprintf(stderr,
1023 "ERROR: Could not parse %s. Aborting.\n",
1024 fqName.string().c_str());
1025
1026 return UNKNOWN_ERROR;
1027 }
1028
1029 ast->appendToExportedTypesVector(&exportedTypes);
1030 }
1031
1032 if (exportedTypes.empty()) {
1033 return OK;
1034 }
1035
Andreas Huber1c507272016-10-05 14:33:21 -07001036 std::string path = outputPath;
1037
1038 if (forJava) {
1039 path.append(coordinator->convertPackageRootToPath(packageFQName));
1040
1041 path.append(coordinator->getPackagePath(
Yifan Hong97288ac2016-12-12 16:03:51 -08001042 packageFQName, true /* relative */, true /* sanitized */));
Andreas Huber1c507272016-10-05 14:33:21 -07001043
1044 path.append("Constants.java");
1045 }
1046
1047 CHECK(Coordinator::MakeParentHierarchy(path));
1048 FILE *file = fopen(path.c_str(), "w");
Andreas Huber019d21d2016-10-03 12:59:47 -07001049
1050 if (file == nullptr) {
1051 return -errno;
1052 }
1053
1054 Formatter out(file);
1055
Steven Morelandd177b122016-12-12 09:15:37 -08001056 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
Glenn Kastend18c3ba2017-02-23 16:35:24 -08001057 << "// Source: " << packageFQName.string() << "\n"
1058 << "// Root: " << coordinator->getPackageRootOption(packageFQName) << "\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001059
Andreas Huber1c507272016-10-05 14:33:21 -07001060 std::string guard;
1061 if (forJava) {
1062 out << "package " << packageFQName.javaPackage() << ";\n\n";
1063 out << "public class Constants {\n";
1064 out.indent();
1065 } else {
1066 guard = "HIDL_GENERATED_";
Steven Morelandd177b122016-12-12 09:15:37 -08001067 guard += StringHelper::Uppercase(packageFQName.tokenName());
Andreas Huber1c507272016-10-05 14:33:21 -07001068 guard += "_";
1069 guard += "EXPORTED_CONSTANTS_H_";
Andreas Huber019d21d2016-10-03 12:59:47 -07001070
Andreas Huber1c507272016-10-05 14:33:21 -07001071 out << "#ifndef "
1072 << guard
1073 << "\n#define "
1074 << guard
1075 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001076 }
1077
Andreas Huber1c507272016-10-05 14:33:21 -07001078 for (const auto &type : exportedTypes) {
1079 type->emitExportedHeader(out, forJava);
1080 }
1081
1082 if (forJava) {
1083 out.unindent();
1084 out << "}\n";
1085 } else {
1086 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
1087 << guard
1088 << "\n";
1089 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001090
1091 return OK;
1092}
1093
Steven Morelandf2e44692017-04-18 20:19:09 -07001094static status_t generateHashOutput(const FQName &fqName,
1095 const char* /*hidl_gen*/,
1096 Coordinator *coordinator,
1097 const std::string & /*outputDir*/) {
1098
1099 status_t err;
1100 std::vector<FQName> packageInterfaces;
1101
1102 if (fqName.isFullyQualified()) {
1103 packageInterfaces = {fqName};
1104 } else {
1105 err = coordinator->appendPackageInterfacesToVector(
1106 fqName, &packageInterfaces);
1107 if (err != OK) {
1108 return err;
1109 }
1110 }
1111
1112 for (const auto &currentFqName : packageInterfaces) {
1113 AST *ast = coordinator->parse(currentFqName);
1114
1115 if (ast == NULL) {
1116 fprintf(stderr,
1117 "ERROR: Could not parse %s. Aborting.\n",
1118 currentFqName.string().c_str());
1119
1120 return UNKNOWN_ERROR;
1121 }
1122
1123 printf("%s %s\n",
1124 Hash::getHash(ast->getFilename()).hexString().c_str(),
1125 currentFqName.string().c_str());
1126 }
1127
1128 return OK;
1129}
1130
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001131static std::vector<OutputHandler> formats = {
Steven Moreland3b1ce262017-04-21 14:19:59 -07001132 {"check",
1133 OutputHandler::NOT_NEEDED /* mOutputMode */,
1134 validateForSource,
1135 [](const FQName &fqName,
1136 const char *hidl_gen, Coordinator *coordinator,
1137 const std::string &outputDir) -> status_t {
1138 if (fqName.isFullyQualified()) {
1139 return generateSourcesForFile(fqName,
1140 hidl_gen,
1141 coordinator,
1142 outputDir,
1143 "check");
1144 } else {
1145 return generateSourcesForPackage(fqName,
1146 hidl_gen,
1147 coordinator,
1148 outputDir,
1149 "check");
1150 }
1151 }
1152 },
1153
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001154 {"c++",
Andreas Huber019d21d2016-10-03 12:59:47 -07001155 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001156 validateForSource,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001157 [](const FQName &fqName,
1158 const char *hidl_gen, Coordinator *coordinator,
1159 const std::string &outputDir) -> status_t {
1160 if (fqName.isFullyQualified()) {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001161 return generateSourcesForFile(fqName,
1162 hidl_gen,
1163 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001164 outputDir,
1165 "c++");
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001166 } else {
1167 return generateSourcesForPackage(fqName,
1168 hidl_gen,
1169 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001170 outputDir,
1171 "c++");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001172 }
1173 }
1174 },
1175
Steven Moreland1cbf0362017-05-09 14:32:53 -07001176 {"c++-headers",
1177 OutputHandler::NEEDS_DIR /* mOutputMode */,
1178 validateForSource,
1179 generationFunctionForFileOrPackage("c++-headers")
1180 },
1181
1182 {"c++-sources",
1183 OutputHandler::NEEDS_DIR /* mOutputMode */,
1184 validateForSource,
1185 generationFunctionForFileOrPackage("c++-sources")
1186 },
1187
Andreas Huber019d21d2016-10-03 12:59:47 -07001188 {"export-header",
1189 OutputHandler::NEEDS_FILE /* mOutputMode */,
1190 validateForExportHeader,
1191 [](const FQName &fqName,
1192 const char *hidl_gen,
1193 Coordinator *coordinator,
1194 const std::string &outputPath) -> status_t {
1195 CHECK(!fqName.isFullyQualified());
1196
1197 return generateExportHeaderForPackage(
1198 fqName,
1199 hidl_gen,
1200 coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001201 outputPath,
1202 false /* forJava */);
Andreas Huber019d21d2016-10-03 12:59:47 -07001203 }
1204 },
1205
Steven Moreland9c387612016-09-07 09:54:26 -07001206 {"c++-impl",
Andreas Huber019d21d2016-10-03 12:59:47 -07001207 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001208 validateForSource,
1209 [](const FQName &fqName,
1210 const char *hidl_gen, Coordinator *coordinator,
1211 const std::string &outputDir) -> status_t {
1212 if (fqName.isFullyQualified()) {
1213 return generateSourcesForFile(fqName,
1214 hidl_gen,
1215 coordinator,
1216 outputDir, "c++-impl");
1217 } else {
1218 return generateSourcesForPackage(fqName,
1219 hidl_gen,
1220 coordinator,
1221 outputDir, "c++-impl");
1222 }
1223 }
1224 },
1225
1226
Andreas Huber2831d512016-08-15 09:33:47 -07001227 {"java",
Andreas Huber019d21d2016-10-03 12:59:47 -07001228 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001229 validateForSource,
Andreas Huber2831d512016-08-15 09:33:47 -07001230 [](const FQName &fqName,
1231 const char *hidl_gen, Coordinator *coordinator,
1232 const std::string &outputDir) -> status_t {
1233 if (fqName.isFullyQualified()) {
1234 return generateSourcesForFile(fqName,
1235 hidl_gen,
1236 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001237 outputDir,
1238 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001239 }
1240 else {
1241 return generateSourcesForPackage(fqName,
1242 hidl_gen,
1243 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001244 outputDir,
1245 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001246 }
1247 }
1248 },
1249
Andreas Huber1c507272016-10-05 14:33:21 -07001250 {"java-constants",
1251 OutputHandler::NEEDS_DIR /* mOutputMode */,
1252 validateForExportHeader,
1253 [](const FQName &fqName,
1254 const char *hidl_gen, Coordinator *coordinator,
1255 const std::string &outputDir) -> status_t {
1256 CHECK(!fqName.isFullyQualified());
1257 return generateExportHeaderForPackage(
1258 fqName,
1259 hidl_gen,
1260 coordinator,
1261 outputDir,
1262 true /* forJava */);
1263 }
1264 },
1265
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001266 {"vts",
Andreas Huber019d21d2016-10-03 12:59:47 -07001267 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001268 validateForSource,
1269 [](const FQName &fqName,
1270 const char * hidl_gen,
1271 Coordinator *coordinator,
1272 const std::string &outputDir) -> status_t {
1273 if (fqName.isFullyQualified()) {
1274 return generateSourcesForFile(fqName,
1275 hidl_gen,
1276 coordinator,
1277 outputDir, "vts");
1278 } else {
1279 return generateSourcesForPackage(fqName,
1280 hidl_gen,
1281 coordinator,
1282 outputDir, "vts");
1283 }
1284 }
1285 },
1286
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001287 {"makefile",
Andreas Huber019d21d2016-10-03 12:59:47 -07001288 OutputHandler::NOT_NEEDED /* mOutputMode */,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001289 validateForMakefile,
1290 generateMakefileForPackage,
1291 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001292
Dan Willemsen676abdc2016-09-28 19:42:22 -07001293 {"androidbp",
Andreas Huber019d21d2016-10-03 12:59:47 -07001294 OutputHandler::NOT_NEEDED /* mOutputMode */,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001295 validateForMakefile,
1296 generateAndroidBpForPackage,
1297 },
1298
Yifan Hong958ee462016-12-06 17:09:51 -08001299 {"androidbp-impl",
Yifan Hong94bcea02016-10-06 13:51:31 -07001300 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland197d56c2016-09-09 10:03:58 -07001301 validateForMakefile,
Yifan Hong958ee462016-12-06 17:09:51 -08001302 generateAndroidBpImplForPackage,
Steven Morelandf2e44692017-04-18 20:19:09 -07001303 },
1304
1305 {"hash",
1306 OutputHandler::NOT_NEEDED /* mOutputMode */,
1307 validateForSource,
1308 generateHashOutput,
1309 },
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001310};
1311
1312static void usage(const char *me) {
1313 fprintf(stderr,
1314 "usage: %s -o output-path -L <language> (-r interface-root)+ fqname+\n",
1315 me);
1316
1317 fprintf(stderr, " -o output path\n");
1318
1319 fprintf(stderr, " -L <language> (one of");
1320 for (auto &e : formats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001321 fprintf(stderr, " %s", e.name().c_str());
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001322 }
1323 fprintf(stderr, ")\n");
1324
1325 fprintf(stderr,
1326 " -r package:path root "
1327 "(e.g., android.hardware:hardware/interfaces)\n");
1328}
1329
Andreas Gampec4ce9262017-04-27 21:03:20 -07001330// hidl is intentionally leaky. Turn off LeakSanitizer by default.
1331extern "C" const char *__asan_default_options() {
1332 return "detect_leaks=0";
1333}
1334
Andreas Huberb82318c2016-08-02 14:45:54 -07001335int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001336 std::string outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001337 std::vector<std::string> packageRootPaths;
1338 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001339
Andreas Huber737080b2016-08-02 15:38:04 -07001340 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001341 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001342
Andreas Huberb82318c2016-08-02 14:45:54 -07001343 int res;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001344 while ((res = getopt(argc, argv, "ho:r:L:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001345 switch (res) {
1346 case 'o':
1347 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001348 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001349 break;
1350 }
1351
Andreas Huberdca261f2016-08-04 13:47:51 -07001352 case 'r':
1353 {
1354 std::string val(optarg);
1355 auto index = val.find_first_of(':');
Steven Moreland4ff74202017-04-21 14:24:47 -07001356 if (index == std::string::npos) {
1357 fprintf(stderr, "ERROR: -r option must contain ':': %s\n", val.c_str());
1358 exit(1);
1359 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001360
1361 auto package = val.substr(0, index);
1362 auto path = val.substr(index + 1);
1363 packageRootPaths.push_back(path);
1364 packageRoots.push_back(package);
1365 break;
1366 }
1367
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001368 case 'L':
1369 {
Steven Morelanddd583842017-04-19 13:09:57 -07001370 if (outputFormat != nullptr) {
1371 fprintf(stderr,
1372 "ERROR: only one -L option allowed. \"%s\" already specified.\n",
1373 outputFormat->name().c_str());
1374 exit(1);
1375 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001376 for (auto &e : formats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001377 if (e.name() == optarg) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001378 outputFormat = &e;
1379 break;
1380 }
1381 }
Steven Morelanddd583842017-04-19 13:09:57 -07001382 if (outputFormat == nullptr) {
1383 fprintf(stderr,
1384 "ERROR: unrecognized -L option: \"%s\".\n",
1385 optarg);
1386 exit(1);
1387 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001388 break;
1389 }
1390
Andreas Huberb82318c2016-08-02 14:45:54 -07001391 case '?':
1392 case 'h':
1393 default:
1394 {
Andreas Huber737080b2016-08-02 15:38:04 -07001395 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001396 exit(1);
1397 break;
1398 }
1399 }
1400 }
1401
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001402 if (outputFormat == nullptr) {
Steven Morelanddd583842017-04-19 13:09:57 -07001403 fprintf(stderr,
1404 "ERROR: no -L option provided.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001405 exit(1);
1406 }
1407
Andreas Huberb82318c2016-08-02 14:45:54 -07001408 argc -= optind;
1409 argv += optind;
1410
Andreas Huberdca261f2016-08-04 13:47:51 -07001411 if (packageRootPaths.empty()) {
1412 // Pick reasonable defaults.
1413
1414 packageRoots.push_back("android.hardware");
1415
1416 const char *TOP = getenv("TOP");
Steven Morelandaf330382016-11-09 15:48:03 -08001417 if (TOP == nullptr) {
1418 fprintf(stderr,
1419 "ERROR: No root path (-r) specified"
1420 " and $TOP environment variable not set.\n");
1421 exit(1);
1422 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001423
1424 std::string path = TOP;
1425 path.append("/hardware/interfaces");
1426
1427 packageRootPaths.push_back(path);
1428 }
1429
Andreas Huber737080b2016-08-02 15:38:04 -07001430 // Valid options are now in argv[0] .. argv[argc - 1].
1431
Andreas Huber019d21d2016-10-03 12:59:47 -07001432 switch (outputFormat->mOutputMode) {
1433 case OutputHandler::NEEDS_DIR:
1434 case OutputHandler::NEEDS_FILE:
1435 {
1436 if (outputPath.empty()) {
1437 usage(me);
1438 exit(1);
1439 }
1440
1441 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
1442 const size_t len = outputPath.size();
1443 if (outputPath[len - 1] != '/') {
1444 outputPath += "/";
1445 }
1446 }
1447 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001448 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001449
1450 default:
1451 outputPath.clear(); // Unused.
1452 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001453 }
1454
Andreas Huberdca261f2016-08-04 13:47:51 -07001455 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -07001456
Andreas Huber737080b2016-08-02 15:38:04 -07001457 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001458 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001459
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001460 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001461 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001462 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001463 exit(1);
1464 }
Andreas Huber881227d2016-08-02 14:20:21 -07001465
Andreas Huber0fa9e392016-08-31 09:05:44 -07001466 OutputHandler::ValRes valid =
Steven Morelanddd583842017-04-19 13:09:57 -07001467 outputFormat->validate(fqName, outputFormat->name());
Andreas Huber0fa9e392016-08-31 09:05:44 -07001468
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001469 if (valid == OutputHandler::FAILED) {
Steven Morelandf2e44692017-04-18 20:19:09 -07001470 fprintf(stderr,
1471 "ERROR: output handler failed.\n");
Andreas Hubere61e3f72016-08-03 10:22:03 -07001472 exit(1);
1473 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001474
1475 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001476 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001477
1478 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001479 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001480 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001481 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001482
Andreas Huberd2943e12016-08-05 11:59:31 -07001483 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001484}