blob: c3589f07c1cf22a80cd72bbd21abdd7dc3e8131b [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 Huber84f89de2016-07-28 15:39:51 -070019#include "FQName.h"
Andreas Huber0fa9e392016-08-31 09:05:44 -070020#include "Scope.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070021
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070022#include <hidl-util/Formatter.h>
Andreas Huber68f24592016-07-29 14:53:48 -070023#include <android-base/logging.h>
Iliyan Malchev5bb14022016-08-09 15:04:39 -070024#include <set>
Andreas Huberc9410c72016-07-28 12:18:40 -070025#include <stdio.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070026#include <string>
Andreas Huberb82318c2016-08-02 14:45:54 -070027#include <unistd.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070028#include <vector>
Andreas Huberc9410c72016-07-28 12:18:40 -070029
30using namespace android;
31
Iliyan Malchev5bb14022016-08-09 15:04:39 -070032struct OutputHandler {
33 std::string mKey;
Andreas Huber019d21d2016-10-03 12:59:47 -070034 enum OutputMode {
35 NEEDS_DIR,
36 NEEDS_FILE,
37 NOT_NEEDED
38 } mOutputMode;
39
Iliyan Malchev5bb14022016-08-09 15:04:39 -070040 enum ValRes {
41 FAILED,
42 PASS_PACKAGE,
43 PASS_FULL
44 };
Andreas Huber0fa9e392016-08-31 09:05:44 -070045 ValRes (*validate)(const FQName &, const std::string &language);
Iliyan Malchev5bb14022016-08-09 15:04:39 -070046 status_t (*generate)(const FQName &fqName,
47 const char *hidl_gen,
48 Coordinator *coordinator,
49 const std::string &outputDir);
50};
Andreas Huberdca261f2016-08-04 13:47:51 -070051
Iliyan Malchev5bb14022016-08-09 15:04:39 -070052static status_t generateSourcesForFile(
53 const FQName &fqName,
54 const char *,
55 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -070056 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070057 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -070058 CHECK(fqName.isFullyQualified());
59
Andreas Huber0fa9e392016-08-31 09:05:44 -070060 AST *ast;
Andreas Huberd29724f2016-09-14 09:33:13 -070061 std::string limitToType;
Andreas Huber0fa9e392016-08-31 09:05:44 -070062
63 if (fqName.name().find("types.") == 0) {
64 CHECK(lang == "java"); // Already verified in validate().
65
Andreas Huberd29724f2016-09-14 09:33:13 -070066 limitToType = fqName.name().substr(strlen("types."));
Andreas Huber0fa9e392016-08-31 09:05:44 -070067
68 FQName typesName(fqName.package(), fqName.version(), "types");
69 ast = coordinator->parse(typesName);
70 } else {
71 ast = coordinator->parse(fqName);
72 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -070073
74 if (ast == NULL) {
75 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -070076 "ERROR: Could not parse %s. Aborting.\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -070077 fqName.string().c_str());
78
79 return UNKNOWN_ERROR;
80 }
81
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070082 if (lang == "c++") {
83 return ast->generateCpp(outputDir);
84 }
Steven Moreland9c387612016-09-07 09:54:26 -070085 if (lang == "c++-impl") {
86 return ast->generateCppImpl(outputDir);
87 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070088 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -070089 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070090 }
91 if (lang == "vts") {
92 return ast->generateVts(outputDir);
93 }
94 // Unknown language.
95 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -070096}
97
98static status_t generateSourcesForPackage(
99 const FQName &packageFQName,
100 const char *hidl_gen,
101 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700102 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700103 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700104 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700105 !packageFQName.isFullyQualified() &&
106 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700107
108 std::vector<FQName> packageInterfaces;
109
110 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700111 coordinator->appendPackageInterfacesToVector(packageFQName,
112 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700113
114 if (err != OK) {
115 return err;
116 }
117
118 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700119 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700120 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700121 if (err != OK) {
122 return err;
123 }
124 }
125
126 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700127}
128
Andreas Huberd2943e12016-08-05 11:59:31 -0700129static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700130 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700131}
132
Dan Willemsen676abdc2016-09-28 19:42:22 -0700133static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700134 Formatter &out,
135 Coordinator *coordinator,
136 const FQName &packageFQName,
137 const FQName &fqName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700138 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700139 out << "\n"
140 << "\n#"
141 << "\n# Build " << fqName.name() << ".hal";
142
Dan Willemsen676abdc2016-09-28 19:42:22 -0700143 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700144 out << " (" << typeName << ")";
145 }
146
147 out << "\n#"
148 << "\nGEN := $(intermediates)/"
149 << coordinator->convertPackageRootToPath(packageFQName)
150 << coordinator->getPackagePath(packageFQName, true /* relative */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700151 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700152 out << fqName.name() << ".java";
153 } else {
154 out << typeName << ".java";
155 }
156
157 out << "\n$(GEN): $(HIDL)";
158 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
159 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
160 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700161
162 {
163 AST *ast = coordinator->parse(fqName);
164 CHECK(ast != nullptr);
165 const std::set<FQName>& refs = ast->getImportedNames();
166 for (auto depFQName : refs) {
167 // If the package of depFQName is the same as this fqName's package,
168 // then add it explicitly as a .hal dependency within the same
169 // package.
170 if (fqName.package() == depFQName.package() &&
171 fqName.version() == depFQName.version()) {
172 // PRIVATE_DEPS is not actually being used in the
173 // auto-generated file, but is necessary if the build rule
174 // ever needs to use the dependency information, since the
175 // built-in Make variables are not supported in the Android
176 // build system.
177 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
178 << depFQName.name() << ".hal";
179 // This is the actual dependency.
180 out << "\n$(GEN): $(LOCAL_PATH)/"
181 << depFQName.name() << ".hal";
182 }
183 }
184 }
185
Andreas Huber0fa9e392016-08-31 09:05:44 -0700186 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
187 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
188 out.indent();
189 out.indent();
190 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Yifan Hongc8934042016-11-17 17:10:52 -0800191 << "\n-Ljava \\"
192 << "\n-r"
193 << coordinator->getPackageRootOption(packageFQName) << " \\"
194 << "\n-r"
195 << coordinator->getPackageRootOption(gIBasePackageFqName) << " \\\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700196
197 out << packageFQName.string()
198 << "::"
199 << fqName.name();
200
Dan Willemsen676abdc2016-09-28 19:42:22 -0700201 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700202 out << "." << typeName;
203 }
204
205 out << "\n";
206
207 out.unindent();
208 out.unindent();
209
210 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
211 out << "\n\t$(transform-generated-source)";
212 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
213}
214
Dan Willemsen676abdc2016-09-28 19:42:22 -0700215static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700216 Formatter &out,
217 Coordinator *coordinator,
218 const FQName &packageFQName,
219 const std::vector<FQName> &packageInterfaces,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700220 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700221 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700222 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700223 CHECK(typesAST != nullptr);
224
225 Scope *rootScope = typesAST->scope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700226
Andreas Huberb747bd92016-09-26 15:55:31 -0700227 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
228 std::sort(
229 subTypes.begin(),
230 subTypes.end(),
231 [](const NamedType *a, const NamedType *b) -> bool {
232 return a->fqName() < b->fqName();
233 });
234
235 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700236 if (type->isTypeDef()) {
237 continue;
238 }
239
Dan Willemsen676abdc2016-09-28 19:42:22 -0700240 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700241 out,
242 coordinator,
243 packageFQName,
244 fqName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700245 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700246 }
247
248 continue;
249 }
250
Dan Willemsen676abdc2016-09-28 19:42:22 -0700251 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700252 out,
253 coordinator,
254 packageFQName,
255 fqName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700256 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700257 }
258}
259
Andreas Huber75ae95d2016-10-12 16:08:26 -0700260static status_t isPackageJavaCompatible(
261 const FQName &packageFQName,
262 Coordinator *coordinator,
263 bool *compatible) {
264 std::vector<FQName> todo;
265 status_t err =
266 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
267
268 if (err != OK) {
269 return err;
270 }
271
272 std::set<FQName> seen;
273 for (const auto &iface : todo) {
274 seen.insert(iface);
275 }
276
277 // Form the transitive closure of all imported interfaces (and types.hal-s)
278 // If any one of them is not java compatible, this package isn't either.
279 while (!todo.empty()) {
280 const FQName fqName = todo.back();
281 todo.pop_back();
282
283 AST *ast = coordinator->parse(fqName);
284
285 if (ast == nullptr) {
286 return UNKNOWN_ERROR;
287 }
288
289 if (!ast->isJavaCompatible()) {
290 *compatible = false;
291 return OK;
292 }
293
294 std::set<FQName> importedPackages;
295 ast->getImportedPackages(&importedPackages);
296
297 for (const auto &package : importedPackages) {
298 std::vector<FQName> packageInterfaces;
299 status_t err = coordinator->appendPackageInterfacesToVector(
300 package, &packageInterfaces);
301
302 if (err != OK) {
303 return err;
304 }
305
306 for (const auto &iface : packageInterfaces) {
307 if (seen.find(iface) != seen.end()) {
308 continue;
309 }
310
311 todo.push_back(iface);
312 seen.insert(iface);
313 }
314 }
315 }
316
317 *compatible = true;
318 return OK;
319}
320
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700321static bool packageNeedsJavaCode(
322 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
323 // If there is more than just a types.hal file to this package we'll
324 // definitely need to generate Java code.
325 if (packageInterfaces.size() > 1
326 || packageInterfaces[0].name() != "types") {
327 return true;
328 }
329
330 CHECK(typesAST != nullptr);
331
332 // We'll have to generate Java code if types.hal contains any non-typedef
333 // type declarations.
334
335 Scope *rootScope = typesAST->scope();
336 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
337
338 for (const auto &subType : subTypes) {
339 if (!subType->isTypeDef()) {
340 return true;
341 }
342 }
343
344 return false;
345}
346
Andreas Huber1c507272016-10-05 14:33:21 -0700347static void generateMakefileSectionForJavaConstants(
348 Formatter &out,
349 Coordinator *coordinator,
350 const FQName &packageFQName,
351 const std::vector<FQName> &packageInterfaces) {
352 out << "\n#"
353 << "\nGEN := $(intermediates)/"
354 << coordinator->convertPackageRootToPath(packageFQName)
355 << coordinator->getPackagePath(packageFQName, true /* relative */)
356 << "Constants.java";
357
358 out << "\n$(GEN): $(HIDL)\n";
359 for (const auto &iface : packageInterfaces) {
360 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
361 }
362 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
363 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
364 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
365 out.indent();
366 out.indent();
367 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Yifan Hongc8934042016-11-17 17:10:52 -0800368 << "\n-Ljava-constants \\"
369 << "\n-r"
370 << coordinator->getPackageRootOption(packageFQName) << " \\"
371 << "\n-r"
372 << coordinator->getPackageRootOption(gIBasePackageFqName) << " \\\n";
Andreas Huber1c507272016-10-05 14:33:21 -0700373
374 out << packageFQName.string();
375 out << "\n";
376
377 out.unindent();
378 out.unindent();
379
380 out << "\n$(GEN):";
381 out << "\n\t$(transform-generated-source)";
382 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
383}
384
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700385static status_t generateMakefileForPackage(
386 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700387 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700388 Coordinator *coordinator,
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700389 const std::string &) {
390
391 CHECK(packageFQName.isValid() &&
392 !packageFQName.isFullyQualified() &&
393 packageFQName.name().empty());
394
Andreas Huberd2943e12016-08-05 11:59:31 -0700395 std::vector<FQName> packageInterfaces;
396
397 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700398 coordinator->appendPackageInterfacesToVector(packageFQName,
399 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700400
401 if (err != OK) {
402 return err;
403 }
404
405 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700406 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700407 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700408
Andreas Huberd2943e12016-08-05 11:59:31 -0700409 for (const auto &fqName : packageInterfaces) {
410 AST *ast = coordinator->parse(fqName);
411
412 if (ast == NULL) {
413 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700414 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700415 fqName.string().c_str());
416
417 return UNKNOWN_ERROR;
418 }
419
Andreas Huber0fa9e392016-08-31 09:05:44 -0700420 if (fqName.name() == "types") {
421 typesAST = ast;
422 }
423
Yifan Hong40a373d2016-11-30 15:16:47 -0800424 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700425 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700426 }
427
Andreas Huber75ae95d2016-10-12 16:08:26 -0700428 bool packageIsJavaCompatible;
429 err = isPackageJavaCompatible(
430 packageFQName, coordinator, &packageIsJavaCompatible);
431
432 if (err != OK) {
433 return err;
434 }
435
Andreas Huber1c507272016-10-05 14:33:21 -0700436 bool haveJavaConstants = !exportedTypes.empty();
437
438 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800439 // TODO(b/33420795)
440 fprintf(stderr,
441 "WARNING: %s is not java compatible. No java makefile created.\n",
442 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700443 return OK;
444 }
445
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700446 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
447 return OK;
448 }
449
Andreas Huberd2943e12016-08-05 11:59:31 -0700450 std::string path =
451 coordinator->getPackagePath(packageFQName, false /* relative */);
452
453 path.append("Android.mk");
454
455 CHECK(Coordinator::MakeParentHierarchy(path));
456 FILE *file = fopen(path.c_str(), "w");
457
458 if (file == NULL) {
459 return -errno;
460 }
461
462 const std::string libraryName = makeLibraryName(packageFQName);
463
464 Formatter out(file);
465
Dan Willemsen676abdc2016-09-28 19:42:22 -0700466 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
467 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700468
Dan Willemsen676abdc2016-09-28 19:42:22 -0700469 enum LibraryStyle {
470 LIBRARY_STYLE_REGULAR,
471 LIBRARY_STYLE_STATIC,
472 LIBRARY_STYLE_END,
473 };
Andreas Huberd2943e12016-08-05 11:59:31 -0700474
Andreas Huber1c507272016-10-05 14:33:21 -0700475 for (int style = LIBRARY_STYLE_REGULAR;
476 (packageIsJavaCompatible && style != LIBRARY_STYLE_END);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700477 ++style) {
478 const std::string staticSuffix =
479 (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700480
Dan Willemsen676abdc2016-09-28 19:42:22 -0700481 out << "\n"
482 << "########################################"
483 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700484
Dan Willemsen676abdc2016-09-28 19:42:22 -0700485 out << "include $(CLEAR_VARS)\n"
486 << "LOCAL_MODULE := "
487 << libraryName
488 << "-java"
489 << staticSuffix
490 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
491 << "intermediates := $(local-generated-sources-dir)\n\n"
492 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
493 << hidl_gen
494 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700495
Dan Willemsen676abdc2016-09-28 19:42:22 -0700496 if (!importedPackages.empty()) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700497 out << "\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700498 << "\nLOCAL_"
Andreas Huber782d45e2016-09-22 13:25:14 -0700499 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
Dan Willemsen676abdc2016-09-28 19:42:22 -0700500 << "JAVA_LIBRARIES := \\";
501
502 out.indent();
503 for (const auto &importedPackage : importedPackages) {
504 out << "\n"
505 << makeLibraryName(importedPackage)
506 << "-java"
507 << staticSuffix
508 << " \\";
509 }
510 out << "\n";
511 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700512 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700513
514 generateMakefileSection(
515 out,
516 coordinator,
517 packageFQName,
518 packageInterfaces,
519 typesAST);
520
521 out << "\ninclude $(BUILD_"
522 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
523 << "JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700524 }
525
Andreas Huber1c507272016-10-05 14:33:21 -0700526 if (haveJavaConstants) {
527 out << "\n"
528 << "########################################"
529 << "########################################\n\n";
530
531 out << "include $(CLEAR_VARS)\n"
532 << "LOCAL_MODULE := "
533 << libraryName
534 << "-java-constants"
535 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
536 << "intermediates := $(local-generated-sources-dir)\n\n"
537 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
538 << hidl_gen
539 << "$(HOST_EXECUTABLE_SUFFIX)";
540
541 generateMakefileSectionForJavaConstants(
542 out, coordinator, packageFQName, packageInterfaces);
543
544 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
545 << "-> framework.jar\n"
546 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
547 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
548 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
549 }
550
Iliyan Malchev8be09552016-09-22 16:20:33 -0700551 out << "\n\n"
552 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
553
Andreas Huberd2943e12016-08-05 11:59:31 -0700554 return OK;
555}
556
Andreas Huber0fa9e392016-08-31 09:05:44 -0700557OutputHandler::ValRes validateForMakefile(
558 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700559 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700560 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700561 return OutputHandler::FAILED;
562 }
563
564 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700565 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700566 return OutputHandler::FAILED;
567 }
568
569 if (!fqName.name().empty()) {
570 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700571 "ERROR: Expecting only package name and version.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700572 return OutputHandler::FAILED;
573 }
574
575 return OutputHandler::PASS_PACKAGE;
576}
577
Dan Willemsen676abdc2016-09-28 19:42:22 -0700578static void generateAndroidBpGenSection(
579 Formatter &out,
580 const FQName &packageFQName,
581 const char *hidl_gen,
582 Coordinator *coordinator,
583 const std::string &genName,
584 const char *language,
585 const std::vector<FQName> &packageInterfaces,
586 const std::function<void(Formatter&, const FQName)> outputFn) {
587
588 out << "genrule {\n";
589 out.indent();
590 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700591 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700592
Colin Crossd5419bd2016-11-04 15:05:54 -0700593 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700594 << " -L" << language
595 << " -r"
Yifan Hongc8934042016-11-17 17:10:52 -0800596 << coordinator->getPackageRootOption(packageFQName)
597 << " -r"
598 << coordinator->getPackageRootOption(gIBasePackageFqName)
Dan Willemsen676abdc2016-09-28 19:42:22 -0700599 << " " << packageFQName.string() << "\",\n";
600
601 out << "srcs: [\n";
602 out.indent();
603 for (const auto &fqName : packageInterfaces) {
604 out << "\"" << fqName.name() << ".hal\",\n";
605 }
606 out.unindent();
607 out << "],\n";
608
609 out << "out: [\n";
610 out.indent();
611 for (const auto &fqName : packageInterfaces) {
612 outputFn(out, fqName);
613 }
614 out.unindent();
615 out << "],\n";
616
617 out.unindent();
618 out << "}\n\n";
619}
620
621static status_t generateAndroidBpForPackage(
622 const FQName &packageFQName,
623 const char *hidl_gen,
624 Coordinator *coordinator,
625 const std::string &) {
626
627 CHECK(packageFQName.isValid() &&
628 !packageFQName.isFullyQualified() &&
629 packageFQName.name().empty());
630
631 std::vector<FQName> packageInterfaces;
632
633 status_t err =
634 coordinator->appendPackageInterfacesToVector(packageFQName,
635 &packageInterfaces);
636
637 if (err != OK) {
638 return err;
639 }
640
641 std::set<FQName> importedPackages;
642 AST *typesAST = nullptr;
643
644 for (const auto &fqName : packageInterfaces) {
645 AST *ast = coordinator->parse(fqName);
646
647 if (ast == NULL) {
648 fprintf(stderr,
649 "ERROR: Could not parse %s. Aborting.\n",
650 fqName.string().c_str());
651
652 return UNKNOWN_ERROR;
653 }
654
655 if (fqName.name() == "types") {
656 typesAST = ast;
657 }
658
659 ast->getImportedPackages(&importedPackages);
660 }
661
662 std::string path =
663 coordinator->getPackagePath(packageFQName, false /* relative */);
664
665 path.append("Android.bp");
666
667 CHECK(Coordinator::MakeParentHierarchy(path));
668 FILE *file = fopen(path.c_str(), "w");
669
670 if (file == NULL) {
671 return -errno;
672 }
673
674 const std::string libraryName = makeLibraryName(packageFQName);
675 const std::string genSourceName = libraryName + "_genc++";
676 const std::string genHeaderName = libraryName + "_genc++_headers";
677 const std::string pathPrefix =
678 coordinator->convertPackageRootToPath(packageFQName) +
679 coordinator->getPackagePath(packageFQName, true /* relative */);
680
681 Formatter out(file);
682
683 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
684
685 // Rule to generate the C++ source files
686 generateAndroidBpGenSection(
687 out,
688 packageFQName,
689 hidl_gen,
690 coordinator,
691 genSourceName,
692 "c++",
693 packageInterfaces,
694 [&pathPrefix](Formatter &out, const FQName &fqName) {
695 if (fqName.name() == "types") {
696 out << "\"" << pathPrefix << "types.cpp\",\n";
697 } else {
698 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
699 }
700 });
701
702 // Rule to generate the C++ header files
703 generateAndroidBpGenSection(
704 out,
705 packageFQName,
706 hidl_gen,
707 coordinator,
708 genHeaderName,
709 "c++",
710 packageInterfaces,
711 [&pathPrefix](Formatter &out, const FQName &fqName) {
712 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
713 if (fqName.name() != "types") {
714 out << "\"" << pathPrefix << "IHw" << fqName.name().substr(1) << ".h\",\n";
715 out << "\"" << pathPrefix << "Bn" << fqName.name().substr(1) << ".h\",\n";
716 out << "\"" << pathPrefix << "Bp" << fqName.name().substr(1) << ".h\",\n";
717 out << "\"" << pathPrefix << "Bs" << fqName.name().substr(1) << ".h\",\n";
718 }
719 });
720
721 // C++ library definition
722 out << "cc_library_shared {\n";
723 out.indent();
724 out << "name: \"" << libraryName << "\",\n"
725 << "generated_sources: [\"" << genSourceName << "\"],\n"
726 << "generated_headers: [\"" << genHeaderName << "\"],\n"
727 << "export_generated_headers: [\"" << genHeaderName << "\"],\n"
728 << "shared_libs: [\n";
729
730 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -0800731 out << "\"libhidlbase\",\n"
732 << "\"libhidltransport\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700733 << "\"libhwbinder\",\n"
Steven Moreland05cd4232016-11-21 16:01:12 -0800734 << "\"liblog\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700735 << "\"libutils\",\n"
736 << "\"libcutils\",\n";
737 for (const auto &importedPackage : importedPackages) {
738 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
739 }
740 out.unindent();
741
742 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -0700743
744 out << "export_shared_lib_headers: [\n";
745 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -0800746 out << "\"libhidlbase\",\n"
747 << "\"libhidltransport\",\n"
Steven Morelandb8a26c02016-10-21 13:40:14 -0700748 << "\"libhwbinder\",\n"
Steven Moreland865243c2016-11-01 13:05:24 -0700749 << "\"libutils\",\n";
Yifan Hongc1f9b8d2016-11-07 14:35:44 -0800750 for (const auto &importedPackage : importedPackages) {
751 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
752 }
Steven Moreland865243c2016-11-01 13:05:24 -0700753 out.unindent();
754 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -0700755 out.unindent();
756
Dan Willemsen676abdc2016-09-28 19:42:22 -0700757 out << "}\n";
758
759 return OK;
760}
761
Yifan Hong958ee462016-12-06 17:09:51 -0800762static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -0700763 const FQName &packageFQName,
764 const char *,
765 Coordinator *coordinator,
766 const std::string &outputDir) {
767
Iliyan Malchev4923f932016-09-09 13:04:59 -0700768 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -0700769
770 std::vector<FQName> packageInterfaces;
771
772 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700773 coordinator->appendPackageInterfacesToVector(packageFQName,
774 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -0700775
776 if (err != OK) {
777 return err;
778 }
779
780 std::set<FQName> importedPackages;
781
782 for (const auto &fqName : packageInterfaces) {
783 AST *ast = coordinator->parse(fqName);
784
785 if (ast == NULL) {
786 fprintf(stderr,
787 "ERROR: Could not parse %s. Aborting.\n",
788 fqName.string().c_str());
789
790 return UNKNOWN_ERROR;
791 }
792
793 ast->getImportedPackages(&importedPackages);
794 }
795
796 std::string path = outputDir + "Android.mk";
797
798 CHECK(Coordinator::MakeParentHierarchy(path));
799 FILE *file = fopen(path.c_str(), "w");
800
801 if (file == NULL) {
802 return -errno;
803 }
804
805 Formatter out(file);
806
Yifan Hong958ee462016-12-06 17:09:51 -0800807 out << "cc_library_shared {\n";
808 out.indentBlock([&] {
809 out << "name: \"" << libraryName << "\",\n"
810 << "relative_install_path: \"hw\",\n"
811 << "srcs: [\n";
812 out.indentBlock([&] {
813 for (const auto &fqName : packageInterfaces) {
814 if (fqName.name() == "types") {
815 continue;
816 }
817 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
818 }
819 });
820 out << "],\n"
821 << "shared_libs: [\n";
822 out.indentBlock([&] {
823 out << "\"libhidlbase\",\n"
824 << "\"libhidltransport\",\n"
825 << "\"libhwbinder\",\n"
826 << "\"libutils\",\n"
827 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -0700828
Yifan Hong958ee462016-12-06 17:09:51 -0800829 for (const auto &importedPackage : importedPackages) {
830 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
831 }
832 });
833 out << "],\n";
834 });
835 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -0700836
837 return OK;
838}
839
Andreas Huber0fa9e392016-08-31 09:05:44 -0700840OutputHandler::ValRes validateForSource(
841 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700842 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700843 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700844 return OutputHandler::FAILED;
845 }
846
847 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700848 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700849 return OutputHandler::FAILED;
850 }
851
Andreas Huber0fa9e392016-08-31 09:05:44 -0700852 const std::string &name = fqName.name();
853 if (!name.empty()) {
854 if (name.find('.') == std::string::npos) {
855 return OutputHandler::PASS_FULL;
856 }
857
858 if (language != "java" || name.find("types.") != 0) {
859 // When generating java sources for "types.hal", output can be
860 // constrained to just one of the top-level types declared
861 // by using the extended syntax
862 // android.hardware.Foo@1.0::types.TopLevelTypeName.
863 // In all other cases (different language, not 'types') the dot
864 // notation in the name is illegal in this context.
865 return OutputHandler::FAILED;
866 }
867
868 return OutputHandler::PASS_FULL;
869 }
870
871 return OutputHandler::PASS_PACKAGE;
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700872}
873
Andreas Huber019d21d2016-10-03 12:59:47 -0700874OutputHandler::ValRes validateForExportHeader(
875 const FQName &fqName, const std::string & /* language */) {
876 if (fqName.package().empty()) {
877 fprintf(stderr, "ERROR: Expecting package name\n");
878 return OutputHandler::FAILED;
879 }
880
881 if (fqName.version().empty()) {
882 fprintf(stderr, "ERROR: Expecting package version\n");
883 return OutputHandler::FAILED;
884 }
885
886 if (!fqName.name().empty()) {
887 fprintf(stderr,
888 "ERROR: Expecting only package name and version.\n");
889 return OutputHandler::FAILED;
890 }
891
892 return OutputHandler::PASS_PACKAGE;
893}
894
895
896static status_t generateExportHeaderForPackage(
897 const FQName &packageFQName,
898 const char * /* hidl_gen */,
899 Coordinator *coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -0700900 const std::string &outputPath,
901 bool forJava) {
Andreas Huber019d21d2016-10-03 12:59:47 -0700902
903 CHECK(packageFQName.isValid()
904 && !packageFQName.isFullyQualified()
905 && packageFQName.name().empty());
906
907 std::vector<FQName> packageInterfaces;
908
909 status_t err = coordinator->appendPackageInterfacesToVector(
910 packageFQName, &packageInterfaces);
911
912 if (err != OK) {
913 return err;
914 }
915
916 std::vector<const Type *> exportedTypes;
917
918 for (const auto &fqName : packageInterfaces) {
919 AST *ast = coordinator->parse(fqName);
920
921 if (ast == NULL) {
922 fprintf(stderr,
923 "ERROR: Could not parse %s. Aborting.\n",
924 fqName.string().c_str());
925
926 return UNKNOWN_ERROR;
927 }
928
929 ast->appendToExportedTypesVector(&exportedTypes);
930 }
931
932 if (exportedTypes.empty()) {
933 return OK;
934 }
935
Andreas Huber1c507272016-10-05 14:33:21 -0700936 std::string path = outputPath;
937
938 if (forJava) {
939 path.append(coordinator->convertPackageRootToPath(packageFQName));
940
941 path.append(coordinator->getPackagePath(
942 packageFQName, true /* relative */));
943
944 path.append("Constants.java");
945 }
946
947 CHECK(Coordinator::MakeParentHierarchy(path));
948 FILE *file = fopen(path.c_str(), "w");
Andreas Huber019d21d2016-10-03 12:59:47 -0700949
950 if (file == nullptr) {
951 return -errno;
952 }
953
954 Formatter out(file);
955
956 out << "// This file is autogenerated by hidl-gen. Do not edit manually."
957 "\n\n";
958
Andreas Huber1c507272016-10-05 14:33:21 -0700959 std::string guard;
960 if (forJava) {
961 out << "package " << packageFQName.javaPackage() << ";\n\n";
962 out << "public class Constants {\n";
963 out.indent();
964 } else {
965 guard = "HIDL_GENERATED_";
966 guard += packageFQName.tokenName();
967 guard += "_";
968 guard += "EXPORTED_CONSTANTS_H_";
Andreas Huber019d21d2016-10-03 12:59:47 -0700969
Andreas Huber1c507272016-10-05 14:33:21 -0700970 out << "#ifndef "
971 << guard
972 << "\n#define "
973 << guard
974 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -0700975 }
976
Andreas Huber1c507272016-10-05 14:33:21 -0700977 for (const auto &type : exportedTypes) {
978 type->emitExportedHeader(out, forJava);
979 }
980
981 if (forJava) {
982 out.unindent();
983 out << "}\n";
984 } else {
985 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
986 << guard
987 << "\n";
988 }
Andreas Huber019d21d2016-10-03 12:59:47 -0700989
990 return OK;
991}
992
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700993static std::vector<OutputHandler> formats = {
994 {"c++",
Andreas Huber019d21d2016-10-03 12:59:47 -0700995 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700996 validateForSource,
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700997 [](const FQName &fqName,
998 const char *hidl_gen, Coordinator *coordinator,
999 const std::string &outputDir) -> status_t {
1000 if (fqName.isFullyQualified()) {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001001 return generateSourcesForFile(fqName,
1002 hidl_gen,
1003 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001004 outputDir,
1005 "c++");
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001006 } else {
1007 return generateSourcesForPackage(fqName,
1008 hidl_gen,
1009 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001010 outputDir,
1011 "c++");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001012 }
1013 }
1014 },
1015
Andreas Huber019d21d2016-10-03 12:59:47 -07001016 {"export-header",
1017 OutputHandler::NEEDS_FILE /* mOutputMode */,
1018 validateForExportHeader,
1019 [](const FQName &fqName,
1020 const char *hidl_gen,
1021 Coordinator *coordinator,
1022 const std::string &outputPath) -> status_t {
1023 CHECK(!fqName.isFullyQualified());
1024
1025 return generateExportHeaderForPackage(
1026 fqName,
1027 hidl_gen,
1028 coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001029 outputPath,
1030 false /* forJava */);
Andreas Huber019d21d2016-10-03 12:59:47 -07001031 }
1032 },
1033
Steven Moreland9c387612016-09-07 09:54:26 -07001034 {"c++-impl",
Andreas Huber019d21d2016-10-03 12:59:47 -07001035 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001036 validateForSource,
1037 [](const FQName &fqName,
1038 const char *hidl_gen, Coordinator *coordinator,
1039 const std::string &outputDir) -> status_t {
1040 if (fqName.isFullyQualified()) {
1041 return generateSourcesForFile(fqName,
1042 hidl_gen,
1043 coordinator,
1044 outputDir, "c++-impl");
1045 } else {
1046 return generateSourcesForPackage(fqName,
1047 hidl_gen,
1048 coordinator,
1049 outputDir, "c++-impl");
1050 }
1051 }
1052 },
1053
1054
Andreas Huber2831d512016-08-15 09:33:47 -07001055 {"java",
Andreas Huber019d21d2016-10-03 12:59:47 -07001056 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001057 validateForSource,
Andreas Huber2831d512016-08-15 09:33:47 -07001058 [](const FQName &fqName,
1059 const char *hidl_gen, Coordinator *coordinator,
1060 const std::string &outputDir) -> status_t {
1061 if (fqName.isFullyQualified()) {
1062 return generateSourcesForFile(fqName,
1063 hidl_gen,
1064 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001065 outputDir,
1066 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001067 }
1068 else {
1069 return generateSourcesForPackage(fqName,
1070 hidl_gen,
1071 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001072 outputDir,
1073 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001074 }
1075 }
1076 },
1077
Andreas Huber1c507272016-10-05 14:33:21 -07001078 {"java-constants",
1079 OutputHandler::NEEDS_DIR /* mOutputMode */,
1080 validateForExportHeader,
1081 [](const FQName &fqName,
1082 const char *hidl_gen, Coordinator *coordinator,
1083 const std::string &outputDir) -> status_t {
1084 CHECK(!fqName.isFullyQualified());
1085 return generateExportHeaderForPackage(
1086 fqName,
1087 hidl_gen,
1088 coordinator,
1089 outputDir,
1090 true /* forJava */);
1091 }
1092 },
1093
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001094 {"vts",
Andreas Huber019d21d2016-10-03 12:59:47 -07001095 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001096 validateForSource,
1097 [](const FQName &fqName,
1098 const char * hidl_gen,
1099 Coordinator *coordinator,
1100 const std::string &outputDir) -> status_t {
1101 if (fqName.isFullyQualified()) {
1102 return generateSourcesForFile(fqName,
1103 hidl_gen,
1104 coordinator,
1105 outputDir, "vts");
1106 } else {
1107 return generateSourcesForPackage(fqName,
1108 hidl_gen,
1109 coordinator,
1110 outputDir, "vts");
1111 }
1112 }
1113 },
1114
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001115 {"makefile",
Andreas Huber019d21d2016-10-03 12:59:47 -07001116 OutputHandler::NOT_NEEDED /* mOutputMode */,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001117 validateForMakefile,
1118 generateMakefileForPackage,
1119 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001120
Dan Willemsen676abdc2016-09-28 19:42:22 -07001121 {"androidbp",
Andreas Huber019d21d2016-10-03 12:59:47 -07001122 OutputHandler::NOT_NEEDED /* mOutputMode */,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001123 validateForMakefile,
1124 generateAndroidBpForPackage,
1125 },
1126
Yifan Hong958ee462016-12-06 17:09:51 -08001127 {"androidbp-impl",
Yifan Hong94bcea02016-10-06 13:51:31 -07001128 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland197d56c2016-09-09 10:03:58 -07001129 validateForMakefile,
Yifan Hong958ee462016-12-06 17:09:51 -08001130 generateAndroidBpImplForPackage,
Steven Moreland197d56c2016-09-09 10:03:58 -07001131 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001132};
1133
1134static void usage(const char *me) {
1135 fprintf(stderr,
1136 "usage: %s -o output-path -L <language> (-r interface-root)+ fqname+\n",
1137 me);
1138
1139 fprintf(stderr, " -o output path\n");
1140
1141 fprintf(stderr, " -L <language> (one of");
1142 for (auto &e : formats) {
1143 fprintf(stderr, " %s", e.mKey.c_str());
1144 }
1145 fprintf(stderr, ")\n");
1146
1147 fprintf(stderr,
1148 " -r package:path root "
1149 "(e.g., android.hardware:hardware/interfaces)\n");
1150}
1151
Andreas Huberb82318c2016-08-02 14:45:54 -07001152int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001153 std::string outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001154 std::vector<std::string> packageRootPaths;
1155 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001156
Andreas Huber737080b2016-08-02 15:38:04 -07001157 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001158 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001159
Andreas Huberb82318c2016-08-02 14:45:54 -07001160 int res;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001161 while ((res = getopt(argc, argv, "ho:r:L:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001162 switch (res) {
1163 case 'o':
1164 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001165 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001166 break;
1167 }
1168
Andreas Huberdca261f2016-08-04 13:47:51 -07001169 case 'r':
1170 {
1171 std::string val(optarg);
1172 auto index = val.find_first_of(':');
1173 CHECK(index != std::string::npos);
1174
1175 auto package = val.substr(0, index);
1176 auto path = val.substr(index + 1);
1177 packageRootPaths.push_back(path);
1178 packageRoots.push_back(package);
1179 break;
1180 }
1181
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001182 case 'L':
1183 {
Steven Morelande429a262016-11-15 09:54:32 -08001184 CHECK(outputFormat == nullptr) << "Only one -L option allowed.";
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001185 for (auto &e : formats) {
1186 if (e.mKey == optarg) {
1187 outputFormat = &e;
1188 break;
1189 }
1190 }
Steven Morelande429a262016-11-15 09:54:32 -08001191 CHECK(outputFormat != nullptr) << "Output format not recognized.";
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001192 break;
1193 }
1194
Andreas Huberb82318c2016-08-02 14:45:54 -07001195 case '?':
1196 case 'h':
1197 default:
1198 {
Andreas Huber737080b2016-08-02 15:38:04 -07001199 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001200 exit(1);
1201 break;
1202 }
1203 }
1204 }
1205
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001206 if (outputFormat == nullptr) {
1207 usage(me);
1208 exit(1);
1209 }
1210
Andreas Huberb82318c2016-08-02 14:45:54 -07001211 argc -= optind;
1212 argv += optind;
1213
Andreas Huberdca261f2016-08-04 13:47:51 -07001214 if (packageRootPaths.empty()) {
1215 // Pick reasonable defaults.
1216
1217 packageRoots.push_back("android.hardware");
1218
1219 const char *TOP = getenv("TOP");
Steven Morelandaf330382016-11-09 15:48:03 -08001220 if (TOP == nullptr) {
1221 fprintf(stderr,
1222 "ERROR: No root path (-r) specified"
1223 " and $TOP environment variable not set.\n");
1224 exit(1);
1225 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001226
1227 std::string path = TOP;
1228 path.append("/hardware/interfaces");
1229
1230 packageRootPaths.push_back(path);
1231 }
1232
Andreas Huber737080b2016-08-02 15:38:04 -07001233 // Valid options are now in argv[0] .. argv[argc - 1].
1234
Andreas Huber019d21d2016-10-03 12:59:47 -07001235 switch (outputFormat->mOutputMode) {
1236 case OutputHandler::NEEDS_DIR:
1237 case OutputHandler::NEEDS_FILE:
1238 {
1239 if (outputPath.empty()) {
1240 usage(me);
1241 exit(1);
1242 }
1243
1244 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
1245 const size_t len = outputPath.size();
1246 if (outputPath[len - 1] != '/') {
1247 outputPath += "/";
1248 }
1249 }
1250 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001251 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001252
1253 default:
1254 outputPath.clear(); // Unused.
1255 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001256 }
1257
Andreas Huberdca261f2016-08-04 13:47:51 -07001258 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -07001259
Andreas Huber737080b2016-08-02 15:38:04 -07001260 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001261 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001262
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001263 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001264 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001265 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001266 exit(1);
1267 }
Andreas Huber881227d2016-08-02 14:20:21 -07001268
Andreas Huber0fa9e392016-08-31 09:05:44 -07001269 OutputHandler::ValRes valid =
1270 outputFormat->validate(fqName, outputFormat->mKey);
1271
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001272 if (valid == OutputHandler::FAILED) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001273 exit(1);
1274 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001275
1276 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001277 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001278
1279 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001280 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001281 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001282 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001283
Andreas Huberd2943e12016-08-05 11:59:31 -07001284 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001285}