blob: a91c2e20f7441a91a547a5308bfa18ef103e0c94 [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>
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
69 FQName typesName(fqName.package(), fqName.version(), "types");
70 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
Dan Willemsen676abdc2016-09-28 19:42:22 -0700134static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700135 Formatter &out,
136 Coordinator *coordinator,
137 const FQName &packageFQName,
138 const FQName &fqName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700139 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700140 out << "\n"
141 << "\n#"
142 << "\n# Build " << fqName.name() << ".hal";
143
Dan Willemsen676abdc2016-09-28 19:42:22 -0700144 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700145 out << " (" << typeName << ")";
146 }
147
148 out << "\n#"
149 << "\nGEN := $(intermediates)/"
150 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800151 << coordinator->getPackagePath(packageFQName, true /* relative */,
152 true /* sanitized */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700153 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700154 out << fqName.name() << ".java";
155 } else {
156 out << typeName << ".java";
157 }
158
159 out << "\n$(GEN): $(HIDL)";
160 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
161 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
162 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700163
164 {
165 AST *ast = coordinator->parse(fqName);
166 CHECK(ast != nullptr);
167 const std::set<FQName>& refs = ast->getImportedNames();
168 for (auto depFQName : refs) {
169 // If the package of depFQName is the same as this fqName's package,
170 // then add it explicitly as a .hal dependency within the same
171 // package.
172 if (fqName.package() == depFQName.package() &&
173 fqName.version() == depFQName.version()) {
174 // PRIVATE_DEPS is not actually being used in the
175 // auto-generated file, but is necessary if the build rule
176 // ever needs to use the dependency information, since the
177 // built-in Make variables are not supported in the Android
178 // build system.
179 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
180 << depFQName.name() << ".hal";
181 // This is the actual dependency.
182 out << "\n$(GEN): $(LOCAL_PATH)/"
183 << depFQName.name() << ".hal";
184 }
185 }
186 }
187
Andreas Huber0fa9e392016-08-31 09:05:44 -0700188 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
189 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
190 out.indent();
191 out.indent();
192 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Yifan Hongc8934042016-11-17 17:10:52 -0800193 << "\n-Ljava \\"
194 << "\n-r"
195 << coordinator->getPackageRootOption(packageFQName) << " \\"
196 << "\n-r"
197 << coordinator->getPackageRootOption(gIBasePackageFqName) << " \\\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700198
199 out << packageFQName.string()
200 << "::"
201 << fqName.name();
202
Dan Willemsen676abdc2016-09-28 19:42:22 -0700203 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700204 out << "." << typeName;
205 }
206
207 out << "\n";
208
209 out.unindent();
210 out.unindent();
211
212 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
213 out << "\n\t$(transform-generated-source)";
214 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
215}
216
Dan Willemsen676abdc2016-09-28 19:42:22 -0700217static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700218 Formatter &out,
219 Coordinator *coordinator,
220 const FQName &packageFQName,
221 const std::vector<FQName> &packageInterfaces,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700222 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700223 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700224 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700225 CHECK(typesAST != nullptr);
226
227 Scope *rootScope = typesAST->scope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700228
Andreas Huberb747bd92016-09-26 15:55:31 -0700229 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
230 std::sort(
231 subTypes.begin(),
232 subTypes.end(),
233 [](const NamedType *a, const NamedType *b) -> bool {
234 return a->fqName() < b->fqName();
235 });
236
237 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700238 if (type->isTypeDef()) {
239 continue;
240 }
241
Dan Willemsen676abdc2016-09-28 19:42:22 -0700242 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700243 out,
244 coordinator,
245 packageFQName,
246 fqName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700247 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700248 }
249
250 continue;
251 }
252
Dan Willemsen676abdc2016-09-28 19:42:22 -0700253 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700254 out,
255 coordinator,
256 packageFQName,
257 fqName,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700258 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700259 }
260}
261
Andreas Huber75ae95d2016-10-12 16:08:26 -0700262static status_t isPackageJavaCompatible(
263 const FQName &packageFQName,
264 Coordinator *coordinator,
265 bool *compatible) {
266 std::vector<FQName> todo;
267 status_t err =
268 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
269
270 if (err != OK) {
271 return err;
272 }
273
274 std::set<FQName> seen;
275 for (const auto &iface : todo) {
276 seen.insert(iface);
277 }
278
279 // Form the transitive closure of all imported interfaces (and types.hal-s)
280 // If any one of them is not java compatible, this package isn't either.
281 while (!todo.empty()) {
282 const FQName fqName = todo.back();
283 todo.pop_back();
284
285 AST *ast = coordinator->parse(fqName);
286
287 if (ast == nullptr) {
288 return UNKNOWN_ERROR;
289 }
290
291 if (!ast->isJavaCompatible()) {
292 *compatible = false;
293 return OK;
294 }
295
296 std::set<FQName> importedPackages;
297 ast->getImportedPackages(&importedPackages);
298
299 for (const auto &package : importedPackages) {
300 std::vector<FQName> packageInterfaces;
301 status_t err = coordinator->appendPackageInterfacesToVector(
302 package, &packageInterfaces);
303
304 if (err != OK) {
305 return err;
306 }
307
308 for (const auto &iface : packageInterfaces) {
309 if (seen.find(iface) != seen.end()) {
310 continue;
311 }
312
313 todo.push_back(iface);
314 seen.insert(iface);
315 }
316 }
317 }
318
319 *compatible = true;
320 return OK;
321}
322
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700323static bool packageNeedsJavaCode(
324 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
325 // If there is more than just a types.hal file to this package we'll
326 // definitely need to generate Java code.
327 if (packageInterfaces.size() > 1
328 || packageInterfaces[0].name() != "types") {
329 return true;
330 }
331
332 CHECK(typesAST != nullptr);
333
334 // We'll have to generate Java code if types.hal contains any non-typedef
335 // type declarations.
336
337 Scope *rootScope = typesAST->scope();
338 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
339
340 for (const auto &subType : subTypes) {
341 if (!subType->isTypeDef()) {
342 return true;
343 }
344 }
345
346 return false;
347}
348
Andreas Huber1c507272016-10-05 14:33:21 -0700349static void generateMakefileSectionForJavaConstants(
350 Formatter &out,
351 Coordinator *coordinator,
352 const FQName &packageFQName,
353 const std::vector<FQName> &packageInterfaces) {
354 out << "\n#"
355 << "\nGEN := $(intermediates)/"
356 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800357 << coordinator->getPackagePath(packageFQName, true /* relative */, true /* sanitized */)
Andreas Huber1c507272016-10-05 14:33:21 -0700358 << "Constants.java";
359
360 out << "\n$(GEN): $(HIDL)\n";
361 for (const auto &iface : packageInterfaces) {
362 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
363 }
364 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
365 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
366 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
367 out.indent();
368 out.indent();
369 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Yifan Hongc8934042016-11-17 17:10:52 -0800370 << "\n-Ljava-constants \\"
371 << "\n-r"
372 << coordinator->getPackageRootOption(packageFQName) << " \\"
373 << "\n-r"
374 << coordinator->getPackageRootOption(gIBasePackageFqName) << " \\\n";
Andreas Huber1c507272016-10-05 14:33:21 -0700375
376 out << packageFQName.string();
377 out << "\n";
378
379 out.unindent();
380 out.unindent();
381
382 out << "\n$(GEN):";
383 out << "\n\t$(transform-generated-source)";
384 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
385}
386
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700387static status_t generateMakefileForPackage(
388 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700389 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700390 Coordinator *coordinator,
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700391 const std::string &) {
392
393 CHECK(packageFQName.isValid() &&
394 !packageFQName.isFullyQualified() &&
395 packageFQName.name().empty());
396
Andreas Huberd2943e12016-08-05 11:59:31 -0700397 std::vector<FQName> packageInterfaces;
398
399 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700400 coordinator->appendPackageInterfacesToVector(packageFQName,
401 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700402
403 if (err != OK) {
404 return err;
405 }
406
407 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700408 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700409 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700410
Andreas Huberd2943e12016-08-05 11:59:31 -0700411 for (const auto &fqName : packageInterfaces) {
412 AST *ast = coordinator->parse(fqName);
413
414 if (ast == NULL) {
415 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700416 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700417 fqName.string().c_str());
418
419 return UNKNOWN_ERROR;
420 }
421
Andreas Huber0fa9e392016-08-31 09:05:44 -0700422 if (fqName.name() == "types") {
423 typesAST = ast;
424 }
425
Yifan Hong40a373d2016-11-30 15:16:47 -0800426 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700427 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700428 }
429
Andreas Huber75ae95d2016-10-12 16:08:26 -0700430 bool packageIsJavaCompatible;
431 err = isPackageJavaCompatible(
432 packageFQName, coordinator, &packageIsJavaCompatible);
433
434 if (err != OK) {
435 return err;
436 }
437
Andreas Huber1c507272016-10-05 14:33:21 -0700438 bool haveJavaConstants = !exportedTypes.empty();
439
440 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800441 // TODO(b/33420795)
442 fprintf(stderr,
443 "WARNING: %s is not java compatible. No java makefile created.\n",
444 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700445 return OK;
446 }
447
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700448 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
449 return OK;
450 }
451
Andreas Huberd2943e12016-08-05 11:59:31 -0700452 std::string path =
453 coordinator->getPackagePath(packageFQName, false /* relative */);
454
455 path.append("Android.mk");
456
457 CHECK(Coordinator::MakeParentHierarchy(path));
458 FILE *file = fopen(path.c_str(), "w");
459
460 if (file == NULL) {
461 return -errno;
462 }
463
464 const std::string libraryName = makeLibraryName(packageFQName);
465
466 Formatter out(file);
467
Dan Willemsen676abdc2016-09-28 19:42:22 -0700468 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
469 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700470
Dan Willemsen676abdc2016-09-28 19:42:22 -0700471 enum LibraryStyle {
472 LIBRARY_STYLE_REGULAR,
473 LIBRARY_STYLE_STATIC,
474 LIBRARY_STYLE_END,
475 };
Andreas Huberd2943e12016-08-05 11:59:31 -0700476
Andreas Huber1c507272016-10-05 14:33:21 -0700477 for (int style = LIBRARY_STYLE_REGULAR;
478 (packageIsJavaCompatible && style != LIBRARY_STYLE_END);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700479 ++style) {
480 const std::string staticSuffix =
481 (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700482
Dan Willemsen676abdc2016-09-28 19:42:22 -0700483 out << "\n"
484 << "########################################"
485 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700486
Dan Willemsen676abdc2016-09-28 19:42:22 -0700487 out << "include $(CLEAR_VARS)\n"
488 << "LOCAL_MODULE := "
489 << libraryName
490 << "-java"
491 << staticSuffix
492 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
493 << "intermediates := $(local-generated-sources-dir)\n\n"
494 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
495 << hidl_gen
496 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700497
Dan Willemsen676abdc2016-09-28 19:42:22 -0700498 if (!importedPackages.empty()) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700499 out << "\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700500 << "\nLOCAL_"
Andreas Huber782d45e2016-09-22 13:25:14 -0700501 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
Dan Willemsen676abdc2016-09-28 19:42:22 -0700502 << "JAVA_LIBRARIES := \\";
503
504 out.indent();
505 for (const auto &importedPackage : importedPackages) {
506 out << "\n"
507 << makeLibraryName(importedPackage)
508 << "-java"
509 << staticSuffix
510 << " \\";
511 }
512 out << "\n";
513 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700514 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700515
516 generateMakefileSection(
517 out,
518 coordinator,
519 packageFQName,
520 packageInterfaces,
521 typesAST);
522
523 out << "\ninclude $(BUILD_"
524 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
525 << "JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700526 }
527
Andreas Huber1c507272016-10-05 14:33:21 -0700528 if (haveJavaConstants) {
529 out << "\n"
530 << "########################################"
531 << "########################################\n\n";
532
533 out << "include $(CLEAR_VARS)\n"
534 << "LOCAL_MODULE := "
535 << libraryName
536 << "-java-constants"
537 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
538 << "intermediates := $(local-generated-sources-dir)\n\n"
539 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
540 << hidl_gen
541 << "$(HOST_EXECUTABLE_SUFFIX)";
542
543 generateMakefileSectionForJavaConstants(
544 out, coordinator, packageFQName, packageInterfaces);
545
546 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
547 << "-> framework.jar\n"
548 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
549 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
550 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
551 }
552
Iliyan Malchev8be09552016-09-22 16:20:33 -0700553 out << "\n\n"
554 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
555
Andreas Huberd2943e12016-08-05 11:59:31 -0700556 return OK;
557}
558
Andreas Huber0fa9e392016-08-31 09:05:44 -0700559OutputHandler::ValRes validateForMakefile(
560 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700561 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700562 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700563 return OutputHandler::FAILED;
564 }
565
566 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700567 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700568 return OutputHandler::FAILED;
569 }
570
571 if (!fqName.name().empty()) {
572 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700573 "ERROR: Expecting only package name and version.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700574 return OutputHandler::FAILED;
575 }
576
577 return OutputHandler::PASS_PACKAGE;
578}
579
Dan Willemsen676abdc2016-09-28 19:42:22 -0700580static void generateAndroidBpGenSection(
581 Formatter &out,
582 const FQName &packageFQName,
583 const char *hidl_gen,
584 Coordinator *coordinator,
585 const std::string &genName,
586 const char *language,
587 const std::vector<FQName> &packageInterfaces,
588 const std::function<void(Formatter&, const FQName)> outputFn) {
589
590 out << "genrule {\n";
591 out.indent();
592 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700593 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700594
Colin Crossd5419bd2016-11-04 15:05:54 -0700595 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700596 << " -L" << language
597 << " -r"
Yifan Hongc8934042016-11-17 17:10:52 -0800598 << coordinator->getPackageRootOption(packageFQName)
599 << " -r"
600 << coordinator->getPackageRootOption(gIBasePackageFqName)
Dan Willemsen676abdc2016-09-28 19:42:22 -0700601 << " " << packageFQName.string() << "\",\n";
602
603 out << "srcs: [\n";
604 out.indent();
605 for (const auto &fqName : packageInterfaces) {
606 out << "\"" << fqName.name() << ".hal\",\n";
607 }
608 out.unindent();
609 out << "],\n";
610
611 out << "out: [\n";
612 out.indent();
613 for (const auto &fqName : packageInterfaces) {
614 outputFn(out, fqName);
615 }
616 out.unindent();
617 out << "],\n";
618
619 out.unindent();
620 out << "}\n\n";
621}
622
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800623static void generateAndroidBpVtsGenSection(
624 Formatter &out,
625 const FQName &packageFQName,
626 const char *hidl_gen,
627 const char *vtsc,
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800628 const std::string &vtsc_mode,
629 const std::string &vtsc_type,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800630 Coordinator *coordinator,
631 const std::string &genName,
632 const char *language,
633 const std::vector<FQName> &packageInterfaces,
634 const std::function<void(Formatter&, const FQName)> outputFn) {
635 out << "genrule {\n";
636 out.indent();
637 out << "name: \"" << genName << "\",\n"
638 << "tools: [\"" << hidl_gen << "\", \"" << vtsc << "\"],\n";
639
640 std::string package_dir_path = packageFQName.string().substr(
641 0, packageFQName.string().find("@"));
642 replace(package_dir_path.begin(), package_dir_path.end(), '.', '/');
643 package_dir_path += "/" + packageFQName.string().substr(
644 packageFQName.string().find("@") + 1);
645 if (package_dir_path.c_str()[package_dir_path.length() - 1] != '/') {
646 package_dir_path += "/";
647 }
648
649 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
650 << " -L" << language
651 << " -r"
652 << coordinator->getPackageRootOption(packageFQName)
653 << " -r"
654 << coordinator->getPackageRootOption(gIBasePackageFqName)
655 << " " << packageFQName.string()
656 << " && $(location vtsc) -m" << vtsc_mode << " -t" << vtsc_type
657 << " -b$(genDir) " << package_dir_path
658 << " $(genDir)/" << package_dir_path
659 << "\",\n";
660
661 out << "srcs: [\n";
662 out.indent();
663 for (const auto &fqName : packageInterfaces) {
664 out << "\"" << fqName.name() << ".hal\",\n";
665 }
666 out.unindent();
667 out << "],\n";
668
669 out << "out: [\n";
670 out.indent();
671 for (const auto &fqName : packageInterfaces) {
672 outputFn(out, fqName);
673 }
674 out.unindent();
675 out << "],\n";
676
677 out.unindent();
678 out << "}\n\n";
679}
680
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800681static status_t generateAndroidBpForVtsPackage(
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800682 Formatter& out,
683 const std::set<FQName>& importedPackages,
684 std::vector<FQName>& packageInterfaces,
685 const FQName &packageFQName,
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800686 const std::string &libraryName,
687 const std::string &vtsCompileMode,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800688 const char *hidl_gen,
689 Coordinator *coordinator) {
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800690 const std::string genSourceName = libraryName + "_genc++";
691 const std::string genHeaderName = libraryName + "_genc++_headers";
692 const std::string pathPrefix =
693 coordinator->convertPackageRootToPath(packageFQName) +
694 coordinator->getPackagePath(packageFQName, true /* relative */);
695 const char *vtsc = "vtsc";
696
697 out << "\n";
698
699 // Rule to generate the C++ source files
700 generateAndroidBpVtsGenSection(
701 out,
702 packageFQName,
703 hidl_gen,
704 vtsc,
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800705 vtsCompileMode,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800706 "SOURCE",
707 coordinator,
708 genSourceName,
709 "vts",
710 packageInterfaces,
711 [&pathPrefix](Formatter &out, const FQName &fqName) {
712 if (fqName.name() == "types") {
713 out << "\"" << pathPrefix << "types.vts.cpp\",\n";
714 } else {
715 out << "\"" << pathPrefix << fqName.name().substr(1) << ".vts.cpp\",\n";
716 }
717 });
718
719 // Rule to generate the C++ header files
720 generateAndroidBpVtsGenSection(
721 out,
722 packageFQName,
723 hidl_gen,
724 vtsc,
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800725 vtsCompileMode,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800726 "HEADER",
727 coordinator,
728 genHeaderName,
729 "vts",
730 packageInterfaces,
731 [&pathPrefix](Formatter &out, const FQName &fqName) {
732 if (fqName.name() == "types") {
733 out << "\"" << pathPrefix << "types.vts.h\",\n";
734 } else {
735 out << "\"" << pathPrefix << fqName.name().substr(1) << ".vts.h\",\n";
736 }
737 });
738
739 // C++ library definition
740 out << "cc_library_shared {\n";
741 out.indent();
742 out << "name: \"" << libraryName << "\",\n"
743 << "generated_sources: [\"" << genSourceName << "\"],\n"
744 << "generated_headers: [\"" << genHeaderName << "\"],\n"
745 << "export_generated_headers: [\"" << genHeaderName << "\"],\n"
746 << "shared_libs: [\n";
747
748 out.indent();
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800749 if (vtsCompileMode =="DRIVER") {
750 out << "\"libhidlbase\",\n"
751 << "\"libhidltransport\",\n"
752 << "\"libhwbinder\",\n"
753 << "\"liblog\",\n"
754 << "\"libutils\",\n"
755 << "\"libcutils\",\n"
756 << "\"libvts_common\",\n"
757 << "\"libvts_datatype\",\n"
758 << "\"libvts_measurement\",\n"
759 << "\"libvts_multidevice_proto\",\n"
760 << "\"libcamera_metadata\",\n"
761 << "\"libprotobuf-cpp-full\",\n";
762 } else if (vtsCompileMode == "PROFILER") {
763 out << "\"libbase\",\n"
764 << "\"libhidlbase\",\n"
765 << "\"libhidltransport\",\n"
766 << "\"libvts_profiling\",\n"
767 << "\"libvts_multidevice_proto\",\n"
768 << "\"libprotobuf-cpp-full\",\n";
769 } else {
770 fprintf(stderr,
771 "ERROR: Unknow vts compile mode: %s. Aborting.\n",
772 vtsCompileMode.c_str());
773 return UNKNOWN_ERROR;
774 }
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800775 for (const auto &importedPackage : importedPackages) {
776 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
777 }
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800778 out << "\"" << makeLibraryName(packageFQName) << "\",\n";
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800779 out.unindent();
780
781 out << "],\n";
782
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800783 if (vtsCompileMode == "DRIVER") {
784 out << "export_shared_lib_headers: [\n";
785 out.indent();
786 out << "\"libhidlbase\",\n"
787 << "\"libhidltransport\",\n"
788 << "\"libhwbinder\",\n"
789 << "\"libutils\",\n";
790 for (const auto &importedPackage : importedPackages) {
791 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
792 }
793 out.unindent();
794 out << "],\n";
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800795 }
796 out.unindent();
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800797 out << "}\n";
798
799 return OK;
800}
801
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800802static status_t generateAndroidBpForVtsDriverPackage(
803 Formatter& out,
804 const std::set<FQName>& importedPackages,
805 std::vector<FQName>& packageInterfaces,
806 const FQName &packageFQName,
807 const char *hidl_gen,
808 Coordinator *coordinator) {
809 const std::string targetLibraryName = makeLibraryName(packageFQName);
810 const std::string libraryName = targetLibraryName.substr(
811 0, targetLibraryName.find_last_of("@")) + ".vts.driver" +
812 targetLibraryName.substr(targetLibraryName.find_last_of("@"));
813 return generateAndroidBpForVtsPackage(out, importedPackages,
814 packageInterfaces,
815 packageFQName,
816 libraryName,
817 "DRIVER", hidl_gen,
818 coordinator);
819}
820
821static status_t generateAndroidBpForVtsProfilerPackage(
822 Formatter& out,
823 const std::set<FQName>& importedPackages,
824 std::vector<FQName>& packageInterfaces,
825 const FQName &packageFQName,
826 const char *hidl_gen,
827 Coordinator *coordinator) {
828 std::vector<std::vector<FQName>> interfacesForProfiler;
829 bool hasTypesInterface = false;
830 FQName typesInterface;
831 // Split interfaces except for the types interface.
832 for (const auto &fqName : packageInterfaces) {
833 if (fqName.name() == "types") {
834 hasTypesInterface = true;
835 typesInterface = fqName;
836 } else {
837 std::vector<FQName> interfaces;
838 interfaces.push_back(fqName);
839 interfacesForProfiler.push_back(interfaces);
840 }
841 }
842 // Generate profiler library for each interface.
843 for (auto interfaces : interfacesForProfiler) {
844 if (hasTypesInterface) {
845 interfaces.push_back(typesInterface);
846 }
847 const std::string targetLibraryName = makeLibraryName(packageFQName);
848 const std::string libraryName = targetLibraryName + "-"
849 + interfaces[0].name() + "-vts.profiler";
850 status_t status = generateAndroidBpForVtsPackage(out, importedPackages,
851 interfaces,
852 packageFQName,
853 libraryName,
854 "PROFILER", hidl_gen,
855 coordinator);
856 if (status != OK) {
857 return status;
858 }
859 }
860 return OK;
861}
862
Dan Willemsen676abdc2016-09-28 19:42:22 -0700863static status_t generateAndroidBpForPackage(
864 const FQName &packageFQName,
865 const char *hidl_gen,
866 Coordinator *coordinator,
867 const std::string &) {
868
869 CHECK(packageFQName.isValid() &&
870 !packageFQName.isFullyQualified() &&
871 packageFQName.name().empty());
872
873 std::vector<FQName> packageInterfaces;
874
875 status_t err =
876 coordinator->appendPackageInterfacesToVector(packageFQName,
877 &packageInterfaces);
878
879 if (err != OK) {
880 return err;
881 }
882
883 std::set<FQName> importedPackages;
884 AST *typesAST = nullptr;
885
886 for (const auto &fqName : packageInterfaces) {
887 AST *ast = coordinator->parse(fqName);
888
889 if (ast == NULL) {
890 fprintf(stderr,
891 "ERROR: Could not parse %s. Aborting.\n",
892 fqName.string().c_str());
893
894 return UNKNOWN_ERROR;
895 }
896
897 if (fqName.name() == "types") {
898 typesAST = ast;
899 }
900
901 ast->getImportedPackages(&importedPackages);
902 }
903
904 std::string path =
905 coordinator->getPackagePath(packageFQName, false /* relative */);
906
907 path.append("Android.bp");
908
909 CHECK(Coordinator::MakeParentHierarchy(path));
910 FILE *file = fopen(path.c_str(), "w");
911
912 if (file == NULL) {
913 return -errno;
914 }
915
916 const std::string libraryName = makeLibraryName(packageFQName);
917 const std::string genSourceName = libraryName + "_genc++";
918 const std::string genHeaderName = libraryName + "_genc++_headers";
919 const std::string pathPrefix =
920 coordinator->convertPackageRootToPath(packageFQName) +
921 coordinator->getPackagePath(packageFQName, true /* relative */);
922
923 Formatter out(file);
924
925 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
926
927 // Rule to generate the C++ source files
928 generateAndroidBpGenSection(
929 out,
930 packageFQName,
931 hidl_gen,
932 coordinator,
933 genSourceName,
934 "c++",
935 packageInterfaces,
936 [&pathPrefix](Formatter &out, const FQName &fqName) {
937 if (fqName.name() == "types") {
938 out << "\"" << pathPrefix << "types.cpp\",\n";
939 } else {
940 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
941 }
942 });
943
944 // Rule to generate the C++ header files
945 generateAndroidBpGenSection(
946 out,
947 packageFQName,
948 hidl_gen,
949 coordinator,
950 genHeaderName,
951 "c++",
952 packageInterfaces,
953 [&pathPrefix](Formatter &out, const FQName &fqName) {
954 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
955 if (fqName.name() != "types") {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800956 out << "\"" << pathPrefix << fqName.getInterfaceHwName() << ".h\",\n";
957 out << "\"" << pathPrefix << fqName.getInterfaceStubName() << ".h\",\n";
958 out << "\"" << pathPrefix << fqName.getInterfaceProxyName() << ".h\",\n";
959 out << "\"" << pathPrefix << fqName.getInterfacePassthroughName() << ".h\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700960 }
961 });
962
963 // C++ library definition
964 out << "cc_library_shared {\n";
965 out.indent();
966 out << "name: \"" << libraryName << "\",\n"
967 << "generated_sources: [\"" << genSourceName << "\"],\n"
968 << "generated_headers: [\"" << genHeaderName << "\"],\n"
969 << "export_generated_headers: [\"" << genHeaderName << "\"],\n"
970 << "shared_libs: [\n";
971
972 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -0800973 out << "\"libhidlbase\",\n"
974 << "\"libhidltransport\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700975 << "\"libhwbinder\",\n"
Steven Moreland05cd4232016-11-21 16:01:12 -0800976 << "\"liblog\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700977 << "\"libutils\",\n"
978 << "\"libcutils\",\n";
979 for (const auto &importedPackage : importedPackages) {
980 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
981 }
982 out.unindent();
983
984 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -0700985
986 out << "export_shared_lib_headers: [\n";
987 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -0800988 out << "\"libhidlbase\",\n"
989 << "\"libhidltransport\",\n"
Steven Morelandb8a26c02016-10-21 13:40:14 -0700990 << "\"libhwbinder\",\n"
Steven Moreland865243c2016-11-01 13:05:24 -0700991 << "\"libutils\",\n";
Yifan Hongc1f9b8d2016-11-07 14:35:44 -0800992 for (const auto &importedPackage : importedPackages) {
993 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
994 }
Steven Moreland865243c2016-11-01 13:05:24 -0700995 out.unindent();
996 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -0700997 out.unindent();
998
Dan Willemsen676abdc2016-09-28 19:42:22 -0700999 out << "}\n";
1000
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -08001001 // For VTS driver
1002 // TODO(yim): b/31930023 remove below check when all HAL's driver
1003 // and profiler are auto-generated.
Keun Soo Yim442aa3d2016-12-16 13:05:32 -08001004 if (packageFQName.string() != "android.hardware.nfc@1.0"
1005 && packageFQName.string() != "android.hardware.vibrator@1.0"
1006 && packageFQName.string() != "android.hardware.light@2.0"
1007 && packageFQName.string() != "android.hardware.thermal@1.0"
1008 && packageFQName.string() != "android.hardware.vr@1.0"
1009 && packageFQName.string() != "android.hardware.vehicle@2.0"
1010 && packageFQName.string() != "android.hardware.boot@1.0"
1011 && packageFQName.string() != "android.hardware.input@1.0"
1012 && packageFQName.string() != "android.hardware.power@1.0"
1013 && packageFQName.string() != "android.hardware.tv.cec@1.0"
Yuexi Ma8867ba92016-12-21 13:45:28 -08001014 && packageFQName.string() != "android.hardware.tv.input@1.0"
Keun Soo Yim442aa3d2016-12-16 13:05:32 -08001015 && packageFQName.string() != "android.hardware.memtrack@1.0"
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -08001016 && packageFQName.string() != "android.hardware.sensors@1.0") {
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -08001017 fprintf(stderr,
Steven Morelanda6466052016-12-21 13:17:29 -08001018 "WARNING: %s does not yet have auto-generated VTS driver & profiler.\n",
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -08001019 packageFQName.string().c_str());
1020 return OK;
1021 }
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -08001022 // Generate Driver package.
1023 status_t status = generateAndroidBpForVtsDriverPackage(out,
1024 importedPackages,
1025 packageInterfaces,
1026 packageFQName,
1027 hidl_gen,
1028 coordinator);
1029 if (status != OK) {
1030 return status;
1031 }
1032 // Generate Profiler packages.
1033 status = generateAndroidBpForVtsProfilerPackage(out,
1034 importedPackages,
1035 packageInterfaces,
1036 packageFQName,
1037 hidl_gen,
1038 coordinator);
1039 if (status != OK) {
1040 return status;
1041 }
1042 return OK;
Dan Willemsen676abdc2016-09-28 19:42:22 -07001043}
1044
Yifan Hong958ee462016-12-06 17:09:51 -08001045static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -07001046 const FQName &packageFQName,
1047 const char *,
1048 Coordinator *coordinator,
1049 const std::string &outputDir) {
1050
Iliyan Malchev4923f932016-09-09 13:04:59 -07001051 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -07001052
1053 std::vector<FQName> packageInterfaces;
1054
1055 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -07001056 coordinator->appendPackageInterfacesToVector(packageFQName,
1057 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -07001058
1059 if (err != OK) {
1060 return err;
1061 }
1062
1063 std::set<FQName> importedPackages;
1064
1065 for (const auto &fqName : packageInterfaces) {
1066 AST *ast = coordinator->parse(fqName);
1067
1068 if (ast == NULL) {
1069 fprintf(stderr,
1070 "ERROR: Could not parse %s. Aborting.\n",
1071 fqName.string().c_str());
1072
1073 return UNKNOWN_ERROR;
1074 }
1075
1076 ast->getImportedPackages(&importedPackages);
1077 }
1078
Yifan Hongaafed702016-12-14 12:59:47 -08001079 std::string path = outputDir + "Android.bp";
Steven Moreland197d56c2016-09-09 10:03:58 -07001080
1081 CHECK(Coordinator::MakeParentHierarchy(path));
1082 FILE *file = fopen(path.c_str(), "w");
1083
1084 if (file == NULL) {
1085 return -errno;
1086 }
1087
1088 Formatter out(file);
1089
Yifan Hong958ee462016-12-06 17:09:51 -08001090 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001091 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -08001092 out << "name: \"" << libraryName << "\",\n"
1093 << "relative_install_path: \"hw\",\n"
1094 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001095 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -08001096 for (const auto &fqName : packageInterfaces) {
1097 if (fqName.name() == "types") {
1098 continue;
1099 }
1100 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
1101 }
1102 });
1103 out << "],\n"
1104 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001105 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -08001106 out << "\"libhidlbase\",\n"
1107 << "\"libhidltransport\",\n"
1108 << "\"libhwbinder\",\n"
1109 << "\"libutils\",\n"
1110 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -07001111
Yifan Hong958ee462016-12-06 17:09:51 -08001112 for (const auto &importedPackage : importedPackages) {
1113 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
1114 }
1115 });
1116 out << "],\n";
1117 });
1118 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -07001119
1120 return OK;
1121}
1122
Andreas Huber0fa9e392016-08-31 09:05:44 -07001123OutputHandler::ValRes validateForSource(
1124 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001125 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -07001126 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001127 return OutputHandler::FAILED;
1128 }
1129
1130 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -07001131 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001132 return OutputHandler::FAILED;
1133 }
1134
Andreas Huber0fa9e392016-08-31 09:05:44 -07001135 const std::string &name = fqName.name();
1136 if (!name.empty()) {
1137 if (name.find('.') == std::string::npos) {
1138 return OutputHandler::PASS_FULL;
1139 }
1140
1141 if (language != "java" || name.find("types.") != 0) {
1142 // When generating java sources for "types.hal", output can be
1143 // constrained to just one of the top-level types declared
1144 // by using the extended syntax
1145 // android.hardware.Foo@1.0::types.TopLevelTypeName.
1146 // In all other cases (different language, not 'types') the dot
1147 // notation in the name is illegal in this context.
1148 return OutputHandler::FAILED;
1149 }
1150
1151 return OutputHandler::PASS_FULL;
1152 }
1153
1154 return OutputHandler::PASS_PACKAGE;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001155}
1156
Andreas Huber019d21d2016-10-03 12:59:47 -07001157OutputHandler::ValRes validateForExportHeader(
1158 const FQName &fqName, const std::string & /* language */) {
1159 if (fqName.package().empty()) {
1160 fprintf(stderr, "ERROR: Expecting package name\n");
1161 return OutputHandler::FAILED;
1162 }
1163
1164 if (fqName.version().empty()) {
1165 fprintf(stderr, "ERROR: Expecting package version\n");
1166 return OutputHandler::FAILED;
1167 }
1168
1169 if (!fqName.name().empty()) {
1170 fprintf(stderr,
1171 "ERROR: Expecting only package name and version.\n");
1172 return OutputHandler::FAILED;
1173 }
1174
1175 return OutputHandler::PASS_PACKAGE;
1176}
1177
1178
1179static status_t generateExportHeaderForPackage(
1180 const FQName &packageFQName,
1181 const char * /* hidl_gen */,
1182 Coordinator *coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001183 const std::string &outputPath,
1184 bool forJava) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001185
1186 CHECK(packageFQName.isValid()
1187 && !packageFQName.isFullyQualified()
1188 && packageFQName.name().empty());
1189
1190 std::vector<FQName> packageInterfaces;
1191
1192 status_t err = coordinator->appendPackageInterfacesToVector(
1193 packageFQName, &packageInterfaces);
1194
1195 if (err != OK) {
1196 return err;
1197 }
1198
1199 std::vector<const Type *> exportedTypes;
1200
1201 for (const auto &fqName : packageInterfaces) {
1202 AST *ast = coordinator->parse(fqName);
1203
1204 if (ast == NULL) {
1205 fprintf(stderr,
1206 "ERROR: Could not parse %s. Aborting.\n",
1207 fqName.string().c_str());
1208
1209 return UNKNOWN_ERROR;
1210 }
1211
1212 ast->appendToExportedTypesVector(&exportedTypes);
1213 }
1214
1215 if (exportedTypes.empty()) {
1216 return OK;
1217 }
1218
Andreas Huber1c507272016-10-05 14:33:21 -07001219 std::string path = outputPath;
1220
1221 if (forJava) {
1222 path.append(coordinator->convertPackageRootToPath(packageFQName));
1223
1224 path.append(coordinator->getPackagePath(
Yifan Hong97288ac2016-12-12 16:03:51 -08001225 packageFQName, true /* relative */, true /* sanitized */));
Andreas Huber1c507272016-10-05 14:33:21 -07001226
1227 path.append("Constants.java");
1228 }
1229
1230 CHECK(Coordinator::MakeParentHierarchy(path));
1231 FILE *file = fopen(path.c_str(), "w");
Andreas Huber019d21d2016-10-03 12:59:47 -07001232
1233 if (file == nullptr) {
1234 return -errno;
1235 }
1236
1237 Formatter out(file);
1238
Steven Morelandd177b122016-12-12 09:15:37 -08001239 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
1240 << "// Source: " << packageFQName.string() << "\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001241
Andreas Huber1c507272016-10-05 14:33:21 -07001242 std::string guard;
1243 if (forJava) {
1244 out << "package " << packageFQName.javaPackage() << ";\n\n";
1245 out << "public class Constants {\n";
1246 out.indent();
1247 } else {
1248 guard = "HIDL_GENERATED_";
Steven Morelandd177b122016-12-12 09:15:37 -08001249 guard += StringHelper::Uppercase(packageFQName.tokenName());
Andreas Huber1c507272016-10-05 14:33:21 -07001250 guard += "_";
1251 guard += "EXPORTED_CONSTANTS_H_";
Andreas Huber019d21d2016-10-03 12:59:47 -07001252
Andreas Huber1c507272016-10-05 14:33:21 -07001253 out << "#ifndef "
1254 << guard
1255 << "\n#define "
1256 << guard
1257 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001258 }
1259
Andreas Huber1c507272016-10-05 14:33:21 -07001260 for (const auto &type : exportedTypes) {
1261 type->emitExportedHeader(out, forJava);
1262 }
1263
1264 if (forJava) {
1265 out.unindent();
1266 out << "}\n";
1267 } else {
1268 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
1269 << guard
1270 << "\n";
1271 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001272
1273 return OK;
1274}
1275
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001276static std::vector<OutputHandler> formats = {
1277 {"c++",
Andreas Huber019d21d2016-10-03 12:59:47 -07001278 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001279 validateForSource,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001280 [](const FQName &fqName,
1281 const char *hidl_gen, Coordinator *coordinator,
1282 const std::string &outputDir) -> status_t {
1283 if (fqName.isFullyQualified()) {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001284 return generateSourcesForFile(fqName,
1285 hidl_gen,
1286 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001287 outputDir,
1288 "c++");
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001289 } else {
1290 return generateSourcesForPackage(fqName,
1291 hidl_gen,
1292 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001293 outputDir,
1294 "c++");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001295 }
1296 }
1297 },
1298
Andreas Huber019d21d2016-10-03 12:59:47 -07001299 {"export-header",
1300 OutputHandler::NEEDS_FILE /* mOutputMode */,
1301 validateForExportHeader,
1302 [](const FQName &fqName,
1303 const char *hidl_gen,
1304 Coordinator *coordinator,
1305 const std::string &outputPath) -> status_t {
1306 CHECK(!fqName.isFullyQualified());
1307
1308 return generateExportHeaderForPackage(
1309 fqName,
1310 hidl_gen,
1311 coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001312 outputPath,
1313 false /* forJava */);
Andreas Huber019d21d2016-10-03 12:59:47 -07001314 }
1315 },
1316
Steven Moreland9c387612016-09-07 09:54:26 -07001317 {"c++-impl",
Andreas Huber019d21d2016-10-03 12:59:47 -07001318 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001319 validateForSource,
1320 [](const FQName &fqName,
1321 const char *hidl_gen, Coordinator *coordinator,
1322 const std::string &outputDir) -> status_t {
1323 if (fqName.isFullyQualified()) {
1324 return generateSourcesForFile(fqName,
1325 hidl_gen,
1326 coordinator,
1327 outputDir, "c++-impl");
1328 } else {
1329 return generateSourcesForPackage(fqName,
1330 hidl_gen,
1331 coordinator,
1332 outputDir, "c++-impl");
1333 }
1334 }
1335 },
1336
1337
Andreas Huber2831d512016-08-15 09:33:47 -07001338 {"java",
Andreas Huber019d21d2016-10-03 12:59:47 -07001339 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001340 validateForSource,
Andreas Huber2831d512016-08-15 09:33:47 -07001341 [](const FQName &fqName,
1342 const char *hidl_gen, Coordinator *coordinator,
1343 const std::string &outputDir) -> status_t {
1344 if (fqName.isFullyQualified()) {
1345 return generateSourcesForFile(fqName,
1346 hidl_gen,
1347 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001348 outputDir,
1349 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001350 }
1351 else {
1352 return generateSourcesForPackage(fqName,
1353 hidl_gen,
1354 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001355 outputDir,
1356 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001357 }
1358 }
1359 },
1360
Andreas Huber1c507272016-10-05 14:33:21 -07001361 {"java-constants",
1362 OutputHandler::NEEDS_DIR /* mOutputMode */,
1363 validateForExportHeader,
1364 [](const FQName &fqName,
1365 const char *hidl_gen, Coordinator *coordinator,
1366 const std::string &outputDir) -> status_t {
1367 CHECK(!fqName.isFullyQualified());
1368 return generateExportHeaderForPackage(
1369 fqName,
1370 hidl_gen,
1371 coordinator,
1372 outputDir,
1373 true /* forJava */);
1374 }
1375 },
1376
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001377 {"vts",
Andreas Huber019d21d2016-10-03 12:59:47 -07001378 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001379 validateForSource,
1380 [](const FQName &fqName,
1381 const char * hidl_gen,
1382 Coordinator *coordinator,
1383 const std::string &outputDir) -> status_t {
1384 if (fqName.isFullyQualified()) {
1385 return generateSourcesForFile(fqName,
1386 hidl_gen,
1387 coordinator,
1388 outputDir, "vts");
1389 } else {
1390 return generateSourcesForPackage(fqName,
1391 hidl_gen,
1392 coordinator,
1393 outputDir, "vts");
1394 }
1395 }
1396 },
1397
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001398 {"makefile",
Andreas Huber019d21d2016-10-03 12:59:47 -07001399 OutputHandler::NOT_NEEDED /* mOutputMode */,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001400 validateForMakefile,
1401 generateMakefileForPackage,
1402 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001403
Dan Willemsen676abdc2016-09-28 19:42:22 -07001404 {"androidbp",
Andreas Huber019d21d2016-10-03 12:59:47 -07001405 OutputHandler::NOT_NEEDED /* mOutputMode */,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001406 validateForMakefile,
1407 generateAndroidBpForPackage,
1408 },
1409
Yifan Hong958ee462016-12-06 17:09:51 -08001410 {"androidbp-impl",
Yifan Hong94bcea02016-10-06 13:51:31 -07001411 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland197d56c2016-09-09 10:03:58 -07001412 validateForMakefile,
Yifan Hong958ee462016-12-06 17:09:51 -08001413 generateAndroidBpImplForPackage,
Steven Moreland197d56c2016-09-09 10:03:58 -07001414 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001415};
1416
1417static void usage(const char *me) {
1418 fprintf(stderr,
1419 "usage: %s -o output-path -L <language> (-r interface-root)+ fqname+\n",
1420 me);
1421
1422 fprintf(stderr, " -o output path\n");
1423
1424 fprintf(stderr, " -L <language> (one of");
1425 for (auto &e : formats) {
1426 fprintf(stderr, " %s", e.mKey.c_str());
1427 }
1428 fprintf(stderr, ")\n");
1429
1430 fprintf(stderr,
1431 " -r package:path root "
1432 "(e.g., android.hardware:hardware/interfaces)\n");
1433}
1434
Andreas Huberb82318c2016-08-02 14:45:54 -07001435int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001436 std::string outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001437 std::vector<std::string> packageRootPaths;
1438 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001439
Andreas Huber737080b2016-08-02 15:38:04 -07001440 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001441 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001442
Andreas Huberb82318c2016-08-02 14:45:54 -07001443 int res;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001444 while ((res = getopt(argc, argv, "ho:r:L:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001445 switch (res) {
1446 case 'o':
1447 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001448 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001449 break;
1450 }
1451
Andreas Huberdca261f2016-08-04 13:47:51 -07001452 case 'r':
1453 {
1454 std::string val(optarg);
1455 auto index = val.find_first_of(':');
1456 CHECK(index != std::string::npos);
1457
1458 auto package = val.substr(0, index);
1459 auto path = val.substr(index + 1);
1460 packageRootPaths.push_back(path);
1461 packageRoots.push_back(package);
1462 break;
1463 }
1464
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001465 case 'L':
1466 {
Steven Morelande429a262016-11-15 09:54:32 -08001467 CHECK(outputFormat == nullptr) << "Only one -L option allowed.";
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001468 for (auto &e : formats) {
1469 if (e.mKey == optarg) {
1470 outputFormat = &e;
1471 break;
1472 }
1473 }
Steven Morelande429a262016-11-15 09:54:32 -08001474 CHECK(outputFormat != nullptr) << "Output format not recognized.";
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001475 break;
1476 }
1477
Andreas Huberb82318c2016-08-02 14:45:54 -07001478 case '?':
1479 case 'h':
1480 default:
1481 {
Andreas Huber737080b2016-08-02 15:38:04 -07001482 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001483 exit(1);
1484 break;
1485 }
1486 }
1487 }
1488
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001489 if (outputFormat == nullptr) {
1490 usage(me);
1491 exit(1);
1492 }
1493
Andreas Huberb82318c2016-08-02 14:45:54 -07001494 argc -= optind;
1495 argv += optind;
1496
Andreas Huberdca261f2016-08-04 13:47:51 -07001497 if (packageRootPaths.empty()) {
1498 // Pick reasonable defaults.
1499
1500 packageRoots.push_back("android.hardware");
1501
1502 const char *TOP = getenv("TOP");
Steven Morelandaf330382016-11-09 15:48:03 -08001503 if (TOP == nullptr) {
1504 fprintf(stderr,
1505 "ERROR: No root path (-r) specified"
1506 " and $TOP environment variable not set.\n");
1507 exit(1);
1508 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001509
1510 std::string path = TOP;
1511 path.append("/hardware/interfaces");
1512
1513 packageRootPaths.push_back(path);
1514 }
1515
Andreas Huber737080b2016-08-02 15:38:04 -07001516 // Valid options are now in argv[0] .. argv[argc - 1].
1517
Andreas Huber019d21d2016-10-03 12:59:47 -07001518 switch (outputFormat->mOutputMode) {
1519 case OutputHandler::NEEDS_DIR:
1520 case OutputHandler::NEEDS_FILE:
1521 {
1522 if (outputPath.empty()) {
1523 usage(me);
1524 exit(1);
1525 }
1526
1527 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
1528 const size_t len = outputPath.size();
1529 if (outputPath[len - 1] != '/') {
1530 outputPath += "/";
1531 }
1532 }
1533 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001534 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001535
1536 default:
1537 outputPath.clear(); // Unused.
1538 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001539 }
1540
Andreas Huberdca261f2016-08-04 13:47:51 -07001541 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -07001542
Andreas Huber737080b2016-08-02 15:38:04 -07001543 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001544 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001545
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001546 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001547 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001548 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001549 exit(1);
1550 }
Andreas Huber881227d2016-08-02 14:20:21 -07001551
Andreas Huber0fa9e392016-08-31 09:05:44 -07001552 OutputHandler::ValRes valid =
1553 outputFormat->validate(fqName, outputFormat->mKey);
1554
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001555 if (valid == OutputHandler::FAILED) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001556 exit(1);
1557 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001558
1559 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001560 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001561
1562 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001563 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001564 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001565 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001566
Andreas Huberd2943e12016-08-05 11:59:31 -07001567 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001568}