blob: ab6b9ff7f23daf883a17e8d434b8631c34b356b9 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "AST.h"
Andreas Huber5345ec22016-07-29 13:33:27 -070018#include "Coordinator.h"
Andreas Huber0fa9e392016-08-31 09:05:44 -070019#include "Scope.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070020
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070021#include <hidl-util/Formatter.h>
Steven Moreland7ae3d542017-01-18 16:46:01 -080022#include <hidl-util/FQName.h>
Steven Morelandd177b122016-12-12 09:15:37 -080023#include <hidl-util/StringHelper.h>
Andreas Huber68f24592016-07-29 14:53:48 -070024#include <android-base/logging.h>
Iliyan Malchev5bb14022016-08-09 15:04:39 -070025#include <set>
Andreas Huberc9410c72016-07-28 12:18:40 -070026#include <stdio.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070027#include <string>
Andreas Huberb82318c2016-08-02 14:45:54 -070028#include <unistd.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070029#include <vector>
Andreas Huberc9410c72016-07-28 12:18:40 -070030
31using namespace android;
32
Iliyan Malchev5bb14022016-08-09 15:04:39 -070033struct OutputHandler {
34 std::string mKey;
Andreas Huber019d21d2016-10-03 12:59:47 -070035 enum OutputMode {
36 NEEDS_DIR,
37 NEEDS_FILE,
38 NOT_NEEDED
39 } mOutputMode;
40
Iliyan Malchev5bb14022016-08-09 15:04:39 -070041 enum ValRes {
42 FAILED,
43 PASS_PACKAGE,
44 PASS_FULL
45 };
Andreas Huber0fa9e392016-08-31 09:05:44 -070046 ValRes (*validate)(const FQName &, const std::string &language);
Iliyan Malchev5bb14022016-08-09 15:04:39 -070047 status_t (*generate)(const FQName &fqName,
48 const char *hidl_gen,
49 Coordinator *coordinator,
50 const std::string &outputDir);
51};
Andreas Huberdca261f2016-08-04 13:47:51 -070052
Iliyan Malchev5bb14022016-08-09 15:04:39 -070053static status_t generateSourcesForFile(
54 const FQName &fqName,
55 const char *,
56 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -070057 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070058 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -070059 CHECK(fqName.isFullyQualified());
60
Andreas Huber0fa9e392016-08-31 09:05:44 -070061 AST *ast;
Andreas Huberd29724f2016-09-14 09:33:13 -070062 std::string limitToType;
Andreas Huber0fa9e392016-08-31 09:05:44 -070063
64 if (fqName.name().find("types.") == 0) {
65 CHECK(lang == "java"); // Already verified in validate().
66
Andreas Huberd29724f2016-09-14 09:33:13 -070067 limitToType = fqName.name().substr(strlen("types."));
Andreas Huber0fa9e392016-08-31 09:05:44 -070068
Yifan Hongfece6ec2017-01-12 17:04:04 -080069 FQName typesName = fqName.getTypesForPackage();
Andreas Huber0fa9e392016-08-31 09:05:44 -070070 ast = coordinator->parse(typesName);
71 } else {
72 ast = coordinator->parse(fqName);
73 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -070074
75 if (ast == NULL) {
76 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -070077 "ERROR: Could not parse %s. Aborting.\n",
Iliyan Malchev5bb14022016-08-09 15:04:39 -070078 fqName.string().c_str());
79
80 return UNKNOWN_ERROR;
81 }
82
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070083 if (lang == "c++") {
84 return ast->generateCpp(outputDir);
85 }
Steven Moreland9c387612016-09-07 09:54:26 -070086 if (lang == "c++-impl") {
87 return ast->generateCppImpl(outputDir);
88 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070089 if (lang == "java") {
Andreas Huber0fa9e392016-08-31 09:05:44 -070090 return ast->generateJava(outputDir, limitToType);
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070091 }
92 if (lang == "vts") {
93 return ast->generateVts(outputDir);
94 }
95 // Unknown language.
96 return UNKNOWN_ERROR;
Iliyan Malchev5bb14022016-08-09 15:04:39 -070097}
98
99static status_t generateSourcesForPackage(
100 const FQName &packageFQName,
101 const char *hidl_gen,
102 Coordinator *coordinator,
Andreas Huber2831d512016-08-15 09:33:47 -0700103 const std::string &outputDir,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700104 const std::string &lang) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700105 CHECK(packageFQName.isValid() &&
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700106 !packageFQName.isFullyQualified() &&
107 packageFQName.name().empty());
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700108
109 std::vector<FQName> packageInterfaces;
110
111 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700112 coordinator->appendPackageInterfacesToVector(packageFQName,
113 &packageInterfaces);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700114
115 if (err != OK) {
116 return err;
117 }
118
119 for (const auto &fqName : packageInterfaces) {
Andreas Huber2831d512016-08-15 09:33:47 -0700120 err = generateSourcesForFile(
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700121 fqName, hidl_gen, coordinator, outputDir, lang);
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700122 if (err != OK) {
123 return err;
124 }
125 }
126
127 return OK;
Andreas Huberb82318c2016-08-02 14:45:54 -0700128}
129
Andreas Huberd2943e12016-08-05 11:59:31 -0700130static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -0700131 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -0700132}
133
Steven Moreland5715fed2017-01-16 11:06:47 -0800134static void generatePackagePathsSection(
135 Formatter &out,
136 Coordinator *coordinator,
137 const FQName &packageFQName,
138 const std::set<FQName> &importedPackages,
139 bool forMakefiles = false) {
140 std::set<std::string> options{};
141 for (const auto &interface : importedPackages) {
142 options.insert(coordinator->getPackageRootOption(interface));
143 }
144 options.insert(coordinator->getPackageRootOption(packageFQName));
145 options.insert(coordinator->getPackageRootOption(gIBasePackageFqName));
146 for (const auto &option : options) {
147 out << "-r"
148 << option
149 << " ";
150 if (forMakefiles) {
151 out << "\\\n";
152 }
153 }
154}
155
Dan Willemsen676abdc2016-09-28 19:42:22 -0700156static void generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700157 Formatter &out,
158 Coordinator *coordinator,
159 const FQName &packageFQName,
160 const FQName &fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800161 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700162 const char *typeName) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700163 out << "\n"
164 << "\n#"
165 << "\n# Build " << fqName.name() << ".hal";
166
Dan Willemsen676abdc2016-09-28 19:42:22 -0700167 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700168 out << " (" << typeName << ")";
169 }
170
171 out << "\n#"
172 << "\nGEN := $(intermediates)/"
173 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800174 << coordinator->getPackagePath(packageFQName, true /* relative */,
175 true /* sanitized */);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700176 if (typeName == nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700177 out << fqName.name() << ".java";
178 } else {
179 out << typeName << ".java";
180 }
181
182 out << "\n$(GEN): $(HIDL)";
183 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
184 out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
185 << fqName.name() << ".hal";
Iliyan Malchevb9819132016-09-07 12:38:31 -0700186
187 {
188 AST *ast = coordinator->parse(fqName);
189 CHECK(ast != nullptr);
190 const std::set<FQName>& refs = ast->getImportedNames();
191 for (auto depFQName : refs) {
192 // If the package of depFQName is the same as this fqName's package,
193 // then add it explicitly as a .hal dependency within the same
194 // package.
195 if (fqName.package() == depFQName.package() &&
196 fqName.version() == depFQName.version()) {
197 // PRIVATE_DEPS is not actually being used in the
198 // auto-generated file, but is necessary if the build rule
199 // ever needs to use the dependency information, since the
200 // built-in Make variables are not supported in the Android
201 // build system.
202 out << "\n$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/"
203 << depFQName.name() << ".hal";
204 // This is the actual dependency.
205 out << "\n$(GEN): $(LOCAL_PATH)/"
206 << depFQName.name() << ".hal";
207 }
208 }
209 }
210
Andreas Huber0fa9e392016-08-31 09:05:44 -0700211 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
212 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
213 out.indent();
214 out.indent();
215 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800216 << "\n-Ljava \\\n";
217
218 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700219
220 out << packageFQName.string()
221 << "::"
222 << fqName.name();
223
Dan Willemsen676abdc2016-09-28 19:42:22 -0700224 if (typeName != nullptr) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700225 out << "." << typeName;
226 }
227
228 out << "\n";
229
230 out.unindent();
231 out.unindent();
232
233 out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
234 out << "\n\t$(transform-generated-source)";
235 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
236}
237
Dan Willemsen676abdc2016-09-28 19:42:22 -0700238static void generateMakefileSection(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700239 Formatter &out,
240 Coordinator *coordinator,
241 const FQName &packageFQName,
242 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800243 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700244 AST *typesAST) {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700245 for (const auto &fqName : packageInterfaces) {
Dan Willemsen676abdc2016-09-28 19:42:22 -0700246 if (fqName.name() == "types") {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700247 CHECK(typesAST != nullptr);
248
249 Scope *rootScope = typesAST->scope();
Andreas Huber0fa9e392016-08-31 09:05:44 -0700250
Andreas Huberb747bd92016-09-26 15:55:31 -0700251 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
252 std::sort(
253 subTypes.begin(),
254 subTypes.end(),
255 [](const NamedType *a, const NamedType *b) -> bool {
256 return a->fqName() < b->fqName();
257 });
258
259 for (const auto &type : subTypes) {
Andreas Huberdda25cc2016-09-22 10:39:47 -0700260 if (type->isTypeDef()) {
261 continue;
262 }
263
Dan Willemsen676abdc2016-09-28 19:42:22 -0700264 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700265 out,
266 coordinator,
267 packageFQName,
268 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800269 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700270 type->localName().c_str());
Andreas Huber0fa9e392016-08-31 09:05:44 -0700271 }
272
273 continue;
274 }
275
Dan Willemsen676abdc2016-09-28 19:42:22 -0700276 generateMakefileSectionForType(
Andreas Huber0fa9e392016-08-31 09:05:44 -0700277 out,
278 coordinator,
279 packageFQName,
280 fqName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800281 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700282 nullptr /* typeName */);
Andreas Huber0fa9e392016-08-31 09:05:44 -0700283 }
284}
285
Andreas Huber75ae95d2016-10-12 16:08:26 -0700286static status_t isPackageJavaCompatible(
287 const FQName &packageFQName,
288 Coordinator *coordinator,
289 bool *compatible) {
290 std::vector<FQName> todo;
291 status_t err =
292 coordinator->appendPackageInterfacesToVector(packageFQName, &todo);
293
294 if (err != OK) {
295 return err;
296 }
297
298 std::set<FQName> seen;
299 for (const auto &iface : todo) {
300 seen.insert(iface);
301 }
302
303 // Form the transitive closure of all imported interfaces (and types.hal-s)
304 // If any one of them is not java compatible, this package isn't either.
305 while (!todo.empty()) {
306 const FQName fqName = todo.back();
307 todo.pop_back();
308
309 AST *ast = coordinator->parse(fqName);
310
311 if (ast == nullptr) {
312 return UNKNOWN_ERROR;
313 }
314
315 if (!ast->isJavaCompatible()) {
316 *compatible = false;
317 return OK;
318 }
319
320 std::set<FQName> importedPackages;
321 ast->getImportedPackages(&importedPackages);
322
323 for (const auto &package : importedPackages) {
324 std::vector<FQName> packageInterfaces;
325 status_t err = coordinator->appendPackageInterfacesToVector(
326 package, &packageInterfaces);
327
328 if (err != OK) {
329 return err;
330 }
331
332 for (const auto &iface : packageInterfaces) {
333 if (seen.find(iface) != seen.end()) {
334 continue;
335 }
336
337 todo.push_back(iface);
338 seen.insert(iface);
339 }
340 }
341 }
342
343 *compatible = true;
344 return OK;
345}
346
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700347static bool packageNeedsJavaCode(
348 const std::vector<FQName> &packageInterfaces, AST *typesAST) {
349 // If there is more than just a types.hal file to this package we'll
350 // definitely need to generate Java code.
351 if (packageInterfaces.size() > 1
352 || packageInterfaces[0].name() != "types") {
353 return true;
354 }
355
356 CHECK(typesAST != nullptr);
357
358 // We'll have to generate Java code if types.hal contains any non-typedef
359 // type declarations.
360
361 Scope *rootScope = typesAST->scope();
362 std::vector<NamedType *> subTypes = rootScope->getSubTypes();
363
364 for (const auto &subType : subTypes) {
365 if (!subType->isTypeDef()) {
366 return true;
367 }
368 }
369
370 return false;
371}
372
Andreas Huber1c507272016-10-05 14:33:21 -0700373static void generateMakefileSectionForJavaConstants(
374 Formatter &out,
375 Coordinator *coordinator,
376 const FQName &packageFQName,
Steven Moreland5715fed2017-01-16 11:06:47 -0800377 const std::vector<FQName> &packageInterfaces,
378 const std::set<FQName> &importedPackages) {
Andreas Huber1c507272016-10-05 14:33:21 -0700379 out << "\n#"
380 << "\nGEN := $(intermediates)/"
381 << coordinator->convertPackageRootToPath(packageFQName)
Yifan Hong97288ac2016-12-12 16:03:51 -0800382 << coordinator->getPackagePath(packageFQName, true /* relative */, true /* sanitized */)
Andreas Huber1c507272016-10-05 14:33:21 -0700383 << "Constants.java";
384
385 out << "\n$(GEN): $(HIDL)\n";
386 for (const auto &iface : packageInterfaces) {
387 out << "$(GEN): $(LOCAL_PATH)/" << iface.name() << ".hal\n";
388 }
389 out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
390 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
391 << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
392 out.indent();
393 out.indent();
394 out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
Steven Moreland5715fed2017-01-16 11:06:47 -0800395 << "\n-Ljava-constants \\\n";
396
397 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages, true /* forJava */);
Andreas Huber1c507272016-10-05 14:33:21 -0700398
399 out << packageFQName.string();
400 out << "\n";
401
402 out.unindent();
403 out.unindent();
404
405 out << "\n$(GEN):";
406 out << "\n\t$(transform-generated-source)";
407 out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
408}
409
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700410static status_t generateMakefileForPackage(
411 const FQName &packageFQName,
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700412 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -0700413 Coordinator *coordinator,
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700414 const std::string &) {
415
416 CHECK(packageFQName.isValid() &&
417 !packageFQName.isFullyQualified() &&
418 packageFQName.name().empty());
419
Andreas Huberd2943e12016-08-05 11:59:31 -0700420 std::vector<FQName> packageInterfaces;
421
422 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -0700423 coordinator->appendPackageInterfacesToVector(packageFQName,
424 &packageInterfaces);
Andreas Huberd2943e12016-08-05 11:59:31 -0700425
426 if (err != OK) {
427 return err;
428 }
429
430 std::set<FQName> importedPackages;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700431 AST *typesAST = nullptr;
Andreas Huber1c507272016-10-05 14:33:21 -0700432 std::vector<const Type *> exportedTypes;
Andreas Huber0fa9e392016-08-31 09:05:44 -0700433
Andreas Huberd2943e12016-08-05 11:59:31 -0700434 for (const auto &fqName : packageInterfaces) {
435 AST *ast = coordinator->parse(fqName);
436
437 if (ast == NULL) {
438 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700439 "ERROR: Could not parse %s. Aborting.\n",
Andreas Huberd2943e12016-08-05 11:59:31 -0700440 fqName.string().c_str());
441
442 return UNKNOWN_ERROR;
443 }
444
Andreas Huber0fa9e392016-08-31 09:05:44 -0700445 if (fqName.name() == "types") {
446 typesAST = ast;
447 }
448
Yifan Hong40a373d2016-11-30 15:16:47 -0800449 ast->getImportedPackagesHierarchy(&importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700450 ast->appendToExportedTypesVector(&exportedTypes);
Andreas Huberd2943e12016-08-05 11:59:31 -0700451 }
452
Andreas Huber75ae95d2016-10-12 16:08:26 -0700453 bool packageIsJavaCompatible;
454 err = isPackageJavaCompatible(
455 packageFQName, coordinator, &packageIsJavaCompatible);
456
457 if (err != OK) {
458 return err;
459 }
460
Andreas Huber1c507272016-10-05 14:33:21 -0700461 bool haveJavaConstants = !exportedTypes.empty();
462
463 if (!packageIsJavaCompatible && !haveJavaConstants) {
Steven Moreland81979932016-12-07 15:11:06 -0800464 // TODO(b/33420795)
465 fprintf(stderr,
466 "WARNING: %s is not java compatible. No java makefile created.\n",
467 packageFQName.string().c_str());
Dan Willemsen676abdc2016-09-28 19:42:22 -0700468 return OK;
469 }
470
Andreas Huber5a9fe2c2016-10-13 15:31:10 -0700471 if (!packageNeedsJavaCode(packageInterfaces, typesAST)) {
472 return OK;
473 }
474
Andreas Huberd2943e12016-08-05 11:59:31 -0700475 std::string path =
476 coordinator->getPackagePath(packageFQName, false /* relative */);
477
478 path.append("Android.mk");
479
480 CHECK(Coordinator::MakeParentHierarchy(path));
481 FILE *file = fopen(path.c_str(), "w");
482
483 if (file == NULL) {
484 return -errno;
485 }
486
487 const std::string libraryName = makeLibraryName(packageFQName);
488
489 Formatter out(file);
490
Dan Willemsen676abdc2016-09-28 19:42:22 -0700491 out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
492 out << "LOCAL_PATH := $(call my-dir)\n";
Andreas Huberd2943e12016-08-05 11:59:31 -0700493
Dan Willemsen676abdc2016-09-28 19:42:22 -0700494 enum LibraryStyle {
495 LIBRARY_STYLE_REGULAR,
496 LIBRARY_STYLE_STATIC,
497 LIBRARY_STYLE_END,
498 };
Andreas Huberd2943e12016-08-05 11:59:31 -0700499
Andreas Huber1c507272016-10-05 14:33:21 -0700500 for (int style = LIBRARY_STYLE_REGULAR;
501 (packageIsJavaCompatible && style != LIBRARY_STYLE_END);
Dan Willemsen676abdc2016-09-28 19:42:22 -0700502 ++style) {
503 const std::string staticSuffix =
504 (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700505
Dan Willemsen676abdc2016-09-28 19:42:22 -0700506 out << "\n"
507 << "########################################"
508 << "########################################\n\n";
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700509
Dan Willemsen676abdc2016-09-28 19:42:22 -0700510 out << "include $(CLEAR_VARS)\n"
511 << "LOCAL_MODULE := "
512 << libraryName
513 << "-java"
514 << staticSuffix
515 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
516 << "intermediates := $(local-generated-sources-dir)\n\n"
517 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
518 << hidl_gen
519 << "$(HOST_EXECUTABLE_SUFFIX)";
Andreas Huberd2943e12016-08-05 11:59:31 -0700520
Dan Willemsen676abdc2016-09-28 19:42:22 -0700521 if (!importedPackages.empty()) {
Iliyan Malchev800273d2016-09-02 15:25:07 -0700522 out << "\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -0700523 << "\nLOCAL_"
Andreas Huber782d45e2016-09-22 13:25:14 -0700524 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
Dan Willemsen676abdc2016-09-28 19:42:22 -0700525 << "JAVA_LIBRARIES := \\";
526
527 out.indent();
528 for (const auto &importedPackage : importedPackages) {
529 out << "\n"
530 << makeLibraryName(importedPackage)
531 << "-java"
532 << staticSuffix
533 << " \\";
534 }
535 out << "\n";
536 out.unindent();
Iliyan Malchev800273d2016-09-02 15:25:07 -0700537 }
Dan Willemsen676abdc2016-09-28 19:42:22 -0700538
539 generateMakefileSection(
540 out,
541 coordinator,
542 packageFQName,
543 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800544 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700545 typesAST);
546
547 out << "\ninclude $(BUILD_"
548 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
549 << "JAVA_LIBRARY)\n\n";
Andreas Huber0fa9e392016-08-31 09:05:44 -0700550 }
551
Andreas Huber1c507272016-10-05 14:33:21 -0700552 if (haveJavaConstants) {
553 out << "\n"
554 << "########################################"
555 << "########################################\n\n";
556
557 out << "include $(CLEAR_VARS)\n"
558 << "LOCAL_MODULE := "
559 << libraryName
560 << "-java-constants"
561 << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
562 << "intermediates := $(local-generated-sources-dir)\n\n"
563 << "HIDL := $(HOST_OUT_EXECUTABLES)/"
564 << hidl_gen
565 << "$(HOST_EXECUTABLE_SUFFIX)";
566
567 generateMakefileSectionForJavaConstants(
Steven Moreland5715fed2017-01-16 11:06:47 -0800568 out, coordinator, packageFQName, packageInterfaces, importedPackages);
Andreas Huber1c507272016-10-05 14:33:21 -0700569
570 out << "\n# Avoid dependency cycle of framework.jar -> this-library "
571 << "-> framework.jar\n"
572 << "LOCAL_NO_STANDARD_LIBRARIES := true\n"
573 << "LOCAL_JAVA_LIBRARIES := core-oj\n\n"
574 << "include $(BUILD_STATIC_JAVA_LIBRARY)\n\n";
575 }
576
Iliyan Malchev8be09552016-09-22 16:20:33 -0700577 out << "\n\n"
578 << "include $(call all-makefiles-under,$(LOCAL_PATH))\n";
579
Andreas Huberd2943e12016-08-05 11:59:31 -0700580 return OK;
581}
582
Andreas Huber0fa9e392016-08-31 09:05:44 -0700583OutputHandler::ValRes validateForMakefile(
584 const FQName &fqName, const std::string & /* language */) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700585 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700586 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700587 return OutputHandler::FAILED;
588 }
589
590 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700591 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700592 return OutputHandler::FAILED;
593 }
594
595 if (!fqName.name().empty()) {
596 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -0700597 "ERROR: Expecting only package name and version.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -0700598 return OutputHandler::FAILED;
599 }
600
601 return OutputHandler::PASS_PACKAGE;
602}
603
Dan Willemsen676abdc2016-09-28 19:42:22 -0700604static void generateAndroidBpGenSection(
605 Formatter &out,
606 const FQName &packageFQName,
607 const char *hidl_gen,
608 Coordinator *coordinator,
609 const std::string &genName,
610 const char *language,
611 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800612 const std::set<FQName> &importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700613 const std::function<void(Formatter&, const FQName)> outputFn) {
614
615 out << "genrule {\n";
616 out.indent();
617 out << "name: \"" << genName << "\",\n"
Colin Crossd5419bd2016-11-04 15:05:54 -0700618 << "tools: [\"" << hidl_gen << "\"],\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700619
Colin Crossd5419bd2016-11-04 15:05:54 -0700620 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Steven Moreland5715fed2017-01-16 11:06:47 -0800621 << " -L" << language << " ";
622
623 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages);
624
625 out << packageFQName.string() << "\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700626
627 out << "srcs: [\n";
628 out.indent();
629 for (const auto &fqName : packageInterfaces) {
630 out << "\"" << fqName.name() << ".hal\",\n";
631 }
632 out.unindent();
633 out << "],\n";
634
635 out << "out: [\n";
636 out.indent();
637 for (const auto &fqName : packageInterfaces) {
638 outputFn(out, fqName);
639 }
640 out.unindent();
641 out << "],\n";
642
643 out.unindent();
644 out << "}\n\n";
645}
646
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800647static void generateAndroidBpVtsGenSection(
648 Formatter &out,
649 const FQName &packageFQName,
650 const char *hidl_gen,
651 const char *vtsc,
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800652 const std::string &vtsc_mode,
653 const std::string &vtsc_type,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800654 Coordinator *coordinator,
655 const std::string &genName,
656 const char *language,
657 const std::vector<FQName> &packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800658 const std::set<FQName> &importedPackages,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800659 const std::function<void(Formatter&, const FQName)> outputFn) {
660 out << "genrule {\n";
661 out.indent();
662 out << "name: \"" << genName << "\",\n"
663 << "tools: [\"" << hidl_gen << "\", \"" << vtsc << "\"],\n";
664
665 std::string package_dir_path = packageFQName.string().substr(
666 0, packageFQName.string().find("@"));
667 replace(package_dir_path.begin(), package_dir_path.end(), '.', '/');
668 package_dir_path += "/" + packageFQName.string().substr(
669 packageFQName.string().find("@") + 1);
670 if (package_dir_path.c_str()[package_dir_path.length() - 1] != '/') {
671 package_dir_path += "/";
672 }
673
674 out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)"
Steven Moreland5715fed2017-01-16 11:06:47 -0800675 << " -L" << language << " ";
676
677 generatePackagePathsSection(out, coordinator, packageFQName, importedPackages);
678
679 out << packageFQName.string()
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800680 << " && $(location vtsc) -m" << vtsc_mode << " -t" << vtsc_type
681 << " -b$(genDir) " << package_dir_path
682 << " $(genDir)/" << package_dir_path
683 << "\",\n";
684
685 out << "srcs: [\n";
686 out.indent();
687 for (const auto &fqName : packageInterfaces) {
688 out << "\"" << fqName.name() << ".hal\",\n";
689 }
690 out.unindent();
691 out << "],\n";
692
693 out << "out: [\n";
694 out.indent();
695 for (const auto &fqName : packageInterfaces) {
696 outputFn(out, fqName);
697 }
698 out.unindent();
699 out << "],\n";
700
701 out.unindent();
702 out << "}\n\n";
703}
704
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800705static status_t generateAndroidBpForVtsPackage(
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800706 Formatter& out,
707 const std::set<FQName>& importedPackages,
708 std::vector<FQName>& packageInterfaces,
709 const FQName &packageFQName,
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800710 const std::string &libraryName,
711 const std::string &vtsCompileMode,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800712 const char *hidl_gen,
713 Coordinator *coordinator) {
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800714 const std::string genSourceName = libraryName + "_genc++";
715 const std::string genHeaderName = libraryName + "_genc++_headers";
716 const std::string pathPrefix =
717 coordinator->convertPackageRootToPath(packageFQName) +
718 coordinator->getPackagePath(packageFQName, true /* relative */);
719 const char *vtsc = "vtsc";
720
721 out << "\n";
722
723 // Rule to generate the C++ source files
724 generateAndroidBpVtsGenSection(
725 out,
726 packageFQName,
727 hidl_gen,
728 vtsc,
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800729 vtsCompileMode,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800730 "SOURCE",
731 coordinator,
732 genSourceName,
733 "vts",
734 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800735 importedPackages,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800736 [&pathPrefix](Formatter &out, const FQName &fqName) {
737 if (fqName.name() == "types") {
738 out << "\"" << pathPrefix << "types.vts.cpp\",\n";
739 } else {
740 out << "\"" << pathPrefix << fqName.name().substr(1) << ".vts.cpp\",\n";
741 }
742 });
743
744 // Rule to generate the C++ header files
745 generateAndroidBpVtsGenSection(
746 out,
747 packageFQName,
748 hidl_gen,
749 vtsc,
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800750 vtsCompileMode,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800751 "HEADER",
752 coordinator,
753 genHeaderName,
754 "vts",
755 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800756 importedPackages,
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800757 [&pathPrefix](Formatter &out, const FQName &fqName) {
758 if (fqName.name() == "types") {
759 out << "\"" << pathPrefix << "types.vts.h\",\n";
760 } else {
761 out << "\"" << pathPrefix << fqName.name().substr(1) << ".vts.h\",\n";
762 }
763 });
764
765 // C++ library definition
766 out << "cc_library_shared {\n";
767 out.indent();
768 out << "name: \"" << libraryName << "\",\n"
769 << "generated_sources: [\"" << genSourceName << "\"],\n"
770 << "generated_headers: [\"" << genHeaderName << "\"],\n"
771 << "export_generated_headers: [\"" << genHeaderName << "\"],\n"
772 << "shared_libs: [\n";
773
774 out.indent();
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800775 if (vtsCompileMode =="DRIVER") {
776 out << "\"libhidlbase\",\n"
777 << "\"libhidltransport\",\n"
778 << "\"libhwbinder\",\n"
779 << "\"liblog\",\n"
780 << "\"libutils\",\n"
781 << "\"libcutils\",\n"
782 << "\"libvts_common\",\n"
783 << "\"libvts_datatype\",\n"
784 << "\"libvts_measurement\",\n"
785 << "\"libvts_multidevice_proto\",\n"
786 << "\"libcamera_metadata\",\n"
787 << "\"libprotobuf-cpp-full\",\n";
788 } else if (vtsCompileMode == "PROFILER") {
789 out << "\"libbase\",\n"
790 << "\"libhidlbase\",\n"
791 << "\"libhidltransport\",\n"
792 << "\"libvts_profiling\",\n"
793 << "\"libvts_multidevice_proto\",\n"
794 << "\"libprotobuf-cpp-full\",\n";
795 } else {
796 fprintf(stderr,
797 "ERROR: Unknow vts compile mode: %s. Aborting.\n",
798 vtsCompileMode.c_str());
799 return UNKNOWN_ERROR;
800 }
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800801 for (const auto &importedPackage : importedPackages) {
802 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
803 }
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800804 out << "\"" << makeLibraryName(packageFQName) << "\",\n";
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800805 out.unindent();
806
807 out << "],\n";
808
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800809 if (vtsCompileMode == "DRIVER") {
810 out << "export_shared_lib_headers: [\n";
811 out.indent();
812 out << "\"libhidlbase\",\n"
813 << "\"libhidltransport\",\n"
814 << "\"libhwbinder\",\n"
815 << "\"libutils\",\n";
816 for (const auto &importedPackage : importedPackages) {
817 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
818 }
819 out.unindent();
820 out << "],\n";
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800821 }
822 out.unindent();
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -0800823 out << "}\n";
824
825 return OK;
826}
827
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -0800828static status_t generateAndroidBpForVtsDriverPackage(
829 Formatter& out,
830 const std::set<FQName>& importedPackages,
831 std::vector<FQName>& packageInterfaces,
832 const FQName &packageFQName,
833 const char *hidl_gen,
834 Coordinator *coordinator) {
835 const std::string targetLibraryName = makeLibraryName(packageFQName);
836 const std::string libraryName = targetLibraryName.substr(
837 0, targetLibraryName.find_last_of("@")) + ".vts.driver" +
838 targetLibraryName.substr(targetLibraryName.find_last_of("@"));
839 return generateAndroidBpForVtsPackage(out, importedPackages,
840 packageInterfaces,
841 packageFQName,
842 libraryName,
843 "DRIVER", hidl_gen,
844 coordinator);
845}
846
847static status_t generateAndroidBpForVtsProfilerPackage(
848 Formatter& out,
849 const std::set<FQName>& importedPackages,
850 std::vector<FQName>& packageInterfaces,
851 const FQName &packageFQName,
852 const char *hidl_gen,
853 Coordinator *coordinator) {
854 std::vector<std::vector<FQName>> interfacesForProfiler;
855 bool hasTypesInterface = false;
856 FQName typesInterface;
857 // Split interfaces except for the types interface.
858 for (const auto &fqName : packageInterfaces) {
859 if (fqName.name() == "types") {
860 hasTypesInterface = true;
861 typesInterface = fqName;
862 } else {
863 std::vector<FQName> interfaces;
864 interfaces.push_back(fqName);
865 interfacesForProfiler.push_back(interfaces);
866 }
867 }
868 // Generate profiler library for each interface.
869 for (auto interfaces : interfacesForProfiler) {
870 if (hasTypesInterface) {
871 interfaces.push_back(typesInterface);
872 }
873 const std::string targetLibraryName = makeLibraryName(packageFQName);
874 const std::string libraryName = targetLibraryName + "-"
875 + interfaces[0].name() + "-vts.profiler";
876 status_t status = generateAndroidBpForVtsPackage(out, importedPackages,
877 interfaces,
878 packageFQName,
879 libraryName,
880 "PROFILER", hidl_gen,
881 coordinator);
882 if (status != OK) {
883 return status;
884 }
885 }
886 return OK;
887}
888
Dan Willemsen676abdc2016-09-28 19:42:22 -0700889static status_t generateAndroidBpForPackage(
890 const FQName &packageFQName,
891 const char *hidl_gen,
892 Coordinator *coordinator,
893 const std::string &) {
894
895 CHECK(packageFQName.isValid() &&
896 !packageFQName.isFullyQualified() &&
897 packageFQName.name().empty());
898
899 std::vector<FQName> packageInterfaces;
900
901 status_t err =
902 coordinator->appendPackageInterfacesToVector(packageFQName,
903 &packageInterfaces);
904
905 if (err != OK) {
906 return err;
907 }
908
909 std::set<FQName> importedPackages;
910 AST *typesAST = nullptr;
911
912 for (const auto &fqName : packageInterfaces) {
913 AST *ast = coordinator->parse(fqName);
914
915 if (ast == NULL) {
916 fprintf(stderr,
917 "ERROR: Could not parse %s. Aborting.\n",
918 fqName.string().c_str());
919
920 return UNKNOWN_ERROR;
921 }
922
923 if (fqName.name() == "types") {
924 typesAST = ast;
925 }
926
927 ast->getImportedPackages(&importedPackages);
928 }
929
930 std::string path =
931 coordinator->getPackagePath(packageFQName, false /* relative */);
932
933 path.append("Android.bp");
934
935 CHECK(Coordinator::MakeParentHierarchy(path));
936 FILE *file = fopen(path.c_str(), "w");
937
938 if (file == NULL) {
939 return -errno;
940 }
941
942 const std::string libraryName = makeLibraryName(packageFQName);
943 const std::string genSourceName = libraryName + "_genc++";
944 const std::string genHeaderName = libraryName + "_genc++_headers";
945 const std::string pathPrefix =
946 coordinator->convertPackageRootToPath(packageFQName) +
947 coordinator->getPackagePath(packageFQName, true /* relative */);
948
949 Formatter out(file);
950
951 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
952
953 // Rule to generate the C++ source files
954 generateAndroidBpGenSection(
955 out,
956 packageFQName,
957 hidl_gen,
958 coordinator,
959 genSourceName,
960 "c++",
961 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800962 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700963 [&pathPrefix](Formatter &out, const FQName &fqName) {
964 if (fqName.name() == "types") {
965 out << "\"" << pathPrefix << "types.cpp\",\n";
966 } else {
967 out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
968 }
969 });
970
971 // Rule to generate the C++ header files
972 generateAndroidBpGenSection(
973 out,
974 packageFQName,
975 hidl_gen,
976 coordinator,
977 genHeaderName,
978 "c++",
979 packageInterfaces,
Steven Moreland5715fed2017-01-16 11:06:47 -0800980 importedPackages,
Dan Willemsen676abdc2016-09-28 19:42:22 -0700981 [&pathPrefix](Formatter &out, const FQName &fqName) {
982 out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
983 if (fqName.name() != "types") {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800984 out << "\"" << pathPrefix << fqName.getInterfaceHwName() << ".h\",\n";
985 out << "\"" << pathPrefix << fqName.getInterfaceStubName() << ".h\",\n";
986 out << "\"" << pathPrefix << fqName.getInterfaceProxyName() << ".h\",\n";
987 out << "\"" << pathPrefix << fqName.getInterfacePassthroughName() << ".h\",\n";
Dan Willemsen676abdc2016-09-28 19:42:22 -0700988 }
989 });
990
991 // C++ library definition
992 out << "cc_library_shared {\n";
993 out.indent();
994 out << "name: \"" << libraryName << "\",\n"
995 << "generated_sources: [\"" << genSourceName << "\"],\n"
996 << "generated_headers: [\"" << genHeaderName << "\"],\n"
997 << "export_generated_headers: [\"" << genHeaderName << "\"],\n"
998 << "shared_libs: [\n";
999
1000 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -08001001 out << "\"libhidlbase\",\n"
1002 << "\"libhidltransport\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -07001003 << "\"libhwbinder\",\n"
Steven Moreland05cd4232016-11-21 16:01:12 -08001004 << "\"liblog\",\n"
Dan Willemsen676abdc2016-09-28 19:42:22 -07001005 << "\"libutils\",\n"
1006 << "\"libcutils\",\n";
1007 for (const auto &importedPackage : importedPackages) {
1008 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
1009 }
1010 out.unindent();
1011
1012 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -07001013
1014 out << "export_shared_lib_headers: [\n";
1015 out.indent();
Yifan Honga5abe922016-11-16 14:18:37 -08001016 out << "\"libhidlbase\",\n"
1017 << "\"libhidltransport\",\n"
Steven Morelandb8a26c02016-10-21 13:40:14 -07001018 << "\"libhwbinder\",\n"
Steven Moreland865243c2016-11-01 13:05:24 -07001019 << "\"libutils\",\n";
Yifan Hongc1f9b8d2016-11-07 14:35:44 -08001020 for (const auto &importedPackage : importedPackages) {
1021 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
1022 }
Steven Moreland865243c2016-11-01 13:05:24 -07001023 out.unindent();
1024 out << "],\n";
Steven Morelandb8a26c02016-10-21 13:40:14 -07001025 out.unindent();
1026
Dan Willemsen676abdc2016-09-28 19:42:22 -07001027 out << "}\n";
1028
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -08001029 // For VTS driver
1030 // TODO(yim): b/31930023 remove below check when all HAL's driver
1031 // and profiler are auto-generated.
Keun Soo Yim442aa3d2016-12-16 13:05:32 -08001032 if (packageFQName.string() != "android.hardware.nfc@1.0"
1033 && packageFQName.string() != "android.hardware.vibrator@1.0"
1034 && packageFQName.string() != "android.hardware.light@2.0"
1035 && packageFQName.string() != "android.hardware.thermal@1.0"
1036 && packageFQName.string() != "android.hardware.vr@1.0"
1037 && packageFQName.string() != "android.hardware.vehicle@2.0"
1038 && packageFQName.string() != "android.hardware.boot@1.0"
1039 && packageFQName.string() != "android.hardware.input@1.0"
1040 && packageFQName.string() != "android.hardware.power@1.0"
Yuexi Ma518fbf12017-01-13 16:21:37 -08001041 && packageFQName.string() != "android.hardware.radio@1.0"
Keun Soo Yim442aa3d2016-12-16 13:05:32 -08001042 && packageFQName.string() != "android.hardware.tv.cec@1.0"
Yuexi Ma8867ba92016-12-21 13:45:28 -08001043 && packageFQName.string() != "android.hardware.tv.input@1.0"
Keun Soo Yim442aa3d2016-12-16 13:05:32 -08001044 && packageFQName.string() != "android.hardware.memtrack@1.0"
Zhuoyao Zhang83013622017-01-12 18:31:34 -08001045 && packageFQName.string() != "android.hardware.sensors@1.0"
Keun Soo Yim6a01fb52017-01-18 13:34:12 -08001046 && packageFQName.string() != "android.hardware.soundtrigger@2.0"
Zhuoyao Zhang83013622017-01-12 18:31:34 -08001047 && packageFQName.string()
1048 != "android.hardware.graphics.allocator@2.0") {
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -08001049 fprintf(stderr,
Steven Morelanda6466052016-12-21 13:17:29 -08001050 "WARNING: %s does not yet have auto-generated VTS driver & profiler.\n",
Keun Soo Yimc4b72ce2016-12-14 16:54:12 -08001051 packageFQName.string().c_str());
1052 return OK;
1053 }
Zhuoyao Zhangb85e8c22016-12-21 10:24:16 -08001054 // Generate Driver package.
1055 status_t status = generateAndroidBpForVtsDriverPackage(out,
1056 importedPackages,
1057 packageInterfaces,
1058 packageFQName,
1059 hidl_gen,
1060 coordinator);
1061 if (status != OK) {
1062 return status;
1063 }
1064 // Generate Profiler packages.
1065 status = generateAndroidBpForVtsProfilerPackage(out,
1066 importedPackages,
1067 packageInterfaces,
1068 packageFQName,
1069 hidl_gen,
1070 coordinator);
1071 if (status != OK) {
1072 return status;
1073 }
1074 return OK;
Dan Willemsen676abdc2016-09-28 19:42:22 -07001075}
1076
Yifan Hong958ee462016-12-06 17:09:51 -08001077static status_t generateAndroidBpImplForPackage(
Steven Moreland197d56c2016-09-09 10:03:58 -07001078 const FQName &packageFQName,
1079 const char *,
1080 Coordinator *coordinator,
1081 const std::string &outputDir) {
1082
Iliyan Malchev4923f932016-09-09 13:04:59 -07001083 const std::string libraryName = makeLibraryName(packageFQName) + "-impl";
Steven Moreland197d56c2016-09-09 10:03:58 -07001084
1085 std::vector<FQName> packageInterfaces;
1086
1087 status_t err =
Steven Morelandaa186832016-09-26 13:51:43 -07001088 coordinator->appendPackageInterfacesToVector(packageFQName,
1089 &packageInterfaces);
Steven Moreland197d56c2016-09-09 10:03:58 -07001090
1091 if (err != OK) {
1092 return err;
1093 }
1094
1095 std::set<FQName> importedPackages;
1096
1097 for (const auto &fqName : packageInterfaces) {
1098 AST *ast = coordinator->parse(fqName);
1099
1100 if (ast == NULL) {
1101 fprintf(stderr,
1102 "ERROR: Could not parse %s. Aborting.\n",
1103 fqName.string().c_str());
1104
1105 return UNKNOWN_ERROR;
1106 }
1107
1108 ast->getImportedPackages(&importedPackages);
1109 }
1110
Yifan Hongaafed702016-12-14 12:59:47 -08001111 std::string path = outputDir + "Android.bp";
Steven Moreland197d56c2016-09-09 10:03:58 -07001112
1113 CHECK(Coordinator::MakeParentHierarchy(path));
1114 FILE *file = fopen(path.c_str(), "w");
1115
1116 if (file == NULL) {
1117 return -errno;
1118 }
1119
1120 Formatter out(file);
1121
Yifan Hong958ee462016-12-06 17:09:51 -08001122 out << "cc_library_shared {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001123 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -08001124 out << "name: \"" << libraryName << "\",\n"
1125 << "relative_install_path: \"hw\",\n"
1126 << "srcs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001127 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -08001128 for (const auto &fqName : packageInterfaces) {
1129 if (fqName.name() == "types") {
1130 continue;
1131 }
1132 out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n";
1133 }
1134 });
1135 out << "],\n"
1136 << "shared_libs: [\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001137 out.indent([&] {
Yifan Hong958ee462016-12-06 17:09:51 -08001138 out << "\"libhidlbase\",\n"
1139 << "\"libhidltransport\",\n"
1140 << "\"libhwbinder\",\n"
1141 << "\"libutils\",\n"
1142 << "\"" << makeLibraryName(packageFQName) << "\",\n";
Yifan Honge0f7d692016-10-20 17:51:33 -07001143
Yifan Hong958ee462016-12-06 17:09:51 -08001144 for (const auto &importedPackage : importedPackages) {
1145 out << "\"" << makeLibraryName(importedPackage) << "\",\n";
1146 }
1147 });
1148 out << "],\n";
1149 });
1150 out << "}\n";
Steven Moreland197d56c2016-09-09 10:03:58 -07001151
1152 return OK;
1153}
1154
Andreas Huber0fa9e392016-08-31 09:05:44 -07001155OutputHandler::ValRes validateForSource(
1156 const FQName &fqName, const std::string &language) {
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001157 if (fqName.package().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -07001158 fprintf(stderr, "ERROR: Expecting package name\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001159 return OutputHandler::FAILED;
1160 }
1161
1162 if (fqName.version().empty()) {
Andreas Huber70a59e12016-08-16 12:57:01 -07001163 fprintf(stderr, "ERROR: Expecting package version\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001164 return OutputHandler::FAILED;
1165 }
1166
Andreas Huber0fa9e392016-08-31 09:05:44 -07001167 const std::string &name = fqName.name();
1168 if (!name.empty()) {
1169 if (name.find('.') == std::string::npos) {
1170 return OutputHandler::PASS_FULL;
1171 }
1172
1173 if (language != "java" || name.find("types.") != 0) {
1174 // When generating java sources for "types.hal", output can be
1175 // constrained to just one of the top-level types declared
1176 // by using the extended syntax
1177 // android.hardware.Foo@1.0::types.TopLevelTypeName.
1178 // In all other cases (different language, not 'types') the dot
1179 // notation in the name is illegal in this context.
1180 return OutputHandler::FAILED;
1181 }
1182
1183 return OutputHandler::PASS_FULL;
1184 }
1185
1186 return OutputHandler::PASS_PACKAGE;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001187}
1188
Andreas Huber019d21d2016-10-03 12:59:47 -07001189OutputHandler::ValRes validateForExportHeader(
1190 const FQName &fqName, const std::string & /* language */) {
1191 if (fqName.package().empty()) {
1192 fprintf(stderr, "ERROR: Expecting package name\n");
1193 return OutputHandler::FAILED;
1194 }
1195
1196 if (fqName.version().empty()) {
1197 fprintf(stderr, "ERROR: Expecting package version\n");
1198 return OutputHandler::FAILED;
1199 }
1200
1201 if (!fqName.name().empty()) {
1202 fprintf(stderr,
1203 "ERROR: Expecting only package name and version.\n");
1204 return OutputHandler::FAILED;
1205 }
1206
1207 return OutputHandler::PASS_PACKAGE;
1208}
1209
1210
1211static status_t generateExportHeaderForPackage(
1212 const FQName &packageFQName,
1213 const char * /* hidl_gen */,
1214 Coordinator *coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001215 const std::string &outputPath,
1216 bool forJava) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001217
1218 CHECK(packageFQName.isValid()
1219 && !packageFQName.isFullyQualified()
1220 && packageFQName.name().empty());
1221
1222 std::vector<FQName> packageInterfaces;
1223
1224 status_t err = coordinator->appendPackageInterfacesToVector(
1225 packageFQName, &packageInterfaces);
1226
1227 if (err != OK) {
1228 return err;
1229 }
1230
1231 std::vector<const Type *> exportedTypes;
1232
1233 for (const auto &fqName : packageInterfaces) {
1234 AST *ast = coordinator->parse(fqName);
1235
1236 if (ast == NULL) {
1237 fprintf(stderr,
1238 "ERROR: Could not parse %s. Aborting.\n",
1239 fqName.string().c_str());
1240
1241 return UNKNOWN_ERROR;
1242 }
1243
1244 ast->appendToExportedTypesVector(&exportedTypes);
1245 }
1246
1247 if (exportedTypes.empty()) {
1248 return OK;
1249 }
1250
Andreas Huber1c507272016-10-05 14:33:21 -07001251 std::string path = outputPath;
1252
1253 if (forJava) {
1254 path.append(coordinator->convertPackageRootToPath(packageFQName));
1255
1256 path.append(coordinator->getPackagePath(
Yifan Hong97288ac2016-12-12 16:03:51 -08001257 packageFQName, true /* relative */, true /* sanitized */));
Andreas Huber1c507272016-10-05 14:33:21 -07001258
1259 path.append("Constants.java");
1260 }
1261
1262 CHECK(Coordinator::MakeParentHierarchy(path));
1263 FILE *file = fopen(path.c_str(), "w");
Andreas Huber019d21d2016-10-03 12:59:47 -07001264
1265 if (file == nullptr) {
1266 return -errno;
1267 }
1268
1269 Formatter out(file);
1270
Steven Morelandd177b122016-12-12 09:15:37 -08001271 out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n"
1272 << "// Source: " << packageFQName.string() << "\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001273
Andreas Huber1c507272016-10-05 14:33:21 -07001274 std::string guard;
1275 if (forJava) {
1276 out << "package " << packageFQName.javaPackage() << ";\n\n";
1277 out << "public class Constants {\n";
1278 out.indent();
1279 } else {
1280 guard = "HIDL_GENERATED_";
Steven Morelandd177b122016-12-12 09:15:37 -08001281 guard += StringHelper::Uppercase(packageFQName.tokenName());
Andreas Huber1c507272016-10-05 14:33:21 -07001282 guard += "_";
1283 guard += "EXPORTED_CONSTANTS_H_";
Andreas Huber019d21d2016-10-03 12:59:47 -07001284
Andreas Huber1c507272016-10-05 14:33:21 -07001285 out << "#ifndef "
1286 << guard
1287 << "\n#define "
1288 << guard
1289 << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
Andreas Huber019d21d2016-10-03 12:59:47 -07001290 }
1291
Andreas Huber1c507272016-10-05 14:33:21 -07001292 for (const auto &type : exportedTypes) {
1293 type->emitExportedHeader(out, forJava);
1294 }
1295
1296 if (forJava) {
1297 out.unindent();
1298 out << "}\n";
1299 } else {
1300 out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // "
1301 << guard
1302 << "\n";
1303 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001304
1305 return OK;
1306}
1307
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001308static std::vector<OutputHandler> formats = {
1309 {"c++",
Andreas Huber019d21d2016-10-03 12:59:47 -07001310 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001311 validateForSource,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001312 [](const FQName &fqName,
1313 const char *hidl_gen, Coordinator *coordinator,
1314 const std::string &outputDir) -> status_t {
1315 if (fqName.isFullyQualified()) {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001316 return generateSourcesForFile(fqName,
1317 hidl_gen,
1318 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001319 outputDir,
1320 "c++");
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001321 } else {
1322 return generateSourcesForPackage(fqName,
1323 hidl_gen,
1324 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001325 outputDir,
1326 "c++");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001327 }
1328 }
1329 },
1330
Andreas Huber019d21d2016-10-03 12:59:47 -07001331 {"export-header",
1332 OutputHandler::NEEDS_FILE /* mOutputMode */,
1333 validateForExportHeader,
1334 [](const FQName &fqName,
1335 const char *hidl_gen,
1336 Coordinator *coordinator,
1337 const std::string &outputPath) -> status_t {
1338 CHECK(!fqName.isFullyQualified());
1339
1340 return generateExportHeaderForPackage(
1341 fqName,
1342 hidl_gen,
1343 coordinator,
Andreas Huber1c507272016-10-05 14:33:21 -07001344 outputPath,
1345 false /* forJava */);
Andreas Huber019d21d2016-10-03 12:59:47 -07001346 }
1347 },
1348
Steven Moreland9c387612016-09-07 09:54:26 -07001349 {"c++-impl",
Andreas Huber019d21d2016-10-03 12:59:47 -07001350 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland9c387612016-09-07 09:54:26 -07001351 validateForSource,
1352 [](const FQName &fqName,
1353 const char *hidl_gen, Coordinator *coordinator,
1354 const std::string &outputDir) -> status_t {
1355 if (fqName.isFullyQualified()) {
1356 return generateSourcesForFile(fqName,
1357 hidl_gen,
1358 coordinator,
1359 outputDir, "c++-impl");
1360 } else {
1361 return generateSourcesForPackage(fqName,
1362 hidl_gen,
1363 coordinator,
1364 outputDir, "c++-impl");
1365 }
1366 }
1367 },
1368
1369
Andreas Huber2831d512016-08-15 09:33:47 -07001370 {"java",
Andreas Huber019d21d2016-10-03 12:59:47 -07001371 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001372 validateForSource,
Andreas Huber2831d512016-08-15 09:33:47 -07001373 [](const FQName &fqName,
1374 const char *hidl_gen, Coordinator *coordinator,
1375 const std::string &outputDir) -> status_t {
1376 if (fqName.isFullyQualified()) {
1377 return generateSourcesForFile(fqName,
1378 hidl_gen,
1379 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001380 outputDir,
1381 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001382 }
1383 else {
1384 return generateSourcesForPackage(fqName,
1385 hidl_gen,
1386 coordinator,
Andreas Huber0fa9e392016-08-31 09:05:44 -07001387 outputDir,
1388 "java");
Andreas Huber2831d512016-08-15 09:33:47 -07001389 }
1390 }
1391 },
1392
Andreas Huber1c507272016-10-05 14:33:21 -07001393 {"java-constants",
1394 OutputHandler::NEEDS_DIR /* mOutputMode */,
1395 validateForExportHeader,
1396 [](const FQName &fqName,
1397 const char *hidl_gen, Coordinator *coordinator,
1398 const std::string &outputDir) -> status_t {
1399 CHECK(!fqName.isFullyQualified());
1400 return generateExportHeaderForPackage(
1401 fqName,
1402 hidl_gen,
1403 coordinator,
1404 outputDir,
1405 true /* forJava */);
1406 }
1407 },
1408
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001409 {"vts",
Andreas Huber019d21d2016-10-03 12:59:47 -07001410 OutputHandler::NEEDS_DIR /* mOutputMode */,
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001411 validateForSource,
1412 [](const FQName &fqName,
1413 const char * hidl_gen,
1414 Coordinator *coordinator,
1415 const std::string &outputDir) -> status_t {
1416 if (fqName.isFullyQualified()) {
1417 return generateSourcesForFile(fqName,
1418 hidl_gen,
1419 coordinator,
1420 outputDir, "vts");
1421 } else {
1422 return generateSourcesForPackage(fqName,
1423 hidl_gen,
1424 coordinator,
1425 outputDir, "vts");
1426 }
1427 }
1428 },
1429
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001430 {"makefile",
Andreas Huber019d21d2016-10-03 12:59:47 -07001431 OutputHandler::NOT_NEEDED /* mOutputMode */,
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001432 validateForMakefile,
1433 generateMakefileForPackage,
1434 },
Steven Moreland197d56c2016-09-09 10:03:58 -07001435
Dan Willemsen676abdc2016-09-28 19:42:22 -07001436 {"androidbp",
Andreas Huber019d21d2016-10-03 12:59:47 -07001437 OutputHandler::NOT_NEEDED /* mOutputMode */,
Dan Willemsen676abdc2016-09-28 19:42:22 -07001438 validateForMakefile,
1439 generateAndroidBpForPackage,
1440 },
1441
Yifan Hong958ee462016-12-06 17:09:51 -08001442 {"androidbp-impl",
Yifan Hong94bcea02016-10-06 13:51:31 -07001443 OutputHandler::NEEDS_DIR /* mOutputMode */,
Steven Moreland197d56c2016-09-09 10:03:58 -07001444 validateForMakefile,
Yifan Hong958ee462016-12-06 17:09:51 -08001445 generateAndroidBpImplForPackage,
Steven Moreland197d56c2016-09-09 10:03:58 -07001446 }
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001447};
1448
1449static void usage(const char *me) {
1450 fprintf(stderr,
1451 "usage: %s -o output-path -L <language> (-r interface-root)+ fqname+\n",
1452 me);
1453
1454 fprintf(stderr, " -o output path\n");
1455
1456 fprintf(stderr, " -L <language> (one of");
1457 for (auto &e : formats) {
1458 fprintf(stderr, " %s", e.mKey.c_str());
1459 }
1460 fprintf(stderr, ")\n");
1461
1462 fprintf(stderr,
1463 " -r package:path root "
1464 "(e.g., android.hardware:hardware/interfaces)\n");
1465}
1466
Andreas Huberb82318c2016-08-02 14:45:54 -07001467int main(int argc, char **argv) {
Andreas Huber019d21d2016-10-03 12:59:47 -07001468 std::string outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -07001469 std::vector<std::string> packageRootPaths;
1470 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -07001471
Andreas Huber737080b2016-08-02 15:38:04 -07001472 const char *me = argv[0];
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001473 OutputHandler *outputFormat = nullptr;
Andreas Huber737080b2016-08-02 15:38:04 -07001474
Andreas Huberb82318c2016-08-02 14:45:54 -07001475 int res;
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001476 while ((res = getopt(argc, argv, "ho:r:L:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -07001477 switch (res) {
1478 case 'o':
1479 {
Andreas Huber019d21d2016-10-03 12:59:47 -07001480 outputPath = optarg;
Andreas Huberb82318c2016-08-02 14:45:54 -07001481 break;
1482 }
1483
Andreas Huberdca261f2016-08-04 13:47:51 -07001484 case 'r':
1485 {
1486 std::string val(optarg);
1487 auto index = val.find_first_of(':');
1488 CHECK(index != std::string::npos);
1489
1490 auto package = val.substr(0, index);
1491 auto path = val.substr(index + 1);
1492 packageRootPaths.push_back(path);
1493 packageRoots.push_back(package);
1494 break;
1495 }
1496
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001497 case 'L':
1498 {
Steven Morelande429a262016-11-15 09:54:32 -08001499 CHECK(outputFormat == nullptr) << "Only one -L option allowed.";
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001500 for (auto &e : formats) {
1501 if (e.mKey == optarg) {
1502 outputFormat = &e;
1503 break;
1504 }
1505 }
Steven Morelande429a262016-11-15 09:54:32 -08001506 CHECK(outputFormat != nullptr) << "Output format not recognized.";
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001507 break;
1508 }
1509
Andreas Huberb82318c2016-08-02 14:45:54 -07001510 case '?':
1511 case 'h':
1512 default:
1513 {
Andreas Huber737080b2016-08-02 15:38:04 -07001514 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -07001515 exit(1);
1516 break;
1517 }
1518 }
1519 }
1520
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001521 if (outputFormat == nullptr) {
1522 usage(me);
1523 exit(1);
1524 }
1525
Andreas Huberb82318c2016-08-02 14:45:54 -07001526 argc -= optind;
1527 argv += optind;
1528
Andreas Huberdca261f2016-08-04 13:47:51 -07001529 if (packageRootPaths.empty()) {
1530 // Pick reasonable defaults.
1531
1532 packageRoots.push_back("android.hardware");
1533
1534 const char *TOP = getenv("TOP");
Steven Morelandaf330382016-11-09 15:48:03 -08001535 if (TOP == nullptr) {
1536 fprintf(stderr,
1537 "ERROR: No root path (-r) specified"
1538 " and $TOP environment variable not set.\n");
1539 exit(1);
1540 }
Andreas Huberdca261f2016-08-04 13:47:51 -07001541
1542 std::string path = TOP;
1543 path.append("/hardware/interfaces");
1544
1545 packageRootPaths.push_back(path);
1546 }
1547
Andreas Huber737080b2016-08-02 15:38:04 -07001548 // Valid options are now in argv[0] .. argv[argc - 1].
1549
Andreas Huber019d21d2016-10-03 12:59:47 -07001550 switch (outputFormat->mOutputMode) {
1551 case OutputHandler::NEEDS_DIR:
1552 case OutputHandler::NEEDS_FILE:
1553 {
1554 if (outputPath.empty()) {
1555 usage(me);
1556 exit(1);
1557 }
1558
1559 if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) {
1560 const size_t len = outputPath.size();
1561 if (outputPath[len - 1] != '/') {
1562 outputPath += "/";
1563 }
1564 }
1565 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001566 }
Andreas Huber019d21d2016-10-03 12:59:47 -07001567
1568 default:
1569 outputPath.clear(); // Unused.
1570 break;
Andreas Huberb82318c2016-08-02 14:45:54 -07001571 }
1572
Andreas Huberdca261f2016-08-04 13:47:51 -07001573 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -07001574
Andreas Huber737080b2016-08-02 15:38:04 -07001575 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -07001576 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -07001577
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001578 if (!fqName.isValid()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001579 fprintf(stderr,
Andreas Huber70a59e12016-08-16 12:57:01 -07001580 "ERROR: Invalid fully-qualified name.\n");
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001581 exit(1);
1582 }
Andreas Huber881227d2016-08-02 14:20:21 -07001583
Andreas Huber0fa9e392016-08-31 09:05:44 -07001584 OutputHandler::ValRes valid =
1585 outputFormat->validate(fqName, outputFormat->mKey);
1586
Iliyan Malchev5bb14022016-08-09 15:04:39 -07001587 if (valid == OutputHandler::FAILED) {
Andreas Hubere61e3f72016-08-03 10:22:03 -07001588 exit(1);
1589 }
Andreas Huberd2943e12016-08-05 11:59:31 -07001590
1591 status_t err =
Andreas Huber019d21d2016-10-03 12:59:47 -07001592 outputFormat->generate(fqName, me, &coordinator, outputPath);
Andreas Huberd2943e12016-08-05 11:59:31 -07001593
1594 if (err != OK) {
Steven Moreland261370a2016-08-29 15:36:59 -07001595 exit(1);
Andreas Huberd2943e12016-08-05 11:59:31 -07001596 }
Andreas Hubereb1081f2016-07-28 13:13:24 -07001597 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001598
Andreas Huberd2943e12016-08-05 11:59:31 -07001599 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -07001600}