blob: 62d97c3ff64a7a764978eb6720d9ad6f5d8494da [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 };
Andreas Huber0fa9e392016-08-31 09:05:44 -070047 ValRes (*validate)(const FQName &, const std::string &language);
Iliyan Malchev5bb14022016-08-09 15:04:39 -070048 status_t (*generate)(const FQName &fqName,
49 const char *hidl_gen,
50 Coordinator *coordinator,
51 const std::string &outputDir);
52};
Andreas Huberdca261f2016-08-04 13:47:51 -070053
Iliyan Malchev5bb14022016-08-09 15:04:39 -070054static status_t generateSourcesForFile(
55 const FQName &fqName,
56 const char *,
57 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -070058 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070059 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -070060 CHECK(fqName.isFullyQualified());
61
Andreas Huber0fa9e392016-08-31 09:05:44 -070062 AST *ast;
Andreas Huberd29724f2016-09-14 09:33:13 -070063 std::string limitToType;
Andreas Huber0fa9e392016-08-31 09:05:44 -070064
65 if (fqName.name().find("types.") == 0) {
66 CHECK(lang == "java"); // Already verified in validate().
67
Andreas Huberd29724f2016-09-14 09:33:13 -070068 limitToType = fqName.name().substr(strlen("types."));
Andreas Huber0fa9e392016-08-31 09:05:44 -070069
Yifan Hongfece6ec2017-01-12 17:04:04 -080070 FQName typesName = fqName.getTypesForPackage();
Andreas Huber0fa9e392016-08-31 09:05:44 -070071 ast = coordinator->parse(typesName);
72 } else {
73 ast = coordinator->parse(fqName);
74 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -070075
76 if (ast == NULL) {
77 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -070078 "ERROR: Could not parse %s. Aborting.\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -070079 fqName.string().c_str());
80
81 return UNKNOWN_ERROR;
82 }
83
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070084 if (lang == "c++") {
85 return ast->generateCpp(outputDir);
86 }
Steven Moreland9c387612016-09-07 09:54:26 -070087 if (lang == "c++-impl") {
88 return ast->generateCppImpl(outputDir);
89 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070090 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -070091 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070092 }
93 if (lang == "vts") {
94 return ast->generateVts(outputDir);
95 }
96 // Unknown language.
97 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -070098}
99
100static status_t generateSourcesForPackage(
101 const FQName &packageFQName,
102 const char *hidl_gen,
103 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700104 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700105 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700106 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700107 !packageFQName.isFullyQualified() &&
108 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700109
110 std::vector<FQName> packageInterfaces;
111
112 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700113 coordinator->appendPackageInterfacesToVector(packageFQName,
114 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700115
116 if (err != OK) {
117 return err;
118 }
119
120 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700121 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700122 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700123 if (err != OK) {
124 return err;
125 }
126 }
127
128 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700129}
130
Andreas Huberd2943e12016-08-05 11:59:31 -0700131static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700132 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700133}
134
Andreas Huberaa573272017-04-13 09:58:06 -0700135static std::string makeJavaLibraryName(const FQName &packageFQName) {
136 std::string out;
137 out = packageFQName.package();
138 out += "-V";
139 out += packageFQName.version();
140 return out;
141}
142
Steven Moreland5715fed2017-01-16 11:06:47 -0800143static void generatePackagePathsSection(
144 Formatter &out,
145 Coordinator *coordinator,
146 const FQName &packageFQName,
147 const std::set<FQName> &importedPackages,
148 bool forMakefiles = false) {
149 std::set<std::string> options{};
150 for (const auto &interface : importedPackages) {
151 options.insert(coordinator->getPackageRootOption(interface));
152 }
153 options.insert(coordinator->getPackageRootOption(packageFQName));
154 options.insert(coordinator->getPackageRootOption(gIBasePackageFqName));
155 for (const auto &option : options) {
156 out << "-r"
157 << option
158 << " ";
159 if (forMakefiles) {
160 out << "\\\n";
161 }
162 }
163}
164
Dan Willemsen676abdc2016-09-28 19:42:22 -0700165static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700166 Formatter &out,
167 Coordinator *coordinator,
168 const FQName &packageFQName,
169 const FQName &fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800170 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700171 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700172 out << "\n"
173 << "\n#"
174 << "\n# Build " << fqName.name() << ".hal";
175
Dan Willemsen676abdc2016-09-28 19:42:22 -0700176 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700177 out << " (" << typeName << ")";
178 }
179
180 out << "\n#"
181 << "\nGEN := $(intermediates)/"
182 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800183 << coordinator->getPackagePath(packageFQName, true /* relative */,
184 true /* sanitized */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700185 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700186 out << fqName.name() << ".java";
187 } else {
188 out << typeName << ".java";
189 }
190
191 out << "\n$(GEN): $(HIDL)";
192 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
193 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
194 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700195
196 {
197 AST *ast = coordinator->parse(fqName);
198 CHECK(ast != nullptr);
199 const std::set<FQName>& refs = ast->getImportedNames();
200 for (auto depFQName : refs) {
201 // If the package of depFQName is the same as this fqName's package,
202 // then add it explicitly as a .hal dependency within the same
203 // package.
204 if (fqName.package() == depFQName.package() &&
205 fqName.version() == depFQName.version()) {
206 // PRIVATE_DEPS is not actually being used in the
207 // auto-generated file, but is necessary if the build rule
208 // ever needs to use the dependency information, since the
209 // built-in Make variables are not supported in the Android
210 // build system.
211 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
212 << depFQName.name() << ".hal";
213 // This is the actual dependency.
214 out << "\n$(GEN): $(LOCAL_PATH)/"
215 << depFQName.name() << ".hal";
216 }
217 }
218 }
219
Andreas Huber0fa9e392016-08-31 09:05:44 -0700220 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
221 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
222 out.indent();
223 out.indent();
224 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800225 << "\n-Ljava \\\n";
226
227 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700228
229 out << packageFQName.string()
230 << "::"
231 << fqName.name();
232
Dan Willemsen676abdc2016-09-28 19:42:22 -0700233 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700234 out << "." << typeName;
235 }
236
237 out << "\n";
238
239 out.unindent();
240 out.unindent();
241
242 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
243 out << "\n\t$(transform-generated-source)";
244 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
245}
246
Dan Willemsen676abdc2016-09-28 19:42:22 -0700247static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700248 Formatter &out,
249 Coordinator *coordinator,
250 const FQName &packageFQName,
251 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800252 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700253 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700254 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700255 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700256 CHECK(typesAST != nullptr);
257
258 Scope *rootScope = typesAST->scope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700259
Andreas Huberb747bd92016-09-26 15:55:31 -0700260 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
261 std::sort(
262 subTypes.begin(),
263 subTypes.end(),
264 [](const NamedType *a, const NamedType *b) -> bool {
265 return a->fqName() < b->fqName();
266 });
267
268 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700269 if (type->isTypeDef()) {
270 continue;
271 }
272
Dan Willemsen676abdc2016-09-28 19:42:22 -0700273 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700274 out,
275 coordinator,
276 packageFQName,
277 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800278 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700279 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700280 }
281
282 continue;
283 }
284
Dan Willemsen676abdc2016-09-28 19:42:22 -0700285 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700286 out,
287 coordinator,
288 packageFQName,
289 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800290 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700291 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700292 }
293}
294
Andreas Huber75ae95d2016-10-12 16:08:26 -0700295static status_t isPackageJavaCompatible(
296 const FQName &packageFQName,
297 Coordinator *coordinator,
298 bool *compatible) {
299 std::vector<FQName> todo;
300 status_t err =
301 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
302
303 if (err != OK) {
304 return err;
305 }
306
307 std::set<FQName> seen;
308 for (const auto &iface : todo) {
309 seen.insert(iface);
310 }
311
312 // Form the transitive closure of all imported interfaces (and types.hal-s)
313 // If any one of them is not java compatible, this package isn't either.
314 while (!todo.empty()) {
315 const FQName fqName = todo.back();
316 todo.pop_back();
317
318 AST *ast = coordinator->parse(fqName);
319
320 if (ast == nullptr) {
321 return UNKNOWN_ERROR;
322 }
323
324 if (!ast->isJavaCompatible()) {
325 *compatible = false;
326 return OK;
327 }
328
329 std::set<FQName> importedPackages;
330 ast->getImportedPackages(&importedPackages);
331
332 for (const auto &package : importedPackages) {
333 std::vector<FQName> packageInterfaces;
334 status_t err = coordinator->appendPackageInterfacesToVector(
335 package, &packageInterfaces);
336
337 if (err != OK) {
338 return err;
339 }
340
341 for (const auto &iface : packageInterfaces) {
342 if (seen.find(iface) != seen.end()) {
343 continue;
344 }
345
346 todo.push_back(iface);
347 seen.insert(iface);
348 }
349 }
350 }
351
352 *compatible = true;
353 return OK;
354}
355
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700356static bool packageNeedsJavaCode(
357 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
358 // If there is more than just a types.hal file to this package we'll
359 // definitely need to generate Java code.
360 if (packageInterfaces.size() > 1
361 || packageInterfaces[0].name() != "types") {
362 return true;
363 }
364
365 CHECK(typesAST != nullptr);
366
367 // We'll have to generate Java code if types.hal contains any non-typedef
368 // type declarations.
369
370 Scope *rootScope = typesAST->scope();
371 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
372
373 for (const auto &subType : subTypes) {
374 if (!subType->isTypeDef()) {
375 return true;
376 }
377 }
378
379 return false;
380}
381
Andreas Huber1c507272016-10-05 14:33:21 -0700382static void generateMakefileSectionForJavaConstants(
383 Formatter &out,
384 Coordinator *coordinator,
385 const FQName &packageFQName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800386 const std::vector<FQName> &packageInterfaces,
387 const std::set<FQName> &importedPackages) {
Andreas Huber1c507272016-10-05 14:33:21 -0700388 out << "\n#"
389 << "\nGEN := $(intermediates)/"
390 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800391 << coordinator->getPackagePath(packageFQName, true /* relative */, true /* sanitized */)
Andreas Huber1c507272016-10-05 14:33:21 -0700392 << "Constants.java";
393
394 out << "\n$(GEN): $(HIDL)\n";
395 for (const auto &iface : packageInterfaces) {
396 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
397 }
398 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
399 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
400 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
401 out.indent();
402 out.indent();
403 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800404 << "\n-Ljava-constants \\\n";
405
406 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber1c507272016-10-05 14:33:21 -0700407
408 out << packageFQName.string();
409 out << "\n";
410
411 out.unindent();
412 out.unindent();
413
414 out << "\n$(GEN):";
415 out << "\n\t$(transform-generated-source)";
416 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
417}
418
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700419static status_t generateMakefileForPackage(
420 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700421 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700422 Coordinator *coordinator,
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700423 const std::string &) {
424
425 CHECK(packageFQName.isValid() &&
426 !packageFQName.isFullyQualified() &&
427 packageFQName.name().empty());
428
Andreas Huberd2943e12016-08-05 11:59:31 -0700429 std::vector<FQName> packageInterfaces;
430
431 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700432 coordinator->appendPackageInterfacesToVector(packageFQName,
433 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700434
435 if (err != OK) {
436 return err;
437 }
438
439 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700440 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700441 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700442
Andreas Huberd2943e12016-08-05 11:59:31 -0700443 for (const auto &fqName : packageInterfaces) {
444 AST *ast = coordinator->parse(fqName);
445
446 if (ast == NULL) {
447 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700448 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700449 fqName.string().c_str());
450
451 return UNKNOWN_ERROR;
452 }
453
Andreas Huber0fa9e392016-08-31 09:05:44 -0700454 if (fqName.name() == "types") {
455 typesAST = ast;
456 }
457
Yifan Hong40a373d2016-11-30 15:16:47 -0800458 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700459 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700460 }
461
Andreas Huber75ae95d2016-10-12 16:08:26 -0700462 bool packageIsJavaCompatible;
463 err = isPackageJavaCompatible(
464 packageFQName, coordinator, &packageIsJavaCompatible);
465
466 if (err != OK) {
467 return err;
468 }
469
Andreas Huber1c507272016-10-05 14:33:21 -0700470 bool haveJavaConstants = !exportedTypes.empty();
471
472 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800473 // TODO(b/33420795)
474 fprintf(stderr,
475 "WARNING: %s is not java compatible. No java makefile created.\n",
476 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700477 return OK;
478 }
479
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700480 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
481 return OK;
482 }
483
Andreas Huberd2943e12016-08-05 11:59:31 -0700484 std::string path =
485 coordinator->getPackagePath(packageFQName, false /* relative */);
486
487 path.append("Android.mk");
488
489 CHECK(Coordinator::MakeParentHierarchy(path));
490 FILE *file = fopen(path.c_str(), "w");
491
492 if (file == NULL) {
493 return -errno;
494 }
495
Andreas Huberaa573272017-04-13 09:58:06 -0700496 const std::string libraryName = makeJavaLibraryName(packageFQName);
Andreas Huberd2943e12016-08-05 11:59:31 -0700497
498 Formatter out(file);
499
Dan Willemsen676abdc2016-09-28 19:42:22 -0700500 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
501 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700502
Dan Willemsen676abdc2016-09-28 19:42:22 -0700503 enum LibraryStyle {
504 LIBRARY_STYLE_REGULAR,
505 LIBRARY_STYLE_STATIC,
506 LIBRARY_STYLE_END,
507 };
Andreas Huberd2943e12016-08-05 11:59:31 -0700508
Andreas Huber1c507272016-10-05 14:33:21 -0700509 for (int style = LIBRARY_STYLE_REGULAR;
510 (packageIsJavaCompatible && style != LIBRARY_STYLE_END);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700511 ++style) {
512 const std::string staticSuffix =
513 (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700514
Dan Willemsen676abdc2016-09-28 19:42:22 -0700515 out << "\n"
516 << "########################################"
517 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700518
Dan Willemsen676abdc2016-09-28 19:42:22 -0700519 out << "include $(CLEAR_VARS)\n"
520 << "LOCAL_MODULE := "
521 << libraryName
522 << "-java"
523 << staticSuffix
524 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800525 << "intermediates := $(call local-generated-sources-dir, COMMON)"
526 << "\n\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700527 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
528 << hidl_gen
529 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700530
Dan Willemsen676abdc2016-09-28 19:42:22 -0700531 if (!importedPackages.empty()) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700532 out << "\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700533 << "\nLOCAL_"
Andreas Huber782d45e2016-09-22 13:25:14 -0700534 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
Dan Willemsen676abdc2016-09-28 19:42:22 -0700535 << "JAVA_LIBRARIES := \\";
536
537 out.indent();
538 for (const auto &importedPackage : importedPackages) {
539 out << "\n"
Andreas Huberaa573272017-04-13 09:58:06 -0700540 << makeJavaLibraryName(importedPackage)
Dan Willemsen676abdc2016-09-28 19:42:22 -0700541 << "-java"
542 << staticSuffix
543 << " \\";
544 }
545 out << "\n";
546 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700547 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700548
549 generateMakefileSection(
550 out,
551 coordinator,
552 packageFQName,
553 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800554 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700555 typesAST);
556
557 out << "\ninclude $(BUILD_"
558 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
559 << "JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700560 }
561
Andreas Huber1c507272016-10-05 14:33:21 -0700562 if (haveJavaConstants) {
563 out << "\n"
564 << "########################################"
565 << "########################################\n\n";
566
567 out << "include $(CLEAR_VARS)\n"
568 << "LOCAL_MODULE := "
569 << libraryName
570 << "-java-constants"
571 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800572 << "intermediates := $(call local-generated-sources-dir, COMMON)"
573 << "\n\n"
Andreas Huber1c507272016-10-05 14:33:21 -0700574 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
575 << hidl_gen
576 << "$(HOST_EXECUTABLE_SUFFIX)";
577
578 generateMakefileSectionForJavaConstants(
Steven Moreland5715fed2017-01-16 11:06:47 -0800579 out, coordinator, packageFQName, packageInterfaces, importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700580
581 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
582 << "-> framework.jar\n"
583 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
584 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
585 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
586 }
587
Iliyan Malchev8be09552016-09-22 16:20:33 -0700588 out << "\n\n"
589 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
590
Andreas Huberd2943e12016-08-05 11:59:31 -0700591 return OK;
592}
593
Andreas Huber0fa9e392016-08-31 09:05:44 -0700594OutputHandler::ValRes validateForMakefile(
595 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700596 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700597 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700598 return OutputHandler::FAILED;
599 }
600
601 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700602 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700603 return OutputHandler::FAILED;
604 }
605
606 if (!fqName.name().empty()) {
607 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700608 "ERROR: Expecting only package name and version.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700609 return OutputHandler::FAILED;
610 }
611
612 return OutputHandler::PASS_PACKAGE;
613}
614
Dan Willemsen676abdc2016-09-28 19:42:22 -0700615static void generateAndroidBpGenSection(
616 Formatter &out,
617 const FQName &packageFQName,
618 const char *hidl_gen,
619 Coordinator *coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800620 const std::string &halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700621 const std::string &genName,
622 const char *language,
623 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800624 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700625 const std::function<void(Formatter&, const FQName)> outputFn) {
626
627 out << "genrule {\n";
628 out.indent();
629 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700630 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700631
Colin Crossd5419bd2016-11-04 15:05:54 -0700632 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Steven Moreland5715fed2017-01-16 11:06:47 -0800633 << " -L" << language << " ";
634
635 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages);
636
637 out << packageFQName.string() << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700638
639 out << "srcs: [\n";
640 out.indent();
Tri Vo6a827fa2017-02-08 10:24:42 -0800641 out << "\":" << halFilegroupName << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700642 out.unindent();
643 out << "],\n";
644
645 out << "out: [\n";
646 out.indent();
647 for (const auto &fqName : packageInterfaces) {
648 outputFn(out, fqName);
649 }
650 out.unindent();
651 out << "],\n";
652
653 out.unindent();
654 out << "}\n\n";
655}
656
657static status_t generateAndroidBpForPackage(
658 const FQName &packageFQName,
659 const char *hidl_gen,
660 Coordinator *coordinator,
661 const std::string &) {
662
663 CHECK(packageFQName.isValid() &&
664 !packageFQName.isFullyQualified() &&
665 packageFQName.name().empty());
666
667 std::vector<FQName> packageInterfaces;
668
669 status_t err =
670 coordinator->appendPackageInterfacesToVector(packageFQName,
671 &packageInterfaces);
672
673 if (err != OK) {
674 return err;
675 }
676
Steven Morelandff5262b2017-03-20 06:59:03 -0700677 std::set<FQName> importedPackagesHierarchy;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700678 AST *typesAST = nullptr;
679
680 for (const auto &fqName : packageInterfaces) {
681 AST *ast = coordinator->parse(fqName);
682
683 if (ast == NULL) {
684 fprintf(stderr,
685 "ERROR: Could not parse %s. Aborting.\n",
686 fqName.string().c_str());
687
688 return UNKNOWN_ERROR;
689 }
690
691 if (fqName.name() == "types") {
692 typesAST = ast;
693 }
694
Steven Morelandff5262b2017-03-20 06:59:03 -0700695 ast->getImportedPackagesHierarchy(&importedPackagesHierarchy);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700696 }
697
698 std::string path =
699 coordinator->getPackagePath(packageFQName, false /* relative */);
700
701 path.append("Android.bp");
702
703 CHECK(Coordinator::MakeParentHierarchy(path));
704 FILE *file = fopen(path.c_str(), "w");
705
706 if (file == NULL) {
707 return -errno;
708 }
709
710 const std::string libraryName = makeLibraryName(packageFQName);
Tri Vo15052c62017-02-06 10:04:07 -0800711 const std::string halFilegroupName = libraryName + "_hal";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700712 const std::string genSourceName = libraryName + "_genc++";
713 const std::string genHeaderName = libraryName + "_genc++_headers";
714 const std::string pathPrefix =
715 coordinator->convertPackageRootToPath(packageFQName) +
716 coordinator->getPackagePath(packageFQName, true /* relative */);
717
718 Formatter out(file);
719
720 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
721
Tri Vo15052c62017-02-06 10:04:07 -0800722 // Rule to generate .hal filegroup
723 out << "filegroup {\n";
724 out.indent();
725 out << "name: \"" << halFilegroupName << "\",\n";
726 out << "srcs: [\n";
727 out.indent();
728 for (const auto &fqName : packageInterfaces) {
729 out << "\"" << fqName.name() << ".hal\",\n";
730 }
731 out.unindent();
732 out << "],\n";
733 out.unindent();
734 out << "}\n\n";
735
Dan Willemsen676abdc2016-09-28 19:42:22 -0700736 // Rule to generate the C++ source files
737 generateAndroidBpGenSection(
738 out,
739 packageFQName,
740 hidl_gen,
741 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800742 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700743 genSourceName,
744 "c++",
745 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700746 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700747 [&pathPrefix](Formatter &out, const FQName &fqName) {
748 if (fqName.name() == "types") {
749 out << "\"" << pathPrefix << "types.cpp\",\n";
750 } else {
751 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
752 }
753 });
754
755 // Rule to generate the C++ header files
756 generateAndroidBpGenSection(
757 out,
758 packageFQName,
759 hidl_gen,
760 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800761 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700762 genHeaderName,
763 "c++",
764 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700765 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700766 [&pathPrefix](Formatter &out, const FQName &fqName) {
767 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
768 if (fqName.name() != "types") {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800769 out << "\"" << pathPrefix << fqName.getInterfaceHwName() << ".h\",\n";
770 out << "\"" << pathPrefix << fqName.getInterfaceStubName() << ".h\",\n";
771 out << "\"" << pathPrefix << fqName.getInterfaceProxyName() << ".h\",\n";
772 out << "\"" << pathPrefix << fqName.getInterfacePassthroughName() << ".h\",\n";
Steven Moreland9774d622017-03-24 21:51:45 -0700773 } else {
774 out << "\"" << pathPrefix << "hwtypes.h\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700775 }
776 });
777
778 // C++ library definition
779 out << "cc_library_shared {\n";
780 out.indent();
781 out << "name: \"" << libraryName << "\",\n"
782 << "generated_sources: [\"" << genSourceName << "\"],\n"
783 << "generated_headers: [\"" << genHeaderName << "\"],\n"
784 << "export_generated_headers: [\"" << genHeaderName << "\"],\n"
Dan Willemsen2cf4b9a2017-04-07 13:21:11 -0700785 << "vendor_available: true,\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700786 << "shared_libs: [\n";
787
788 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -0800789 out << "\"libhidlbase\",\n"
790 << "\"libhidltransport\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700791 << "\"libhwbinder\",\n"
Steven Moreland05cd4232016-11-21 16:01:12 -0800792 << "\"liblog\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700793 << "\"libutils\",\n"
794 << "\"libcutils\",\n";
Steven Morelandff5262b2017-03-20 06:59:03 -0700795 for (const auto &importedPackage : importedPackagesHierarchy) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700796 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
797 }
798 out.unindent();
799
800 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -0700801
802 out << "export_shared_lib_headers: [\n";
803 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -0800804 out << "\"libhidlbase\",\n"
805 << "\"libhidltransport\",\n"
Steven Morelandb8a26c02016-10-21 13:40:14 -0700806 << "\"libhwbinder\",\n"
Steven Moreland865243c2016-11-01 13:05:24 -0700807 << "\"libutils\",\n";
Steven Morelandff5262b2017-03-20 06:59:03 -0700808 for (const auto &importedPackage : importedPackagesHierarchy) {
Yifan Hongc1f9b8d2016-11-07 14:35:44 -0800809 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
810 }
Steven Moreland865243c2016-11-01 13:05:24 -0700811 out.unindent();
812 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -0700813 out.unindent();
814
Dan Willemsen676abdc2016-09-28 19:42:22 -0700815 out << "}\n";
816
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800817 return OK;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700818}
819
Yifan Hong958ee462016-12-06 17:09:51 -0800820static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -0700821 const FQName &packageFQName,
822 const char *,
823 Coordinator *coordinator,
824 const std::string &outputDir) {
825
Iliyan Malchev4923f932016-09-09 13:04:59 -0700826 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700827
828 std::vector<FQName> packageInterfaces;
829
830 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700831 coordinator->appendPackageInterfacesToVector(packageFQName,
832 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700833
834 if (err != OK) {
835 return err;
836 }
837
838 std::set<FQName> importedPackages;
839
840 for (const auto &fqName : packageInterfaces) {
841 AST *ast = coordinator->parse(fqName);
842
843 if (ast == NULL) {
844 fprintf(stderr,
845 "ERROR: Could not parse %s. Aborting.\n",
846 fqName.string().c_str());
847
848 return UNKNOWN_ERROR;
849 }
850
851 ast->getImportedPackages(&importedPackages);
852 }
853
Yifan Hongaafed702016-12-14 12:59:47 -0800854 std::string path = outputDir + "Android.bp";
Steven Moreland197d56c2016-09-09 10:03:58 -0700855
856 CHECK(Coordinator::MakeParentHierarchy(path));
857 FILE *file = fopen(path.c_str(), "w");
858
859 if (file == NULL) {
860 return -errno;
861 }
862
863 Formatter out(file);
864
Yifan Hong958ee462016-12-06 17:09:51 -0800865 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800866 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800867 out << "name: \"" << libraryName << "\",\n"
868 << "relative_install_path: \"hw\",\n"
Steven Morelandf8a22e92017-02-15 18:46:04 -0800869 << "proprietary: true,\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800870 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800871 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800872 for (const auto &fqName : packageInterfaces) {
873 if (fqName.name() == "types") {
874 continue;
875 }
876 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
877 }
878 });
879 out << "],\n"
880 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800881 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800882 out << "\"libhidlbase\",\n"
883 << "\"libhidltransport\",\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800884 << "\"libutils\",\n"
885 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -0700886
Yifan Hong958ee462016-12-06 17:09:51 -0800887 for (const auto &importedPackage : importedPackages) {
888 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
889 }
890 });
891 out << "],\n";
892 });
893 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -0700894
895 return OK;
896}
897
Andreas Huber0fa9e392016-08-31 09:05:44 -0700898OutputHandler::ValRes validateForSource(
899 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700900 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700901 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700902 return OutputHandler::FAILED;
903 }
904
905 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700906 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700907 return OutputHandler::FAILED;
908 }
909
Andreas Huber0fa9e392016-08-31 09:05:44 -0700910 const std::string &name = fqName.name();
911 if (!name.empty()) {
912 if (name.find('.') == std::string::npos) {
913 return OutputHandler::PASS_FULL;
914 }
915
916 if (language != "java" || name.find("types.") != 0) {
917 // When generating java sources for "types.hal", output can be
918 // constrained to just one of the top-level types declared
919 // by using the extended syntax
920 // android.hardware.Foo@1.0::types.TopLevelTypeName.
921 // In all other cases (different language, not 'types') the dot
922 // notation in the name is illegal in this context.
923 return OutputHandler::FAILED;
924 }
925
926 return OutputHandler::PASS_FULL;
927 }
928
929 return OutputHandler::PASS_PACKAGE;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700930}
931
Andreas Huber019d21d2016-10-03 12:59:47 -0700932OutputHandler::ValRes validateForExportHeader(
933 const FQName &fqName, const std::string & /* language */) {
934 if (fqName.package().empty()) {
935 fprintf(stderr, "ERROR: Expecting package name\n");
936 return OutputHandler::FAILED;
937 }
938
939 if (fqName.version().empty()) {
940 fprintf(stderr, "ERROR: Expecting package version\n");
941 return OutputHandler::FAILED;
942 }
943
944 if (!fqName.name().empty()) {
945 fprintf(stderr,
946 "ERROR: Expecting only package name and version.\n");
947 return OutputHandler::FAILED;
948 }
949
950 return OutputHandler::PASS_PACKAGE;
951}
952
953
954static status_t generateExportHeaderForPackage(
955 const FQName &packageFQName,
956 const char * /* hidl_gen */,
957 Coordinator *coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -0700958 const std::string &outputPath,
959 bool forJava) {
Andreas Huber019d21d2016-10-03 12:59:47 -0700960
961 CHECK(packageFQName.isValid()
962 && !packageFQName.isFullyQualified()
963 && packageFQName.name().empty());
964
965 std::vector<FQName> packageInterfaces;
966
967 status_t err = coordinator->appendPackageInterfacesToVector(
968 packageFQName, &packageInterfaces);
969
970 if (err != OK) {
971 return err;
972 }
973
974 std::vector<const Type *> exportedTypes;
975
976 for (const auto &fqName : packageInterfaces) {
977 AST *ast = coordinator->parse(fqName);
978
979 if (ast == NULL) {
980 fprintf(stderr,
981 "ERROR: Could not parse %s. Aborting.\n",
982 fqName.string().c_str());
983
984 return UNKNOWN_ERROR;
985 }
986
987 ast->appendToExportedTypesVector(&exportedTypes);
988 }
989
990 if (exportedTypes.empty()) {
991 return OK;
992 }
993
Andreas Huber1c507272016-10-05 14:33:21 -0700994 std::string path = outputPath;
995
996 if (forJava) {
997 path.append(coordinator->convertPackageRootToPath(packageFQName));
998
999 path.append(coordinator->getPackagePath(
Yifan Hong97288ac2016-12-12 16:03:51 -08001000 packageFQName, true /* relative */, true /* sanitized */));
Andreas Huber1c507272016-10-05 14:33:21 -07001001
1002 path.append("Constants.java");
1003 }
1004
1005 CHECK(Coordinator::MakeParentHierarchy(path));
1006 FILE *file = fopen(path.c_str(), "w");
Andreas Huber019d21d2016-10-03 12:59:47 -07001007
1008 if (file == nullptr) {
1009 return -errno;
1010 }
1011
1012 Formatter out(file);
1013
Steven Morelandd177b122016-12-12 09:15:37 -08001014 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
Glenn Kastend18c3ba2017-02-23 16:35:24 -08001015 << "// Source: " << packageFQName.string() << "\n"
1016 << "// Root: " << coordinator->getPackageRootOption(packageFQName) << "\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001017
Andreas Huber1c507272016-10-05 14:33:21 -07001018 std::string guard;
1019 if (forJava) {
1020 out << "package " << packageFQName.javaPackage() << ";\n\n";
1021 out << "public class Constants {\n";
1022 out.indent();
1023 } else {
1024 guard = "HIDL_GENERATED_";
Steven Morelandd177b122016-12-12 09:15:37 -08001025 guard += StringHelper::Uppercase(packageFQName.tokenName());
Andreas Huber1c507272016-10-05 14:33:21 -07001026 guard += "_";
1027 guard += "EXPORTED_CONSTANTS_H_";
Andreas Huber019d21d2016-10-03 12:59:47 -07001028
Andreas Huber1c507272016-10-05 14:33:21 -07001029 out << "#ifndef "
1030 << guard
1031 << "\n#define "
1032 << guard
1033 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001034 }
1035
Andreas Huber1c507272016-10-05 14:33:21 -07001036 for (const auto &type : exportedTypes) {
1037 type->emitExportedHeader(out, forJava);
1038 }
1039
1040 if (forJava) {
1041 out.unindent();
1042 out << "}\n";
1043 } else {
1044 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
1045 << guard
1046 << "\n";
1047 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001048
1049 return OK;
1050}
1051
Steven Morelandf2e44692017-04-18 20:19:09 -07001052static status_t generateHashOutput(const FQName &fqName,
1053 const char* /*hidl_gen*/,
1054 Coordinator *coordinator,
1055 const std::string & /*outputDir*/) {
1056
1057 status_t err;
1058 std::vector<FQName> packageInterfaces;
1059
1060 if (fqName.isFullyQualified()) {
1061 packageInterfaces = {fqName};
1062 } else {
1063 err = coordinator->appendPackageInterfacesToVector(
1064 fqName, &packageInterfaces);
1065 if (err != OK) {
1066 return err;
1067 }
1068 }
1069
1070 for (const auto &currentFqName : packageInterfaces) {
1071 AST *ast = coordinator->parse(currentFqName);
1072
1073 if (ast == NULL) {
1074 fprintf(stderr,
1075 "ERROR: Could not parse %s. Aborting.\n",
1076 currentFqName.string().c_str());
1077
1078 return UNKNOWN_ERROR;
1079 }
1080
1081 printf("%s %s\n",
1082 Hash::getHash(ast->getFilename()).hexString().c_str(),
1083 currentFqName.string().c_str());
1084 }
1085
1086 return OK;
1087}
1088
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001089static std::vector<OutputHandler> formats = {
1090 {"c++",
Andreas Huber019d21d2016-10-03 12:59:47 -07001091 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001092 validateForSource,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001093 [](const FQName &fqName,
1094 const char *hidl_gen, Coordinator *coordinator,
1095 const std::string &outputDir) -> status_t {
1096 if (fqName.isFullyQualified()) {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001097 return generateSourcesForFile(fqName,
1098 hidl_gen,
1099 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001100 outputDir,
1101 "c++");
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001102 } else {
1103 return generateSourcesForPackage(fqName,
1104 hidl_gen,
1105 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001106 outputDir,
1107 "c++");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001108 }
1109 }
1110 },
1111
Andreas Huber019d21d2016-10-03 12:59:47 -07001112 {"export-header",
1113 OutputHandler::NEEDS_FILE /* mOutputMode */,
1114 validateForExportHeader,
1115 [](const FQName &fqName,
1116 const char *hidl_gen,
1117 Coordinator *coordinator,
1118 const std::string &outputPath) -> status_t {
1119 CHECK(!fqName.isFullyQualified());
1120
1121 return generateExportHeaderForPackage(
1122 fqName,
1123 hidl_gen,
1124 coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001125 outputPath,
1126 false /* forJava */);
Andreas Huber019d21d2016-10-03 12:59:47 -07001127 }
1128 },
1129
Steven Moreland9c387612016-09-07 09:54:26 -07001130 {"c++-impl",
Andreas Huber019d21d2016-10-03 12:59:47 -07001131 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001132 validateForSource,
1133 [](const FQName &fqName,
1134 const char *hidl_gen, Coordinator *coordinator,
1135 const std::string &outputDir) -> status_t {
1136 if (fqName.isFullyQualified()) {
1137 return generateSourcesForFile(fqName,
1138 hidl_gen,
1139 coordinator,
1140 outputDir, "c++-impl");
1141 } else {
1142 return generateSourcesForPackage(fqName,
1143 hidl_gen,
1144 coordinator,
1145 outputDir, "c++-impl");
1146 }
1147 }
1148 },
1149
1150
Andreas Huber2831d512016-08-15 09:33:47 -07001151 {"java",
Andreas Huber019d21d2016-10-03 12:59:47 -07001152 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001153 validateForSource,
Andreas Huber2831d512016-08-15 09:33:47 -07001154 [](const FQName &fqName,
1155 const char *hidl_gen, Coordinator *coordinator,
1156 const std::string &outputDir) -> status_t {
1157 if (fqName.isFullyQualified()) {
1158 return generateSourcesForFile(fqName,
1159 hidl_gen,
1160 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001161 outputDir,
1162 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001163 }
1164 else {
1165 return generateSourcesForPackage(fqName,
1166 hidl_gen,
1167 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001168 outputDir,
1169 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001170 }
1171 }
1172 },
1173
Andreas Huber1c507272016-10-05 14:33:21 -07001174 {"java-constants",
1175 OutputHandler::NEEDS_DIR /* mOutputMode */,
1176 validateForExportHeader,
1177 [](const FQName &fqName,
1178 const char *hidl_gen, Coordinator *coordinator,
1179 const std::string &outputDir) -> status_t {
1180 CHECK(!fqName.isFullyQualified());
1181 return generateExportHeaderForPackage(
1182 fqName,
1183 hidl_gen,
1184 coordinator,
1185 outputDir,
1186 true /* forJava */);
1187 }
1188 },
1189
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001190 {"vts",
Andreas Huber019d21d2016-10-03 12:59:47 -07001191 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001192 validateForSource,
1193 [](const FQName &fqName,
1194 const char * hidl_gen,
1195 Coordinator *coordinator,
1196 const std::string &outputDir) -> status_t {
1197 if (fqName.isFullyQualified()) {
1198 return generateSourcesForFile(fqName,
1199 hidl_gen,
1200 coordinator,
1201 outputDir, "vts");
1202 } else {
1203 return generateSourcesForPackage(fqName,
1204 hidl_gen,
1205 coordinator,
1206 outputDir, "vts");
1207 }
1208 }
1209 },
1210
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001211 {"makefile",
Andreas Huber019d21d2016-10-03 12:59:47 -07001212 OutputHandler::NOT_NEEDED /* mOutputMode */,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001213 validateForMakefile,
1214 generateMakefileForPackage,
1215 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001216
Dan Willemsen676abdc2016-09-28 19:42:22 -07001217 {"androidbp",
Andreas Huber019d21d2016-10-03 12:59:47 -07001218 OutputHandler::NOT_NEEDED /* mOutputMode */,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001219 validateForMakefile,
1220 generateAndroidBpForPackage,
1221 },
1222
Yifan Hong958ee462016-12-06 17:09:51 -08001223 {"androidbp-impl",
Yifan Hong94bcea02016-10-06 13:51:31 -07001224 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland197d56c2016-09-09 10:03:58 -07001225 validateForMakefile,
Yifan Hong958ee462016-12-06 17:09:51 -08001226 generateAndroidBpImplForPackage,
Steven Morelandf2e44692017-04-18 20:19:09 -07001227 },
1228
1229 {"hash",
1230 OutputHandler::NOT_NEEDED /* mOutputMode */,
1231 validateForSource,
1232 generateHashOutput,
1233 },
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001234};
1235
1236static void usage(const char *me) {
1237 fprintf(stderr,
1238 "usage: %s -o output-path -L <language> (-r interface-root)+ fqname+\n",
1239 me);
1240
1241 fprintf(stderr, " -o output path\n");
1242
1243 fprintf(stderr, " -L <language> (one of");
1244 for (auto &e : formats) {
1245 fprintf(stderr, " %s", e.mKey.c_str());
1246 }
1247 fprintf(stderr, ")\n");
1248
1249 fprintf(stderr,
1250 " -r package:path root "
1251 "(e.g., android.hardware:hardware/interfaces)\n");
1252}
1253
Andreas Huberb82318c2016-08-02 14:45:54 -07001254int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001255 std::string outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001256 std::vector<std::string> packageRootPaths;
1257 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001258
Andreas Huber737080b2016-08-02 15:38:04 -07001259 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001260 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001261
Andreas Huberb82318c2016-08-02 14:45:54 -07001262 int res;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001263 while ((res = getopt(argc, argv, "ho:r:L:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001264 switch (res) {
1265 case 'o':
1266 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001267 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001268 break;
1269 }
1270
Andreas Huberdca261f2016-08-04 13:47:51 -07001271 case 'r':
1272 {
1273 std::string val(optarg);
1274 auto index = val.find_first_of(':');
1275 CHECK(index != std::string::npos);
1276
1277 auto package = val.substr(0, index);
1278 auto path = val.substr(index + 1);
1279 packageRootPaths.push_back(path);
1280 packageRoots.push_back(package);
1281 break;
1282 }
1283
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001284 case 'L':
1285 {
Steven Morelande429a262016-11-15 09:54:32 -08001286 CHECK(outputFormat == nullptr) << "Only one -L option allowed.";
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001287 for (auto &e : formats) {
1288 if (e.mKey == optarg) {
1289 outputFormat = &e;
1290 break;
1291 }
1292 }
Steven Morelande429a262016-11-15 09:54:32 -08001293 CHECK(outputFormat != nullptr) << "Output format not recognized.";
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001294 break;
1295 }
1296
Andreas Huberb82318c2016-08-02 14:45:54 -07001297 case '?':
1298 case 'h':
1299 default:
1300 {
Andreas Huber737080b2016-08-02 15:38:04 -07001301 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001302 exit(1);
1303 break;
1304 }
1305 }
1306 }
1307
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001308 if (outputFormat == nullptr) {
1309 usage(me);
1310 exit(1);
1311 }
1312
Andreas Huberb82318c2016-08-02 14:45:54 -07001313 argc -= optind;
1314 argv += optind;
1315
Andreas Huberdca261f2016-08-04 13:47:51 -07001316 if (packageRootPaths.empty()) {
1317 // Pick reasonable defaults.
1318
1319 packageRoots.push_back("android.hardware");
1320
1321 const char *TOP = getenv("TOP");
Steven Morelandaf330382016-11-09 15:48:03 -08001322 if (TOP == nullptr) {
1323 fprintf(stderr,
1324 "ERROR: No root path (-r) specified"
1325 " and $TOP environment variable not set.\n");
1326 exit(1);
1327 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001328
1329 std::string path = TOP;
1330 path.append("/hardware/interfaces");
1331
1332 packageRootPaths.push_back(path);
1333 }
1334
Andreas Huber737080b2016-08-02 15:38:04 -07001335 // Valid options are now in argv[0] .. argv[argc - 1].
1336
Andreas Huber019d21d2016-10-03 12:59:47 -07001337 switch (outputFormat->mOutputMode) {
1338 case OutputHandler::NEEDS_DIR:
1339 case OutputHandler::NEEDS_FILE:
1340 {
1341 if (outputPath.empty()) {
1342 usage(me);
1343 exit(1);
1344 }
1345
1346 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
1347 const size_t len = outputPath.size();
1348 if (outputPath[len - 1] != '/') {
1349 outputPath += "/";
1350 }
1351 }
1352 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001353 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001354
1355 default:
1356 outputPath.clear(); // Unused.
1357 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001358 }
1359
Andreas Huberdca261f2016-08-04 13:47:51 -07001360 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -07001361
Andreas Huber737080b2016-08-02 15:38:04 -07001362 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001363 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001364
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001365 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001366 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001367 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001368 exit(1);
1369 }
Andreas Huber881227d2016-08-02 14:20:21 -07001370
Andreas Huber0fa9e392016-08-31 09:05:44 -07001371 OutputHandler::ValRes valid =
1372 outputFormat->validate(fqName, outputFormat->mKey);
1373
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001374 if (valid == OutputHandler::FAILED) {
Steven Morelandf2e44692017-04-18 20:19:09 -07001375 fprintf(stderr,
1376 "ERROR: output handler failed.\n");
Andreas Hubere61e3f72016-08-03 10:22:03 -07001377 exit(1);
1378 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001379
1380 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001381 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001382
1383 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001384 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001385 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001386 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001387
Andreas Huberd2943e12016-08-05 11:59:31 -07001388 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001389}