blob: a86970c1770440296c02bcbbf65c2c29d3bcaf7a [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "AST.h"
Andreas Huber5345ec22016-07-29 13:33:27 -070018#include "Coordinator.h"
Andreas Huber0fa9e392016-08-31 09:05:44 -070019#include "Scope.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070020
Steven Moreland5bdfa702017-04-18 23:20:39 -070021#include <hidl-hash/Hash.h>
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070022#include <hidl-util/Formatter.h>
Steven Moreland7ae3d542017-01-18 16:46:01 -080023#include <hidl-util/FQName.h>
Steven Morelandd177b122016-12-12 09:15:37 -080024#include <hidl-util/StringHelper.h>
Andreas Huber68f24592016-07-29 14:53:48 -070025#include <android-base/logging.h>
Iliyan Malchev5bb14022016-08-09 15:04:39 -070026#include <set>
Andreas Huberc9410c72016-07-28 12:18:40 -070027#include <stdio.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070028#include <string>
Andreas Huberb82318c2016-08-02 14:45:54 -070029#include <unistd.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070030#include <vector>
Andreas Huberc9410c72016-07-28 12:18:40 -070031
32using namespace android;
33
Iliyan Malchev5bb14022016-08-09 15:04:39 -070034struct OutputHandler {
35 std::string mKey;
Steven Moreland97e52332017-05-12 16:47:19 -070036 std::string mDescription;
Andreas Huber019d21d2016-10-03 12:59:47 -070037 enum OutputMode {
38 NEEDS_DIR,
39 NEEDS_FILE,
Steven Morelanda171b562017-05-12 15:18:03 -070040 NEEDS_SRC, // for changes inside the source tree itself
Andreas Huber019d21d2016-10-03 12:59:47 -070041 NOT_NEEDED
42 } mOutputMode;
43
Iliyan Malchev5bb14022016-08-09 15:04:39 -070044 enum ValRes {
45 FAILED,
46 PASS_PACKAGE,
47 PASS_FULL
48 };
Steven Morelanddd583842017-04-19 13:09:57 -070049 const std::string& name() { return mKey; }
Steven Moreland97e52332017-05-12 16:47:19 -070050 const std::string& description() { return mDescription; }
Steven Morelandbbbbeb82017-05-09 14:20:50 -070051
52 using ValidationFunction = std::function<ValRes(const FQName &, const std::string &language)>;
53 using GenerationFunction = std::function<status_t(const FQName &fqName,
54 const char *hidl_gen,
55 Coordinator *coordinator,
56 const std::string &outputDir)>;
57
58 ValidationFunction validate;
59 GenerationFunction generate;
Iliyan Malchev5bb14022016-08-09 15:04:39 -070060};
Andreas Huberdca261f2016-08-04 13:47:51 -070061
Iliyan Malchev5bb14022016-08-09 15:04:39 -070062static status_t generateSourcesForFile(
63 const FQName &fqName,
64 const char *,
65 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -070066 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070067 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -070068 CHECK(fqName.isFullyQualified());
69
Andreas Huber0fa9e392016-08-31 09:05:44 -070070 AST *ast;
Andreas Huberd29724f2016-09-14 09:33:13 -070071 std::string limitToType;
Andreas Huber0fa9e392016-08-31 09:05:44 -070072
73 if (fqName.name().find("types.") == 0) {
74 CHECK(lang == "java"); // Already verified in validate().
75
Andreas Huberd29724f2016-09-14 09:33:13 -070076 limitToType = fqName.name().substr(strlen("types."));
Andreas Huber0fa9e392016-08-31 09:05:44 -070077
Yifan Hongfece6ec2017-01-12 17:04:04 -080078 FQName typesName = fqName.getTypesForPackage();
Andreas Huber0fa9e392016-08-31 09:05:44 -070079 ast = coordinator->parse(typesName);
80 } else {
81 ast = coordinator->parse(fqName);
82 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -070083
84 if (ast == NULL) {
85 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -070086 "ERROR: Could not parse %s. Aborting.\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -070087 fqName.string().c_str());
88
89 return UNKNOWN_ERROR;
90 }
91
Steven Moreland3b1ce262017-04-21 14:19:59 -070092 if (lang == "check") {
93 return OK; // only parsing, not generating
94 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070095 if (lang == "c++") {
96 return ast->generateCpp(outputDir);
97 }
Steven Moreland1cbf0362017-05-09 14:32:53 -070098 if (lang == "c++-headers") {
99 return ast->generateCppHeaders(outputDir);
100 }
101 if (lang == "c++-sources") {
102 return ast->generateCppSources(outputDir);
103 }
Steven Moreland9c387612016-09-07 09:54:26 -0700104 if (lang == "c++-impl") {
105 return ast->generateCppImpl(outputDir);
106 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700107 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700108 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700109 }
110 if (lang == "vts") {
111 return ast->generateVts(outputDir);
112 }
113 // Unknown language.
114 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700115}
116
117static status_t generateSourcesForPackage(
118 const FQName &packageFQName,
119 const char *hidl_gen,
120 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700121 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700122 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700123 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700124 !packageFQName.isFullyQualified() &&
125 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700126
127 std::vector<FQName> packageInterfaces;
128
129 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700130 coordinator->appendPackageInterfacesToVector(packageFQName,
131 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700132
133 if (err != OK) {
134 return err;
135 }
136
137 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700138 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700139 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700140 if (err != OK) {
141 return err;
142 }
143 }
144
145 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700146}
147
Steven Morelandbbbbeb82017-05-09 14:20:50 -0700148OutputHandler::GenerationFunction generationFunctionForFileOrPackage(const std::string &language) {
149 return [language](const FQName &fqName,
150 const char *hidl_gen, Coordinator *coordinator,
151 const std::string &outputDir) -> status_t {
152 if (fqName.isFullyQualified()) {
153 return generateSourcesForFile(fqName,
154 hidl_gen,
155 coordinator,
156 outputDir,
157 language);
158 } else {
159 return generateSourcesForPackage(fqName,
160 hidl_gen,
161 coordinator,
162 outputDir,
163 language);
164 }
165 };
166}
167
Andreas Huberd2943e12016-08-05 11:59:31 -0700168static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700169 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700170}
171
Andreas Huberaa573272017-04-13 09:58:06 -0700172static std::string makeJavaLibraryName(const FQName &packageFQName) {
173 std::string out;
174 out = packageFQName.package();
175 out += "-V";
176 out += packageFQName.version();
177 return out;
178}
179
Steven Moreland5715fed2017-01-16 11:06:47 -0800180static void generatePackagePathsSection(
181 Formatter &out,
182 Coordinator *coordinator,
183 const FQName &packageFQName,
184 const std::set<FQName> &importedPackages,
185 bool forMakefiles = false) {
186 std::set<std::string> options{};
187 for (const auto &interface : importedPackages) {
188 options.insert(coordinator->getPackageRootOption(interface));
189 }
190 options.insert(coordinator->getPackageRootOption(packageFQName));
191 options.insert(coordinator->getPackageRootOption(gIBasePackageFqName));
192 for (const auto &option : options) {
193 out << "-r"
194 << option
195 << " ";
196 if (forMakefiles) {
197 out << "\\\n";
198 }
199 }
200}
201
Dan Willemsen676abdc2016-09-28 19:42:22 -0700202static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700203 Formatter &out,
204 Coordinator *coordinator,
205 const FQName &packageFQName,
206 const FQName &fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800207 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700208 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700209 out << "\n"
210 << "\n#"
211 << "\n# Build " << fqName.name() << ".hal";
212
Dan Willemsen676abdc2016-09-28 19:42:22 -0700213 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700214 out << " (" << typeName << ")";
215 }
216
217 out << "\n#"
218 << "\nGEN := $(intermediates)/"
219 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800220 << coordinator->getPackagePath(packageFQName, true /* relative */,
221 true /* sanitized */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700222 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700223 out << fqName.name() << ".java";
224 } else {
225 out << typeName << ".java";
226 }
227
228 out << "\n$(GEN): $(HIDL)";
229 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
230 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
231 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700232
233 {
234 AST *ast = coordinator->parse(fqName);
235 CHECK(ast != nullptr);
236 const std::set<FQName>& refs = ast->getImportedNames();
237 for (auto depFQName : refs) {
238 // If the package of depFQName is the same as this fqName's package,
239 // then add it explicitly as a .hal dependency within the same
240 // package.
241 if (fqName.package() == depFQName.package() &&
242 fqName.version() == depFQName.version()) {
243 // PRIVATE_DEPS is not actually being used in the
244 // auto-generated file, but is necessary if the build rule
245 // ever needs to use the dependency information, since the
246 // built-in Make variables are not supported in the Android
247 // build system.
248 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
249 << depFQName.name() << ".hal";
250 // This is the actual dependency.
251 out << "\n$(GEN): $(LOCAL_PATH)/"
252 << depFQName.name() << ".hal";
253 }
254 }
255 }
256
Andreas Huber0fa9e392016-08-31 09:05:44 -0700257 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
258 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
259 out.indent();
260 out.indent();
261 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800262 << "\n-Ljava \\\n";
263
264 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700265
266 out << packageFQName.string()
267 << "::"
268 << fqName.name();
269
Dan Willemsen676abdc2016-09-28 19:42:22 -0700270 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700271 out << "." << typeName;
272 }
273
274 out << "\n";
275
276 out.unindent();
277 out.unindent();
278
279 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
280 out << "\n\t$(transform-generated-source)";
281 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
282}
283
Dan Willemsen676abdc2016-09-28 19:42:22 -0700284static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700285 Formatter &out,
286 Coordinator *coordinator,
287 const FQName &packageFQName,
288 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800289 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700290 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700291 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700292 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700293 CHECK(typesAST != nullptr);
294
295 Scope *rootScope = typesAST->scope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700296
Andreas Huberb747bd92016-09-26 15:55:31 -0700297 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
298 std::sort(
299 subTypes.begin(),
300 subTypes.end(),
301 [](const NamedType *a, const NamedType *b) -> bool {
302 return a->fqName() < b->fqName();
303 });
304
305 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700306 if (type->isTypeDef()) {
307 continue;
308 }
309
Dan Willemsen676abdc2016-09-28 19:42:22 -0700310 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700311 out,
312 coordinator,
313 packageFQName,
314 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800315 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700316 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700317 }
318
319 continue;
320 }
321
Dan Willemsen676abdc2016-09-28 19:42:22 -0700322 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700323 out,
324 coordinator,
325 packageFQName,
326 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800327 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700328 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700329 }
330}
331
Andreas Huber75ae95d2016-10-12 16:08:26 -0700332static status_t isPackageJavaCompatible(
333 const FQName &packageFQName,
334 Coordinator *coordinator,
335 bool *compatible) {
336 std::vector<FQName> todo;
337 status_t err =
338 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
339
340 if (err != OK) {
341 return err;
342 }
343
344 std::set<FQName> seen;
345 for (const auto &iface : todo) {
346 seen.insert(iface);
347 }
348
349 // Form the transitive closure of all imported interfaces (and types.hal-s)
350 // If any one of them is not java compatible, this package isn't either.
351 while (!todo.empty()) {
352 const FQName fqName = todo.back();
353 todo.pop_back();
354
355 AST *ast = coordinator->parse(fqName);
356
357 if (ast == nullptr) {
358 return UNKNOWN_ERROR;
359 }
360
361 if (!ast->isJavaCompatible()) {
362 *compatible = false;
363 return OK;
364 }
365
366 std::set<FQName> importedPackages;
367 ast->getImportedPackages(&importedPackages);
368
369 for (const auto &package : importedPackages) {
370 std::vector<FQName> packageInterfaces;
371 status_t err = coordinator->appendPackageInterfacesToVector(
372 package, &packageInterfaces);
373
374 if (err != OK) {
375 return err;
376 }
377
378 for (const auto &iface : packageInterfaces) {
379 if (seen.find(iface) != seen.end()) {
380 continue;
381 }
382
383 todo.push_back(iface);
384 seen.insert(iface);
385 }
386 }
387 }
388
389 *compatible = true;
390 return OK;
391}
392
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700393static bool packageNeedsJavaCode(
394 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
395 // If there is more than just a types.hal file to this package we'll
396 // definitely need to generate Java code.
397 if (packageInterfaces.size() > 1
398 || packageInterfaces[0].name() != "types") {
399 return true;
400 }
401
402 CHECK(typesAST != nullptr);
403
404 // We'll have to generate Java code if types.hal contains any non-typedef
405 // type declarations.
406
407 Scope *rootScope = typesAST->scope();
408 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
409
410 for (const auto &subType : subTypes) {
411 if (!subType->isTypeDef()) {
412 return true;
413 }
414 }
415
416 return false;
417}
418
Andreas Huber1c507272016-10-05 14:33:21 -0700419static void generateMakefileSectionForJavaConstants(
420 Formatter &out,
421 Coordinator *coordinator,
422 const FQName &packageFQName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800423 const std::vector<FQName> &packageInterfaces,
424 const std::set<FQName> &importedPackages) {
Andreas Huber1c507272016-10-05 14:33:21 -0700425 out << "\n#"
426 << "\nGEN := $(intermediates)/"
427 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800428 << coordinator->getPackagePath(packageFQName, true /* relative */, true /* sanitized */)
Andreas Huber1c507272016-10-05 14:33:21 -0700429 << "Constants.java";
430
431 out << "\n$(GEN): $(HIDL)\n";
432 for (const auto &iface : packageInterfaces) {
433 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
434 }
435 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
436 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
437 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
438 out.indent();
439 out.indent();
440 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800441 << "\n-Ljava-constants \\\n";
442
443 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber1c507272016-10-05 14:33:21 -0700444
445 out << packageFQName.string();
446 out << "\n";
447
448 out.unindent();
449 out.unindent();
450
451 out << "\n$(GEN):";
452 out << "\n\t$(transform-generated-source)";
453 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
454}
455
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700456static status_t generateMakefileForPackage(
457 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700458 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700459 Coordinator *coordinator,
Steven Morelanda171b562017-05-12 15:18:03 -0700460 const std::string &outputPath) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700461
462 CHECK(packageFQName.isValid() &&
463 !packageFQName.isFullyQualified() &&
464 packageFQName.name().empty());
465
Andreas Huberd2943e12016-08-05 11:59:31 -0700466 std::vector<FQName> packageInterfaces;
467
468 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700469 coordinator->appendPackageInterfacesToVector(packageFQName,
470 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700471
472 if (err != OK) {
473 return err;
474 }
475
476 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700477 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700478 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700479
Andreas Huberd2943e12016-08-05 11:59:31 -0700480 for (const auto &fqName : packageInterfaces) {
481 AST *ast = coordinator->parse(fqName);
482
483 if (ast == NULL) {
484 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700485 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700486 fqName.string().c_str());
487
488 return UNKNOWN_ERROR;
489 }
490
Andreas Huber0fa9e392016-08-31 09:05:44 -0700491 if (fqName.name() == "types") {
492 typesAST = ast;
493 }
494
Yifan Hong40a373d2016-11-30 15:16:47 -0800495 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700496 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700497 }
498
Andreas Huber75ae95d2016-10-12 16:08:26 -0700499 bool packageIsJavaCompatible;
500 err = isPackageJavaCompatible(
501 packageFQName, coordinator, &packageIsJavaCompatible);
502
503 if (err != OK) {
504 return err;
505 }
506
Andreas Huber1c507272016-10-05 14:33:21 -0700507 bool haveJavaConstants = !exportedTypes.empty();
508
509 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800510 // TODO(b/33420795)
511 fprintf(stderr,
512 "WARNING: %s is not java compatible. No java makefile created.\n",
513 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700514 return OK;
515 }
516
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700517 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
518 return OK;
519 }
520
Steven Morelanda171b562017-05-12 15:18:03 -0700521 std::string path = outputPath;
Steven Morelandf7fa0682017-05-11 16:14:55 -0700522 path.append(coordinator->getPackagePath(packageFQName, false /* relative */));
Andreas Huberd2943e12016-08-05 11:59:31 -0700523 path.append("Android.mk");
524
525 CHECK(Coordinator::MakeParentHierarchy(path));
526 FILE *file = fopen(path.c_str(), "w");
527
528 if (file == NULL) {
529 return -errno;
530 }
531
Andreas Huberaa573272017-04-13 09:58:06 -0700532 const std::string libraryName = makeJavaLibraryName(packageFQName);
Andreas Huberd2943e12016-08-05 11:59:31 -0700533
534 Formatter out(file);
535
Dan Willemsen676abdc2016-09-28 19:42:22 -0700536 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
537 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700538
Dan Willemsen676abdc2016-09-28 19:42:22 -0700539 enum LibraryStyle {
540 LIBRARY_STYLE_REGULAR,
541 LIBRARY_STYLE_STATIC,
542 LIBRARY_STYLE_END,
543 };
Andreas Huberd2943e12016-08-05 11:59:31 -0700544
Andreas Huber1c507272016-10-05 14:33:21 -0700545 for (int style = LIBRARY_STYLE_REGULAR;
546 (packageIsJavaCompatible && style != LIBRARY_STYLE_END);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700547 ++style) {
548 const std::string staticSuffix =
549 (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700550
Dan Willemsen676abdc2016-09-28 19:42:22 -0700551 out << "\n"
552 << "########################################"
553 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700554
Dan Willemsen676abdc2016-09-28 19:42:22 -0700555 out << "include $(CLEAR_VARS)\n"
556 << "LOCAL_MODULE := "
557 << libraryName
558 << "-java"
559 << staticSuffix
560 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800561 << "intermediates := $(call local-generated-sources-dir, COMMON)"
562 << "\n\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700563 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
564 << hidl_gen
565 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700566
Dan Willemsen676abdc2016-09-28 19:42:22 -0700567 if (!importedPackages.empty()) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700568 out << "\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700569 << "\nLOCAL_"
Andreas Huber782d45e2016-09-22 13:25:14 -0700570 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
Dan Willemsen676abdc2016-09-28 19:42:22 -0700571 << "JAVA_LIBRARIES := \\";
572
573 out.indent();
574 for (const auto &importedPackage : importedPackages) {
575 out << "\n"
Andreas Huberaa573272017-04-13 09:58:06 -0700576 << makeJavaLibraryName(importedPackage)
Dan Willemsen676abdc2016-09-28 19:42:22 -0700577 << "-java"
578 << staticSuffix
579 << " \\";
580 }
581 out << "\n";
582 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700583 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700584
585 generateMakefileSection(
586 out,
587 coordinator,
588 packageFQName,
589 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800590 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700591 typesAST);
592
593 out << "\ninclude $(BUILD_"
594 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
595 << "JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700596 }
597
Andreas Huber1c507272016-10-05 14:33:21 -0700598 if (haveJavaConstants) {
599 out << "\n"
600 << "########################################"
601 << "########################################\n\n";
602
603 out << "include $(CLEAR_VARS)\n"
604 << "LOCAL_MODULE := "
605 << libraryName
606 << "-java-constants"
607 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800608 << "intermediates := $(call local-generated-sources-dir, COMMON)"
609 << "\n\n"
Andreas Huber1c507272016-10-05 14:33:21 -0700610 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
611 << hidl_gen
612 << "$(HOST_EXECUTABLE_SUFFIX)";
613
614 generateMakefileSectionForJavaConstants(
Steven Moreland5715fed2017-01-16 11:06:47 -0800615 out, coordinator, packageFQName, packageInterfaces, importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700616
617 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
618 << "-> framework.jar\n"
619 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
620 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
621 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
622 }
623
Iliyan Malchev8be09552016-09-22 16:20:33 -0700624 out << "\n\n"
625 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
626
Andreas Huberd2943e12016-08-05 11:59:31 -0700627 return OK;
628}
629
Andreas Huber0fa9e392016-08-31 09:05:44 -0700630OutputHandler::ValRes validateForMakefile(
631 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700632 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700633 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700634 return OutputHandler::FAILED;
635 }
636
637 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700638 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700639 return OutputHandler::FAILED;
640 }
641
642 if (!fqName.name().empty()) {
643 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700644 "ERROR: Expecting only package name and version.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700645 return OutputHandler::FAILED;
646 }
647
648 return OutputHandler::PASS_PACKAGE;
649}
650
Dan Willemsen676abdc2016-09-28 19:42:22 -0700651static void generateAndroidBpGenSection(
652 Formatter &out,
653 const FQName &packageFQName,
654 const char *hidl_gen,
655 Coordinator *coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800656 const std::string &halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700657 const std::string &genName,
658 const char *language,
659 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800660 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700661 const std::function<void(Formatter&, const FQName)> outputFn) {
662
663 out << "genrule {\n";
664 out.indent();
665 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700666 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700667
Colin Crossd5419bd2016-11-04 15:05:54 -0700668 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Steven Moreland5715fed2017-01-16 11:06:47 -0800669 << " -L" << language << " ";
670
671 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages);
672
673 out << packageFQName.string() << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700674
675 out << "srcs: [\n";
676 out.indent();
Tri Vo6a827fa2017-02-08 10:24:42 -0800677 out << "\":" << halFilegroupName << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700678 out.unindent();
679 out << "],\n";
680
681 out << "out: [\n";
682 out.indent();
683 for (const auto &fqName : packageInterfaces) {
684 outputFn(out, fqName);
685 }
686 out.unindent();
687 out << "],\n";
688
689 out.unindent();
690 out << "}\n\n";
691}
692
Steven Moreland1b2167b2017-05-01 10:06:21 -0700693bool isHidlTransportPackage(const FQName &package) {
694 return package == gIBasePackageFqName ||
695 package == gIManagerPackageFqName;
696}
697
Dan Willemsen676abdc2016-09-28 19:42:22 -0700698static status_t generateAndroidBpForPackage(
699 const FQName &packageFQName,
700 const char *hidl_gen,
701 Coordinator *coordinator,
Steven Morelanda171b562017-05-12 15:18:03 -0700702 const std::string &outputPath) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700703
704 CHECK(packageFQName.isValid() &&
705 !packageFQName.isFullyQualified() &&
706 packageFQName.name().empty());
707
708 std::vector<FQName> packageInterfaces;
709
710 status_t err =
711 coordinator->appendPackageInterfacesToVector(packageFQName,
712 &packageInterfaces);
713
714 if (err != OK) {
715 return err;
716 }
717
Steven Morelandff5262b2017-03-20 06:59:03 -0700718 std::set<FQName> importedPackagesHierarchy;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700719 AST *typesAST = nullptr;
720
721 for (const auto &fqName : packageInterfaces) {
722 AST *ast = coordinator->parse(fqName);
723
724 if (ast == NULL) {
725 fprintf(stderr,
726 "ERROR: Could not parse %s. Aborting.\n",
727 fqName.string().c_str());
728
729 return UNKNOWN_ERROR;
730 }
731
732 if (fqName.name() == "types") {
733 typesAST = ast;
734 }
735
Steven Morelandff5262b2017-03-20 06:59:03 -0700736 ast->getImportedPackagesHierarchy(&importedPackagesHierarchy);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700737 }
738
Steven Morelanda171b562017-05-12 15:18:03 -0700739 std::string path = outputPath;
Steven Morelandf7fa0682017-05-11 16:14:55 -0700740 path.append(coordinator->getPackagePath(packageFQName, false /* relative */));
Dan Willemsen676abdc2016-09-28 19:42:22 -0700741 path.append("Android.bp");
742
743 CHECK(Coordinator::MakeParentHierarchy(path));
744 FILE *file = fopen(path.c_str(), "w");
745
746 if (file == NULL) {
747 return -errno;
748 }
749
750 const std::string libraryName = makeLibraryName(packageFQName);
Tri Vo15052c62017-02-06 10:04:07 -0800751 const std::string halFilegroupName = libraryName + "_hal";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700752 const std::string genSourceName = libraryName + "_genc++";
753 const std::string genHeaderName = libraryName + "_genc++_headers";
754 const std::string pathPrefix =
755 coordinator->convertPackageRootToPath(packageFQName) +
756 coordinator->getPackagePath(packageFQName, true /* relative */);
757
758 Formatter out(file);
759
760 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
761
Tri Vo15052c62017-02-06 10:04:07 -0800762 // Rule to generate .hal filegroup
763 out << "filegroup {\n";
764 out.indent();
765 out << "name: \"" << halFilegroupName << "\",\n";
766 out << "srcs: [\n";
767 out.indent();
768 for (const auto &fqName : packageInterfaces) {
769 out << "\"" << fqName.name() << ".hal\",\n";
770 }
771 out.unindent();
772 out << "],\n";
773 out.unindent();
774 out << "}\n\n";
775
Dan Willemsen676abdc2016-09-28 19:42:22 -0700776 // Rule to generate the C++ source files
777 generateAndroidBpGenSection(
778 out,
779 packageFQName,
780 hidl_gen,
781 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800782 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700783 genSourceName,
Steven Moreland1cbf0362017-05-09 14:32:53 -0700784 "c++-sources",
Dan Willemsen676abdc2016-09-28 19:42:22 -0700785 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700786 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700787 [&pathPrefix](Formatter &out, const FQName &fqName) {
788 if (fqName.name() == "types") {
789 out << "\"" << pathPrefix << "types.cpp\",\n";
790 } else {
791 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
792 }
793 });
794
795 // Rule to generate the C++ header files
796 generateAndroidBpGenSection(
797 out,
798 packageFQName,
799 hidl_gen,
800 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800801 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700802 genHeaderName,
Steven Moreland1cbf0362017-05-09 14:32:53 -0700803 "c++-headers",
Dan Willemsen676abdc2016-09-28 19:42:22 -0700804 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700805 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700806 [&pathPrefix](Formatter &out, const FQName &fqName) {
807 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
808 if (fqName.name() != "types") {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800809 out << "\"" << pathPrefix << fqName.getInterfaceHwName() << ".h\",\n";
810 out << "\"" << pathPrefix << fqName.getInterfaceStubName() << ".h\",\n";
811 out << "\"" << pathPrefix << fqName.getInterfaceProxyName() << ".h\",\n";
812 out << "\"" << pathPrefix << fqName.getInterfacePassthroughName() << ".h\",\n";
Steven Moreland9774d622017-03-24 21:51:45 -0700813 } else {
814 out << "\"" << pathPrefix << "hwtypes.h\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700815 }
816 });
817
Steven Morelandf5f593f2017-05-02 13:13:00 -0700818 if (isHidlTransportPackage(packageFQName)) {
819 out << "// " << packageFQName.string() << " is exported from libhidltransport\n";
Steven Moreland0e875df2017-04-25 13:24:17 -0700820 } else {
Steven Morelandf5f593f2017-05-02 13:13:00 -0700821 // C++ library definition
822 out << "cc_library_shared {\n";
823 out.indent();
824 out << "name: \"" << libraryName << "\",\n"
825 << "generated_sources: [\"" << genSourceName << "\"],\n"
826 << "generated_headers: [\"" << genHeaderName << "\"],\n"
827 << "export_generated_headers: [\"" << genHeaderName << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700828
Steven Morelandf5f593f2017-05-02 13:13:00 -0700829 // TODO(b/35813011): make always vendor_available
830 // Explicitly mark libraries vendor until BOARD_VNDK_VERSION can
831 // be enabled.
832 if (packageFQName.inPackage("android.hidl") ||
833 packageFQName.inPackage("android.system") ||
834 packageFQName.inPackage("android.frameworks") ||
835 packageFQName.inPackage("android.hardware")) {
836 out << "vendor_available: true,\n";
837 } else {
838 out << "vendor: true,\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700839 }
Steven Morelandf5f593f2017-05-02 13:13:00 -0700840 out << "shared_libs: [\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700841
Steven Morelandf5f593f2017-05-02 13:13:00 -0700842 out.indent();
843 out << "\"libhidlbase\",\n"
844 << "\"libhidltransport\",\n"
845 << "\"libhwbinder\",\n"
846 << "\"liblog\",\n"
847 << "\"libutils\",\n"
848 << "\"libcutils\",\n";
849 for (const auto &importedPackage : importedPackagesHierarchy) {
850 if (isHidlTransportPackage(importedPackage)) {
851 continue;
852 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700853
Steven Morelandf5f593f2017-05-02 13:13:00 -0700854 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
Steven Moreland1b2167b2017-05-01 10:06:21 -0700855 }
Steven Morelandf5f593f2017-05-02 13:13:00 -0700856 out.unindent();
Steven Moreland1b2167b2017-05-01 10:06:21 -0700857
Steven Morelandf5f593f2017-05-02 13:13:00 -0700858 out << "],\n";
859
860 out << "export_shared_lib_headers: [\n";
861 out.indent();
862 out << "\"libhidlbase\",\n"
863 << "\"libhidltransport\",\n"
864 << "\"libhwbinder\",\n"
865 << "\"libutils\",\n";
866 for (const auto &importedPackage : importedPackagesHierarchy) {
867 if (isHidlTransportPackage(importedPackage)) {
868 continue;
869 }
870
871 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
872 }
873 out.unindent();
874 out << "],\n";
875 out.unindent();
876
877 out << "}\n";
Yifan Hongc1f9b8d2016-11-07 14:35:44 -0800878 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700879
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800880 return OK;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700881}
882
Yifan Hong958ee462016-12-06 17:09:51 -0800883static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -0700884 const FQName &packageFQName,
885 const char *,
886 Coordinator *coordinator,
887 const std::string &outputDir) {
888
Iliyan Malchev4923f932016-09-09 13:04:59 -0700889 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700890
891 std::vector<FQName> packageInterfaces;
892
893 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700894 coordinator->appendPackageInterfacesToVector(packageFQName,
895 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700896
897 if (err != OK) {
898 return err;
899 }
900
901 std::set<FQName> importedPackages;
902
903 for (const auto &fqName : packageInterfaces) {
904 AST *ast = coordinator->parse(fqName);
905
906 if (ast == NULL) {
907 fprintf(stderr,
908 "ERROR: Could not parse %s. Aborting.\n",
909 fqName.string().c_str());
910
911 return UNKNOWN_ERROR;
912 }
913
914 ast->getImportedPackages(&importedPackages);
915 }
916
Yifan Hongaafed702016-12-14 12:59:47 -0800917 std::string path = outputDir + "Android.bp";
Steven Moreland197d56c2016-09-09 10:03:58 -0700918
919 CHECK(Coordinator::MakeParentHierarchy(path));
920 FILE *file = fopen(path.c_str(), "w");
921
922 if (file == NULL) {
923 return -errno;
924 }
925
926 Formatter out(file);
927
Yifan Hong958ee462016-12-06 17:09:51 -0800928 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800929 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800930 out << "name: \"" << libraryName << "\",\n"
931 << "relative_install_path: \"hw\",\n"
Steven Morelandf8a22e92017-02-15 18:46:04 -0800932 << "proprietary: true,\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800933 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800934 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800935 for (const auto &fqName : packageInterfaces) {
936 if (fqName.name() == "types") {
937 continue;
938 }
939 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
940 }
941 });
942 out << "],\n"
943 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800944 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800945 out << "\"libhidlbase\",\n"
946 << "\"libhidltransport\",\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800947 << "\"libutils\",\n"
948 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -0700949
Yifan Hong958ee462016-12-06 17:09:51 -0800950 for (const auto &importedPackage : importedPackages) {
Steven Morelanddadd1842017-05-09 13:24:54 -0700951 if (isHidlTransportPackage(importedPackage)) {
952 continue;
953 }
954
Yifan Hong958ee462016-12-06 17:09:51 -0800955 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
956 }
957 });
958 out << "],\n";
959 });
960 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -0700961
962 return OK;
963}
964
Andreas Huber0fa9e392016-08-31 09:05:44 -0700965OutputHandler::ValRes validateForSource(
966 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700967 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700968 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700969 return OutputHandler::FAILED;
970 }
971
972 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700973 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700974 return OutputHandler::FAILED;
975 }
976
Andreas Huber0fa9e392016-08-31 09:05:44 -0700977 const std::string &name = fqName.name();
978 if (!name.empty()) {
979 if (name.find('.') == std::string::npos) {
980 return OutputHandler::PASS_FULL;
981 }
982
983 if (language != "java" || name.find("types.") != 0) {
984 // When generating java sources for "types.hal", output can be
985 // constrained to just one of the top-level types declared
986 // by using the extended syntax
987 // android.hardware.Foo@1.0::types.TopLevelTypeName.
988 // In all other cases (different language, not 'types') the dot
989 // notation in the name is illegal in this context.
990 return OutputHandler::FAILED;
991 }
992
993 return OutputHandler::PASS_FULL;
994 }
995
996 return OutputHandler::PASS_PACKAGE;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700997}
998
Andreas Huber019d21d2016-10-03 12:59:47 -0700999OutputHandler::ValRes validateForExportHeader(
1000 const FQName &fqName, const std::string & /* language */) {
1001 if (fqName.package().empty()) {
1002 fprintf(stderr, "ERROR: Expecting package name\n");
1003 return OutputHandler::FAILED;
1004 }
1005
1006 if (fqName.version().empty()) {
1007 fprintf(stderr, "ERROR: Expecting package version\n");
1008 return OutputHandler::FAILED;
1009 }
1010
1011 if (!fqName.name().empty()) {
1012 fprintf(stderr,
1013 "ERROR: Expecting only package name and version.\n");
1014 return OutputHandler::FAILED;
1015 }
1016
1017 return OutputHandler::PASS_PACKAGE;
1018}
1019
1020
Steven Morelandf47912d2017-05-12 16:25:44 -07001021OutputHandler::GenerationFunction generateExportHeaderForPackage(bool forJava) {
1022 return [forJava](const FQName &packageFQName,
1023 const char * /* hidl_gen */,
1024 Coordinator *coordinator,
1025 const std::string &outputPath) -> status_t {
1026 CHECK(packageFQName.isValid()
1027 && !packageFQName.package().empty()
1028 && !packageFQName.version().empty()
1029 && packageFQName.name().empty());
Andreas Huber019d21d2016-10-03 12:59:47 -07001030
Steven Morelandf47912d2017-05-12 16:25:44 -07001031 std::vector<FQName> packageInterfaces;
Andreas Huber019d21d2016-10-03 12:59:47 -07001032
Steven Morelandf47912d2017-05-12 16:25:44 -07001033 status_t err = coordinator->appendPackageInterfacesToVector(
1034 packageFQName, &packageInterfaces);
Andreas Huber019d21d2016-10-03 12:59:47 -07001035
Steven Morelandf47912d2017-05-12 16:25:44 -07001036 if (err != OK) {
1037 return err;
Andreas Huber019d21d2016-10-03 12:59:47 -07001038 }
1039
Steven Morelandf47912d2017-05-12 16:25:44 -07001040 std::vector<const Type *> exportedTypes;
Andreas Huber019d21d2016-10-03 12:59:47 -07001041
Steven Morelandf47912d2017-05-12 16:25:44 -07001042 for (const auto &fqName : packageInterfaces) {
1043 AST *ast = coordinator->parse(fqName);
1044
1045 if (ast == NULL) {
1046 fprintf(stderr,
1047 "ERROR: Could not parse %s. Aborting.\n",
1048 fqName.string().c_str());
1049
1050 return UNKNOWN_ERROR;
1051 }
1052
1053 ast->appendToExportedTypesVector(&exportedTypes);
1054 }
1055
1056 if (exportedTypes.empty()) {
1057 return OK;
1058 }
1059
1060 std::string path = outputPath;
1061
1062 if (forJava) {
1063 path.append(coordinator->convertPackageRootToPath(packageFQName));
1064
1065 path.append(coordinator->getPackagePath(
1066 packageFQName, true /* relative */, true /* sanitized */));
1067
1068 path.append("Constants.java");
1069 }
1070
1071 CHECK(Coordinator::MakeParentHierarchy(path));
1072 FILE *file = fopen(path.c_str(), "w");
1073
1074 if (file == nullptr) {
1075 return -errno;
1076 }
1077
1078 Formatter out(file);
1079
1080 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
1081 << "// Source: " << packageFQName.string() << "\n"
1082 << "// Root: " << coordinator->getPackageRootOption(packageFQName) << "\n\n";
1083
1084 std::string guard;
1085 if (forJava) {
1086 out << "package " << packageFQName.javaPackage() << ";\n\n";
1087 out << "public class Constants {\n";
1088 out.indent();
1089 } else {
1090 guard = "HIDL_GENERATED_";
1091 guard += StringHelper::Uppercase(packageFQName.tokenName());
1092 guard += "_";
1093 guard += "EXPORTED_CONSTANTS_H_";
1094
1095 out << "#ifndef "
1096 << guard
1097 << "\n#define "
1098 << guard
1099 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
1100 }
1101
1102 for (const auto &type : exportedTypes) {
1103 type->emitExportedHeader(out, forJava);
1104 }
1105
1106 if (forJava) {
1107 out.unindent();
1108 out << "}\n";
1109 } else {
1110 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
1111 << guard
1112 << "\n";
1113 }
1114
Andreas Huber019d21d2016-10-03 12:59:47 -07001115 return OK;
Steven Morelandf47912d2017-05-12 16:25:44 -07001116 };
Andreas Huber019d21d2016-10-03 12:59:47 -07001117}
1118
Steven Morelandf2e44692017-04-18 20:19:09 -07001119static status_t generateHashOutput(const FQName &fqName,
1120 const char* /*hidl_gen*/,
1121 Coordinator *coordinator,
1122 const std::string & /*outputDir*/) {
1123
1124 status_t err;
1125 std::vector<FQName> packageInterfaces;
1126
1127 if (fqName.isFullyQualified()) {
1128 packageInterfaces = {fqName};
1129 } else {
1130 err = coordinator->appendPackageInterfacesToVector(
1131 fqName, &packageInterfaces);
1132 if (err != OK) {
1133 return err;
1134 }
1135 }
1136
1137 for (const auto &currentFqName : packageInterfaces) {
1138 AST *ast = coordinator->parse(currentFqName);
1139
1140 if (ast == NULL) {
1141 fprintf(stderr,
1142 "ERROR: Could not parse %s. Aborting.\n",
1143 currentFqName.string().c_str());
1144
1145 return UNKNOWN_ERROR;
1146 }
1147
1148 printf("%s %s\n",
1149 Hash::getHash(ast->getFilename()).hexString().c_str(),
1150 currentFqName.string().c_str());
1151 }
1152
1153 return OK;
1154}
1155
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001156static std::vector<OutputHandler> formats = {
Steven Moreland3b1ce262017-04-21 14:19:59 -07001157 {"check",
Steven Moreland97e52332017-05-12 16:47:19 -07001158 "Parses the interface to see if valid but doesn't write any files.",
Steven Moreland3b1ce262017-04-21 14:19:59 -07001159 OutputHandler::NOT_NEEDED /* mOutputMode */,
1160 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001161 generationFunctionForFileOrPackage("check")
Steven Moreland3b1ce262017-04-21 14:19:59 -07001162 },
1163
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001164 {"c++",
Steven Moreland97e52332017-05-12 16:47:19 -07001165 "(internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001166 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001167 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001168 generationFunctionForFileOrPackage("c++")
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001169 },
1170
Steven Moreland1cbf0362017-05-09 14:32:53 -07001171 {"c++-headers",
Steven Moreland97e52332017-05-12 16:47:19 -07001172 "(internal) Generates C++ headers for interface files for talking to HIDL interfaces.",
Steven Moreland1cbf0362017-05-09 14:32:53 -07001173 OutputHandler::NEEDS_DIR /* mOutputMode */,
1174 validateForSource,
1175 generationFunctionForFileOrPackage("c++-headers")
1176 },
1177
1178 {"c++-sources",
Steven Moreland97e52332017-05-12 16:47:19 -07001179 "(internal) Generates C++ sources for interface files for talking to HIDL interfaces.",
Steven Moreland1cbf0362017-05-09 14:32:53 -07001180 OutputHandler::NEEDS_DIR /* mOutputMode */,
1181 validateForSource,
1182 generationFunctionForFileOrPackage("c++-sources")
1183 },
1184
Andreas Huber019d21d2016-10-03 12:59:47 -07001185 {"export-header",
Steven Moreland97e52332017-05-12 16:47:19 -07001186 "Generates a header file from @export enumerations to help maintain legacy code.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001187 OutputHandler::NEEDS_FILE /* mOutputMode */,
1188 validateForExportHeader,
Steven Morelandf47912d2017-05-12 16:25:44 -07001189 generateExportHeaderForPackage(false /* forJava */)
Andreas Huber019d21d2016-10-03 12:59:47 -07001190 },
1191
Steven Moreland9c387612016-09-07 09:54:26 -07001192 {"c++-impl",
Steven Moreland97e52332017-05-12 16:47:19 -07001193 "Generates boilerplate implementation of a hidl interface in C++ (for convenience).",
Andreas Huber019d21d2016-10-03 12:59:47 -07001194 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001195 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001196 generationFunctionForFileOrPackage("c++-impl")
Steven Moreland9c387612016-09-07 09:54:26 -07001197 },
1198
1199
Andreas Huber2831d512016-08-15 09:33:47 -07001200 {"java",
Steven Moreland97e52332017-05-12 16:47:19 -07001201 "(internal) Generates Java library for talking to HIDL interfaces in Java.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001202 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001203 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001204 generationFunctionForFileOrPackage("java")
Andreas Huber2831d512016-08-15 09:33:47 -07001205 },
1206
Andreas Huber1c507272016-10-05 14:33:21 -07001207 {"java-constants",
Steven Moreland97e52332017-05-12 16:47:19 -07001208 "(internal) Like export-header but for Java (always created by -Lmakefile if @export exists).",
Andreas Huber1c507272016-10-05 14:33:21 -07001209 OutputHandler::NEEDS_DIR /* mOutputMode */,
1210 validateForExportHeader,
Steven Morelandf47912d2017-05-12 16:25:44 -07001211 generateExportHeaderForPackage(true /* forJava */)
Andreas Huber1c507272016-10-05 14:33:21 -07001212 },
1213
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001214 {"vts",
Steven Moreland97e52332017-05-12 16:47:19 -07001215 "(internal) Generates vts proto files for use in vtsd.",
Andreas Huber019d21d2016-10-03 12:59:47 -07001216 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001217 validateForSource,
Steven Morelandbbbbeb82017-05-09 14:20:50 -07001218 generationFunctionForFileOrPackage("vts")
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001219 },
1220
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001221 {"makefile",
Steven Moreland97e52332017-05-12 16:47:19 -07001222 "(internal) Generates makefiles for -Ljava and -Ljava-constants.",
Steven Morelanda171b562017-05-12 15:18:03 -07001223 OutputHandler::NEEDS_SRC /* mOutputMode */,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001224 validateForMakefile,
1225 generateMakefileForPackage,
1226 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001227
Dan Willemsen676abdc2016-09-28 19:42:22 -07001228 {"androidbp",
Steven Moreland97e52332017-05-12 16:47:19 -07001229 "(internal) Generates Soong bp files for -Lc++-headers and -Lc++-sources.",
Steven Morelanda171b562017-05-12 15:18:03 -07001230 OutputHandler::NEEDS_SRC /* mOutputMode */,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001231 validateForMakefile,
1232 generateAndroidBpForPackage,
1233 },
1234
Yifan Hong958ee462016-12-06 17:09:51 -08001235 {"androidbp-impl",
Steven Moreland97e52332017-05-12 16:47:19 -07001236 "Generates boilerplate bp files for implementation created with -Lc++-impl.",
Yifan Hong94bcea02016-10-06 13:51:31 -07001237 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland197d56c2016-09-09 10:03:58 -07001238 validateForMakefile,
Yifan Hong958ee462016-12-06 17:09:51 -08001239 generateAndroidBpImplForPackage,
Steven Morelandf2e44692017-04-18 20:19:09 -07001240 },
1241
1242 {"hash",
Steven Moreland97e52332017-05-12 16:47:19 -07001243 "Prints hashes of interface in `current.txt` format to standard out.",
Steven Morelandf2e44692017-04-18 20:19:09 -07001244 OutputHandler::NOT_NEEDED /* mOutputMode */,
1245 validateForSource,
1246 generateHashOutput,
1247 },
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001248};
1249
1250static void usage(const char *me) {
1251 fprintf(stderr,
Steven Moreland97e52332017-05-12 16:47:19 -07001252 "usage: %s [-p <root path>] -o <output path> -L <language> (-r <interface root>)+ fqname+\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001253 me);
1254
Steven Moreland97e52332017-05-12 16:47:19 -07001255 fprintf(stderr, " -h: Prints this menu.\n");
1256 fprintf(stderr, " -L <language>: The following options are available:\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001257 for (auto &e : formats) {
Steven Moreland97e52332017-05-12 16:47:19 -07001258 fprintf(stderr, " %-16s: %s\n", e.name().c_str(), e.description().c_str());
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001259 }
Steven Moreland97e52332017-05-12 16:47:19 -07001260 fprintf(stderr, " -o <output path>: Location to output files.\n");
1261 fprintf(stderr, " -p <root path>: Android build root, defaults to $ANDROID_BUILD_TOP or pwd.\n");
1262 fprintf(stderr, " -r <package:path root>: E.g., android.hardware:hardware/interfaces.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001263}
1264
Andreas Gampec4ce9262017-04-27 21:03:20 -07001265// hidl is intentionally leaky. Turn off LeakSanitizer by default.
1266extern "C" const char *__asan_default_options() {
1267 return "detect_leaks=0";
1268}
1269
Andreas Huberb82318c2016-08-02 14:45:54 -07001270int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001271 std::string outputPath;
Steven Morelandf7fa0682017-05-11 16:14:55 -07001272 std::string rootPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001273 std::vector<std::string> packageRootPaths;
1274 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001275
Andreas Huber737080b2016-08-02 15:38:04 -07001276 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001277 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001278
Steven Moreland3db99f22017-05-11 16:21:46 -07001279 if (argc == 1) {
1280 usage(me);
1281 exit(1);
1282 }
1283
Andreas Huberb82318c2016-08-02 14:45:54 -07001284 int res;
Steven Morelandf7fa0682017-05-11 16:14:55 -07001285 while ((res = getopt(argc, argv, "hp:o:r:L:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001286 switch (res) {
Steven Morelandf7fa0682017-05-11 16:14:55 -07001287 case 'p':
1288 {
1289 rootPath = optarg;
1290 break;
1291 }
1292
Andreas Huberb82318c2016-08-02 14:45:54 -07001293 case 'o':
1294 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001295 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001296 break;
1297 }
1298
Andreas Huberdca261f2016-08-04 13:47:51 -07001299 case 'r':
1300 {
1301 std::string val(optarg);
1302 auto index = val.find_first_of(':');
Steven Moreland4ff74202017-04-21 14:24:47 -07001303 if (index == std::string::npos) {
1304 fprintf(stderr, "ERROR: -r option must contain ':': %s\n", val.c_str());
1305 exit(1);
1306 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001307
1308 auto package = val.substr(0, index);
1309 auto path = val.substr(index + 1);
1310 packageRootPaths.push_back(path);
1311 packageRoots.push_back(package);
1312 break;
1313 }
1314
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001315 case 'L':
1316 {
Steven Morelanddd583842017-04-19 13:09:57 -07001317 if (outputFormat != nullptr) {
1318 fprintf(stderr,
1319 "ERROR: only one -L option allowed. \"%s\" already specified.\n",
1320 outputFormat->name().c_str());
1321 exit(1);
1322 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001323 for (auto &e : formats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001324 if (e.name() == optarg) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001325 outputFormat = &e;
1326 break;
1327 }
1328 }
Steven Morelanddd583842017-04-19 13:09:57 -07001329 if (outputFormat == nullptr) {
1330 fprintf(stderr,
1331 "ERROR: unrecognized -L option: \"%s\".\n",
1332 optarg);
1333 exit(1);
1334 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001335 break;
1336 }
1337
Andreas Huberb82318c2016-08-02 14:45:54 -07001338 case '?':
1339 case 'h':
1340 default:
1341 {
Andreas Huber737080b2016-08-02 15:38:04 -07001342 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001343 exit(1);
1344 break;
1345 }
1346 }
1347 }
1348
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001349 if (outputFormat == nullptr) {
Steven Morelanddd583842017-04-19 13:09:57 -07001350 fprintf(stderr,
1351 "ERROR: no -L option provided.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001352 exit(1);
1353 }
1354
Andreas Huberb82318c2016-08-02 14:45:54 -07001355 argc -= optind;
1356 argv += optind;
1357
Steven Morelandf7fa0682017-05-11 16:14:55 -07001358 if (rootPath.empty()) {
1359 const char *ANDROID_BUILD_TOP = getenv("ANDROID_BUILD_TOP");
1360
1361 if (ANDROID_BUILD_TOP != nullptr) {
1362 rootPath = ANDROID_BUILD_TOP;
1363 }
1364
1365 // else default to pwd
1366 }
1367
1368 if (!rootPath.empty() && !StringHelper::EndsWith(rootPath, "/")) {
1369 rootPath += "/";
1370 }
1371
Andreas Huber737080b2016-08-02 15:38:04 -07001372 // Valid options are now in argv[0] .. argv[argc - 1].
1373
Andreas Huber019d21d2016-10-03 12:59:47 -07001374 switch (outputFormat->mOutputMode) {
1375 case OutputHandler::NEEDS_DIR:
1376 case OutputHandler::NEEDS_FILE:
1377 {
1378 if (outputPath.empty()) {
1379 usage(me);
1380 exit(1);
1381 }
1382
1383 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
1384 const size_t len = outputPath.size();
1385 if (outputPath[len - 1] != '/') {
1386 outputPath += "/";
1387 }
1388 }
1389 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001390 }
Steven Morelanda171b562017-05-12 15:18:03 -07001391 case OutputHandler::NEEDS_SRC:
1392 {
1393 if (outputPath.empty()) {
1394 outputPath = rootPath;
1395 }
1396
1397 break;
1398 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001399
1400 default:
1401 outputPath.clear(); // Unused.
1402 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001403 }
1404
Steven Morelandf7fa0682017-05-11 16:14:55 -07001405 Coordinator coordinator(packageRootPaths, packageRoots, rootPath);
Steven Moreland25c81662017-05-12 14:57:36 -07001406 coordinator.addDefaultPackagePath("android.hardware", "hardware/interfaces");
1407 coordinator.addDefaultPackagePath("android.hidl", "system/libhidl/transport");
1408 coordinator.addDefaultPackagePath("android.frameworks", "frameworks/hardware/interfaces");
1409 coordinator.addDefaultPackagePath("android.system", "system/hardware/interfaces");
Andreas Huber5345ec22016-07-29 13:33:27 -07001410
Andreas Huber737080b2016-08-02 15:38:04 -07001411 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001412 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001413
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001414 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001415 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001416 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001417 exit(1);
1418 }
Andreas Huber881227d2016-08-02 14:20:21 -07001419
Andreas Huber0fa9e392016-08-31 09:05:44 -07001420 OutputHandler::ValRes valid =
Steven Morelanddd583842017-04-19 13:09:57 -07001421 outputFormat->validate(fqName, outputFormat->name());
Andreas Huber0fa9e392016-08-31 09:05:44 -07001422
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001423 if (valid == OutputHandler::FAILED) {
Steven Morelandf2e44692017-04-18 20:19:09 -07001424 fprintf(stderr,
1425 "ERROR: output handler failed.\n");
Andreas Hubere61e3f72016-08-03 10:22:03 -07001426 exit(1);
1427 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001428
1429 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001430 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001431
1432 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001433 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001434 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001435 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001436
Andreas Huberd2943e12016-08-05 11:59:31 -07001437 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001438}