blob: 329096d1789b1bbd064b611611f4c2d795ec283c [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 Moreland9c387612016-09-07 09:54:26 -070091 if (lang == "c++-impl") {
92 return ast->generateCppImpl(outputDir);
93 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070094 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -070095 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070096 }
97 if (lang == "vts") {
98 return ast->generateVts(outputDir);
99 }
100 // Unknown language.
101 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700102}
103
104static status_t generateSourcesForPackage(
105 const FQName &packageFQName,
106 const char *hidl_gen,
107 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700108 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700109 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700110 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700111 !packageFQName.isFullyQualified() &&
112 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700113
114 std::vector<FQName> packageInterfaces;
115
116 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700117 coordinator->appendPackageInterfacesToVector(packageFQName,
118 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700119
120 if (err != OK) {
121 return err;
122 }
123
124 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700125 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700126 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700127 if (err != OK) {
128 return err;
129 }
130 }
131
132 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700133}
134
Andreas Huberd2943e12016-08-05 11:59:31 -0700135static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700136 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700137}
138
Andreas Huberaa573272017-04-13 09:58:06 -0700139static std::string makeJavaLibraryName(const FQName &packageFQName) {
140 std::string out;
141 out = packageFQName.package();
142 out += "-V";
143 out += packageFQName.version();
144 return out;
145}
146
Steven Moreland5715fed2017-01-16 11:06:47 -0800147static void generatePackagePathsSection(
148 Formatter &out,
149 Coordinator *coordinator,
150 const FQName &packageFQName,
151 const std::set<FQName> &importedPackages,
152 bool forMakefiles = false) {
153 std::set<std::string> options{};
154 for (const auto &interface : importedPackages) {
155 options.insert(coordinator->getPackageRootOption(interface));
156 }
157 options.insert(coordinator->getPackageRootOption(packageFQName));
158 options.insert(coordinator->getPackageRootOption(gIBasePackageFqName));
159 for (const auto &option : options) {
160 out << "-r"
161 << option
162 << " ";
163 if (forMakefiles) {
164 out << "\\\n";
165 }
166 }
167}
168
Dan Willemsen676abdc2016-09-28 19:42:22 -0700169static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700170 Formatter &out,
171 Coordinator *coordinator,
172 const FQName &packageFQName,
173 const FQName &fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800174 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700175 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700176 out << "\n"
177 << "\n#"
178 << "\n# Build " << fqName.name() << ".hal";
179
Dan Willemsen676abdc2016-09-28 19:42:22 -0700180 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700181 out << " (" << typeName << ")";
182 }
183
184 out << "\n#"
185 << "\nGEN := $(intermediates)/"
186 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800187 << coordinator->getPackagePath(packageFQName, true /* relative */,
188 true /* sanitized */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700189 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700190 out << fqName.name() << ".java";
191 } else {
192 out << typeName << ".java";
193 }
194
195 out << "\n$(GEN): $(HIDL)";
196 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
197 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
198 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700199
200 {
201 AST *ast = coordinator->parse(fqName);
202 CHECK(ast != nullptr);
203 const std::set<FQName>& refs = ast->getImportedNames();
204 for (auto depFQName : refs) {
205 // If the package of depFQName is the same as this fqName's package,
206 // then add it explicitly as a .hal dependency within the same
207 // package.
208 if (fqName.package() == depFQName.package() &&
209 fqName.version() == depFQName.version()) {
210 // PRIVATE_DEPS is not actually being used in the
211 // auto-generated file, but is necessary if the build rule
212 // ever needs to use the dependency information, since the
213 // built-in Make variables are not supported in the Android
214 // build system.
215 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
216 << depFQName.name() << ".hal";
217 // This is the actual dependency.
218 out << "\n$(GEN): $(LOCAL_PATH)/"
219 << depFQName.name() << ".hal";
220 }
221 }
222 }
223
Andreas Huber0fa9e392016-08-31 09:05:44 -0700224 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
225 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
226 out.indent();
227 out.indent();
228 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800229 << "\n-Ljava \\\n";
230
231 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700232
233 out << packageFQName.string()
234 << "::"
235 << fqName.name();
236
Dan Willemsen676abdc2016-09-28 19:42:22 -0700237 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700238 out << "." << typeName;
239 }
240
241 out << "\n";
242
243 out.unindent();
244 out.unindent();
245
246 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
247 out << "\n\t$(transform-generated-source)";
248 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
249}
250
Dan Willemsen676abdc2016-09-28 19:42:22 -0700251static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700252 Formatter &out,
253 Coordinator *coordinator,
254 const FQName &packageFQName,
255 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800256 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700257 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700258 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700259 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700260 CHECK(typesAST != nullptr);
261
262 Scope *rootScope = typesAST->scope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700263
Andreas Huberb747bd92016-09-26 15:55:31 -0700264 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
265 std::sort(
266 subTypes.begin(),
267 subTypes.end(),
268 [](const NamedType *a, const NamedType *b) -> bool {
269 return a->fqName() < b->fqName();
270 });
271
272 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700273 if (type->isTypeDef()) {
274 continue;
275 }
276
Dan Willemsen676abdc2016-09-28 19:42:22 -0700277 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700278 out,
279 coordinator,
280 packageFQName,
281 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800282 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700283 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700284 }
285
286 continue;
287 }
288
Dan Willemsen676abdc2016-09-28 19:42:22 -0700289 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700290 out,
291 coordinator,
292 packageFQName,
293 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800294 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700295 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700296 }
297}
298
Andreas Huber75ae95d2016-10-12 16:08:26 -0700299static status_t isPackageJavaCompatible(
300 const FQName &packageFQName,
301 Coordinator *coordinator,
302 bool *compatible) {
303 std::vector<FQName> todo;
304 status_t err =
305 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
306
307 if (err != OK) {
308 return err;
309 }
310
311 std::set<FQName> seen;
312 for (const auto &iface : todo) {
313 seen.insert(iface);
314 }
315
316 // Form the transitive closure of all imported interfaces (and types.hal-s)
317 // If any one of them is not java compatible, this package isn't either.
318 while (!todo.empty()) {
319 const FQName fqName = todo.back();
320 todo.pop_back();
321
322 AST *ast = coordinator->parse(fqName);
323
324 if (ast == nullptr) {
325 return UNKNOWN_ERROR;
326 }
327
328 if (!ast->isJavaCompatible()) {
329 *compatible = false;
330 return OK;
331 }
332
333 std::set<FQName> importedPackages;
334 ast->getImportedPackages(&importedPackages);
335
336 for (const auto &package : importedPackages) {
337 std::vector<FQName> packageInterfaces;
338 status_t err = coordinator->appendPackageInterfacesToVector(
339 package, &packageInterfaces);
340
341 if (err != OK) {
342 return err;
343 }
344
345 for (const auto &iface : packageInterfaces) {
346 if (seen.find(iface) != seen.end()) {
347 continue;
348 }
349
350 todo.push_back(iface);
351 seen.insert(iface);
352 }
353 }
354 }
355
356 *compatible = true;
357 return OK;
358}
359
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700360static bool packageNeedsJavaCode(
361 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
362 // If there is more than just a types.hal file to this package we'll
363 // definitely need to generate Java code.
364 if (packageInterfaces.size() > 1
365 || packageInterfaces[0].name() != "types") {
366 return true;
367 }
368
369 CHECK(typesAST != nullptr);
370
371 // We'll have to generate Java code if types.hal contains any non-typedef
372 // type declarations.
373
374 Scope *rootScope = typesAST->scope();
375 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
376
377 for (const auto &subType : subTypes) {
378 if (!subType->isTypeDef()) {
379 return true;
380 }
381 }
382
383 return false;
384}
385
Andreas Huber1c507272016-10-05 14:33:21 -0700386static void generateMakefileSectionForJavaConstants(
387 Formatter &out,
388 Coordinator *coordinator,
389 const FQName &packageFQName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800390 const std::vector<FQName> &packageInterfaces,
391 const std::set<FQName> &importedPackages) {
Andreas Huber1c507272016-10-05 14:33:21 -0700392 out << "\n#"
393 << "\nGEN := $(intermediates)/"
394 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800395 << coordinator->getPackagePath(packageFQName, true /* relative */, true /* sanitized */)
Andreas Huber1c507272016-10-05 14:33:21 -0700396 << "Constants.java";
397
398 out << "\n$(GEN): $(HIDL)\n";
399 for (const auto &iface : packageInterfaces) {
400 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
401 }
402 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
403 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
404 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
405 out.indent();
406 out.indent();
407 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800408 << "\n-Ljava-constants \\\n";
409
410 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber1c507272016-10-05 14:33:21 -0700411
412 out << packageFQName.string();
413 out << "\n";
414
415 out.unindent();
416 out.unindent();
417
418 out << "\n$(GEN):";
419 out << "\n\t$(transform-generated-source)";
420 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
421}
422
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700423static status_t generateMakefileForPackage(
424 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700425 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700426 Coordinator *coordinator,
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700427 const std::string &) {
428
429 CHECK(packageFQName.isValid() &&
430 !packageFQName.isFullyQualified() &&
431 packageFQName.name().empty());
432
Andreas Huberd2943e12016-08-05 11:59:31 -0700433 std::vector<FQName> packageInterfaces;
434
435 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700436 coordinator->appendPackageInterfacesToVector(packageFQName,
437 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700438
439 if (err != OK) {
440 return err;
441 }
442
443 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700444 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700445 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700446
Andreas Huberd2943e12016-08-05 11:59:31 -0700447 for (const auto &fqName : packageInterfaces) {
448 AST *ast = coordinator->parse(fqName);
449
450 if (ast == NULL) {
451 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700452 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700453 fqName.string().c_str());
454
455 return UNKNOWN_ERROR;
456 }
457
Andreas Huber0fa9e392016-08-31 09:05:44 -0700458 if (fqName.name() == "types") {
459 typesAST = ast;
460 }
461
Yifan Hong40a373d2016-11-30 15:16:47 -0800462 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700463 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700464 }
465
Andreas Huber75ae95d2016-10-12 16:08:26 -0700466 bool packageIsJavaCompatible;
467 err = isPackageJavaCompatible(
468 packageFQName, coordinator, &packageIsJavaCompatible);
469
470 if (err != OK) {
471 return err;
472 }
473
Andreas Huber1c507272016-10-05 14:33:21 -0700474 bool haveJavaConstants = !exportedTypes.empty();
475
476 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800477 // TODO(b/33420795)
478 fprintf(stderr,
479 "WARNING: %s is not java compatible. No java makefile created.\n",
480 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700481 return OK;
482 }
483
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700484 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
485 return OK;
486 }
487
Andreas Huberd2943e12016-08-05 11:59:31 -0700488 std::string path =
489 coordinator->getPackagePath(packageFQName, false /* relative */);
490
491 path.append("Android.mk");
492
493 CHECK(Coordinator::MakeParentHierarchy(path));
494 FILE *file = fopen(path.c_str(), "w");
495
496 if (file == NULL) {
497 return -errno;
498 }
499
Andreas Huberaa573272017-04-13 09:58:06 -0700500 const std::string libraryName = makeJavaLibraryName(packageFQName);
Andreas Huberd2943e12016-08-05 11:59:31 -0700501
502 Formatter out(file);
503
Dan Willemsen676abdc2016-09-28 19:42:22 -0700504 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
505 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700506
Dan Willemsen676abdc2016-09-28 19:42:22 -0700507 enum LibraryStyle {
508 LIBRARY_STYLE_REGULAR,
509 LIBRARY_STYLE_STATIC,
510 LIBRARY_STYLE_END,
511 };
Andreas Huberd2943e12016-08-05 11:59:31 -0700512
Andreas Huber1c507272016-10-05 14:33:21 -0700513 for (int style = LIBRARY_STYLE_REGULAR;
514 (packageIsJavaCompatible && style != LIBRARY_STYLE_END);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700515 ++style) {
516 const std::string staticSuffix =
517 (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700518
Dan Willemsen676abdc2016-09-28 19:42:22 -0700519 out << "\n"
520 << "########################################"
521 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700522
Dan Willemsen676abdc2016-09-28 19:42:22 -0700523 out << "include $(CLEAR_VARS)\n"
524 << "LOCAL_MODULE := "
525 << libraryName
526 << "-java"
527 << staticSuffix
528 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800529 << "intermediates := $(call local-generated-sources-dir, COMMON)"
530 << "\n\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700531 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
532 << hidl_gen
533 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700534
Dan Willemsen676abdc2016-09-28 19:42:22 -0700535 if (!importedPackages.empty()) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700536 out << "\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700537 << "\nLOCAL_"
Andreas Huber782d45e2016-09-22 13:25:14 -0700538 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
Dan Willemsen676abdc2016-09-28 19:42:22 -0700539 << "JAVA_LIBRARIES := \\";
540
541 out.indent();
542 for (const auto &importedPackage : importedPackages) {
543 out << "\n"
Andreas Huberaa573272017-04-13 09:58:06 -0700544 << makeJavaLibraryName(importedPackage)
Dan Willemsen676abdc2016-09-28 19:42:22 -0700545 << "-java"
546 << staticSuffix
547 << " \\";
548 }
549 out << "\n";
550 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700551 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700552
553 generateMakefileSection(
554 out,
555 coordinator,
556 packageFQName,
557 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800558 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700559 typesAST);
560
561 out << "\ninclude $(BUILD_"
562 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
563 << "JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700564 }
565
Andreas Huber1c507272016-10-05 14:33:21 -0700566 if (haveJavaConstants) {
567 out << "\n"
568 << "########################################"
569 << "########################################\n\n";
570
571 out << "include $(CLEAR_VARS)\n"
572 << "LOCAL_MODULE := "
573 << libraryName
574 << "-java-constants"
575 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800576 << "intermediates := $(call local-generated-sources-dir, COMMON)"
577 << "\n\n"
Andreas Huber1c507272016-10-05 14:33:21 -0700578 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
579 << hidl_gen
580 << "$(HOST_EXECUTABLE_SUFFIX)";
581
582 generateMakefileSectionForJavaConstants(
Steven Moreland5715fed2017-01-16 11:06:47 -0800583 out, coordinator, packageFQName, packageInterfaces, importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700584
585 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
586 << "-> framework.jar\n"
587 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
588 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
589 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
590 }
591
Iliyan Malchev8be09552016-09-22 16:20:33 -0700592 out << "\n\n"
593 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
594
Andreas Huberd2943e12016-08-05 11:59:31 -0700595 return OK;
596}
597
Andreas Huber0fa9e392016-08-31 09:05:44 -0700598OutputHandler::ValRes validateForMakefile(
599 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700600 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700601 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700602 return OutputHandler::FAILED;
603 }
604
605 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700606 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700607 return OutputHandler::FAILED;
608 }
609
610 if (!fqName.name().empty()) {
611 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700612 "ERROR: Expecting only package name and version.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700613 return OutputHandler::FAILED;
614 }
615
616 return OutputHandler::PASS_PACKAGE;
617}
618
Dan Willemsen676abdc2016-09-28 19:42:22 -0700619static void generateAndroidBpGenSection(
620 Formatter &out,
621 const FQName &packageFQName,
622 const char *hidl_gen,
623 Coordinator *coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800624 const std::string &halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700625 const std::string &genName,
626 const char *language,
627 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800628 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700629 const std::function<void(Formatter&, const FQName)> outputFn) {
630
631 out << "genrule {\n";
632 out.indent();
633 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700634 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700635
Colin Crossd5419bd2016-11-04 15:05:54 -0700636 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Steven Moreland5715fed2017-01-16 11:06:47 -0800637 << " -L" << language << " ";
638
639 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages);
640
641 out << packageFQName.string() << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700642
643 out << "srcs: [\n";
644 out.indent();
Tri Vo6a827fa2017-02-08 10:24:42 -0800645 out << "\":" << halFilegroupName << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700646 out.unindent();
647 out << "],\n";
648
649 out << "out: [\n";
650 out.indent();
651 for (const auto &fqName : packageInterfaces) {
652 outputFn(out, fqName);
653 }
654 out.unindent();
655 out << "],\n";
656
657 out.unindent();
658 out << "}\n\n";
659}
660
Steven Moreland1b2167b2017-05-01 10:06:21 -0700661bool isHidlTransportPackage(const FQName &package) {
662 return package == gIBasePackageFqName ||
663 package == gIManagerPackageFqName;
664}
665
Dan Willemsen676abdc2016-09-28 19:42:22 -0700666static status_t generateAndroidBpForPackage(
667 const FQName &packageFQName,
668 const char *hidl_gen,
669 Coordinator *coordinator,
670 const std::string &) {
671
672 CHECK(packageFQName.isValid() &&
673 !packageFQName.isFullyQualified() &&
674 packageFQName.name().empty());
675
676 std::vector<FQName> packageInterfaces;
677
678 status_t err =
679 coordinator->appendPackageInterfacesToVector(packageFQName,
680 &packageInterfaces);
681
682 if (err != OK) {
683 return err;
684 }
685
Steven Morelandff5262b2017-03-20 06:59:03 -0700686 std::set<FQName> importedPackagesHierarchy;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700687 AST *typesAST = nullptr;
688
689 for (const auto &fqName : packageInterfaces) {
690 AST *ast = coordinator->parse(fqName);
691
692 if (ast == NULL) {
693 fprintf(stderr,
694 "ERROR: Could not parse %s. Aborting.\n",
695 fqName.string().c_str());
696
697 return UNKNOWN_ERROR;
698 }
699
700 if (fqName.name() == "types") {
701 typesAST = ast;
702 }
703
Steven Morelandff5262b2017-03-20 06:59:03 -0700704 ast->getImportedPackagesHierarchy(&importedPackagesHierarchy);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700705 }
706
707 std::string path =
708 coordinator->getPackagePath(packageFQName, false /* relative */);
709
710 path.append("Android.bp");
711
712 CHECK(Coordinator::MakeParentHierarchy(path));
713 FILE *file = fopen(path.c_str(), "w");
714
715 if (file == NULL) {
716 return -errno;
717 }
718
719 const std::string libraryName = makeLibraryName(packageFQName);
Tri Vo15052c62017-02-06 10:04:07 -0800720 const std::string halFilegroupName = libraryName + "_hal";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700721 const std::string genSourceName = libraryName + "_genc++";
722 const std::string genHeaderName = libraryName + "_genc++_headers";
723 const std::string pathPrefix =
724 coordinator->convertPackageRootToPath(packageFQName) +
725 coordinator->getPackagePath(packageFQName, true /* relative */);
726
727 Formatter out(file);
728
729 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
730
Tri Vo15052c62017-02-06 10:04:07 -0800731 // Rule to generate .hal filegroup
732 out << "filegroup {\n";
733 out.indent();
734 out << "name: \"" << halFilegroupName << "\",\n";
735 out << "srcs: [\n";
736 out.indent();
737 for (const auto &fqName : packageInterfaces) {
738 out << "\"" << fqName.name() << ".hal\",\n";
739 }
740 out.unindent();
741 out << "],\n";
742 out.unindent();
743 out << "}\n\n";
744
Dan Willemsen676abdc2016-09-28 19:42:22 -0700745 // Rule to generate the C++ source files
746 generateAndroidBpGenSection(
747 out,
748 packageFQName,
749 hidl_gen,
750 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800751 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700752 genSourceName,
753 "c++",
754 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700755 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700756 [&pathPrefix](Formatter &out, const FQName &fqName) {
757 if (fqName.name() == "types") {
758 out << "\"" << pathPrefix << "types.cpp\",\n";
759 } else {
760 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
761 }
762 });
763
764 // Rule to generate the C++ header files
765 generateAndroidBpGenSection(
766 out,
767 packageFQName,
768 hidl_gen,
769 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800770 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700771 genHeaderName,
772 "c++",
773 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700774 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700775 [&pathPrefix](Formatter &out, const FQName &fqName) {
776 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
777 if (fqName.name() != "types") {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800778 out << "\"" << pathPrefix << fqName.getInterfaceHwName() << ".h\",\n";
779 out << "\"" << pathPrefix << fqName.getInterfaceStubName() << ".h\",\n";
780 out << "\"" << pathPrefix << fqName.getInterfaceProxyName() << ".h\",\n";
781 out << "\"" << pathPrefix << fqName.getInterfacePassthroughName() << ".h\",\n";
Steven Moreland9774d622017-03-24 21:51:45 -0700782 } else {
783 out << "\"" << pathPrefix << "hwtypes.h\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700784 }
785 });
786
Steven Morelandf5f593f2017-05-02 13:13:00 -0700787 if (isHidlTransportPackage(packageFQName)) {
788 out << "// " << packageFQName.string() << " is exported from libhidltransport\n";
Steven Moreland0e875df2017-04-25 13:24:17 -0700789 } else {
Steven Morelandf5f593f2017-05-02 13:13:00 -0700790 // C++ library definition
791 out << "cc_library_shared {\n";
792 out.indent();
793 out << "name: \"" << libraryName << "\",\n"
794 << "generated_sources: [\"" << genSourceName << "\"],\n"
795 << "generated_headers: [\"" << genHeaderName << "\"],\n"
796 << "export_generated_headers: [\"" << genHeaderName << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700797
Steven Morelandf5f593f2017-05-02 13:13:00 -0700798 // TODO(b/35813011): make always vendor_available
799 // Explicitly mark libraries vendor until BOARD_VNDK_VERSION can
800 // be enabled.
801 if (packageFQName.inPackage("android.hidl") ||
802 packageFQName.inPackage("android.system") ||
803 packageFQName.inPackage("android.frameworks") ||
804 packageFQName.inPackage("android.hardware")) {
805 out << "vendor_available: true,\n";
806 } else {
807 out << "vendor: true,\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700808 }
Steven Morelandf5f593f2017-05-02 13:13:00 -0700809 out << "shared_libs: [\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700810
Steven Morelandf5f593f2017-05-02 13:13:00 -0700811 out.indent();
812 out << "\"libhidlbase\",\n"
813 << "\"libhidltransport\",\n"
814 << "\"libhwbinder\",\n"
815 << "\"liblog\",\n"
816 << "\"libutils\",\n"
817 << "\"libcutils\",\n";
818 for (const auto &importedPackage : importedPackagesHierarchy) {
819 if (isHidlTransportPackage(importedPackage)) {
820 continue;
821 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700822
Steven Morelandf5f593f2017-05-02 13:13:00 -0700823 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700824 }
Steven Morelandf5f593f2017-05-02 13:13:00 -0700825 out.unindent();
Steven Moreland1b2167b2017-05-01 10:06:21 -0700826
Steven Morelandf5f593f2017-05-02 13:13:00 -0700827 out << "],\n";
828
829 out << "export_shared_lib_headers: [\n";
830 out.indent();
831 out << "\"libhidlbase\",\n"
832 << "\"libhidltransport\",\n"
833 << "\"libhwbinder\",\n"
834 << "\"libutils\",\n";
835 for (const auto &importedPackage : importedPackagesHierarchy) {
836 if (isHidlTransportPackage(importedPackage)) {
837 continue;
838 }
839
840 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
841 }
842 out.unindent();
843 out << "],\n";
844 out.unindent();
845
846 out << "}\n";
Yifan Hongc1f9b8d2016-11-07 14:35:44 -0800847 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700848
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800849 return OK;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700850}
851
Yifan Hong958ee462016-12-06 17:09:51 -0800852static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -0700853 const FQName &packageFQName,
854 const char *,
855 Coordinator *coordinator,
856 const std::string &outputDir) {
857
Iliyan Malchev4923f932016-09-09 13:04:59 -0700858 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700859
860 std::vector<FQName> packageInterfaces;
861
862 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700863 coordinator->appendPackageInterfacesToVector(packageFQName,
864 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700865
866 if (err != OK) {
867 return err;
868 }
869
870 std::set<FQName> importedPackages;
871
872 for (const auto &fqName : packageInterfaces) {
873 AST *ast = coordinator->parse(fqName);
874
875 if (ast == NULL) {
876 fprintf(stderr,
877 "ERROR: Could not parse %s. Aborting.\n",
878 fqName.string().c_str());
879
880 return UNKNOWN_ERROR;
881 }
882
883 ast->getImportedPackages(&importedPackages);
884 }
885
Yifan Hongaafed702016-12-14 12:59:47 -0800886 std::string path = outputDir + "Android.bp";
Steven Moreland197d56c2016-09-09 10:03:58 -0700887
888 CHECK(Coordinator::MakeParentHierarchy(path));
889 FILE *file = fopen(path.c_str(), "w");
890
891 if (file == NULL) {
892 return -errno;
893 }
894
895 Formatter out(file);
896
Yifan Hong958ee462016-12-06 17:09:51 -0800897 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800898 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800899 out << "name: \"" << libraryName << "\",\n"
900 << "relative_install_path: \"hw\",\n"
Steven Morelandf8a22e92017-02-15 18:46:04 -0800901 << "proprietary: true,\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800902 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800903 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800904 for (const auto &fqName : packageInterfaces) {
905 if (fqName.name() == "types") {
906 continue;
907 }
908 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
909 }
910 });
911 out << "],\n"
912 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800913 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800914 out << "\"libhidlbase\",\n"
915 << "\"libhidltransport\",\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800916 << "\"libutils\",\n"
917 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -0700918
Yifan Hong958ee462016-12-06 17:09:51 -0800919 for (const auto &importedPackage : importedPackages) {
Steven Morelanddadd1842017-05-09 13:24:54 -0700920 if (isHidlTransportPackage(importedPackage)) {
921 continue;
922 }
923
Yifan Hong958ee462016-12-06 17:09:51 -0800924 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
925 }
926 });
927 out << "],\n";
928 });
929 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -0700930
931 return OK;
932}
933
Andreas Huber0fa9e392016-08-31 09:05:44 -0700934OutputHandler::ValRes validateForSource(
935 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700936 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700937 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700938 return OutputHandler::FAILED;
939 }
940
941 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700942 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700943 return OutputHandler::FAILED;
944 }
945
Andreas Huber0fa9e392016-08-31 09:05:44 -0700946 const std::string &name = fqName.name();
947 if (!name.empty()) {
948 if (name.find('.') == std::string::npos) {
949 return OutputHandler::PASS_FULL;
950 }
951
952 if (language != "java" || name.find("types.") != 0) {
953 // When generating java sources for "types.hal", output can be
954 // constrained to just one of the top-level types declared
955 // by using the extended syntax
956 // android.hardware.Foo@1.0::types.TopLevelTypeName.
957 // In all other cases (different language, not 'types') the dot
958 // notation in the name is illegal in this context.
959 return OutputHandler::FAILED;
960 }
961
962 return OutputHandler::PASS_FULL;
963 }
964
965 return OutputHandler::PASS_PACKAGE;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700966}
967
Andreas Huber019d21d2016-10-03 12:59:47 -0700968OutputHandler::ValRes validateForExportHeader(
969 const FQName &fqName, const std::string & /* language */) {
970 if (fqName.package().empty()) {
971 fprintf(stderr, "ERROR: Expecting package name\n");
972 return OutputHandler::FAILED;
973 }
974
975 if (fqName.version().empty()) {
976 fprintf(stderr, "ERROR: Expecting package version\n");
977 return OutputHandler::FAILED;
978 }
979
980 if (!fqName.name().empty()) {
981 fprintf(stderr,
982 "ERROR: Expecting only package name and version.\n");
983 return OutputHandler::FAILED;
984 }
985
986 return OutputHandler::PASS_PACKAGE;
987}
988
989
990static status_t generateExportHeaderForPackage(
991 const FQName &packageFQName,
992 const char * /* hidl_gen */,
993 Coordinator *coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -0700994 const std::string &outputPath,
995 bool forJava) {
Andreas Huber019d21d2016-10-03 12:59:47 -0700996
997 CHECK(packageFQName.isValid()
998 && !packageFQName.isFullyQualified()
999 && packageFQName.name().empty());
1000
1001 std::vector<FQName> packageInterfaces;
1002
1003 status_t err = coordinator->appendPackageInterfacesToVector(
1004 packageFQName, &packageInterfaces);
1005
1006 if (err != OK) {
1007 return err;
1008 }
1009
1010 std::vector<const Type *> exportedTypes;
1011
1012 for (const auto &fqName : packageInterfaces) {
1013 AST *ast = coordinator->parse(fqName);
1014
1015 if (ast == NULL) {
1016 fprintf(stderr,
1017 "ERROR: Could not parse %s. Aborting.\n",
1018 fqName.string().c_str());
1019
1020 return UNKNOWN_ERROR;
1021 }
1022
1023 ast->appendToExportedTypesVector(&exportedTypes);
1024 }
1025
1026 if (exportedTypes.empty()) {
1027 return OK;
1028 }
1029
Andreas Huber1c507272016-10-05 14:33:21 -07001030 std::string path = outputPath;
1031
1032 if (forJava) {
1033 path.append(coordinator->convertPackageRootToPath(packageFQName));
1034
1035 path.append(coordinator->getPackagePath(
Yifan Hong97288ac2016-12-12 16:03:51 -08001036 packageFQName, true /* relative */, true /* sanitized */));
Andreas Huber1c507272016-10-05 14:33:21 -07001037
1038 path.append("Constants.java");
1039 }
1040
1041 CHECK(Coordinator::MakeParentHierarchy(path));
1042 FILE *file = fopen(path.c_str(), "w");
Andreas Huber019d21d2016-10-03 12:59:47 -07001043
1044 if (file == nullptr) {
1045 return -errno;
1046 }
1047
1048 Formatter out(file);
1049
Steven Morelandd177b122016-12-12 09:15:37 -08001050 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
Glenn Kastend18c3ba2017-02-23 16:35:24 -08001051 << "// Source: " << packageFQName.string() << "\n"
1052 << "// Root: " << coordinator->getPackageRootOption(packageFQName) << "\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001053
Andreas Huber1c507272016-10-05 14:33:21 -07001054 std::string guard;
1055 if (forJava) {
1056 out << "package " << packageFQName.javaPackage() << ";\n\n";
1057 out << "public class Constants {\n";
1058 out.indent();
1059 } else {
1060 guard = "HIDL_GENERATED_";
Steven Morelandd177b122016-12-12 09:15:37 -08001061 guard += StringHelper::Uppercase(packageFQName.tokenName());
Andreas Huber1c507272016-10-05 14:33:21 -07001062 guard += "_";
1063 guard += "EXPORTED_CONSTANTS_H_";
Andreas Huber019d21d2016-10-03 12:59:47 -07001064
Andreas Huber1c507272016-10-05 14:33:21 -07001065 out << "#ifndef "
1066 << guard
1067 << "\n#define "
1068 << guard
1069 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001070 }
1071
Andreas Huber1c507272016-10-05 14:33:21 -07001072 for (const auto &type : exportedTypes) {
1073 type->emitExportedHeader(out, forJava);
1074 }
1075
1076 if (forJava) {
1077 out.unindent();
1078 out << "}\n";
1079 } else {
1080 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
1081 << guard
1082 << "\n";
1083 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001084
1085 return OK;
1086}
1087
Steven Morelandf2e44692017-04-18 20:19:09 -07001088static status_t generateHashOutput(const FQName &fqName,
1089 const char* /*hidl_gen*/,
1090 Coordinator *coordinator,
1091 const std::string & /*outputDir*/) {
1092
1093 status_t err;
1094 std::vector<FQName> packageInterfaces;
1095
1096 if (fqName.isFullyQualified()) {
1097 packageInterfaces = {fqName};
1098 } else {
1099 err = coordinator->appendPackageInterfacesToVector(
1100 fqName, &packageInterfaces);
1101 if (err != OK) {
1102 return err;
1103 }
1104 }
1105
1106 for (const auto &currentFqName : packageInterfaces) {
1107 AST *ast = coordinator->parse(currentFqName);
1108
1109 if (ast == NULL) {
1110 fprintf(stderr,
1111 "ERROR: Could not parse %s. Aborting.\n",
1112 currentFqName.string().c_str());
1113
1114 return UNKNOWN_ERROR;
1115 }
1116
1117 printf("%s %s\n",
1118 Hash::getHash(ast->getFilename()).hexString().c_str(),
1119 currentFqName.string().c_str());
1120 }
1121
1122 return OK;
1123}
1124
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001125static std::vector<OutputHandler> formats = {
Steven Moreland3b1ce262017-04-21 14:19:59 -07001126 {"check",
1127 OutputHandler::NOT_NEEDED /* mOutputMode */,
1128 validateForSource,
1129 [](const FQName &fqName,
1130 const char *hidl_gen, Coordinator *coordinator,
1131 const std::string &outputDir) -> status_t {
1132 if (fqName.isFullyQualified()) {
1133 return generateSourcesForFile(fqName,
1134 hidl_gen,
1135 coordinator,
1136 outputDir,
1137 "check");
1138 } else {
1139 return generateSourcesForPackage(fqName,
1140 hidl_gen,
1141 coordinator,
1142 outputDir,
1143 "check");
1144 }
1145 }
1146 },
1147
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001148 {"c++",
Andreas Huber019d21d2016-10-03 12:59:47 -07001149 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001150 validateForSource,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001151 [](const FQName &fqName,
1152 const char *hidl_gen, Coordinator *coordinator,
1153 const std::string &outputDir) -> status_t {
1154 if (fqName.isFullyQualified()) {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001155 return generateSourcesForFile(fqName,
1156 hidl_gen,
1157 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001158 outputDir,
1159 "c++");
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001160 } else {
1161 return generateSourcesForPackage(fqName,
1162 hidl_gen,
1163 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001164 outputDir,
1165 "c++");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001166 }
1167 }
1168 },
1169
Andreas Huber019d21d2016-10-03 12:59:47 -07001170 {"export-header",
1171 OutputHandler::NEEDS_FILE /* mOutputMode */,
1172 validateForExportHeader,
1173 [](const FQName &fqName,
1174 const char *hidl_gen,
1175 Coordinator *coordinator,
1176 const std::string &outputPath) -> status_t {
1177 CHECK(!fqName.isFullyQualified());
1178
1179 return generateExportHeaderForPackage(
1180 fqName,
1181 hidl_gen,
1182 coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001183 outputPath,
1184 false /* forJava */);
Andreas Huber019d21d2016-10-03 12:59:47 -07001185 }
1186 },
1187
Steven Moreland9c387612016-09-07 09:54:26 -07001188 {"c++-impl",
Andreas Huber019d21d2016-10-03 12:59:47 -07001189 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001190 validateForSource,
1191 [](const FQName &fqName,
1192 const char *hidl_gen, Coordinator *coordinator,
1193 const std::string &outputDir) -> status_t {
1194 if (fqName.isFullyQualified()) {
1195 return generateSourcesForFile(fqName,
1196 hidl_gen,
1197 coordinator,
1198 outputDir, "c++-impl");
1199 } else {
1200 return generateSourcesForPackage(fqName,
1201 hidl_gen,
1202 coordinator,
1203 outputDir, "c++-impl");
1204 }
1205 }
1206 },
1207
1208
Andreas Huber2831d512016-08-15 09:33:47 -07001209 {"java",
Andreas Huber019d21d2016-10-03 12:59:47 -07001210 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001211 validateForSource,
Andreas Huber2831d512016-08-15 09:33:47 -07001212 [](const FQName &fqName,
1213 const char *hidl_gen, Coordinator *coordinator,
1214 const std::string &outputDir) -> status_t {
1215 if (fqName.isFullyQualified()) {
1216 return generateSourcesForFile(fqName,
1217 hidl_gen,
1218 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001219 outputDir,
1220 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001221 }
1222 else {
1223 return generateSourcesForPackage(fqName,
1224 hidl_gen,
1225 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001226 outputDir,
1227 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001228 }
1229 }
1230 },
1231
Andreas Huber1c507272016-10-05 14:33:21 -07001232 {"java-constants",
1233 OutputHandler::NEEDS_DIR /* mOutputMode */,
1234 validateForExportHeader,
1235 [](const FQName &fqName,
1236 const char *hidl_gen, Coordinator *coordinator,
1237 const std::string &outputDir) -> status_t {
1238 CHECK(!fqName.isFullyQualified());
1239 return generateExportHeaderForPackage(
1240 fqName,
1241 hidl_gen,
1242 coordinator,
1243 outputDir,
1244 true /* forJava */);
1245 }
1246 },
1247
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001248 {"vts",
Andreas Huber019d21d2016-10-03 12:59:47 -07001249 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001250 validateForSource,
1251 [](const FQName &fqName,
1252 const char * hidl_gen,
1253 Coordinator *coordinator,
1254 const std::string &outputDir) -> status_t {
1255 if (fqName.isFullyQualified()) {
1256 return generateSourcesForFile(fqName,
1257 hidl_gen,
1258 coordinator,
1259 outputDir, "vts");
1260 } else {
1261 return generateSourcesForPackage(fqName,
1262 hidl_gen,
1263 coordinator,
1264 outputDir, "vts");
1265 }
1266 }
1267 },
1268
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001269 {"makefile",
Andreas Huber019d21d2016-10-03 12:59:47 -07001270 OutputHandler::NOT_NEEDED /* mOutputMode */,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001271 validateForMakefile,
1272 generateMakefileForPackage,
1273 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001274
Dan Willemsen676abdc2016-09-28 19:42:22 -07001275 {"androidbp",
Andreas Huber019d21d2016-10-03 12:59:47 -07001276 OutputHandler::NOT_NEEDED /* mOutputMode */,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001277 validateForMakefile,
1278 generateAndroidBpForPackage,
1279 },
1280
Yifan Hong958ee462016-12-06 17:09:51 -08001281 {"androidbp-impl",
Yifan Hong94bcea02016-10-06 13:51:31 -07001282 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland197d56c2016-09-09 10:03:58 -07001283 validateForMakefile,
Yifan Hong958ee462016-12-06 17:09:51 -08001284 generateAndroidBpImplForPackage,
Steven Morelandf2e44692017-04-18 20:19:09 -07001285 },
1286
1287 {"hash",
1288 OutputHandler::NOT_NEEDED /* mOutputMode */,
1289 validateForSource,
1290 generateHashOutput,
1291 },
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001292};
1293
1294static void usage(const char *me) {
1295 fprintf(stderr,
1296 "usage: %s -o output-path -L <language> (-r interface-root)+ fqname+\n",
1297 me);
1298
1299 fprintf(stderr, " -o output path\n");
1300
1301 fprintf(stderr, " -L <language> (one of");
1302 for (auto &e : formats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001303 fprintf(stderr, " %s", e.name().c_str());
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001304 }
1305 fprintf(stderr, ")\n");
1306
1307 fprintf(stderr,
1308 " -r package:path root "
1309 "(e.g., android.hardware:hardware/interfaces)\n");
1310}
1311
Andreas Gampec4ce9262017-04-27 21:03:20 -07001312// hidl is intentionally leaky. Turn off LeakSanitizer by default.
1313extern "C" const char *__asan_default_options() {
1314 return "detect_leaks=0";
1315}
1316
Andreas Huberb82318c2016-08-02 14:45:54 -07001317int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001318 std::string outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001319 std::vector<std::string> packageRootPaths;
1320 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001321
Andreas Huber737080b2016-08-02 15:38:04 -07001322 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001323 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001324
Andreas Huberb82318c2016-08-02 14:45:54 -07001325 int res;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001326 while ((res = getopt(argc, argv, "ho:r:L:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001327 switch (res) {
1328 case 'o':
1329 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001330 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001331 break;
1332 }
1333
Andreas Huberdca261f2016-08-04 13:47:51 -07001334 case 'r':
1335 {
1336 std::string val(optarg);
1337 auto index = val.find_first_of(':');
Steven Moreland4ff74202017-04-21 14:24:47 -07001338 if (index == std::string::npos) {
1339 fprintf(stderr, "ERROR: -r option must contain ':': %s\n", val.c_str());
1340 exit(1);
1341 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001342
1343 auto package = val.substr(0, index);
1344 auto path = val.substr(index + 1);
1345 packageRootPaths.push_back(path);
1346 packageRoots.push_back(package);
1347 break;
1348 }
1349
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001350 case 'L':
1351 {
Steven Morelanddd583842017-04-19 13:09:57 -07001352 if (outputFormat != nullptr) {
1353 fprintf(stderr,
1354 "ERROR: only one -L option allowed. \"%s\" already specified.\n",
1355 outputFormat->name().c_str());
1356 exit(1);
1357 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001358 for (auto &e : formats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001359 if (e.name() == optarg) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001360 outputFormat = &e;
1361 break;
1362 }
1363 }
Steven Morelanddd583842017-04-19 13:09:57 -07001364 if (outputFormat == nullptr) {
1365 fprintf(stderr,
1366 "ERROR: unrecognized -L option: \"%s\".\n",
1367 optarg);
1368 exit(1);
1369 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001370 break;
1371 }
1372
Andreas Huberb82318c2016-08-02 14:45:54 -07001373 case '?':
1374 case 'h':
1375 default:
1376 {
Andreas Huber737080b2016-08-02 15:38:04 -07001377 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001378 exit(1);
1379 break;
1380 }
1381 }
1382 }
1383
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001384 if (outputFormat == nullptr) {
Steven Morelanddd583842017-04-19 13:09:57 -07001385 fprintf(stderr,
1386 "ERROR: no -L option provided.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001387 exit(1);
1388 }
1389
Andreas Huberb82318c2016-08-02 14:45:54 -07001390 argc -= optind;
1391 argv += optind;
1392
Andreas Huberdca261f2016-08-04 13:47:51 -07001393 if (packageRootPaths.empty()) {
1394 // Pick reasonable defaults.
1395
1396 packageRoots.push_back("android.hardware");
1397
1398 const char *TOP = getenv("TOP");
Steven Morelandaf330382016-11-09 15:48:03 -08001399 if (TOP == nullptr) {
1400 fprintf(stderr,
1401 "ERROR: No root path (-r) specified"
1402 " and $TOP environment variable not set.\n");
1403 exit(1);
1404 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001405
1406 std::string path = TOP;
1407 path.append("/hardware/interfaces");
1408
1409 packageRootPaths.push_back(path);
1410 }
1411
Andreas Huber737080b2016-08-02 15:38:04 -07001412 // Valid options are now in argv[0] .. argv[argc - 1].
1413
Andreas Huber019d21d2016-10-03 12:59:47 -07001414 switch (outputFormat->mOutputMode) {
1415 case OutputHandler::NEEDS_DIR:
1416 case OutputHandler::NEEDS_FILE:
1417 {
1418 if (outputPath.empty()) {
1419 usage(me);
1420 exit(1);
1421 }
1422
1423 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
1424 const size_t len = outputPath.size();
1425 if (outputPath[len - 1] != '/') {
1426 outputPath += "/";
1427 }
1428 }
1429 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001430 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001431
1432 default:
1433 outputPath.clear(); // Unused.
1434 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001435 }
1436
Andreas Huberdca261f2016-08-04 13:47:51 -07001437 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -07001438
Andreas Huber737080b2016-08-02 15:38:04 -07001439 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001440 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001441
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001442 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001443 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001444 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001445 exit(1);
1446 }
Andreas Huber881227d2016-08-02 14:20:21 -07001447
Andreas Huber0fa9e392016-08-31 09:05:44 -07001448 OutputHandler::ValRes valid =
Steven Morelanddd583842017-04-19 13:09:57 -07001449 outputFormat->validate(fqName, outputFormat->name());
Andreas Huber0fa9e392016-08-31 09:05:44 -07001450
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001451 if (valid == OutputHandler::FAILED) {
Steven Morelandf2e44692017-04-18 20:19:09 -07001452 fprintf(stderr,
1453 "ERROR: output handler failed.\n");
Andreas Hubere61e3f72016-08-03 10:22:03 -07001454 exit(1);
1455 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001456
1457 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001458 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001459
1460 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001461 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001462 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001463 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001464
Andreas Huberd2943e12016-08-05 11:59:31 -07001465 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001466}