blob: 68e033c1f93b0b960ef9f9718192c1ae8724675b [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
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070021#include <hidl-util/Formatter.h>
Steven Moreland7ae3d542017-01-18 16:46:01 -080022#include <hidl-util/FQName.h>
Steven Morelandd177b122016-12-12 09:15:37 -080023#include <hidl-util/StringHelper.h>
Andreas Huber68f24592016-07-29 14:53:48 -070024#include <android-base/logging.h>
Iliyan Malchev5bb14022016-08-09 15:04:39 -070025#include <set>
Andreas Huberc9410c72016-07-28 12:18:40 -070026#include <stdio.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070027#include <string>
Andreas Huberb82318c2016-08-02 14:45:54 -070028#include <unistd.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070029#include <vector>
Andreas Huberc9410c72016-07-28 12:18:40 -070030
31using namespace android;
32
Iliyan Malchev5bb14022016-08-09 15:04:39 -070033struct OutputHandler {
34 std::string mKey;
Andreas Huber019d21d2016-10-03 12:59:47 -070035 enum OutputMode {
36 NEEDS_DIR,
37 NEEDS_FILE,
38 NOT_NEEDED
39 } mOutputMode;
40
Iliyan Malchev5bb14022016-08-09 15:04:39 -070041 enum ValRes {
42 FAILED,
43 PASS_PACKAGE,
44 PASS_FULL
45 };
Andreas Huber0fa9e392016-08-31 09:05:44 -070046 ValRes (*validate)(const FQName &, const std::string &language);
Iliyan Malchev5bb14022016-08-09 15:04:39 -070047 status_t (*generate)(const FQName &fqName,
48 const char *hidl_gen,
49 Coordinator *coordinator,
50 const std::string &outputDir);
51};
Andreas Huberdca261f2016-08-04 13:47:51 -070052
Iliyan Malchev5bb14022016-08-09 15:04:39 -070053static status_t generateSourcesForFile(
54 const FQName &fqName,
55 const char *,
56 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -070057 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070058 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -070059 CHECK(fqName.isFullyQualified());
60
Andreas Huber0fa9e392016-08-31 09:05:44 -070061 AST *ast;
Andreas Huberd29724f2016-09-14 09:33:13 -070062 std::string limitToType;
Andreas Huber0fa9e392016-08-31 09:05:44 -070063
64 if (fqName.name().find("types.") == 0) {
65 CHECK(lang == "java"); // Already verified in validate().
66
Andreas Huberd29724f2016-09-14 09:33:13 -070067 limitToType = fqName.name().substr(strlen("types."));
Andreas Huber0fa9e392016-08-31 09:05:44 -070068
Yifan Hongfece6ec2017-01-12 17:04:04 -080069 FQName typesName = fqName.getTypesForPackage();
Andreas Huber0fa9e392016-08-31 09:05:44 -070070 ast = coordinator->parse(typesName);
71 } else {
72 ast = coordinator->parse(fqName);
73 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -070074
75 if (ast == NULL) {
76 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -070077 "ERROR: Could not parse %s. Aborting.\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -070078 fqName.string().c_str());
79
80 return UNKNOWN_ERROR;
81 }
82
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070083 if (lang == "c++") {
84 return ast->generateCpp(outputDir);
85 }
Steven Moreland9c387612016-09-07 09:54:26 -070086 if (lang == "c++-impl") {
87 return ast->generateCppImpl(outputDir);
88 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070089 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -070090 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070091 }
92 if (lang == "vts") {
93 return ast->generateVts(outputDir);
94 }
95 // Unknown language.
96 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -070097}
98
99static status_t generateSourcesForPackage(
100 const FQName &packageFQName,
101 const char *hidl_gen,
102 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700103 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700104 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700105 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700106 !packageFQName.isFullyQualified() &&
107 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700108
109 std::vector<FQName> packageInterfaces;
110
111 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700112 coordinator->appendPackageInterfacesToVector(packageFQName,
113 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700114
115 if (err != OK) {
116 return err;
117 }
118
119 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700120 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700121 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700122 if (err != OK) {
123 return err;
124 }
125 }
126
127 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700128}
129
Andreas Huberd2943e12016-08-05 11:59:31 -0700130static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700131 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700132}
133
Andreas Huberaa573272017-04-13 09:58:06 -0700134static std::string makeJavaLibraryName(const FQName &packageFQName) {
135 std::string out;
136 out = packageFQName.package();
137 out += "-V";
138 out += packageFQName.version();
139 return out;
140}
141
Steven Moreland5715fed2017-01-16 11:06:47 -0800142static void generatePackagePathsSection(
143 Formatter &out,
144 Coordinator *coordinator,
145 const FQName &packageFQName,
146 const std::set<FQName> &importedPackages,
147 bool forMakefiles = false) {
148 std::set<std::string> options{};
149 for (const auto &interface : importedPackages) {
150 options.insert(coordinator->getPackageRootOption(interface));
151 }
152 options.insert(coordinator->getPackageRootOption(packageFQName));
153 options.insert(coordinator->getPackageRootOption(gIBasePackageFqName));
154 for (const auto &option : options) {
155 out << "-r"
156 << option
157 << " ";
158 if (forMakefiles) {
159 out << "\\\n";
160 }
161 }
162}
163
Dan Willemsen676abdc2016-09-28 19:42:22 -0700164static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700165 Formatter &out,
166 Coordinator *coordinator,
167 const FQName &packageFQName,
168 const FQName &fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800169 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700170 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700171 out << "\n"
172 << "\n#"
173 << "\n# Build " << fqName.name() << ".hal";
174
Dan Willemsen676abdc2016-09-28 19:42:22 -0700175 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700176 out << " (" << typeName << ")";
177 }
178
179 out << "\n#"
180 << "\nGEN := $(intermediates)/"
181 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800182 << coordinator->getPackagePath(packageFQName, true /* relative */,
183 true /* sanitized */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700184 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700185 out << fqName.name() << ".java";
186 } else {
187 out << typeName << ".java";
188 }
189
190 out << "\n$(GEN): $(HIDL)";
191 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
192 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
193 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700194
195 {
196 AST *ast = coordinator->parse(fqName);
197 CHECK(ast != nullptr);
198 const std::set<FQName>& refs = ast->getImportedNames();
199 for (auto depFQName : refs) {
200 // If the package of depFQName is the same as this fqName's package,
201 // then add it explicitly as a .hal dependency within the same
202 // package.
203 if (fqName.package() == depFQName.package() &&
204 fqName.version() == depFQName.version()) {
205 // PRIVATE_DEPS is not actually being used in the
206 // auto-generated file, but is necessary if the build rule
207 // ever needs to use the dependency information, since the
208 // built-in Make variables are not supported in the Android
209 // build system.
210 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
211 << depFQName.name() << ".hal";
212 // This is the actual dependency.
213 out << "\n$(GEN): $(LOCAL_PATH)/"
214 << depFQName.name() << ".hal";
215 }
216 }
217 }
218
Andreas Huber0fa9e392016-08-31 09:05:44 -0700219 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
220 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
221 out.indent();
222 out.indent();
223 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800224 << "\n-Ljava \\\n";
225
226 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700227
228 out << packageFQName.string()
229 << "::"
230 << fqName.name();
231
Dan Willemsen676abdc2016-09-28 19:42:22 -0700232 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700233 out << "." << typeName;
234 }
235
236 out << "\n";
237
238 out.unindent();
239 out.unindent();
240
241 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
242 out << "\n\t$(transform-generated-source)";
243 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
244}
245
Dan Willemsen676abdc2016-09-28 19:42:22 -0700246static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700247 Formatter &out,
248 Coordinator *coordinator,
249 const FQName &packageFQName,
250 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800251 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700252 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700253 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700254 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700255 CHECK(typesAST != nullptr);
256
257 Scope *rootScope = typesAST->scope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700258
Andreas Huberb747bd92016-09-26 15:55:31 -0700259 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
260 std::sort(
261 subTypes.begin(),
262 subTypes.end(),
263 [](const NamedType *a, const NamedType *b) -> bool {
264 return a->fqName() < b->fqName();
265 });
266
267 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700268 if (type->isTypeDef()) {
269 continue;
270 }
271
Dan Willemsen676abdc2016-09-28 19:42:22 -0700272 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700273 out,
274 coordinator,
275 packageFQName,
276 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800277 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700278 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700279 }
280
281 continue;
282 }
283
Dan Willemsen676abdc2016-09-28 19:42:22 -0700284 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700285 out,
286 coordinator,
287 packageFQName,
288 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800289 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700290 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700291 }
292}
293
Andreas Huber75ae95d2016-10-12 16:08:26 -0700294static status_t isPackageJavaCompatible(
295 const FQName &packageFQName,
296 Coordinator *coordinator,
297 bool *compatible) {
298 std::vector<FQName> todo;
299 status_t err =
300 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
301
302 if (err != OK) {
303 return err;
304 }
305
306 std::set<FQName> seen;
307 for (const auto &iface : todo) {
308 seen.insert(iface);
309 }
310
311 // Form the transitive closure of all imported interfaces (and types.hal-s)
312 // If any one of them is not java compatible, this package isn't either.
313 while (!todo.empty()) {
314 const FQName fqName = todo.back();
315 todo.pop_back();
316
317 AST *ast = coordinator->parse(fqName);
318
319 if (ast == nullptr) {
320 return UNKNOWN_ERROR;
321 }
322
323 if (!ast->isJavaCompatible()) {
324 *compatible = false;
325 return OK;
326 }
327
328 std::set<FQName> importedPackages;
329 ast->getImportedPackages(&importedPackages);
330
331 for (const auto &package : importedPackages) {
332 std::vector<FQName> packageInterfaces;
333 status_t err = coordinator->appendPackageInterfacesToVector(
334 package, &packageInterfaces);
335
336 if (err != OK) {
337 return err;
338 }
339
340 for (const auto &iface : packageInterfaces) {
341 if (seen.find(iface) != seen.end()) {
342 continue;
343 }
344
345 todo.push_back(iface);
346 seen.insert(iface);
347 }
348 }
349 }
350
351 *compatible = true;
352 return OK;
353}
354
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700355static bool packageNeedsJavaCode(
356 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
357 // If there is more than just a types.hal file to this package we'll
358 // definitely need to generate Java code.
359 if (packageInterfaces.size() > 1
360 || packageInterfaces[0].name() != "types") {
361 return true;
362 }
363
364 CHECK(typesAST != nullptr);
365
366 // We'll have to generate Java code if types.hal contains any non-typedef
367 // type declarations.
368
369 Scope *rootScope = typesAST->scope();
370 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
371
372 for (const auto &subType : subTypes) {
373 if (!subType->isTypeDef()) {
374 return true;
375 }
376 }
377
378 return false;
379}
380
Andreas Huber1c507272016-10-05 14:33:21 -0700381static void generateMakefileSectionForJavaConstants(
382 Formatter &out,
383 Coordinator *coordinator,
384 const FQName &packageFQName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800385 const std::vector<FQName> &packageInterfaces,
386 const std::set<FQName> &importedPackages) {
Andreas Huber1c507272016-10-05 14:33:21 -0700387 out << "\n#"
388 << "\nGEN := $(intermediates)/"
389 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800390 << coordinator->getPackagePath(packageFQName, true /* relative */, true /* sanitized */)
Andreas Huber1c507272016-10-05 14:33:21 -0700391 << "Constants.java";
392
393 out << "\n$(GEN): $(HIDL)\n";
394 for (const auto &iface : packageInterfaces) {
395 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
396 }
397 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
398 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
399 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
400 out.indent();
401 out.indent();
402 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800403 << "\n-Ljava-constants \\\n";
404
405 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber1c507272016-10-05 14:33:21 -0700406
407 out << packageFQName.string();
408 out << "\n";
409
410 out.unindent();
411 out.unindent();
412
413 out << "\n$(GEN):";
414 out << "\n\t$(transform-generated-source)";
415 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
416}
417
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700418static status_t generateMakefileForPackage(
419 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700420 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700421 Coordinator *coordinator,
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700422 const std::string &) {
423
424 CHECK(packageFQName.isValid() &&
425 !packageFQName.isFullyQualified() &&
426 packageFQName.name().empty());
427
Andreas Huberd2943e12016-08-05 11:59:31 -0700428 std::vector<FQName> packageInterfaces;
429
430 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700431 coordinator->appendPackageInterfacesToVector(packageFQName,
432 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700433
434 if (err != OK) {
435 return err;
436 }
437
438 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700439 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700440 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700441
Andreas Huberd2943e12016-08-05 11:59:31 -0700442 for (const auto &fqName : packageInterfaces) {
443 AST *ast = coordinator->parse(fqName);
444
445 if (ast == NULL) {
446 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700447 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700448 fqName.string().c_str());
449
450 return UNKNOWN_ERROR;
451 }
452
Andreas Huber0fa9e392016-08-31 09:05:44 -0700453 if (fqName.name() == "types") {
454 typesAST = ast;
455 }
456
Yifan Hong40a373d2016-11-30 15:16:47 -0800457 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700458 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700459 }
460
Andreas Huber75ae95d2016-10-12 16:08:26 -0700461 bool packageIsJavaCompatible;
462 err = isPackageJavaCompatible(
463 packageFQName, coordinator, &packageIsJavaCompatible);
464
465 if (err != OK) {
466 return err;
467 }
468
Andreas Huber1c507272016-10-05 14:33:21 -0700469 bool haveJavaConstants = !exportedTypes.empty();
470
471 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800472 // TODO(b/33420795)
473 fprintf(stderr,
474 "WARNING: %s is not java compatible. No java makefile created.\n",
475 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700476 return OK;
477 }
478
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700479 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
480 return OK;
481 }
482
Andreas Huberd2943e12016-08-05 11:59:31 -0700483 std::string path =
484 coordinator->getPackagePath(packageFQName, false /* relative */);
485
486 path.append("Android.mk");
487
488 CHECK(Coordinator::MakeParentHierarchy(path));
489 FILE *file = fopen(path.c_str(), "w");
490
491 if (file == NULL) {
492 return -errno;
493 }
494
Andreas Huberaa573272017-04-13 09:58:06 -0700495 const std::string libraryName = makeJavaLibraryName(packageFQName);
Andreas Huberd2943e12016-08-05 11:59:31 -0700496
497 Formatter out(file);
498
Dan Willemsen676abdc2016-09-28 19:42:22 -0700499 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
500 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700501
Dan Willemsen676abdc2016-09-28 19:42:22 -0700502 enum LibraryStyle {
503 LIBRARY_STYLE_REGULAR,
504 LIBRARY_STYLE_STATIC,
505 LIBRARY_STYLE_END,
506 };
Andreas Huberd2943e12016-08-05 11:59:31 -0700507
Andreas Huber1c507272016-10-05 14:33:21 -0700508 for (int style = LIBRARY_STYLE_REGULAR;
509 (packageIsJavaCompatible && style != LIBRARY_STYLE_END);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700510 ++style) {
511 const std::string staticSuffix =
512 (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700513
Dan Willemsen676abdc2016-09-28 19:42:22 -0700514 out << "\n"
515 << "########################################"
516 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700517
Dan Willemsen676abdc2016-09-28 19:42:22 -0700518 out << "include $(CLEAR_VARS)\n"
519 << "LOCAL_MODULE := "
520 << libraryName
521 << "-java"
522 << staticSuffix
523 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800524 << "intermediates := $(call local-generated-sources-dir, COMMON)"
525 << "\n\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700526 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
527 << hidl_gen
528 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700529
Dan Willemsen676abdc2016-09-28 19:42:22 -0700530 if (!importedPackages.empty()) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700531 out << "\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700532 << "\nLOCAL_"
Andreas Huber782d45e2016-09-22 13:25:14 -0700533 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
Dan Willemsen676abdc2016-09-28 19:42:22 -0700534 << "JAVA_LIBRARIES := \\";
535
536 out.indent();
537 for (const auto &importedPackage : importedPackages) {
538 out << "\n"
Andreas Huberaa573272017-04-13 09:58:06 -0700539 << makeJavaLibraryName(importedPackage)
Dan Willemsen676abdc2016-09-28 19:42:22 -0700540 << "-java"
541 << staticSuffix
542 << " \\";
543 }
544 out << "\n";
545 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700546 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700547
548 generateMakefileSection(
549 out,
550 coordinator,
551 packageFQName,
552 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800553 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700554 typesAST);
555
556 out << "\ninclude $(BUILD_"
557 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
558 << "JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700559 }
560
Andreas Huber1c507272016-10-05 14:33:21 -0700561 if (haveJavaConstants) {
562 out << "\n"
563 << "########################################"
564 << "########################################\n\n";
565
566 out << "include $(CLEAR_VARS)\n"
567 << "LOCAL_MODULE := "
568 << libraryName
569 << "-java-constants"
570 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
Andreas Huber177a8b12017-02-09 10:08:48 -0800571 << "intermediates := $(call local-generated-sources-dir, COMMON)"
572 << "\n\n"
Andreas Huber1c507272016-10-05 14:33:21 -0700573 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
574 << hidl_gen
575 << "$(HOST_EXECUTABLE_SUFFIX)";
576
577 generateMakefileSectionForJavaConstants(
Steven Moreland5715fed2017-01-16 11:06:47 -0800578 out, coordinator, packageFQName, packageInterfaces, importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700579
580 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
581 << "-> framework.jar\n"
582 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
583 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
584 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
585 }
586
Iliyan Malchev8be09552016-09-22 16:20:33 -0700587 out << "\n\n"
588 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
589
Andreas Huberd2943e12016-08-05 11:59:31 -0700590 return OK;
591}
592
Andreas Huber0fa9e392016-08-31 09:05:44 -0700593OutputHandler::ValRes validateForMakefile(
594 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700595 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700596 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700597 return OutputHandler::FAILED;
598 }
599
600 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700601 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700602 return OutputHandler::FAILED;
603 }
604
605 if (!fqName.name().empty()) {
606 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700607 "ERROR: Expecting only package name and version.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700608 return OutputHandler::FAILED;
609 }
610
611 return OutputHandler::PASS_PACKAGE;
612}
613
Dan Willemsen676abdc2016-09-28 19:42:22 -0700614static void generateAndroidBpGenSection(
615 Formatter &out,
616 const FQName &packageFQName,
617 const char *hidl_gen,
618 Coordinator *coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800619 const std::string &halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700620 const std::string &genName,
621 const char *language,
622 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800623 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700624 const std::function<void(Formatter&, const FQName)> outputFn) {
625
626 out << "genrule {\n";
627 out.indent();
628 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700629 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700630
Colin Crossd5419bd2016-11-04 15:05:54 -0700631 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Steven Moreland5715fed2017-01-16 11:06:47 -0800632 << " -L" << language << " ";
633
634 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages);
635
636 out << packageFQName.string() << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700637
638 out << "srcs: [\n";
639 out.indent();
Tri Vo6a827fa2017-02-08 10:24:42 -0800640 out << "\":" << halFilegroupName << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700641 out.unindent();
642 out << "],\n";
643
644 out << "out: [\n";
645 out.indent();
646 for (const auto &fqName : packageInterfaces) {
647 outputFn(out, fqName);
648 }
649 out.unindent();
650 out << "],\n";
651
652 out.unindent();
653 out << "}\n\n";
654}
655
656static status_t generateAndroidBpForPackage(
657 const FQName &packageFQName,
658 const char *hidl_gen,
659 Coordinator *coordinator,
660 const std::string &) {
661
662 CHECK(packageFQName.isValid() &&
663 !packageFQName.isFullyQualified() &&
664 packageFQName.name().empty());
665
666 std::vector<FQName> packageInterfaces;
667
668 status_t err =
669 coordinator->appendPackageInterfacesToVector(packageFQName,
670 &packageInterfaces);
671
672 if (err != OK) {
673 return err;
674 }
675
Steven Morelandff5262b2017-03-20 06:59:03 -0700676 std::set<FQName> importedPackagesHierarchy;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700677 AST *typesAST = nullptr;
678
679 for (const auto &fqName : packageInterfaces) {
680 AST *ast = coordinator->parse(fqName);
681
682 if (ast == NULL) {
683 fprintf(stderr,
684 "ERROR: Could not parse %s. Aborting.\n",
685 fqName.string().c_str());
686
687 return UNKNOWN_ERROR;
688 }
689
690 if (fqName.name() == "types") {
691 typesAST = ast;
692 }
693
Steven Morelandff5262b2017-03-20 06:59:03 -0700694 ast->getImportedPackagesHierarchy(&importedPackagesHierarchy);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700695 }
696
697 std::string path =
698 coordinator->getPackagePath(packageFQName, false /* relative */);
699
700 path.append("Android.bp");
701
702 CHECK(Coordinator::MakeParentHierarchy(path));
703 FILE *file = fopen(path.c_str(), "w");
704
705 if (file == NULL) {
706 return -errno;
707 }
708
709 const std::string libraryName = makeLibraryName(packageFQName);
Tri Vo15052c62017-02-06 10:04:07 -0800710 const std::string halFilegroupName = libraryName + "_hal";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700711 const std::string genSourceName = libraryName + "_genc++";
712 const std::string genHeaderName = libraryName + "_genc++_headers";
713 const std::string pathPrefix =
714 coordinator->convertPackageRootToPath(packageFQName) +
715 coordinator->getPackagePath(packageFQName, true /* relative */);
716
717 Formatter out(file);
718
719 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
720
Tri Vo15052c62017-02-06 10:04:07 -0800721 // Rule to generate .hal filegroup
722 out << "filegroup {\n";
723 out.indent();
724 out << "name: \"" << halFilegroupName << "\",\n";
725 out << "srcs: [\n";
726 out.indent();
727 for (const auto &fqName : packageInterfaces) {
728 out << "\"" << fqName.name() << ".hal\",\n";
729 }
730 out.unindent();
731 out << "],\n";
732 out.unindent();
733 out << "}\n\n";
734
Dan Willemsen676abdc2016-09-28 19:42:22 -0700735 // Rule to generate the C++ source files
736 generateAndroidBpGenSection(
737 out,
738 packageFQName,
739 hidl_gen,
740 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800741 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700742 genSourceName,
743 "c++",
744 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700745 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700746 [&pathPrefix](Formatter &out, const FQName &fqName) {
747 if (fqName.name() == "types") {
748 out << "\"" << pathPrefix << "types.cpp\",\n";
749 } else {
750 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
751 }
752 });
753
754 // Rule to generate the C++ header files
755 generateAndroidBpGenSection(
756 out,
757 packageFQName,
758 hidl_gen,
759 coordinator,
Tri Vo6a827fa2017-02-08 10:24:42 -0800760 halFilegroupName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700761 genHeaderName,
762 "c++",
763 packageInterfaces,
Steven Morelandff5262b2017-03-20 06:59:03 -0700764 importedPackagesHierarchy,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700765 [&pathPrefix](Formatter &out, const FQName &fqName) {
766 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
767 if (fqName.name() != "types") {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800768 out << "\"" << pathPrefix << fqName.getInterfaceHwName() << ".h\",\n";
769 out << "\"" << pathPrefix << fqName.getInterfaceStubName() << ".h\",\n";
770 out << "\"" << pathPrefix << fqName.getInterfaceProxyName() << ".h\",\n";
771 out << "\"" << pathPrefix << fqName.getInterfacePassthroughName() << ".h\",\n";
Steven Moreland9774d622017-03-24 21:51:45 -0700772 } else {
773 out << "\"" << pathPrefix << "hwtypes.h\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700774 }
775 });
776
777 // C++ library definition
778 out << "cc_library_shared {\n";
779 out.indent();
780 out << "name: \"" << libraryName << "\",\n"
781 << "generated_sources: [\"" << genSourceName << "\"],\n"
782 << "generated_headers: [\"" << genHeaderName << "\"],\n"
783 << "export_generated_headers: [\"" << genHeaderName << "\"],\n"
Dan Willemsen2cf4b9a2017-04-07 13:21:11 -0700784 << "vendor_available: true,\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700785 << "shared_libs: [\n";
786
787 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -0800788 out << "\"libhidlbase\",\n"
789 << "\"libhidltransport\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700790 << "\"libhwbinder\",\n"
Steven Moreland05cd4232016-11-21 16:01:12 -0800791 << "\"liblog\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700792 << "\"libutils\",\n"
793 << "\"libcutils\",\n";
Steven Morelandff5262b2017-03-20 06:59:03 -0700794 for (const auto &importedPackage : importedPackagesHierarchy) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700795 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
796 }
797 out.unindent();
798
799 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -0700800
801 out << "export_shared_lib_headers: [\n";
802 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -0800803 out << "\"libhidlbase\",\n"
804 << "\"libhidltransport\",\n"
Steven Morelandb8a26c02016-10-21 13:40:14 -0700805 << "\"libhwbinder\",\n"
Steven Moreland865243c2016-11-01 13:05:24 -0700806 << "\"libutils\",\n";
Steven Morelandff5262b2017-03-20 06:59:03 -0700807 for (const auto &importedPackage : importedPackagesHierarchy) {
Yifan Hongc1f9b8d2016-11-07 14:35:44 -0800808 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
809 }
Steven Moreland865243c2016-11-01 13:05:24 -0700810 out.unindent();
811 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -0700812 out.unindent();
813
Dan Willemsen676abdc2016-09-28 19:42:22 -0700814 out << "}\n";
815
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800816 return OK;
Dan Willemsen676abdc2016-09-28 19:42:22 -0700817}
818
Yifan Hong958ee462016-12-06 17:09:51 -0800819static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -0700820 const FQName &packageFQName,
821 const char *,
822 Coordinator *coordinator,
823 const std::string &outputDir) {
824
Iliyan Malchev4923f932016-09-09 13:04:59 -0700825 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700826
827 std::vector<FQName> packageInterfaces;
828
829 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700830 coordinator->appendPackageInterfacesToVector(packageFQName,
831 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700832
833 if (err != OK) {
834 return err;
835 }
836
837 std::set<FQName> importedPackages;
838
839 for (const auto &fqName : packageInterfaces) {
840 AST *ast = coordinator->parse(fqName);
841
842 if (ast == NULL) {
843 fprintf(stderr,
844 "ERROR: Could not parse %s. Aborting.\n",
845 fqName.string().c_str());
846
847 return UNKNOWN_ERROR;
848 }
849
850 ast->getImportedPackages(&importedPackages);
851 }
852
Yifan Hongaafed702016-12-14 12:59:47 -0800853 std::string path = outputDir + "Android.bp";
Steven Moreland197d56c2016-09-09 10:03:58 -0700854
855 CHECK(Coordinator::MakeParentHierarchy(path));
856 FILE *file = fopen(path.c_str(), "w");
857
858 if (file == NULL) {
859 return -errno;
860 }
861
862 Formatter out(file);
863
Yifan Hong958ee462016-12-06 17:09:51 -0800864 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800865 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800866 out << "name: \"" << libraryName << "\",\n"
867 << "relative_install_path: \"hw\",\n"
Steven Morelandf8a22e92017-02-15 18:46:04 -0800868 << "proprietary: true,\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800869 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800870 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800871 for (const auto &fqName : packageInterfaces) {
872 if (fqName.name() == "types") {
873 continue;
874 }
875 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
876 }
877 });
878 out << "],\n"
879 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800880 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -0800881 out << "\"libhidlbase\",\n"
882 << "\"libhidltransport\",\n"
Yifan Hong958ee462016-12-06 17:09:51 -0800883 << "\"libutils\",\n"
884 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -0700885
Yifan Hong958ee462016-12-06 17:09:51 -0800886 for (const auto &importedPackage : importedPackages) {
887 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
888 }
889 });
890 out << "],\n";
891 });
892 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -0700893
894 return OK;
895}
896
Andreas Huber0fa9e392016-08-31 09:05:44 -0700897OutputHandler::ValRes validateForSource(
898 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700899 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700900 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700901 return OutputHandler::FAILED;
902 }
903
904 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700905 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700906 return OutputHandler::FAILED;
907 }
908
Andreas Huber0fa9e392016-08-31 09:05:44 -0700909 const std::string &name = fqName.name();
910 if (!name.empty()) {
911 if (name.find('.') == std::string::npos) {
912 return OutputHandler::PASS_FULL;
913 }
914
915 if (language != "java" || name.find("types.") != 0) {
916 // When generating java sources for "types.hal", output can be
917 // constrained to just one of the top-level types declared
918 // by using the extended syntax
919 // android.hardware.Foo@1.0::types.TopLevelTypeName.
920 // In all other cases (different language, not 'types') the dot
921 // notation in the name is illegal in this context.
922 return OutputHandler::FAILED;
923 }
924
925 return OutputHandler::PASS_FULL;
926 }
927
928 return OutputHandler::PASS_PACKAGE;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700929}
930
Andreas Huber019d21d2016-10-03 12:59:47 -0700931OutputHandler::ValRes validateForExportHeader(
932 const FQName &fqName, const std::string & /* language */) {
933 if (fqName.package().empty()) {
934 fprintf(stderr, "ERROR: Expecting package name\n");
935 return OutputHandler::FAILED;
936 }
937
938 if (fqName.version().empty()) {
939 fprintf(stderr, "ERROR: Expecting package version\n");
940 return OutputHandler::FAILED;
941 }
942
943 if (!fqName.name().empty()) {
944 fprintf(stderr,
945 "ERROR: Expecting only package name and version.\n");
946 return OutputHandler::FAILED;
947 }
948
949 return OutputHandler::PASS_PACKAGE;
950}
951
952
953static status_t generateExportHeaderForPackage(
954 const FQName &packageFQName,
955 const char * /* hidl_gen */,
956 Coordinator *coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -0700957 const std::string &outputPath,
958 bool forJava) {
Andreas Huber019d21d2016-10-03 12:59:47 -0700959
960 CHECK(packageFQName.isValid()
961 && !packageFQName.isFullyQualified()
962 && packageFQName.name().empty());
963
964 std::vector<FQName> packageInterfaces;
965
966 status_t err = coordinator->appendPackageInterfacesToVector(
967 packageFQName, &packageInterfaces);
968
969 if (err != OK) {
970 return err;
971 }
972
973 std::vector<const Type *> exportedTypes;
974
975 for (const auto &fqName : packageInterfaces) {
976 AST *ast = coordinator->parse(fqName);
977
978 if (ast == NULL) {
979 fprintf(stderr,
980 "ERROR: Could not parse %s. Aborting.\n",
981 fqName.string().c_str());
982
983 return UNKNOWN_ERROR;
984 }
985
986 ast->appendToExportedTypesVector(&exportedTypes);
987 }
988
989 if (exportedTypes.empty()) {
990 return OK;
991 }
992
Andreas Huber1c507272016-10-05 14:33:21 -0700993 std::string path = outputPath;
994
995 if (forJava) {
996 path.append(coordinator->convertPackageRootToPath(packageFQName));
997
998 path.append(coordinator->getPackagePath(
Yifan Hong97288ac2016-12-12 16:03:51 -0800999 packageFQName, true /* relative */, true /* sanitized */));
Andreas Huber1c507272016-10-05 14:33:21 -07001000
1001 path.append("Constants.java");
1002 }
1003
1004 CHECK(Coordinator::MakeParentHierarchy(path));
1005 FILE *file = fopen(path.c_str(), "w");
Andreas Huber019d21d2016-10-03 12:59:47 -07001006
1007 if (file == nullptr) {
1008 return -errno;
1009 }
1010
1011 Formatter out(file);
1012
Steven Morelandd177b122016-12-12 09:15:37 -08001013 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
Glenn Kastend18c3ba2017-02-23 16:35:24 -08001014 << "// Source: " << packageFQName.string() << "\n"
1015 << "// Root: " << coordinator->getPackageRootOption(packageFQName) << "\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001016
Andreas Huber1c507272016-10-05 14:33:21 -07001017 std::string guard;
1018 if (forJava) {
1019 out << "package " << packageFQName.javaPackage() << ";\n\n";
1020 out << "public class Constants {\n";
1021 out.indent();
1022 } else {
1023 guard = "HIDL_GENERATED_";
Steven Morelandd177b122016-12-12 09:15:37 -08001024 guard += StringHelper::Uppercase(packageFQName.tokenName());
Andreas Huber1c507272016-10-05 14:33:21 -07001025 guard += "_";
1026 guard += "EXPORTED_CONSTANTS_H_";
Andreas Huber019d21d2016-10-03 12:59:47 -07001027
Andreas Huber1c507272016-10-05 14:33:21 -07001028 out << "#ifndef "
1029 << guard
1030 << "\n#define "
1031 << guard
1032 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001033 }
1034
Andreas Huber1c507272016-10-05 14:33:21 -07001035 for (const auto &type : exportedTypes) {
1036 type->emitExportedHeader(out, forJava);
1037 }
1038
1039 if (forJava) {
1040 out.unindent();
1041 out << "}\n";
1042 } else {
1043 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
1044 << guard
1045 << "\n";
1046 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001047
1048 return OK;
1049}
1050
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001051static std::vector<OutputHandler> formats = {
1052 {"c++",
Andreas Huber019d21d2016-10-03 12:59:47 -07001053 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001054 validateForSource,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001055 [](const FQName &fqName,
1056 const char *hidl_gen, Coordinator *coordinator,
1057 const std::string &outputDir) -> status_t {
1058 if (fqName.isFullyQualified()) {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001059 return generateSourcesForFile(fqName,
1060 hidl_gen,
1061 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001062 outputDir,
1063 "c++");
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001064 } else {
1065 return generateSourcesForPackage(fqName,
1066 hidl_gen,
1067 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001068 outputDir,
1069 "c++");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001070 }
1071 }
1072 },
1073
Andreas Huber019d21d2016-10-03 12:59:47 -07001074 {"export-header",
1075 OutputHandler::NEEDS_FILE /* mOutputMode */,
1076 validateForExportHeader,
1077 [](const FQName &fqName,
1078 const char *hidl_gen,
1079 Coordinator *coordinator,
1080 const std::string &outputPath) -> status_t {
1081 CHECK(!fqName.isFullyQualified());
1082
1083 return generateExportHeaderForPackage(
1084 fqName,
1085 hidl_gen,
1086 coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001087 outputPath,
1088 false /* forJava */);
Andreas Huber019d21d2016-10-03 12:59:47 -07001089 }
1090 },
1091
Steven Moreland9c387612016-09-07 09:54:26 -07001092 {"c++-impl",
Andreas Huber019d21d2016-10-03 12:59:47 -07001093 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001094 validateForSource,
1095 [](const FQName &fqName,
1096 const char *hidl_gen, Coordinator *coordinator,
1097 const std::string &outputDir) -> status_t {
1098 if (fqName.isFullyQualified()) {
1099 return generateSourcesForFile(fqName,
1100 hidl_gen,
1101 coordinator,
1102 outputDir, "c++-impl");
1103 } else {
1104 return generateSourcesForPackage(fqName,
1105 hidl_gen,
1106 coordinator,
1107 outputDir, "c++-impl");
1108 }
1109 }
1110 },
1111
1112
Andreas Huber2831d512016-08-15 09:33:47 -07001113 {"java",
Andreas Huber019d21d2016-10-03 12:59:47 -07001114 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001115 validateForSource,
Andreas Huber2831d512016-08-15 09:33:47 -07001116 [](const FQName &fqName,
1117 const char *hidl_gen, Coordinator *coordinator,
1118 const std::string &outputDir) -> status_t {
1119 if (fqName.isFullyQualified()) {
1120 return generateSourcesForFile(fqName,
1121 hidl_gen,
1122 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001123 outputDir,
1124 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001125 }
1126 else {
1127 return generateSourcesForPackage(fqName,
1128 hidl_gen,
1129 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001130 outputDir,
1131 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001132 }
1133 }
1134 },
1135
Andreas Huber1c507272016-10-05 14:33:21 -07001136 {"java-constants",
1137 OutputHandler::NEEDS_DIR /* mOutputMode */,
1138 validateForExportHeader,
1139 [](const FQName &fqName,
1140 const char *hidl_gen, Coordinator *coordinator,
1141 const std::string &outputDir) -> status_t {
1142 CHECK(!fqName.isFullyQualified());
1143 return generateExportHeaderForPackage(
1144 fqName,
1145 hidl_gen,
1146 coordinator,
1147 outputDir,
1148 true /* forJava */);
1149 }
1150 },
1151
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001152 {"vts",
Andreas Huber019d21d2016-10-03 12:59:47 -07001153 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001154 validateForSource,
1155 [](const FQName &fqName,
1156 const char * hidl_gen,
1157 Coordinator *coordinator,
1158 const std::string &outputDir) -> status_t {
1159 if (fqName.isFullyQualified()) {
1160 return generateSourcesForFile(fqName,
1161 hidl_gen,
1162 coordinator,
1163 outputDir, "vts");
1164 } else {
1165 return generateSourcesForPackage(fqName,
1166 hidl_gen,
1167 coordinator,
1168 outputDir, "vts");
1169 }
1170 }
1171 },
1172
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001173 {"makefile",
Andreas Huber019d21d2016-10-03 12:59:47 -07001174 OutputHandler::NOT_NEEDED /* mOutputMode */,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001175 validateForMakefile,
1176 generateMakefileForPackage,
1177 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001178
Dan Willemsen676abdc2016-09-28 19:42:22 -07001179 {"androidbp",
Andreas Huber019d21d2016-10-03 12:59:47 -07001180 OutputHandler::NOT_NEEDED /* mOutputMode */,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001181 validateForMakefile,
1182 generateAndroidBpForPackage,
1183 },
1184
Yifan Hong958ee462016-12-06 17:09:51 -08001185 {"androidbp-impl",
Yifan Hong94bcea02016-10-06 13:51:31 -07001186 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland197d56c2016-09-09 10:03:58 -07001187 validateForMakefile,
Yifan Hong958ee462016-12-06 17:09:51 -08001188 generateAndroidBpImplForPackage,
Steven Moreland197d56c2016-09-09 10:03:58 -07001189 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001190};
1191
1192static void usage(const char *me) {
1193 fprintf(stderr,
1194 "usage: %s -o output-path -L <language> (-r interface-root)+ fqname+\n",
1195 me);
1196
1197 fprintf(stderr, " -o output path\n");
1198
1199 fprintf(stderr, " -L <language> (one of");
1200 for (auto &e : formats) {
1201 fprintf(stderr, " %s", e.mKey.c_str());
1202 }
1203 fprintf(stderr, ")\n");
1204
1205 fprintf(stderr,
1206 " -r package:path root "
1207 "(e.g., android.hardware:hardware/interfaces)\n");
1208}
1209
Andreas Huberb82318c2016-08-02 14:45:54 -07001210int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001211 std::string outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001212 std::vector<std::string> packageRootPaths;
1213 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001214
Andreas Huber737080b2016-08-02 15:38:04 -07001215 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001216 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001217
Andreas Huberb82318c2016-08-02 14:45:54 -07001218 int res;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001219 while ((res = getopt(argc, argv, "ho:r:L:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001220 switch (res) {
1221 case 'o':
1222 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001223 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001224 break;
1225 }
1226
Andreas Huberdca261f2016-08-04 13:47:51 -07001227 case 'r':
1228 {
1229 std::string val(optarg);
1230 auto index = val.find_first_of(':');
1231 CHECK(index != std::string::npos);
1232
1233 auto package = val.substr(0, index);
1234 auto path = val.substr(index + 1);
1235 packageRootPaths.push_back(path);
1236 packageRoots.push_back(package);
1237 break;
1238 }
1239
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001240 case 'L':
1241 {
Steven Morelande429a262016-11-15 09:54:32 -08001242 CHECK(outputFormat == nullptr) << "Only one -L option allowed.";
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001243 for (auto &e : formats) {
1244 if (e.mKey == optarg) {
1245 outputFormat = &e;
1246 break;
1247 }
1248 }
Steven Morelande429a262016-11-15 09:54:32 -08001249 CHECK(outputFormat != nullptr) << "Output format not recognized.";
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001250 break;
1251 }
1252
Andreas Huberb82318c2016-08-02 14:45:54 -07001253 case '?':
1254 case 'h':
1255 default:
1256 {
Andreas Huber737080b2016-08-02 15:38:04 -07001257 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001258 exit(1);
1259 break;
1260 }
1261 }
1262 }
1263
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001264 if (outputFormat == nullptr) {
1265 usage(me);
1266 exit(1);
1267 }
1268
Andreas Huberb82318c2016-08-02 14:45:54 -07001269 argc -= optind;
1270 argv += optind;
1271
Andreas Huberdca261f2016-08-04 13:47:51 -07001272 if (packageRootPaths.empty()) {
1273 // Pick reasonable defaults.
1274
1275 packageRoots.push_back("android.hardware");
1276
1277 const char *TOP = getenv("TOP");
Steven Morelandaf330382016-11-09 15:48:03 -08001278 if (TOP == nullptr) {
1279 fprintf(stderr,
1280 "ERROR: No root path (-r) specified"
1281 " and $TOP environment variable not set.\n");
1282 exit(1);
1283 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001284
1285 std::string path = TOP;
1286 path.append("/hardware/interfaces");
1287
1288 packageRootPaths.push_back(path);
1289 }
1290
Andreas Huber737080b2016-08-02 15:38:04 -07001291 // Valid options are now in argv[0] .. argv[argc - 1].
1292
Andreas Huber019d21d2016-10-03 12:59:47 -07001293 switch (outputFormat->mOutputMode) {
1294 case OutputHandler::NEEDS_DIR:
1295 case OutputHandler::NEEDS_FILE:
1296 {
1297 if (outputPath.empty()) {
1298 usage(me);
1299 exit(1);
1300 }
1301
1302 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
1303 const size_t len = outputPath.size();
1304 if (outputPath[len - 1] != '/') {
1305 outputPath += "/";
1306 }
1307 }
1308 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001309 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001310
1311 default:
1312 outputPath.clear(); // Unused.
1313 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001314 }
1315
Andreas Huberdca261f2016-08-04 13:47:51 -07001316 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -07001317
Andreas Huber737080b2016-08-02 15:38:04 -07001318 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001319 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001320
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001321 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001322 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001323 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001324 exit(1);
1325 }
Andreas Huber881227d2016-08-02 14:20:21 -07001326
Andreas Huber0fa9e392016-08-31 09:05:44 -07001327 OutputHandler::ValRes valid =
1328 outputFormat->validate(fqName, outputFormat->mKey);
1329
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001330 if (valid == OutputHandler::FAILED) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001331 exit(1);
1332 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001333
1334 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001335 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001336
1337 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001338 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001339 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001340 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001341
Andreas Huberd2943e12016-08-05 11:59:31 -07001342 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001343}