blob: 545d26aaea32248be04b8ae753b640af34f0b644 [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
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070085 if (lang == "c++") {
86 return ast->generateCpp(outputDir);
87 }
Steven Moreland9c387612016-09-07 09:54:26 -070088 if (lang == "c++-impl") {
89 return ast->generateCppImpl(outputDir);
90 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070091 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -070092 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070093 }
94 if (lang == "vts") {
95 return ast->generateVts(outputDir);
96 }
97 // Unknown language.
98 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -070099}
100
101static status_t generateSourcesForPackage(
102 const FQName &packageFQName,
103 const char *hidl_gen,
104 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700105 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700106 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700107 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700108 !packageFQName.isFullyQualified() &&
109 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700110
111 std::vector<FQName> packageInterfaces;
112
113 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700114 coordinator->appendPackageInterfacesToVector(packageFQName,
115 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700116
117 if (err != OK) {
118 return err;
119 }
120
121 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700122 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700123 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700124 if (err != OK) {
125 return err;
126 }
127 }
128
129 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700130}
131
Andreas Huberd2943e12016-08-05 11:59:31 -0700132static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700133 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700134}
135
Andreas Huberaa573272017-04-13 09:58:06 -0700136static std::string makeJavaLibraryName(const FQName &packageFQName) {
137 std::string out;
138 out = packageFQName.package();
139 out += "-V";
140 out += packageFQName.version();
141 return out;
142}
143
Steven Moreland5715fed2017-01-16 11:06:47 -0800144static void generatePackagePathsSection(
145 Formatter &out,
146 Coordinator *coordinator,
147 const FQName &packageFQName,
148 const std::set<FQName> &importedPackages,
149 bool forMakefiles = false) {
150 std::set<std::string> options{};
151 for (const auto &interface : importedPackages) {
152 options.insert(coordinator->getPackageRootOption(interface));
153 }
154 options.insert(coordinator->getPackageRootOption(packageFQName));
155 options.insert(coordinator->getPackageRootOption(gIBasePackageFqName));
156 for (const auto &option : options) {
157 out << "-r"
158 << option
159 << " ";
160 if (forMakefiles) {
161 out << "\\\n";
162 }
163 }
164}
165
Dan Willemsen676abdc2016-09-28 19:42:22 -0700166static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700167 Formatter &out,
168 Coordinator *coordinator,
169 const FQName &packageFQName,
170 const FQName &fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800171 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700172 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700173 out << "\n"
174 << "\n#"
175 << "\n# Build " << fqName.name() << ".hal";
176
Dan Willemsen676abdc2016-09-28 19:42:22 -0700177 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700178 out << " (" << typeName << ")";
179 }
180
181 out << "\n#"
182 << "\nGEN := $(intermediates)/"
183 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800184 << coordinator->getPackagePath(packageFQName, true /* relative */,
185 true /* sanitized */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700186 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700187 out << fqName.name() << ".java";
188 } else {
189 out << typeName << ".java";
190 }
191
192 out << "\n$(GEN): $(HIDL)";
193 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
194 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
195 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700196
197 {
198 AST *ast = coordinator->parse(fqName);
199 CHECK(ast != nullptr);
200 const std::set<FQName>& refs = ast->getImportedNames();
201 for (auto depFQName : refs) {
202 // If the package of depFQName is the same as this fqName's package,
203 // then add it explicitly as a .hal dependency within the same
204 // package.
205 if (fqName.package() == depFQName.package() &&
206 fqName.version() == depFQName.version()) {
207 // PRIVATE_DEPS is not actually being used in the
208 // auto-generated file, but is necessary if the build rule
209 // ever needs to use the dependency information, since the
210 // built-in Make variables are not supported in the Android
211 // build system.
212 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
213 << depFQName.name() << ".hal";
214 // This is the actual dependency.
215 out << "\n$(GEN): $(LOCAL_PATH)/"
216 << depFQName.name() << ".hal";
217 }
218 }
219 }
220
Andreas Huber0fa9e392016-08-31 09:05:44 -0700221 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
222 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
223 out.indent();
224 out.indent();
225 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800226 << "\n-Ljava \\\n";
227
228 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700229
230 out << packageFQName.string()
231 << "::"
232 << fqName.name();
233
Dan Willemsen676abdc2016-09-28 19:42:22 -0700234 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700235 out << "." << typeName;
236 }
237
238 out << "\n";
239
240 out.unindent();
241 out.unindent();
242
243 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
244 out << "\n\t$(transform-generated-source)";
245 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
246}
247
Dan Willemsen676abdc2016-09-28 19:42:22 -0700248static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700249 Formatter &out,
250 Coordinator *coordinator,
251 const FQName &packageFQName,
252 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800253 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700254 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700255 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700256 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700257 CHECK(typesAST != nullptr);
258
259 Scope *rootScope = typesAST->scope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700260
Andreas Huberb747bd92016-09-26 15:55:31 -0700261 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
262 std::sort(
263 subTypes.begin(),
264 subTypes.end(),
265 [](const NamedType *a, const NamedType *b) -> bool {
266 return a->fqName() < b->fqName();
267 });
268
269 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700270 if (type->isTypeDef()) {
271 continue;
272 }
273
Dan Willemsen676abdc2016-09-28 19:42:22 -0700274 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700275 out,
276 coordinator,
277 packageFQName,
278 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800279 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700280 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700281 }
282
283 continue;
284 }
285
Dan Willemsen676abdc2016-09-28 19:42:22 -0700286 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700287 out,
288 coordinator,
289 packageFQName,
290 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800291 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700292 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700293 }
294}
295
Andreas Huber75ae95d2016-10-12 16:08:26 -0700296static status_t isPackageJavaCompatible(
297 const FQName &packageFQName,
298 Coordinator *coordinator,
299 bool *compatible) {
300 std::vector<FQName> todo;
301 status_t err =
302 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
303
304 if (err != OK) {
305 return err;
306 }
307
308 std::set<FQName> seen;
309 for (const auto &iface : todo) {
310 seen.insert(iface);
311 }
312
313 // Form the transitive closure of all imported interfaces (and types.hal-s)
314 // If any one of them is not java compatible, this package isn't either.
315 while (!todo.empty()) {
316 const FQName fqName = todo.back();
317 todo.pop_back();
318
319 AST *ast = coordinator->parse(fqName);
320
321 if (ast == nullptr) {
322 return UNKNOWN_ERROR;
323 }
324
325 if (!ast->isJavaCompatible()) {
326 *compatible = false;
327 return OK;
328 }
329
330 std::set<FQName> importedPackages;
331 ast->getImportedPackages(&importedPackages);
332
333 for (const auto &package : importedPackages) {
334 std::vector<FQName> packageInterfaces;
335 status_t err = coordinator->appendPackageInterfacesToVector(
336 package, &packageInterfaces);
337
338 if (err != OK) {
339 return err;
340 }
341
342 for (const auto &iface : packageInterfaces) {
343 if (seen.find(iface) != seen.end()) {
344 continue;
345 }
346
347 todo.push_back(iface);
348 seen.insert(iface);
349 }
350 }
351 }
352
353 *compatible = true;
354 return OK;
355}
356
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700357static bool packageNeedsJavaCode(
358 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
359 // If there is more than just a types.hal file to this package we'll
360 // definitely need to generate Java code.
361 if (packageInterfaces.size() > 1
362 || packageInterfaces[0].name() != "types") {
363 return true;
364 }
365
366 CHECK(typesAST != nullptr);
367
368 // We'll have to generate Java code if types.hal contains any non-typedef
369 // type declarations.
370
371 Scope *rootScope = typesAST->scope();
372 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
373
374 for (const auto &subType : subTypes) {
375 if (!subType->isTypeDef()) {
376 return true;
377 }
378 }
379
380 return false;
381}
382
Andreas Huber1c507272016-10-05 14:33:21 -0700383static void generateMakefileSectionForJavaConstants(
384 Formatter &out,
385 Coordinator *coordinator,
386 const FQName &packageFQName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800387 const std::vector<FQName> &packageInterfaces,
388 const std::set<FQName> &importedPackages) {
Andreas Huber1c507272016-10-05 14:33:21 -0700389 out << "\n#"
390 << "\nGEN := $(intermediates)/"
391 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800392 << coordinator->getPackagePath(packageFQName, true /* relative */, true /* sanitized */)
Andreas Huber1c507272016-10-05 14:33:21 -0700393 << "Constants.java";
394
395 out << "\n$(GEN): $(HIDL)\n";
396 for (const auto &iface : packageInterfaces) {
397 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
398 }
399 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
400 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
401 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
402 out.indent();
403 out.indent();
404 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800405 << "\n-Ljava-constants \\\n";
406
407 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber1c507272016-10-05 14:33:21 -0700408
409 out << packageFQName.string();
410 out << "\n";
411
412 out.unindent();
413 out.unindent();
414
415 out << "\n$(GEN):";
416 out << "\n\t$(transform-generated-source)";
417 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
418}
419
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700420static status_t generateMakefileForPackage(
421 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700422 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700423 Coordinator *coordinator,
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700424 const std::string &) {
425
426 CHECK(packageFQName.isValid() &&
427 !packageFQName.isFullyQualified() &&
428 packageFQName.name().empty());
429
Andreas Huberd2943e12016-08-05 11:59:31 -0700430 std::vector<FQName> packageInterfaces;
431
432 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700433 coordinator->appendPackageInterfacesToVector(packageFQName,
434 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700435
436 if (err != OK) {
437 return err;
438 }
439
440 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700441 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700442 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700443
Andreas Huberd2943e12016-08-05 11:59:31 -0700444 for (const auto &fqName : packageInterfaces) {
445 AST *ast = coordinator->parse(fqName);
446
447 if (ast == NULL) {
448 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700449 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700450 fqName.string().c_str());
451
452 return UNKNOWN_ERROR;
453 }
454
Andreas Huber0fa9e392016-08-31 09:05:44 -0700455 if (fqName.name() == "types") {
456 typesAST = ast;
457 }
458
Yifan Hong40a373d2016-11-30 15:16:47 -0800459 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700460 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700461 }
462
Andreas Huber75ae95d2016-10-12 16:08:26 -0700463 bool packageIsJavaCompatible;
464 err = isPackageJavaCompatible(
465 packageFQName, coordinator, &packageIsJavaCompatible);
466
467 if (err != OK) {
468 return err;
469 }
470
Andreas Huber1c507272016-10-05 14:33:21 -0700471 bool haveJavaConstants = !exportedTypes.empty();
472
473 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800474 // TODO(b/33420795)
475 fprintf(stderr,
476 "WARNING: %s is not java compatible. No java makefile created.\n",
477 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700478 return OK;
479 }
480
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700481 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
482 return OK;
483 }
484
Andreas Huberd2943e12016-08-05 11:59:31 -0700485 std::string path =
486 coordinator->getPackagePath(packageFQName, false /* relative */);
487
488 path.append("Android.mk");
489
490 CHECK(Coordinator::MakeParentHierarchy(path));
491 FILE *file = fopen(path.c_str(), "w");
492
493 if (file == NULL) {
494 return -errno;
495 }
496
Andreas Huberaa573272017-04-13 09:58:06 -0700497 const std::string libraryName = makeJavaLibraryName(packageFQName);
Andreas Huberd2943e12016-08-05 11:59:31 -0700498
499 Formatter out(file);
500
Dan Willemsen676abdc2016-09-28 19:42:22 -0700501 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
502 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700503
Dan Willemsen676abdc2016-09-28 19:42:22 -0700504 enum LibraryStyle {
505 LIBRARY_STYLE_REGULAR,
506 LIBRARY_STYLE_STATIC,
507 LIBRARY_STYLE_END,
508 };
Andreas Huberd2943e12016-08-05 11:59:31 -0700509
Andreas Huber1c507272016-10-05 14:33:21 -0700510 for (int style = LIBRARY_STYLE_REGULAR;
511 (packageIsJavaCompatible && style != LIBRARY_STYLE_END);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700512 ++style) {
513 const std::string staticSuffix =
514 (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700515
Dan Willemsen676abdc2016-09-28 19:42:22 -0700516 out << "\n"
517 << "########################################"
518 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700519
Dan Willemsen676abdc2016-09-28 19:42:22 -0700520 out << "include $(CLEAR_VARS)\n"
521 << "LOCAL_MODULE := "
522 << libraryName
523 << "-java"
524 << staticSuffix
525 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800526 << "intermediates := $(call local-generated-sources-dir, COMMON)"
527 << "\n\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700528 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
529 << hidl_gen
530 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700531
Dan Willemsen676abdc2016-09-28 19:42:22 -0700532 if (!importedPackages.empty()) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700533 out << "\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700534 << "\nLOCAL_"
Andreas Huber782d45e2016-09-22 13:25:14 -0700535 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
Dan Willemsen676abdc2016-09-28 19:42:22 -0700536 << "JAVA_LIBRARIES := \\";
537
538 out.indent();
539 for (const auto &importedPackage : importedPackages) {
540 out << "\n"
Andreas Huberaa573272017-04-13 09:58:06 -0700541 << makeJavaLibraryName(importedPackage)
Dan Willemsen676abdc2016-09-28 19:42:22 -0700542 << "-java"
543 << staticSuffix
544 << " \\";
545 }
546 out << "\n";
547 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700548 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700549
550 generateMakefileSection(
551 out,
552 coordinator,
553 packageFQName,
554 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800555 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700556 typesAST);
557
558 out << "\ninclude $(BUILD_"
559 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
560 << "JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700561 }
562
Andreas Huber1c507272016-10-05 14:33:21 -0700563 if (haveJavaConstants) {
564 out << "\n"
565 << "########################################"
566 << "########################################\n\n";
567
568 out << "include $(CLEAR_VARS)\n"
569 << "LOCAL_MODULE := "
570 << libraryName
571 << "-java-constants"
572 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800573 << "intermediates := $(call local-generated-sources-dir, COMMON)"
574 << "\n\n"
Andreas Huber1c507272016-10-05 14:33:21 -0700575 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
576 << hidl_gen
577 << "$(HOST_EXECUTABLE_SUFFIX)";
578
579 generateMakefileSectionForJavaConstants(
Steven Moreland5715fed2017-01-16 11:06:47 -0800580 out, coordinator, packageFQName, packageInterfaces, importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700581
582 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
583 << "-> framework.jar\n"
584 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
585 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
586 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
587 }
588
Iliyan Malchev8be09552016-09-22 16:20:33 -0700589 out << "\n\n"
590 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
591
Andreas Huberd2943e12016-08-05 11:59:31 -0700592 return OK;
593}
594
Andreas Huber0fa9e392016-08-31 09:05:44 -0700595OutputHandler::ValRes validateForMakefile(
596 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700597 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700598 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700599 return OutputHandler::FAILED;
600 }
601
602 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700603 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700604 return OutputHandler::FAILED;
605 }
606
607 if (!fqName.name().empty()) {
608 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700609 "ERROR: Expecting only package name and version.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700610 return OutputHandler::FAILED;
611 }
612
613 return OutputHandler::PASS_PACKAGE;
614}
615
Dan Willemsen676abdc2016-09-28 19:42:22 -0700616static void generateAndroidBpGenSection(
617 Formatter &out,
618 const FQName &packageFQName,
619 const char *hidl_gen,
620 Coordinator *coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800621 const std::string &halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700622 const std::string &genName,
623 const char *language,
624 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800625 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700626 const std::function<void(Formatter&, const FQName)> outputFn) {
627
628 out << "genrule {\n";
629 out.indent();
630 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700631 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700632
Colin Crossd5419bd2016-11-04 15:05:54 -0700633 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Steven Moreland5715fed2017-01-16 11:06:47 -0800634 << " -L" << language << " ";
635
636 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages);
637
638 out << packageFQName.string() << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700639
640 out << "srcs: [\n";
641 out.indent();
Tri Vo6a827fa2017-02-08 10:24:42 -0800642 out << "\":" << halFilegroupName << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700643 out.unindent();
644 out << "],\n";
645
646 out << "out: [\n";
647 out.indent();
648 for (const auto &fqName : packageInterfaces) {
649 outputFn(out, fqName);
650 }
651 out.unindent();
652 out << "],\n";
653
654 out.unindent();
655 out << "}\n\n";
656}
657
658static status_t generateAndroidBpForPackage(
659 const FQName &packageFQName,
660 const char *hidl_gen,
661 Coordinator *coordinator,
662 const std::string &) {
663
664 CHECK(packageFQName.isValid() &&
665 !packageFQName.isFullyQualified() &&
666 packageFQName.name().empty());
667
668 std::vector<FQName> packageInterfaces;
669
670 status_t err =
671 coordinator->appendPackageInterfacesToVector(packageFQName,
672 &packageInterfaces);
673
674 if (err != OK) {
675 return err;
676 }
677
Steven Morelandff5262b2017-03-20 06:59:03 -0700678 std::set<FQName> importedPackagesHierarchy;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700679 AST *typesAST = nullptr;
680
681 for (const auto &fqName : packageInterfaces) {
682 AST *ast = coordinator->parse(fqName);
683
684 if (ast == NULL) {
685 fprintf(stderr,
686 "ERROR: Could not parse %s. Aborting.\n",
687 fqName.string().c_str());
688
689 return UNKNOWN_ERROR;
690 }
691
692 if (fqName.name() == "types") {
693 typesAST = ast;
694 }
695
Steven Morelandff5262b2017-03-20 06:59:03 -0700696 ast->getImportedPackagesHierarchy(&importedPackagesHierarchy);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700697 }
698
699 std::string path =
700 coordinator->getPackagePath(packageFQName, false /* relative */);
701
702 path.append("Android.bp");
703
704 CHECK(Coordinator::MakeParentHierarchy(path));
705 FILE *file = fopen(path.c_str(), "w");
706
707 if (file == NULL) {
708 return -errno;
709 }
710
711 const std::string libraryName = makeLibraryName(packageFQName);
Tri Vo15052c62017-02-06 10:04:07 -0800712 const std::string halFilegroupName = libraryName + "_hal";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700713 const std::string genSourceName = libraryName + "_genc++";
714 const std::string genHeaderName = libraryName + "_genc++_headers";
715 const std::string pathPrefix =
716 coordinator->convertPackageRootToPath(packageFQName) +
717 coordinator->getPackagePath(packageFQName, true /* relative */);
718
719 Formatter out(file);
720
721 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
722
Tri Vo15052c62017-02-06 10:04:07 -0800723 // Rule to generate .hal filegroup
724 out << "filegroup {\n";
725 out.indent();
726 out << "name: \"" << halFilegroupName << "\",\n";
727 out << "srcs: [\n";
728 out.indent();
729 for (const auto &fqName : packageInterfaces) {
730 out << "\"" << fqName.name() << ".hal\",\n";
731 }
732 out.unindent();
733 out << "],\n";
734 out.unindent();
735 out << "}\n\n";
736
Dan Willemsen676abdc2016-09-28 19:42:22 -0700737 // Rule to generate the C++ source files
738 generateAndroidBpGenSection(
739 out,
740 packageFQName,
741 hidl_gen,
742 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800743 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700744 genSourceName,
745 "c++",
746 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700747 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700748 [&pathPrefix](Formatter &out, const FQName &fqName) {
749 if (fqName.name() == "types") {
750 out << "\"" << pathPrefix << "types.cpp\",\n";
751 } else {
752 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
753 }
754 });
755
756 // Rule to generate the C++ header files
757 generateAndroidBpGenSection(
758 out,
759 packageFQName,
760 hidl_gen,
761 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800762 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700763 genHeaderName,
764 "c++",
765 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700766 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700767 [&pathPrefix](Formatter &out, const FQName &fqName) {
768 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
769 if (fqName.name() != "types") {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800770 out << "\"" << pathPrefix << fqName.getInterfaceHwName() << ".h\",\n";
771 out << "\"" << pathPrefix << fqName.getInterfaceStubName() << ".h\",\n";
772 out << "\"" << pathPrefix << fqName.getInterfaceProxyName() << ".h\",\n";
773 out << "\"" << pathPrefix << fqName.getInterfacePassthroughName() << ".h\",\n";
Steven Moreland9774d622017-03-24 21:51:45 -0700774 } else {
775 out << "\"" << pathPrefix << "hwtypes.h\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700776 }
777 });
778
779 // C++ library definition
780 out << "cc_library_shared {\n";
781 out.indent();
782 out << "name: \"" << libraryName << "\",\n"
783 << "generated_sources: [\"" << genSourceName << "\"],\n"
784 << "generated_headers: [\"" << genHeaderName << "\"],\n"
785 << "export_generated_headers: [\"" << genHeaderName << "\"],\n"
Dan Willemsen2cf4b9a2017-04-07 13:21:11 -0700786 << "vendor_available: true,\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700787 << "shared_libs: [\n";
788
789 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -0800790 out << "\"libhidlbase\",\n"
791 << "\"libhidltransport\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700792 << "\"libhwbinder\",\n"
Steven Moreland05cd4232016-11-21 16:01:12 -0800793 << "\"liblog\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700794 << "\"libutils\",\n"
795 << "\"libcutils\",\n";
Steven Morelandff5262b2017-03-20 06:59:03 -0700796 for (const auto &importedPackage : importedPackagesHierarchy) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700797 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
798 }
799 out.unindent();
800
801 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -0700802
803 out << "export_shared_lib_headers: [\n";
804 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -0800805 out << "\"libhidlbase\",\n"
806 << "\"libhidltransport\",\n"
Steven Morelandb8a26c02016-10-21 13:40:14 -0700807 << "\"libhwbinder\",\n"
Steven Moreland865243c2016-11-01 13:05:24 -0700808 << "\"libutils\",\n";
Steven Morelandff5262b2017-03-20 06:59:03 -0700809 for (const auto &importedPackage : importedPackagesHierarchy) {
Yifan Hongc1f9b8d2016-11-07 14:35:44 -0800810 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
811 }
Steven Moreland865243c2016-11-01 13:05:24 -0700812 out.unindent();
813 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -0700814 out.unindent();
815
Dan Willemsen676abdc2016-09-28 19:42:22 -0700816 out << "}\n";
817
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800818 return OK;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700819}
820
Yifan Hong958ee462016-12-06 17:09:51 -0800821static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -0700822 const FQName &packageFQName,
823 const char *,
824 Coordinator *coordinator,
825 const std::string &outputDir) {
826
Iliyan Malchev4923f932016-09-09 13:04:59 -0700827 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700828
829 std::vector<FQName> packageInterfaces;
830
831 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700832 coordinator->appendPackageInterfacesToVector(packageFQName,
833 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700834
835 if (err != OK) {
836 return err;
837 }
838
839 std::set<FQName> importedPackages;
840
841 for (const auto &fqName : packageInterfaces) {
842 AST *ast = coordinator->parse(fqName);
843
844 if (ast == NULL) {
845 fprintf(stderr,
846 "ERROR: Could not parse %s. Aborting.\n",
847 fqName.string().c_str());
848
849 return UNKNOWN_ERROR;
850 }
851
852 ast->getImportedPackages(&importedPackages);
853 }
854
Yifan Hongaafed702016-12-14 12:59:47 -0800855 std::string path = outputDir + "Android.bp";
Steven Moreland197d56c2016-09-09 10:03:58 -0700856
857 CHECK(Coordinator::MakeParentHierarchy(path));
858 FILE *file = fopen(path.c_str(), "w");
859
860 if (file == NULL) {
861 return -errno;
862 }
863
864 Formatter out(file);
865
Yifan Hong958ee462016-12-06 17:09:51 -0800866 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800867 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800868 out << "name: \"" << libraryName << "\",\n"
869 << "relative_install_path: \"hw\",\n"
Steven Morelandf8a22e92017-02-15 18:46:04 -0800870 << "proprietary: true,\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800871 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800872 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800873 for (const auto &fqName : packageInterfaces) {
874 if (fqName.name() == "types") {
875 continue;
876 }
877 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
878 }
879 });
880 out << "],\n"
881 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800882 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800883 out << "\"libhidlbase\",\n"
884 << "\"libhidltransport\",\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800885 << "\"libutils\",\n"
886 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -0700887
Yifan Hong958ee462016-12-06 17:09:51 -0800888 for (const auto &importedPackage : importedPackages) {
889 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
890 }
891 });
892 out << "],\n";
893 });
894 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -0700895
896 return OK;
897}
898
Andreas Huber0fa9e392016-08-31 09:05:44 -0700899OutputHandler::ValRes validateForSource(
900 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700901 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700902 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700903 return OutputHandler::FAILED;
904 }
905
906 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700907 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700908 return OutputHandler::FAILED;
909 }
910
Andreas Huber0fa9e392016-08-31 09:05:44 -0700911 const std::string &name = fqName.name();
912 if (!name.empty()) {
913 if (name.find('.') == std::string::npos) {
914 return OutputHandler::PASS_FULL;
915 }
916
917 if (language != "java" || name.find("types.") != 0) {
918 // When generating java sources for "types.hal", output can be
919 // constrained to just one of the top-level types declared
920 // by using the extended syntax
921 // android.hardware.Foo@1.0::types.TopLevelTypeName.
922 // In all other cases (different language, not 'types') the dot
923 // notation in the name is illegal in this context.
924 return OutputHandler::FAILED;
925 }
926
927 return OutputHandler::PASS_FULL;
928 }
929
930 return OutputHandler::PASS_PACKAGE;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700931}
932
Andreas Huber019d21d2016-10-03 12:59:47 -0700933OutputHandler::ValRes validateForExportHeader(
934 const FQName &fqName, const std::string & /* language */) {
935 if (fqName.package().empty()) {
936 fprintf(stderr, "ERROR: Expecting package name\n");
937 return OutputHandler::FAILED;
938 }
939
940 if (fqName.version().empty()) {
941 fprintf(stderr, "ERROR: Expecting package version\n");
942 return OutputHandler::FAILED;
943 }
944
945 if (!fqName.name().empty()) {
946 fprintf(stderr,
947 "ERROR: Expecting only package name and version.\n");
948 return OutputHandler::FAILED;
949 }
950
951 return OutputHandler::PASS_PACKAGE;
952}
953
954
955static status_t generateExportHeaderForPackage(
956 const FQName &packageFQName,
957 const char * /* hidl_gen */,
958 Coordinator *coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -0700959 const std::string &outputPath,
960 bool forJava) {
Andreas Huber019d21d2016-10-03 12:59:47 -0700961
962 CHECK(packageFQName.isValid()
963 && !packageFQName.isFullyQualified()
964 && packageFQName.name().empty());
965
966 std::vector<FQName> packageInterfaces;
967
968 status_t err = coordinator->appendPackageInterfacesToVector(
969 packageFQName, &packageInterfaces);
970
971 if (err != OK) {
972 return err;
973 }
974
975 std::vector<const Type *> exportedTypes;
976
977 for (const auto &fqName : packageInterfaces) {
978 AST *ast = coordinator->parse(fqName);
979
980 if (ast == NULL) {
981 fprintf(stderr,
982 "ERROR: Could not parse %s. Aborting.\n",
983 fqName.string().c_str());
984
985 return UNKNOWN_ERROR;
986 }
987
988 ast->appendToExportedTypesVector(&exportedTypes);
989 }
990
991 if (exportedTypes.empty()) {
992 return OK;
993 }
994
Andreas Huber1c507272016-10-05 14:33:21 -0700995 std::string path = outputPath;
996
997 if (forJava) {
998 path.append(coordinator->convertPackageRootToPath(packageFQName));
999
1000 path.append(coordinator->getPackagePath(
Yifan Hong97288ac2016-12-12 16:03:51 -08001001 packageFQName, true /* relative */, true /* sanitized */));
Andreas Huber1c507272016-10-05 14:33:21 -07001002
1003 path.append("Constants.java");
1004 }
1005
1006 CHECK(Coordinator::MakeParentHierarchy(path));
1007 FILE *file = fopen(path.c_str(), "w");
Andreas Huber019d21d2016-10-03 12:59:47 -07001008
1009 if (file == nullptr) {
1010 return -errno;
1011 }
1012
1013 Formatter out(file);
1014
Steven Morelandd177b122016-12-12 09:15:37 -08001015 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
Glenn Kastend18c3ba2017-02-23 16:35:24 -08001016 << "// Source: " << packageFQName.string() << "\n"
1017 << "// Root: " << coordinator->getPackageRootOption(packageFQName) << "\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001018
Andreas Huber1c507272016-10-05 14:33:21 -07001019 std::string guard;
1020 if (forJava) {
1021 out << "package " << packageFQName.javaPackage() << ";\n\n";
1022 out << "public class Constants {\n";
1023 out.indent();
1024 } else {
1025 guard = "HIDL_GENERATED_";
Steven Morelandd177b122016-12-12 09:15:37 -08001026 guard += StringHelper::Uppercase(packageFQName.tokenName());
Andreas Huber1c507272016-10-05 14:33:21 -07001027 guard += "_";
1028 guard += "EXPORTED_CONSTANTS_H_";
Andreas Huber019d21d2016-10-03 12:59:47 -07001029
Andreas Huber1c507272016-10-05 14:33:21 -07001030 out << "#ifndef "
1031 << guard
1032 << "\n#define "
1033 << guard
1034 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001035 }
1036
Andreas Huber1c507272016-10-05 14:33:21 -07001037 for (const auto &type : exportedTypes) {
1038 type->emitExportedHeader(out, forJava);
1039 }
1040
1041 if (forJava) {
1042 out.unindent();
1043 out << "}\n";
1044 } else {
1045 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
1046 << guard
1047 << "\n";
1048 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001049
1050 return OK;
1051}
1052
Steven Morelandf2e44692017-04-18 20:19:09 -07001053static status_t generateHashOutput(const FQName &fqName,
1054 const char* /*hidl_gen*/,
1055 Coordinator *coordinator,
1056 const std::string & /*outputDir*/) {
1057
1058 status_t err;
1059 std::vector<FQName> packageInterfaces;
1060
1061 if (fqName.isFullyQualified()) {
1062 packageInterfaces = {fqName};
1063 } else {
1064 err = coordinator->appendPackageInterfacesToVector(
1065 fqName, &packageInterfaces);
1066 if (err != OK) {
1067 return err;
1068 }
1069 }
1070
1071 for (const auto &currentFqName : packageInterfaces) {
1072 AST *ast = coordinator->parse(currentFqName);
1073
1074 if (ast == NULL) {
1075 fprintf(stderr,
1076 "ERROR: Could not parse %s. Aborting.\n",
1077 currentFqName.string().c_str());
1078
1079 return UNKNOWN_ERROR;
1080 }
1081
1082 printf("%s %s\n",
1083 Hash::getHash(ast->getFilename()).hexString().c_str(),
1084 currentFqName.string().c_str());
1085 }
1086
1087 return OK;
1088}
1089
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001090static std::vector<OutputHandler> formats = {
1091 {"c++",
Andreas Huber019d21d2016-10-03 12:59:47 -07001092 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001093 validateForSource,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001094 [](const FQName &fqName,
1095 const char *hidl_gen, Coordinator *coordinator,
1096 const std::string &outputDir) -> status_t {
1097 if (fqName.isFullyQualified()) {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001098 return generateSourcesForFile(fqName,
1099 hidl_gen,
1100 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001101 outputDir,
1102 "c++");
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001103 } else {
1104 return generateSourcesForPackage(fqName,
1105 hidl_gen,
1106 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001107 outputDir,
1108 "c++");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001109 }
1110 }
1111 },
1112
Andreas Huber019d21d2016-10-03 12:59:47 -07001113 {"export-header",
1114 OutputHandler::NEEDS_FILE /* mOutputMode */,
1115 validateForExportHeader,
1116 [](const FQName &fqName,
1117 const char *hidl_gen,
1118 Coordinator *coordinator,
1119 const std::string &outputPath) -> status_t {
1120 CHECK(!fqName.isFullyQualified());
1121
1122 return generateExportHeaderForPackage(
1123 fqName,
1124 hidl_gen,
1125 coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001126 outputPath,
1127 false /* forJava */);
Andreas Huber019d21d2016-10-03 12:59:47 -07001128 }
1129 },
1130
Steven Moreland9c387612016-09-07 09:54:26 -07001131 {"c++-impl",
Andreas Huber019d21d2016-10-03 12:59:47 -07001132 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001133 validateForSource,
1134 [](const FQName &fqName,
1135 const char *hidl_gen, Coordinator *coordinator,
1136 const std::string &outputDir) -> status_t {
1137 if (fqName.isFullyQualified()) {
1138 return generateSourcesForFile(fqName,
1139 hidl_gen,
1140 coordinator,
1141 outputDir, "c++-impl");
1142 } else {
1143 return generateSourcesForPackage(fqName,
1144 hidl_gen,
1145 coordinator,
1146 outputDir, "c++-impl");
1147 }
1148 }
1149 },
1150
1151
Andreas Huber2831d512016-08-15 09:33:47 -07001152 {"java",
Andreas Huber019d21d2016-10-03 12:59:47 -07001153 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001154 validateForSource,
Andreas Huber2831d512016-08-15 09:33:47 -07001155 [](const FQName &fqName,
1156 const char *hidl_gen, Coordinator *coordinator,
1157 const std::string &outputDir) -> status_t {
1158 if (fqName.isFullyQualified()) {
1159 return generateSourcesForFile(fqName,
1160 hidl_gen,
1161 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001162 outputDir,
1163 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001164 }
1165 else {
1166 return generateSourcesForPackage(fqName,
1167 hidl_gen,
1168 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001169 outputDir,
1170 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001171 }
1172 }
1173 },
1174
Andreas Huber1c507272016-10-05 14:33:21 -07001175 {"java-constants",
1176 OutputHandler::NEEDS_DIR /* mOutputMode */,
1177 validateForExportHeader,
1178 [](const FQName &fqName,
1179 const char *hidl_gen, Coordinator *coordinator,
1180 const std::string &outputDir) -> status_t {
1181 CHECK(!fqName.isFullyQualified());
1182 return generateExportHeaderForPackage(
1183 fqName,
1184 hidl_gen,
1185 coordinator,
1186 outputDir,
1187 true /* forJava */);
1188 }
1189 },
1190
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001191 {"vts",
Andreas Huber019d21d2016-10-03 12:59:47 -07001192 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001193 validateForSource,
1194 [](const FQName &fqName,
1195 const char * hidl_gen,
1196 Coordinator *coordinator,
1197 const std::string &outputDir) -> status_t {
1198 if (fqName.isFullyQualified()) {
1199 return generateSourcesForFile(fqName,
1200 hidl_gen,
1201 coordinator,
1202 outputDir, "vts");
1203 } else {
1204 return generateSourcesForPackage(fqName,
1205 hidl_gen,
1206 coordinator,
1207 outputDir, "vts");
1208 }
1209 }
1210 },
1211
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001212 {"makefile",
Andreas Huber019d21d2016-10-03 12:59:47 -07001213 OutputHandler::NOT_NEEDED /* mOutputMode */,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001214 validateForMakefile,
1215 generateMakefileForPackage,
1216 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001217
Dan Willemsen676abdc2016-09-28 19:42:22 -07001218 {"androidbp",
Andreas Huber019d21d2016-10-03 12:59:47 -07001219 OutputHandler::NOT_NEEDED /* mOutputMode */,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001220 validateForMakefile,
1221 generateAndroidBpForPackage,
1222 },
1223
Yifan Hong958ee462016-12-06 17:09:51 -08001224 {"androidbp-impl",
Yifan Hong94bcea02016-10-06 13:51:31 -07001225 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland197d56c2016-09-09 10:03:58 -07001226 validateForMakefile,
Yifan Hong958ee462016-12-06 17:09:51 -08001227 generateAndroidBpImplForPackage,
Steven Morelandf2e44692017-04-18 20:19:09 -07001228 },
1229
1230 {"hash",
1231 OutputHandler::NOT_NEEDED /* mOutputMode */,
1232 validateForSource,
1233 generateHashOutput,
1234 },
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001235};
1236
1237static void usage(const char *me) {
1238 fprintf(stderr,
1239 "usage: %s -o output-path -L <language> (-r interface-root)+ fqname+\n",
1240 me);
1241
1242 fprintf(stderr, " -o output path\n");
1243
1244 fprintf(stderr, " -L <language> (one of");
1245 for (auto &e : formats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001246 fprintf(stderr, " %s", e.name().c_str());
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001247 }
1248 fprintf(stderr, ")\n");
1249
1250 fprintf(stderr,
1251 " -r package:path root "
1252 "(e.g., android.hardware:hardware/interfaces)\n");
1253}
1254
Andreas Huberb82318c2016-08-02 14:45:54 -07001255int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001256 std::string outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001257 std::vector<std::string> packageRootPaths;
1258 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001259
Andreas Huber737080b2016-08-02 15:38:04 -07001260 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001261 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001262
Andreas Huberb82318c2016-08-02 14:45:54 -07001263 int res;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001264 while ((res = getopt(argc, argv, "ho:r:L:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001265 switch (res) {
1266 case 'o':
1267 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001268 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001269 break;
1270 }
1271
Andreas Huberdca261f2016-08-04 13:47:51 -07001272 case 'r':
1273 {
1274 std::string val(optarg);
1275 auto index = val.find_first_of(':');
1276 CHECK(index != std::string::npos);
1277
1278 auto package = val.substr(0, index);
1279 auto path = val.substr(index + 1);
1280 packageRootPaths.push_back(path);
1281 packageRoots.push_back(package);
1282 break;
1283 }
1284
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001285 case 'L':
1286 {
Steven Morelanddd583842017-04-19 13:09:57 -07001287 if (outputFormat != nullptr) {
1288 fprintf(stderr,
1289 "ERROR: only one -L option allowed. \"%s\" already specified.\n",
1290 outputFormat->name().c_str());
1291 exit(1);
1292 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001293 for (auto &e : formats) {
Steven Morelanddd583842017-04-19 13:09:57 -07001294 if (e.name() == optarg) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001295 outputFormat = &e;
1296 break;
1297 }
1298 }
Steven Morelanddd583842017-04-19 13:09:57 -07001299 if (outputFormat == nullptr) {
1300 fprintf(stderr,
1301 "ERROR: unrecognized -L option: \"%s\".\n",
1302 optarg);
1303 exit(1);
1304 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001305 break;
1306 }
1307
Andreas Huberb82318c2016-08-02 14:45:54 -07001308 case '?':
1309 case 'h':
1310 default:
1311 {
Andreas Huber737080b2016-08-02 15:38:04 -07001312 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001313 exit(1);
1314 break;
1315 }
1316 }
1317 }
1318
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001319 if (outputFormat == nullptr) {
Steven Morelanddd583842017-04-19 13:09:57 -07001320 fprintf(stderr,
1321 "ERROR: no -L option provided.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001322 exit(1);
1323 }
1324
Andreas Huberb82318c2016-08-02 14:45:54 -07001325 argc -= optind;
1326 argv += optind;
1327
Andreas Huberdca261f2016-08-04 13:47:51 -07001328 if (packageRootPaths.empty()) {
1329 // Pick reasonable defaults.
1330
1331 packageRoots.push_back("android.hardware");
1332
1333 const char *TOP = getenv("TOP");
Steven Morelandaf330382016-11-09 15:48:03 -08001334 if (TOP == nullptr) {
1335 fprintf(stderr,
1336 "ERROR: No root path (-r) specified"
1337 " and $TOP environment variable not set.\n");
1338 exit(1);
1339 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001340
1341 std::string path = TOP;
1342 path.append("/hardware/interfaces");
1343
1344 packageRootPaths.push_back(path);
1345 }
1346
Andreas Huber737080b2016-08-02 15:38:04 -07001347 // Valid options are now in argv[0] .. argv[argc - 1].
1348
Andreas Huber019d21d2016-10-03 12:59:47 -07001349 switch (outputFormat->mOutputMode) {
1350 case OutputHandler::NEEDS_DIR:
1351 case OutputHandler::NEEDS_FILE:
1352 {
1353 if (outputPath.empty()) {
1354 usage(me);
1355 exit(1);
1356 }
1357
1358 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
1359 const size_t len = outputPath.size();
1360 if (outputPath[len - 1] != '/') {
1361 outputPath += "/";
1362 }
1363 }
1364 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001365 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001366
1367 default:
1368 outputPath.clear(); // Unused.
1369 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001370 }
1371
Andreas Huberdca261f2016-08-04 13:47:51 -07001372 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -07001373
Andreas Huber737080b2016-08-02 15:38:04 -07001374 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001375 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001376
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001377 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001378 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001379 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001380 exit(1);
1381 }
Andreas Huber881227d2016-08-02 14:20:21 -07001382
Andreas Huber0fa9e392016-08-31 09:05:44 -07001383 OutputHandler::ValRes valid =
Steven Morelanddd583842017-04-19 13:09:57 -07001384 outputFormat->validate(fqName, outputFormat->name());
Andreas Huber0fa9e392016-08-31 09:05:44 -07001385
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001386 if (valid == OutputHandler::FAILED) {
Steven Morelandf2e44692017-04-18 20:19:09 -07001387 fprintf(stderr,
1388 "ERROR: output handler failed.\n");
Andreas Hubere61e3f72016-08-03 10:22:03 -07001389 exit(1);
1390 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001391
1392 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001393 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001394
1395 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001396 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001397 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001398 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001399
Andreas Huberd2943e12016-08-05 11:59:31 -07001400 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001401}