Andreas Huber | 1aec397 | 2016-08-26 09:26:32 -0700 | [diff] [blame] | 1 | /* |
| 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 Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 17 | #include "AST.h" |
Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 18 | #include "Coordinator.h" |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 19 | #include "Scope.h" |
Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 20 | |
Andreas Huber | 308d8a2 | 2017-11-06 14:46:52 -0800 | [diff] [blame] | 21 | #include <android-base/logging.h> |
Steven Moreland | 5bdfa70 | 2017-04-18 23:20:39 -0700 | [diff] [blame] | 22 | #include <hidl-hash/Hash.h> |
Iliyan Malchev | a72e0d2 | 2016-09-09 11:03:08 -0700 | [diff] [blame] | 23 | #include <hidl-util/Formatter.h> |
Steven Moreland | 7ae3d54 | 2017-01-18 16:46:01 -0800 | [diff] [blame] | 24 | #include <hidl-util/FQName.h> |
Steven Moreland | d177b12 | 2016-12-12 09:15:37 -0800 | [diff] [blame] | 25 | #include <hidl-util/StringHelper.h> |
Andreas Huber | 308d8a2 | 2017-11-06 14:46:52 -0800 | [diff] [blame] | 26 | #include <iostream> |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 27 | #include <set> |
Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 28 | #include <stdio.h> |
Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 29 | #include <string> |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 30 | #include <unistd.h> |
Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 31 | #include <vector> |
Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 32 | |
| 33 | using namespace android; |
| 34 | |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 35 | struct OutputHandler { |
| 36 | std::string mKey; |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 37 | std::string mDescription; |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 38 | enum OutputMode { |
| 39 | NEEDS_DIR, |
| 40 | NEEDS_FILE, |
Steven Moreland | a171b56 | 2017-05-12 15:18:03 -0700 | [diff] [blame] | 41 | NEEDS_SRC, // for changes inside the source tree itself |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 42 | NOT_NEEDED |
| 43 | } mOutputMode; |
| 44 | |
Steven Moreland | dd58384 | 2017-04-19 13:09:57 -0700 | [diff] [blame] | 45 | const std::string& name() { return mKey; } |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 46 | const std::string& description() { return mDescription; } |
Steven Moreland | bbbbeb8 | 2017-05-09 14:20:50 -0700 | [diff] [blame] | 47 | |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 48 | using ValidationFunction = std::function<bool(const FQName &, const std::string &language)>; |
Steven Moreland | bbbbeb8 | 2017-05-09 14:20:50 -0700 | [diff] [blame] | 49 | using GenerationFunction = std::function<status_t(const FQName &fqName, |
| 50 | const char *hidl_gen, |
| 51 | Coordinator *coordinator, |
| 52 | const std::string &outputDir)>; |
| 53 | |
| 54 | ValidationFunction validate; |
| 55 | GenerationFunction generate; |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 56 | }; |
Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 57 | |
Jiyong Park | 3728325 | 2017-08-29 14:11:48 +0900 | [diff] [blame] | 58 | static bool generateForTest = false; |
| 59 | |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 60 | static status_t generateSourcesForFile( |
| 61 | const FQName &fqName, |
| 62 | const char *, |
| 63 | Coordinator *coordinator, |
Andreas Huber | 2831d51 | 2016-08-15 09:33:47 -0700 | [diff] [blame] | 64 | const std::string &outputDir, |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 65 | const std::string &lang) { |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 66 | CHECK(fqName.isFullyQualified()); |
| 67 | |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 68 | AST *ast; |
Andreas Huber | d29724f | 2016-09-14 09:33:13 -0700 | [diff] [blame] | 69 | std::string limitToType; |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 70 | |
| 71 | if (fqName.name().find("types.") == 0) { |
| 72 | CHECK(lang == "java"); // Already verified in validate(). |
| 73 | |
Andreas Huber | d29724f | 2016-09-14 09:33:13 -0700 | [diff] [blame] | 74 | limitToType = fqName.name().substr(strlen("types.")); |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 75 | |
Yifan Hong | fece6ec | 2017-01-12 17:04:04 -0800 | [diff] [blame] | 76 | FQName typesName = fqName.getTypesForPackage(); |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 77 | ast = coordinator->parse(typesName); |
| 78 | } else { |
| 79 | ast = coordinator->parse(fqName); |
| 80 | } |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 81 | |
| 82 | if (ast == NULL) { |
| 83 | fprintf(stderr, |
Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 84 | "ERROR: Could not parse %s. Aborting.\n", |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 85 | fqName.string().c_str()); |
| 86 | |
| 87 | return UNKNOWN_ERROR; |
| 88 | } |
| 89 | |
Steven Moreland | 3b1ce26 | 2017-04-21 14:19:59 -0700 | [diff] [blame] | 90 | if (lang == "check") { |
| 91 | return OK; // only parsing, not generating |
| 92 | } |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 93 | if (lang == "c++") { |
| 94 | return ast->generateCpp(outputDir); |
| 95 | } |
Steven Moreland | 1cbf036 | 2017-05-09 14:32:53 -0700 | [diff] [blame] | 96 | if (lang == "c++-headers") { |
| 97 | return ast->generateCppHeaders(outputDir); |
| 98 | } |
| 99 | if (lang == "c++-sources") { |
| 100 | return ast->generateCppSources(outputDir); |
| 101 | } |
Steven Moreland | 9c38761 | 2016-09-07 09:54:26 -0700 | [diff] [blame] | 102 | if (lang == "c++-impl") { |
| 103 | return ast->generateCppImpl(outputDir); |
| 104 | } |
Steven Moreland | f2a0f5b | 2017-07-18 20:39:11 -0700 | [diff] [blame] | 105 | if (lang == "c++-impl-headers") { |
Steven Moreland | 6d68855 | 2017-09-15 11:03:02 -0700 | [diff] [blame] | 106 | return ast->generateCppImplHeader(outputDir); |
Steven Moreland | f2a0f5b | 2017-07-18 20:39:11 -0700 | [diff] [blame] | 107 | } |
| 108 | if (lang == "c++-impl-sources") { |
Steven Moreland | 6d68855 | 2017-09-15 11:03:02 -0700 | [diff] [blame] | 109 | return ast->generateCppImplSource(outputDir); |
Steven Moreland | f2a0f5b | 2017-07-18 20:39:11 -0700 | [diff] [blame] | 110 | } |
Steven Moreland | 9a6da7a | 2017-09-15 16:21:24 -0700 | [diff] [blame] | 111 | if (lang == "c++-adapter") { |
| 112 | return ast->generateCppAdapter(outputDir); |
| 113 | } |
| 114 | if (lang == "c++-adapter-headers") { |
| 115 | return ast->generateCppAdapterHeader(outputDir); |
| 116 | } |
| 117 | if (lang == "c++-adapter-sources") { |
| 118 | return ast->generateCppAdapterSource(outputDir); |
| 119 | } |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 120 | if (lang == "java") { |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 121 | return ast->generateJava(outputDir, limitToType); |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 122 | } |
| 123 | if (lang == "vts") { |
| 124 | return ast->generateVts(outputDir); |
| 125 | } |
| 126 | // Unknown language. |
| 127 | return UNKNOWN_ERROR; |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 128 | } |
| 129 | |
Andreas Huber | 308d8a2 | 2017-11-06 14:46:52 -0800 | [diff] [blame] | 130 | static status_t dumpDefinedButUnreferencedTypeNames( |
| 131 | const std::vector<FQName> &packageInterfaces, |
| 132 | Coordinator *coordinator) { |
| 133 | std::set<FQName> packageDefinedTypes; |
| 134 | std::set<FQName> packageReferencedTypes; |
Andreas Huber | 4f4b382 | 2017-11-15 13:18:50 -0800 | [diff] [blame^] | 135 | std::set<FQName> packageImportedTypes; |
Andreas Huber | 308d8a2 | 2017-11-06 14:46:52 -0800 | [diff] [blame] | 136 | for (const auto &fqName : packageInterfaces) { |
| 137 | AST *ast = coordinator->parse(fqName); |
| 138 | if (!ast) { |
| 139 | std::cerr |
| 140 | << "ERROR: Could not parse " << fqName.string() << ". Aborting." |
| 141 | << std::endl; |
| 142 | |
| 143 | return UNKNOWN_ERROR; |
| 144 | } |
| 145 | |
| 146 | ast->addDefinedTypes(&packageDefinedTypes); |
| 147 | ast->addReferencedTypes(&packageReferencedTypes); |
Andreas Huber | 4f4b382 | 2017-11-15 13:18:50 -0800 | [diff] [blame^] | 148 | ast->getAllImportedNames(&packageImportedTypes); |
Andreas Huber | 308d8a2 | 2017-11-06 14:46:52 -0800 | [diff] [blame] | 149 | } |
| 150 | |
Andreas Huber | 4f4b382 | 2017-11-15 13:18:50 -0800 | [diff] [blame^] | 151 | // Expand each "types" FQName into its constituent types, i.e. |
| 152 | // "android.hardware.foo@1.0::types" might expand into the set |
| 153 | // { android.hardware.foo@1.0::FirstType, android.hardware.foo@1.0::SecondType }. |
| 154 | std::set<FQName> expandedTypes; |
| 155 | for (const auto &importedFQName : packageImportedTypes) { |
| 156 | if (importedFQName.name() == "types") { |
| 157 | AST *ast = coordinator->parse( |
| 158 | importedFQName, |
| 159 | nullptr /* parsedASTs */, |
| 160 | Coordinator::Enforce::NONE); |
| 161 | |
| 162 | ast->addDefinedTypes(&expandedTypes); |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | // Now remove all "types" FQNames. |
| 167 | for (auto it = packageImportedTypes.begin(); |
| 168 | it != packageImportedTypes.end();) { |
| 169 | if (it->name() == "types") { |
| 170 | it = packageImportedTypes.erase(it); |
| 171 | } else { |
| 172 | ++it; |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | // And merge the sets. (set<T>::merge not available until C++17) |
| 177 | std::for_each( |
| 178 | expandedTypes.begin(), |
| 179 | expandedTypes.end(), |
| 180 | [&packageImportedTypes](const auto &fqName) { |
| 181 | packageImportedTypes.insert(fqName); |
| 182 | }); |
Andreas Huber | 308d8a2 | 2017-11-06 14:46:52 -0800 | [diff] [blame] | 183 | #if 0 |
| 184 | for (const auto &fqName : packageDefinedTypes) { |
| 185 | std::cout << "DEFINED: " << fqName.string() << std::endl; |
| 186 | } |
| 187 | |
Andreas Huber | 4f4b382 | 2017-11-15 13:18:50 -0800 | [diff] [blame^] | 188 | for (const auto &fqName : packageImportedTypes) { |
| 189 | std::cout << "IMPORTED: " << fqName.string() << std::endl; |
| 190 | } |
| 191 | |
Andreas Huber | 308d8a2 | 2017-11-06 14:46:52 -0800 | [diff] [blame] | 192 | for (const auto &fqName : packageReferencedTypes) { |
| 193 | std::cout << "REFERENCED: " << fqName.string() << std::endl; |
| 194 | } |
| 195 | #endif |
| 196 | |
| 197 | for (const auto &fqName : packageReferencedTypes) { |
| 198 | packageDefinedTypes.erase(fqName); |
Andreas Huber | 4f4b382 | 2017-11-15 13:18:50 -0800 | [diff] [blame^] | 199 | packageImportedTypes.erase(fqName); |
| 200 | } |
| 201 | |
| 202 | // A package implicitly imports its own types, only track them in one set. |
| 203 | for (const auto &fqName : packageDefinedTypes) { |
| 204 | packageImportedTypes.erase(fqName); |
Andreas Huber | 308d8a2 | 2017-11-06 14:46:52 -0800 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | for (const auto &fqName : packageDefinedTypes) { |
| 208 | std::cerr |
| 209 | << "VERBOSE: DEFINED-BUT-NOT-REFERENCED " |
| 210 | << fqName.string() |
| 211 | << std::endl; |
| 212 | } |
| 213 | |
Andreas Huber | 4f4b382 | 2017-11-15 13:18:50 -0800 | [diff] [blame^] | 214 | for (const auto &fqName : packageImportedTypes) { |
| 215 | std::cerr |
| 216 | << "VERBOSE: IMPORTED-BUT-NOT-REFERENCED " |
| 217 | << fqName.string() |
| 218 | << std::endl; |
| 219 | } |
| 220 | |
Andreas Huber | 308d8a2 | 2017-11-06 14:46:52 -0800 | [diff] [blame] | 221 | return OK; |
| 222 | } |
| 223 | |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 224 | static status_t generateSourcesForPackage( |
| 225 | const FQName &packageFQName, |
| 226 | const char *hidl_gen, |
| 227 | Coordinator *coordinator, |
Andreas Huber | 2831d51 | 2016-08-15 09:33:47 -0700 | [diff] [blame] | 228 | const std::string &outputDir, |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 229 | const std::string &lang) { |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 230 | CHECK(packageFQName.isValid() && |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 231 | !packageFQName.isFullyQualified() && |
| 232 | packageFQName.name().empty()); |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 233 | |
| 234 | std::vector<FQName> packageInterfaces; |
| 235 | |
| 236 | status_t err = |
Steven Moreland | aa18683 | 2016-09-26 13:51:43 -0700 | [diff] [blame] | 237 | coordinator->appendPackageInterfacesToVector(packageFQName, |
| 238 | &packageInterfaces); |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 239 | |
| 240 | if (err != OK) { |
| 241 | return err; |
| 242 | } |
| 243 | |
Andreas Huber | 308d8a2 | 2017-11-06 14:46:52 -0800 | [diff] [blame] | 244 | if (coordinator->isVerbose()) { |
| 245 | err = dumpDefinedButUnreferencedTypeNames( |
| 246 | packageInterfaces, coordinator); |
| 247 | |
| 248 | if (err != OK) { |
| 249 | return err; |
| 250 | } |
| 251 | } |
| 252 | |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 253 | for (const auto &fqName : packageInterfaces) { |
Andreas Huber | 2831d51 | 2016-08-15 09:33:47 -0700 | [diff] [blame] | 254 | err = generateSourcesForFile( |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 255 | fqName, hidl_gen, coordinator, outputDir, lang); |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 256 | if (err != OK) { |
| 257 | return err; |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | return OK; |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 262 | } |
| 263 | |
Steven Moreland | bbbbeb8 | 2017-05-09 14:20:50 -0700 | [diff] [blame] | 264 | OutputHandler::GenerationFunction generationFunctionForFileOrPackage(const std::string &language) { |
| 265 | return [language](const FQName &fqName, |
| 266 | const char *hidl_gen, Coordinator *coordinator, |
| 267 | const std::string &outputDir) -> status_t { |
| 268 | if (fqName.isFullyQualified()) { |
| 269 | return generateSourcesForFile(fqName, |
| 270 | hidl_gen, |
| 271 | coordinator, |
| 272 | outputDir, |
| 273 | language); |
| 274 | } else { |
| 275 | return generateSourcesForPackage(fqName, |
| 276 | hidl_gen, |
| 277 | coordinator, |
| 278 | outputDir, |
| 279 | language); |
| 280 | } |
| 281 | }; |
| 282 | } |
| 283 | |
Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame] | 284 | static std::string makeLibraryName(const FQName &packageFQName) { |
Iliyan Malchev | e2c595a | 2016-08-07 21:20:04 -0700 | [diff] [blame] | 285 | return packageFQName.string(); |
Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame] | 286 | } |
Steven Moreland | 5715fed | 2017-01-16 11:06:47 -0800 | [diff] [blame] | 287 | |
Andreas Huber | 75ae95d | 2016-10-12 16:08:26 -0700 | [diff] [blame] | 288 | static status_t isPackageJavaCompatible( |
| 289 | const FQName &packageFQName, |
| 290 | Coordinator *coordinator, |
| 291 | bool *compatible) { |
| 292 | std::vector<FQName> todo; |
| 293 | status_t err = |
| 294 | coordinator->appendPackageInterfacesToVector(packageFQName, &todo); |
| 295 | |
| 296 | if (err != OK) { |
| 297 | return err; |
| 298 | } |
| 299 | |
| 300 | std::set<FQName> seen; |
| 301 | for (const auto &iface : todo) { |
| 302 | seen.insert(iface); |
| 303 | } |
| 304 | |
| 305 | // Form the transitive closure of all imported interfaces (and types.hal-s) |
| 306 | // If any one of them is not java compatible, this package isn't either. |
| 307 | while (!todo.empty()) { |
| 308 | const FQName fqName = todo.back(); |
| 309 | todo.pop_back(); |
| 310 | |
| 311 | AST *ast = coordinator->parse(fqName); |
| 312 | |
| 313 | if (ast == nullptr) { |
| 314 | return UNKNOWN_ERROR; |
| 315 | } |
| 316 | |
| 317 | if (!ast->isJavaCompatible()) { |
| 318 | *compatible = false; |
| 319 | return OK; |
| 320 | } |
| 321 | |
| 322 | std::set<FQName> importedPackages; |
| 323 | ast->getImportedPackages(&importedPackages); |
| 324 | |
| 325 | for (const auto &package : importedPackages) { |
| 326 | std::vector<FQName> packageInterfaces; |
| 327 | status_t err = coordinator->appendPackageInterfacesToVector( |
| 328 | package, &packageInterfaces); |
| 329 | |
| 330 | if (err != OK) { |
| 331 | return err; |
| 332 | } |
| 333 | |
| 334 | for (const auto &iface : packageInterfaces) { |
| 335 | if (seen.find(iface) != seen.end()) { |
| 336 | continue; |
| 337 | } |
| 338 | |
| 339 | todo.push_back(iface); |
| 340 | seen.insert(iface); |
| 341 | } |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | *compatible = true; |
| 346 | return OK; |
| 347 | } |
| 348 | |
Andreas Huber | 5a9fe2c | 2016-10-13 15:31:10 -0700 | [diff] [blame] | 349 | static bool packageNeedsJavaCode( |
| 350 | const std::vector<FQName> &packageInterfaces, AST *typesAST) { |
Steven Moreland | adc2502 | 2017-10-11 12:42:19 -0700 | [diff] [blame] | 351 | if (packageInterfaces.size() == 0) { |
| 352 | return false; |
| 353 | } |
| 354 | |
Andreas Huber | 5a9fe2c | 2016-10-13 15:31:10 -0700 | [diff] [blame] | 355 | // If there is more than just a types.hal file to this package we'll |
| 356 | // definitely need to generate Java code. |
| 357 | if (packageInterfaces.size() > 1 |
| 358 | || packageInterfaces[0].name() != "types") { |
| 359 | return true; |
| 360 | } |
| 361 | |
| 362 | CHECK(typesAST != nullptr); |
| 363 | |
| 364 | // We'll have to generate Java code if types.hal contains any non-typedef |
| 365 | // type declarations. |
| 366 | |
Timur Iskhakov | cb0ba52 | 2017-07-17 20:01:37 -0700 | [diff] [blame] | 367 | Scope* rootScope = typesAST->getRootScope(); |
Andreas Huber | 5a9fe2c | 2016-10-13 15:31:10 -0700 | [diff] [blame] | 368 | std::vector<NamedType *> subTypes = rootScope->getSubTypes(); |
| 369 | |
| 370 | for (const auto &subType : subTypes) { |
| 371 | if (!subType->isTypeDef()) { |
| 372 | return true; |
| 373 | } |
| 374 | } |
| 375 | |
| 376 | return false; |
| 377 | } |
| 378 | |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 379 | bool validateIsPackage( |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 380 | const FQName &fqName, const std::string & /* language */) { |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 381 | if (fqName.package().empty()) { |
Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 382 | fprintf(stderr, "ERROR: Expecting package name\n"); |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 383 | return false; |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 384 | } |
| 385 | |
| 386 | if (fqName.version().empty()) { |
Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 387 | fprintf(stderr, "ERROR: Expecting package version\n"); |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 388 | return false; |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 389 | } |
| 390 | |
| 391 | if (!fqName.name().empty()) { |
| 392 | fprintf(stderr, |
Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 393 | "ERROR: Expecting only package name and version.\n"); |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 394 | return false; |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 395 | } |
| 396 | |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 397 | return true; |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 398 | } |
| 399 | |
Steven Moreland | f7f2a9a | 2017-07-21 18:05:38 -0700 | [diff] [blame] | 400 | bool isHidlTransportPackage(const FQName& fqName) { |
| 401 | return fqName.package() == gIBasePackageFqName.string() || |
| 402 | fqName.package() == gIManagerPackageFqName.string(); |
Steven Moreland | 77cf764 | 2017-06-15 14:49:39 -0700 | [diff] [blame] | 403 | } |
| 404 | |
Steven Moreland | c7946c9 | 2017-08-08 14:48:32 -0700 | [diff] [blame] | 405 | bool isSystemProcessSupportedPackage(const FQName& fqName) { |
| 406 | // Technically, so is hidl IBase + IServiceManager, but |
| 407 | // these are part of libhidltransport. |
| 408 | return fqName.string() == "android.hardware.graphics.allocator@2.0" || |
| 409 | fqName.string() == "android.hardware.graphics.common@1.0" || |
| 410 | fqName.string() == "android.hardware.graphics.mapper@2.0" || |
Chia-I Wu | 620cc39 | 2017-09-28 15:33:21 -0700 | [diff] [blame] | 411 | fqName.string() == "android.hardware.graphics.mapper@2.1" || |
Steven Moreland | c7946c9 | 2017-08-08 14:48:32 -0700 | [diff] [blame] | 412 | fqName.string() == "android.hardware.renderscript@1.0" || |
| 413 | fqName.string() == "android.hidl.memory@1.0"; |
| 414 | } |
| 415 | |
Steven Moreland | 5edf528 | 2017-07-20 12:56:58 -0700 | [diff] [blame] | 416 | bool isSystemPackage(const FQName &package) { |
| 417 | return package.inPackage("android.hidl") || |
| 418 | package.inPackage("android.system") || |
| 419 | package.inPackage("android.frameworks") || |
| 420 | package.inPackage("android.hardware"); |
| 421 | } |
| 422 | |
Steven Moreland | 9a6da7a | 2017-09-15 16:21:24 -0700 | [diff] [blame] | 423 | static status_t generateAdapterMainSource( |
| 424 | const FQName & packageFQName, |
| 425 | const char* /* hidl_gen */, |
| 426 | Coordinator* coordinator, |
| 427 | const std::string &outputPath) { |
Steven Moreland | a885d25 | 2017-09-25 18:44:43 -0700 | [diff] [blame] | 428 | Formatter out = coordinator->getFormatter(outputPath, packageFQName, |
| 429 | Coordinator::Location::DIRECT, "main.cpp"); |
| 430 | |
| 431 | if (!out.isValid()) { |
| 432 | return UNKNOWN_ERROR; |
Steven Moreland | 9a6da7a | 2017-09-15 16:21:24 -0700 | [diff] [blame] | 433 | } |
Steven Moreland | 9a6da7a | 2017-09-15 16:21:24 -0700 | [diff] [blame] | 434 | |
| 435 | std::vector<FQName> packageInterfaces; |
| 436 | status_t err = |
| 437 | coordinator->appendPackageInterfacesToVector(packageFQName, |
| 438 | &packageInterfaces); |
| 439 | if (err != OK) { |
| 440 | return err; |
| 441 | } |
| 442 | |
| 443 | out << "#include <hidladapter/HidlBinderAdapter.h>\n"; |
| 444 | |
| 445 | for (auto &interface : packageInterfaces) { |
| 446 | if (interface.name() == "types") { |
| 447 | continue; |
| 448 | } |
| 449 | AST::generateCppPackageInclude(out, interface, interface.getInterfaceAdapterName()); |
| 450 | } |
| 451 | |
| 452 | out << "int main(int argc, char** argv) "; |
| 453 | out.block([&] { |
| 454 | out << "return ::android::hardware::adapterMain<\n"; |
| 455 | out.indent(); |
| 456 | for (auto &interface : packageInterfaces) { |
| 457 | if (interface.name() == "types") { |
| 458 | continue; |
| 459 | } |
| 460 | out << interface.getInterfaceAdapterFqName().cppName(); |
| 461 | |
| 462 | if (&interface != &packageInterfaces.back()) { |
| 463 | out << ",\n"; |
| 464 | } |
| 465 | } |
| 466 | out << ">(\"" << packageFQName.string() << "\", argc, argv);\n"; |
| 467 | out.unindent(); |
| 468 | }).endl(); |
| 469 | return OK; |
| 470 | } |
| 471 | |
Steven Moreland | 313a013 | 2017-11-03 14:23:14 -0700 | [diff] [blame] | 472 | static status_t generateAndroidBpForPackage(const FQName& packageFQName, const char* /* hidl_gen */, |
Steven Moreland | 40069d5 | 2017-10-03 09:36:51 -0700 | [diff] [blame] | 473 | Coordinator* coordinator, |
| 474 | const std::string& outputPath) { |
| 475 | CHECK(packageFQName.isValid() && !packageFQName.isFullyQualified() && |
| 476 | packageFQName.name().empty()); |
| 477 | |
| 478 | std::vector<FQName> packageInterfaces; |
| 479 | |
| 480 | status_t err = coordinator->appendPackageInterfacesToVector(packageFQName, &packageInterfaces); |
| 481 | |
| 482 | if (err != OK) { |
| 483 | return err; |
| 484 | } |
| 485 | |
| 486 | std::set<FQName> importedPackagesHierarchy; |
Steven Moreland | 887b84c | 2017-10-09 18:40:58 -0700 | [diff] [blame] | 487 | std::vector<const Type *> exportedTypes; |
Steven Moreland | 40069d5 | 2017-10-03 09:36:51 -0700 | [diff] [blame] | 488 | AST* typesAST = nullptr; |
| 489 | |
| 490 | for (const auto& fqName : packageInterfaces) { |
| 491 | AST* ast = coordinator->parse(fqName); |
| 492 | |
| 493 | if (ast == NULL) { |
| 494 | fprintf(stderr, "ERROR: Could not parse %s. Aborting.\n", fqName.string().c_str()); |
| 495 | |
| 496 | return UNKNOWN_ERROR; |
| 497 | } |
| 498 | |
| 499 | if (fqName.name() == "types") { |
| 500 | typesAST = ast; |
| 501 | } |
| 502 | |
| 503 | ast->getImportedPackagesHierarchy(&importedPackagesHierarchy); |
Steven Moreland | 887b84c | 2017-10-09 18:40:58 -0700 | [diff] [blame] | 504 | ast->appendToExportedTypesVector(&exportedTypes); |
Steven Moreland | 40069d5 | 2017-10-03 09:36:51 -0700 | [diff] [blame] | 505 | } |
| 506 | |
Steven Moreland | 313a013 | 2017-11-03 14:23:14 -0700 | [diff] [blame] | 507 | bool needsJavaCode = packageNeedsJavaCode(packageInterfaces, typesAST); |
| 508 | |
| 509 | bool genJavaConstants = needsJavaCode && !exportedTypes.empty(); |
Steven Moreland | 887b84c | 2017-10-09 18:40:58 -0700 | [diff] [blame] | 510 | |
| 511 | bool isJavaCompatible; |
| 512 | err = isPackageJavaCompatible(packageFQName, coordinator, &isJavaCompatible); |
| 513 | if (err != OK) return err; |
Steven Moreland | 313a013 | 2017-11-03 14:23:14 -0700 | [diff] [blame] | 514 | bool genJavaLibrary = needsJavaCode && isJavaCompatible; |
| 515 | |
| 516 | bool isVndk = !generateForTest && isSystemPackage(packageFQName); |
| 517 | bool isVndkSp = isVndk && isSystemProcessSupportedPackage(packageFQName); |
Steven Moreland | 887b84c | 2017-10-09 18:40:58 -0700 | [diff] [blame] | 518 | |
Steven Moreland | 40069d5 | 2017-10-03 09:36:51 -0700 | [diff] [blame] | 519 | Formatter out = coordinator->getFormatter(outputPath, packageFQName, |
| 520 | Coordinator::Location::PACKAGE_ROOT, "Android.bp"); |
| 521 | |
| 522 | if (!out.isValid()) { |
| 523 | return UNKNOWN_ERROR; |
| 524 | } |
| 525 | |
Steven Moreland | 313a013 | 2017-11-03 14:23:14 -0700 | [diff] [blame] | 526 | out << "// This file is autogenerated by hidl-gen -Landroidbp.\n\n"; |
Steven Moreland | 40069d5 | 2017-10-03 09:36:51 -0700 | [diff] [blame] | 527 | |
Steven Moreland | 313a013 | 2017-11-03 14:23:14 -0700 | [diff] [blame] | 528 | |
| 529 | out << "hidl_interface "; |
Steven Moreland | 40069d5 | 2017-10-03 09:36:51 -0700 | [diff] [blame] | 530 | out.block([&] { |
Steven Moreland | 313a013 | 2017-11-03 14:23:14 -0700 | [diff] [blame] | 531 | out << "name: \"" << makeLibraryName(packageFQName) << "\",\n"; |
| 532 | out << "root: \"" << coordinator->getPackageRoot(packageFQName) << "\",\n"; |
| 533 | if (isHidlTransportPackage(packageFQName)) { |
| 534 | out << "core_interface: true,\n"; |
| 535 | } |
| 536 | if (isVndk) { |
| 537 | out << "vndk: "; |
| 538 | out.block([&]() { |
| 539 | out << "enabled: true,\n"; |
| 540 | if (isVndkSp) { |
| 541 | out << "support_system_process: true,\n"; |
| 542 | } |
| 543 | }) << ",\n"; |
| 544 | } |
| 545 | (out << "srcs: [\n").indent([&] { |
Steven Moreland | 40069d5 | 2017-10-03 09:36:51 -0700 | [diff] [blame] | 546 | for (const auto& fqName : packageInterfaces) { |
| 547 | out << "\"" << fqName.name() << ".hal\",\n"; |
| 548 | } |
Steven Moreland | 313a013 | 2017-11-03 14:23:14 -0700 | [diff] [blame] | 549 | }) << "],\n"; |
| 550 | if (!importedPackagesHierarchy.empty()) { |
| 551 | (out << "interfaces: [\n").indent([&] { |
| 552 | for (const auto& fqName : importedPackagesHierarchy) { |
| 553 | out << "\"" << fqName.string() << "\",\n"; |
| 554 | } |
| 555 | }) << "],\n"; |
| 556 | } |
| 557 | if (typesAST != nullptr) { |
| 558 | (out << "types: [\n").indent([&] { |
| 559 | std::vector<NamedType *> subTypes = typesAST->getRootScope()->getSubTypes(); |
| 560 | std::sort( |
| 561 | subTypes.begin(), |
| 562 | subTypes.end(), |
| 563 | [](const NamedType *a, const NamedType *b) -> bool { |
| 564 | return a->fqName() < b->fqName(); |
| 565 | }); |
| 566 | |
| 567 | for (const auto &type : subTypes) { |
| 568 | if (type->isTypeDef()) { |
| 569 | continue; |
| 570 | } |
| 571 | |
| 572 | out << "\"" << type->localName() << "\",\n"; |
| 573 | } |
| 574 | }) << "],\n"; |
| 575 | } |
| 576 | // Explicity call this out for developers. |
| 577 | out << "gen_java: " << (genJavaLibrary ? "true" : "false") << ",\n"; |
| 578 | if (genJavaConstants) { |
| 579 | out << "gen_java_constants: true,\n"; |
| 580 | } |
Steven Moreland | 40069d5 | 2017-10-03 09:36:51 -0700 | [diff] [blame] | 581 | }).endl().endl(); |
| 582 | |
Steven Moreland | 40069d5 | 2017-10-03 09:36:51 -0700 | [diff] [blame] | 583 | return OK; |
| 584 | } |
| 585 | |
Steven Moreland | a885d25 | 2017-09-25 18:44:43 -0700 | [diff] [blame] | 586 | static status_t generateAndroidBpImplForPackage(const FQName& packageFQName, const char*, |
| 587 | Coordinator* coordinator, |
| 588 | const std::string& outputPath) { |
Iliyan Malchev | 4923f93 | 2016-09-09 13:04:59 -0700 | [diff] [blame] | 589 | const std::string libraryName = makeLibraryName(packageFQName) + "-impl"; |
Steven Moreland | 197d56c | 2016-09-09 10:03:58 -0700 | [diff] [blame] | 590 | |
| 591 | std::vector<FQName> packageInterfaces; |
| 592 | |
| 593 | status_t err = |
Steven Moreland | aa18683 | 2016-09-26 13:51:43 -0700 | [diff] [blame] | 594 | coordinator->appendPackageInterfacesToVector(packageFQName, |
| 595 | &packageInterfaces); |
Steven Moreland | 197d56c | 2016-09-09 10:03:58 -0700 | [diff] [blame] | 596 | |
| 597 | if (err != OK) { |
| 598 | return err; |
| 599 | } |
| 600 | |
| 601 | std::set<FQName> importedPackages; |
| 602 | |
| 603 | for (const auto &fqName : packageInterfaces) { |
| 604 | AST *ast = coordinator->parse(fqName); |
| 605 | |
| 606 | if (ast == NULL) { |
| 607 | fprintf(stderr, |
| 608 | "ERROR: Could not parse %s. Aborting.\n", |
| 609 | fqName.string().c_str()); |
| 610 | |
| 611 | return UNKNOWN_ERROR; |
| 612 | } |
| 613 | |
| 614 | ast->getImportedPackages(&importedPackages); |
| 615 | } |
| 616 | |
Steven Moreland | a885d25 | 2017-09-25 18:44:43 -0700 | [diff] [blame] | 617 | Formatter out = coordinator->getFormatter(outputPath, packageFQName, |
| 618 | Coordinator::Location::DIRECT, "Android.bp"); |
Steven Moreland | 197d56c | 2016-09-09 10:03:58 -0700 | [diff] [blame] | 619 | |
Steven Moreland | a885d25 | 2017-09-25 18:44:43 -0700 | [diff] [blame] | 620 | if (!out.isValid()) { |
| 621 | return UNKNOWN_ERROR; |
Steven Moreland | 197d56c | 2016-09-09 10:03:58 -0700 | [diff] [blame] | 622 | } |
| 623 | |
Yifan Hong | 958ee46 | 2016-12-06 17:09:51 -0800 | [diff] [blame] | 624 | out << "cc_library_shared {\n"; |
Yifan Hong | 33223ca | 2016-12-13 15:07:35 -0800 | [diff] [blame] | 625 | out.indent([&] { |
Yifan Hong | 958ee46 | 2016-12-06 17:09:51 -0800 | [diff] [blame] | 626 | out << "name: \"" << libraryName << "\",\n" |
| 627 | << "relative_install_path: \"hw\",\n" |
Steven Moreland | f8a22e9 | 2017-02-15 18:46:04 -0800 | [diff] [blame] | 628 | << "proprietary: true,\n" |
Yifan Hong | 958ee46 | 2016-12-06 17:09:51 -0800 | [diff] [blame] | 629 | << "srcs: [\n"; |
Yifan Hong | 33223ca | 2016-12-13 15:07:35 -0800 | [diff] [blame] | 630 | out.indent([&] { |
Yifan Hong | 958ee46 | 2016-12-06 17:09:51 -0800 | [diff] [blame] | 631 | for (const auto &fqName : packageInterfaces) { |
| 632 | if (fqName.name() == "types") { |
| 633 | continue; |
| 634 | } |
| 635 | out << "\"" << fqName.getInterfaceBaseName() << ".cpp\",\n"; |
| 636 | } |
| 637 | }); |
| 638 | out << "],\n" |
| 639 | << "shared_libs: [\n"; |
Yifan Hong | 33223ca | 2016-12-13 15:07:35 -0800 | [diff] [blame] | 640 | out.indent([&] { |
Yifan Hong | 958ee46 | 2016-12-06 17:09:51 -0800 | [diff] [blame] | 641 | out << "\"libhidlbase\",\n" |
| 642 | << "\"libhidltransport\",\n" |
Yifan Hong | 958ee46 | 2016-12-06 17:09:51 -0800 | [diff] [blame] | 643 | << "\"libutils\",\n" |
| 644 | << "\"" << makeLibraryName(packageFQName) << "\",\n"; |
Yifan Hong | e0f7d69 | 2016-10-20 17:51:33 -0700 | [diff] [blame] | 645 | |
Yifan Hong | 958ee46 | 2016-12-06 17:09:51 -0800 | [diff] [blame] | 646 | for (const auto &importedPackage : importedPackages) { |
Steven Moreland | dadd184 | 2017-05-09 13:24:54 -0700 | [diff] [blame] | 647 | if (isHidlTransportPackage(importedPackage)) { |
| 648 | continue; |
| 649 | } |
| 650 | |
Yifan Hong | 958ee46 | 2016-12-06 17:09:51 -0800 | [diff] [blame] | 651 | out << "\"" << makeLibraryName(importedPackage) << "\",\n"; |
| 652 | } |
| 653 | }); |
| 654 | out << "],\n"; |
| 655 | }); |
| 656 | out << "}\n"; |
Steven Moreland | 197d56c | 2016-09-09 10:03:58 -0700 | [diff] [blame] | 657 | |
| 658 | return OK; |
| 659 | } |
| 660 | |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 661 | bool validateForSource( |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 662 | const FQName &fqName, const std::string &language) { |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 663 | if (fqName.package().empty()) { |
Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 664 | fprintf(stderr, "ERROR: Expecting package name\n"); |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 665 | return false; |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 666 | } |
| 667 | |
| 668 | if (fqName.version().empty()) { |
Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 669 | fprintf(stderr, "ERROR: Expecting package version\n"); |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 670 | return false; |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 671 | } |
| 672 | |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 673 | const std::string &name = fqName.name(); |
| 674 | if (!name.empty()) { |
| 675 | if (name.find('.') == std::string::npos) { |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 676 | return true; |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 677 | } |
| 678 | |
| 679 | if (language != "java" || name.find("types.") != 0) { |
| 680 | // When generating java sources for "types.hal", output can be |
| 681 | // constrained to just one of the top-level types declared |
| 682 | // by using the extended syntax |
| 683 | // android.hardware.Foo@1.0::types.TopLevelTypeName. |
| 684 | // In all other cases (different language, not 'types') the dot |
| 685 | // notation in the name is illegal in this context. |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 686 | return false; |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 687 | } |
| 688 | |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 689 | return true; |
Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 690 | } |
| 691 | |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 692 | return true; |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 693 | } |
| 694 | |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 695 | OutputHandler::GenerationFunction generateExportHeaderForPackage(bool forJava) { |
| 696 | return [forJava](const FQName &packageFQName, |
| 697 | const char * /* hidl_gen */, |
| 698 | Coordinator *coordinator, |
| 699 | const std::string &outputPath) -> status_t { |
| 700 | CHECK(packageFQName.isValid() |
| 701 | && !packageFQName.package().empty() |
| 702 | && !packageFQName.version().empty() |
| 703 | && packageFQName.name().empty()); |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 704 | |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 705 | std::vector<FQName> packageInterfaces; |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 706 | |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 707 | status_t err = coordinator->appendPackageInterfacesToVector( |
| 708 | packageFQName, &packageInterfaces); |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 709 | |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 710 | if (err != OK) { |
| 711 | return err; |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 712 | } |
| 713 | |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 714 | std::vector<const Type *> exportedTypes; |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 715 | |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 716 | for (const auto &fqName : packageInterfaces) { |
| 717 | AST *ast = coordinator->parse(fqName); |
| 718 | |
| 719 | if (ast == NULL) { |
| 720 | fprintf(stderr, |
| 721 | "ERROR: Could not parse %s. Aborting.\n", |
| 722 | fqName.string().c_str()); |
| 723 | |
| 724 | return UNKNOWN_ERROR; |
| 725 | } |
| 726 | |
| 727 | ast->appendToExportedTypesVector(&exportedTypes); |
| 728 | } |
| 729 | |
| 730 | if (exportedTypes.empty()) { |
| 731 | return OK; |
| 732 | } |
| 733 | |
Steven Moreland | a885d25 | 2017-09-25 18:44:43 -0700 | [diff] [blame] | 734 | // C++ filename is specified in output path |
| 735 | const std::string filename = forJava ? "Constants.java" : ""; |
| 736 | const Coordinator::Location location = |
| 737 | forJava ? Coordinator::Location::GEN_SANITIZED : Coordinator::Location::DIRECT; |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 738 | |
Steven Moreland | a885d25 | 2017-09-25 18:44:43 -0700 | [diff] [blame] | 739 | Formatter out = coordinator->getFormatter(outputPath, packageFQName, location, filename); |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 740 | |
Steven Moreland | a885d25 | 2017-09-25 18:44:43 -0700 | [diff] [blame] | 741 | if (!out.isValid()) { |
| 742 | return UNKNOWN_ERROR; |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 743 | } |
| 744 | |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 745 | out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n" |
| 746 | << "// Source: " << packageFQName.string() << "\n" |
| 747 | << "// Root: " << coordinator->getPackageRootOption(packageFQName) << "\n\n"; |
| 748 | |
| 749 | std::string guard; |
| 750 | if (forJava) { |
| 751 | out << "package " << packageFQName.javaPackage() << ";\n\n"; |
| 752 | out << "public class Constants {\n"; |
| 753 | out.indent(); |
| 754 | } else { |
| 755 | guard = "HIDL_GENERATED_"; |
| 756 | guard += StringHelper::Uppercase(packageFQName.tokenName()); |
| 757 | guard += "_"; |
| 758 | guard += "EXPORTED_CONSTANTS_H_"; |
| 759 | |
| 760 | out << "#ifndef " |
| 761 | << guard |
| 762 | << "\n#define " |
| 763 | << guard |
| 764 | << "\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"; |
| 765 | } |
| 766 | |
| 767 | for (const auto &type : exportedTypes) { |
| 768 | type->emitExportedHeader(out, forJava); |
| 769 | } |
| 770 | |
| 771 | if (forJava) { |
| 772 | out.unindent(); |
| 773 | out << "}\n"; |
| 774 | } else { |
| 775 | out << "#ifdef __cplusplus\n}\n#endif\n\n#endif // " |
| 776 | << guard |
| 777 | << "\n"; |
| 778 | } |
| 779 | |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 780 | return OK; |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 781 | }; |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 782 | } |
| 783 | |
Steven Moreland | f2e4469 | 2017-04-18 20:19:09 -0700 | [diff] [blame] | 784 | static status_t generateHashOutput(const FQName &fqName, |
| 785 | const char* /*hidl_gen*/, |
| 786 | Coordinator *coordinator, |
| 787 | const std::string & /*outputDir*/) { |
| 788 | |
| 789 | status_t err; |
| 790 | std::vector<FQName> packageInterfaces; |
| 791 | |
| 792 | if (fqName.isFullyQualified()) { |
| 793 | packageInterfaces = {fqName}; |
| 794 | } else { |
| 795 | err = coordinator->appendPackageInterfacesToVector( |
| 796 | fqName, &packageInterfaces); |
| 797 | if (err != OK) { |
| 798 | return err; |
| 799 | } |
| 800 | } |
| 801 | |
| 802 | for (const auto ¤tFqName : packageInterfaces) { |
Steven Moreland | c59326e | 2017-06-20 15:19:30 -0700 | [diff] [blame] | 803 | AST* ast = coordinator->parse(currentFqName, {} /* parsed */, |
| 804 | Coordinator::Enforce::NO_HASH /* enforcement */); |
Steven Moreland | f2e4469 | 2017-04-18 20:19:09 -0700 | [diff] [blame] | 805 | |
| 806 | if (ast == NULL) { |
| 807 | fprintf(stderr, |
| 808 | "ERROR: Could not parse %s. Aborting.\n", |
| 809 | currentFqName.string().c_str()); |
| 810 | |
| 811 | return UNKNOWN_ERROR; |
| 812 | } |
| 813 | |
| 814 | printf("%s %s\n", |
| 815 | Hash::getHash(ast->getFilename()).hexString().c_str(), |
| 816 | currentFqName.string().c_str()); |
| 817 | } |
| 818 | |
| 819 | return OK; |
| 820 | } |
| 821 | |
Steven Moreland | 0241a84 | 2017-10-06 10:26:07 -0700 | [diff] [blame] | 822 | // clang-format off |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 823 | static std::vector<OutputHandler> formats = { |
Steven Moreland | 3b1ce26 | 2017-04-21 14:19:59 -0700 | [diff] [blame] | 824 | {"check", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 825 | "Parses the interface to see if valid but doesn't write any files.", |
Steven Moreland | 3b1ce26 | 2017-04-21 14:19:59 -0700 | [diff] [blame] | 826 | OutputHandler::NOT_NEEDED /* mOutputMode */, |
| 827 | validateForSource, |
Steven Moreland | bbbbeb8 | 2017-05-09 14:20:50 -0700 | [diff] [blame] | 828 | generationFunctionForFileOrPackage("check") |
Steven Moreland | 3b1ce26 | 2017-04-21 14:19:59 -0700 | [diff] [blame] | 829 | }, |
| 830 | |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 831 | {"c++", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 832 | "(internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.", |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 833 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 834 | validateForSource, |
Steven Moreland | bbbbeb8 | 2017-05-09 14:20:50 -0700 | [diff] [blame] | 835 | generationFunctionForFileOrPackage("c++") |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 836 | }, |
Steven Moreland | 1cbf036 | 2017-05-09 14:32:53 -0700 | [diff] [blame] | 837 | {"c++-headers", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 838 | "(internal) Generates C++ headers for interface files for talking to HIDL interfaces.", |
Steven Moreland | 1cbf036 | 2017-05-09 14:32:53 -0700 | [diff] [blame] | 839 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
| 840 | validateForSource, |
| 841 | generationFunctionForFileOrPackage("c++-headers") |
| 842 | }, |
Steven Moreland | 1cbf036 | 2017-05-09 14:32:53 -0700 | [diff] [blame] | 843 | {"c++-sources", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 844 | "(internal) Generates C++ sources for interface files for talking to HIDL interfaces.", |
Steven Moreland | 1cbf036 | 2017-05-09 14:32:53 -0700 | [diff] [blame] | 845 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
| 846 | validateForSource, |
| 847 | generationFunctionForFileOrPackage("c++-sources") |
| 848 | }, |
| 849 | |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 850 | {"export-header", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 851 | "Generates a header file from @export enumerations to help maintain legacy code.", |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 852 | OutputHandler::NEEDS_FILE /* mOutputMode */, |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 853 | validateIsPackage, |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 854 | generateExportHeaderForPackage(false /* forJava */) |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 855 | }, |
| 856 | |
Steven Moreland | 9c38761 | 2016-09-07 09:54:26 -0700 | [diff] [blame] | 857 | {"c++-impl", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 858 | "Generates boilerplate implementation of a hidl interface in C++ (for convenience).", |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 859 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
Steven Moreland | 9c38761 | 2016-09-07 09:54:26 -0700 | [diff] [blame] | 860 | validateForSource, |
Steven Moreland | bbbbeb8 | 2017-05-09 14:20:50 -0700 | [diff] [blame] | 861 | generationFunctionForFileOrPackage("c++-impl") |
Steven Moreland | 9c38761 | 2016-09-07 09:54:26 -0700 | [diff] [blame] | 862 | }, |
Steven Moreland | f2a0f5b | 2017-07-18 20:39:11 -0700 | [diff] [blame] | 863 | {"c++-impl-headers", |
| 864 | "c++-impl but headers only", |
| 865 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
| 866 | validateForSource, |
| 867 | generationFunctionForFileOrPackage("c++-impl-headers") |
| 868 | }, |
| 869 | {"c++-impl-sources", |
| 870 | "c++-impl but sources only", |
| 871 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
| 872 | validateForSource, |
| 873 | generationFunctionForFileOrPackage("c++-impl-sources") |
| 874 | }, |
Steven Moreland | 9c38761 | 2016-09-07 09:54:26 -0700 | [diff] [blame] | 875 | |
Steven Moreland | 9a6da7a | 2017-09-15 16:21:24 -0700 | [diff] [blame] | 876 | {"c++-adapter", |
| 877 | "Takes a x.(y+n) interface and mocks an x.y interface.", |
| 878 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
| 879 | validateForSource, |
| 880 | generationFunctionForFileOrPackage("c++-adapter") |
| 881 | }, |
| 882 | {"c++-adapter-headers", |
Steven Moreland | b9a9492 | 2017-10-10 15:16:35 -0700 | [diff] [blame] | 883 | "c++-adapter but helper headers only", |
Steven Moreland | 9a6da7a | 2017-09-15 16:21:24 -0700 | [diff] [blame] | 884 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
| 885 | validateForSource, |
| 886 | generationFunctionForFileOrPackage("c++-adapter-headers") |
| 887 | }, |
| 888 | {"c++-adapter-sources", |
Steven Moreland | b9a9492 | 2017-10-10 15:16:35 -0700 | [diff] [blame] | 889 | "c++-adapter but helper sources only", |
Steven Moreland | 9a6da7a | 2017-09-15 16:21:24 -0700 | [diff] [blame] | 890 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
| 891 | validateForSource, |
| 892 | generationFunctionForFileOrPackage("c++-adapter-sources") |
| 893 | }, |
| 894 | {"c++-adapter-main", |
Steven Moreland | b9a9492 | 2017-10-10 15:16:35 -0700 | [diff] [blame] | 895 | "c++-adapter but the adapter binary source only", |
Steven Moreland | 9a6da7a | 2017-09-15 16:21:24 -0700 | [diff] [blame] | 896 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
| 897 | validateIsPackage, |
| 898 | generateAdapterMainSource, |
| 899 | }, |
| 900 | |
Andreas Huber | 2831d51 | 2016-08-15 09:33:47 -0700 | [diff] [blame] | 901 | {"java", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 902 | "(internal) Generates Java library for talking to HIDL interfaces in Java.", |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 903 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 904 | validateForSource, |
Steven Moreland | bbbbeb8 | 2017-05-09 14:20:50 -0700 | [diff] [blame] | 905 | generationFunctionForFileOrPackage("java") |
Andreas Huber | 2831d51 | 2016-08-15 09:33:47 -0700 | [diff] [blame] | 906 | }, |
| 907 | |
Andreas Huber | 1c50727 | 2016-10-05 14:33:21 -0700 | [diff] [blame] | 908 | {"java-constants", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 909 | "(internal) Like export-header but for Java (always created by -Lmakefile if @export exists).", |
Andreas Huber | 1c50727 | 2016-10-05 14:33:21 -0700 | [diff] [blame] | 910 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 911 | validateIsPackage, |
Steven Moreland | f47912d | 2017-05-12 16:25:44 -0700 | [diff] [blame] | 912 | generateExportHeaderForPackage(true /* forJava */) |
Andreas Huber | 1c50727 | 2016-10-05 14:33:21 -0700 | [diff] [blame] | 913 | }, |
| 914 | |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 915 | {"vts", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 916 | "(internal) Generates vts proto files for use in vtsd.", |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 917 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 918 | validateForSource, |
Steven Moreland | bbbbeb8 | 2017-05-09 14:20:50 -0700 | [diff] [blame] | 919 | generationFunctionForFileOrPackage("vts") |
Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 920 | }, |
| 921 | |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 922 | {"makefile", |
Steven Moreland | 887b84c | 2017-10-09 18:40:58 -0700 | [diff] [blame] | 923 | "(removed) Used to generate makefiles for -Ljava and -Ljava-constants.", |
Steven Moreland | a171b56 | 2017-05-12 15:18:03 -0700 | [diff] [blame] | 924 | OutputHandler::NEEDS_SRC /* mOutputMode */, |
Steven Moreland | 887b84c | 2017-10-09 18:40:58 -0700 | [diff] [blame] | 925 | [](const FQName &, const std::string &) { |
| 926 | fprintf(stderr, "ERROR: makefile output is not supported. Use -Landroidbp for all build file generation.\n"); |
| 927 | return false; |
| 928 | }, |
| 929 | nullptr, |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 930 | }, |
Steven Moreland | 197d56c | 2016-09-09 10:03:58 -0700 | [diff] [blame] | 931 | |
Dan Willemsen | 676abdc | 2016-09-28 19:42:22 -0700 | [diff] [blame] | 932 | {"androidbp", |
Steven Moreland | 887b84c | 2017-10-09 18:40:58 -0700 | [diff] [blame] | 933 | "(internal) Generates Soong bp files for -Lc++-headers, -Lc++-sources, -Ljava, -Ljava-constants, and -Lc++-adapter.", |
Steven Moreland | a171b56 | 2017-05-12 15:18:03 -0700 | [diff] [blame] | 934 | OutputHandler::NEEDS_SRC /* mOutputMode */, |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 935 | validateIsPackage, |
Dan Willemsen | 676abdc | 2016-09-28 19:42:22 -0700 | [diff] [blame] | 936 | generateAndroidBpForPackage, |
| 937 | }, |
| 938 | |
Yifan Hong | 958ee46 | 2016-12-06 17:09:51 -0800 | [diff] [blame] | 939 | {"androidbp-impl", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 940 | "Generates boilerplate bp files for implementation created with -Lc++-impl.", |
Yifan Hong | 94bcea0 | 2016-10-06 13:51:31 -0700 | [diff] [blame] | 941 | OutputHandler::NEEDS_DIR /* mOutputMode */, |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 942 | validateIsPackage, |
Yifan Hong | 958ee46 | 2016-12-06 17:09:51 -0800 | [diff] [blame] | 943 | generateAndroidBpImplForPackage, |
Steven Moreland | f2e4469 | 2017-04-18 20:19:09 -0700 | [diff] [blame] | 944 | }, |
| 945 | |
| 946 | {"hash", |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 947 | "Prints hashes of interface in `current.txt` format to standard out.", |
Steven Moreland | f2e4469 | 2017-04-18 20:19:09 -0700 | [diff] [blame] | 948 | OutputHandler::NOT_NEEDED /* mOutputMode */, |
| 949 | validateForSource, |
| 950 | generateHashOutput, |
| 951 | }, |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 952 | }; |
Steven Moreland | 0241a84 | 2017-10-06 10:26:07 -0700 | [diff] [blame] | 953 | // clang-format on |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 954 | |
| 955 | static void usage(const char *me) { |
| 956 | fprintf(stderr, |
Steven Moreland | 37c57ee | 2017-09-25 19:08:56 -0700 | [diff] [blame] | 957 | "usage: %s [-p <root path>] -o <output path> -L <language> (-r <interface root>)+ [-t] [-v]" |
Jiyong Park | 3728325 | 2017-08-29 14:11:48 +0900 | [diff] [blame] | 958 | "fqname+\n", |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 959 | me); |
| 960 | |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 961 | fprintf(stderr, " -h: Prints this menu.\n"); |
| 962 | fprintf(stderr, " -L <language>: The following options are available:\n"); |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 963 | for (auto &e : formats) { |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 964 | fprintf(stderr, " %-16s: %s\n", e.name().c_str(), e.description().c_str()); |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 965 | } |
Steven Moreland | 97e5233 | 2017-05-12 16:47:19 -0700 | [diff] [blame] | 966 | fprintf(stderr, " -o <output path>: Location to output files.\n"); |
| 967 | fprintf(stderr, " -p <root path>: Android build root, defaults to $ANDROID_BUILD_TOP or pwd.\n"); |
| 968 | fprintf(stderr, " -r <package:path root>: E.g., android.hardware:hardware/interfaces.\n"); |
Jiyong Park | 3728325 | 2017-08-29 14:11:48 +0900 | [diff] [blame] | 969 | fprintf(stderr, " -t: generate build scripts (Android.bp) for tests.\n"); |
Steven Moreland | 37c57ee | 2017-09-25 19:08:56 -0700 | [diff] [blame] | 970 | fprintf(stderr, " -v: verbose output (locations of touched files).\n"); |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 971 | } |
| 972 | |
Andreas Gampe | c4ce926 | 2017-04-27 21:03:20 -0700 | [diff] [blame] | 973 | // hidl is intentionally leaky. Turn off LeakSanitizer by default. |
| 974 | extern "C" const char *__asan_default_options() { |
Evgenii Stepanov | a3ee97c | 2017-08-16 14:59:29 -0700 | [diff] [blame] | 975 | return "detect_leaks=0"; |
Andreas Gampe | c4ce926 | 2017-04-27 21:03:20 -0700 | [diff] [blame] | 976 | } |
| 977 | |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 978 | int main(int argc, char **argv) { |
Andreas Huber | 737080b | 2016-08-02 15:38:04 -0700 | [diff] [blame] | 979 | const char *me = argv[0]; |
Steven Moreland | 3db99f2 | 2017-05-11 16:21:46 -0700 | [diff] [blame] | 980 | if (argc == 1) { |
| 981 | usage(me); |
| 982 | exit(1); |
| 983 | } |
| 984 | |
Steven Moreland | 47792c4 | 2017-09-20 10:03:20 -0700 | [diff] [blame] | 985 | OutputHandler *outputFormat = nullptr; |
| 986 | Coordinator coordinator; |
| 987 | std::string outputPath; |
| 988 | |
| 989 | const char *ANDROID_BUILD_TOP = getenv("ANDROID_BUILD_TOP"); |
| 990 | if (ANDROID_BUILD_TOP != nullptr) { |
| 991 | coordinator.setRootPath(ANDROID_BUILD_TOP); |
| 992 | } |
| 993 | |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 994 | int res; |
Steven Moreland | 37c57ee | 2017-09-25 19:08:56 -0700 | [diff] [blame] | 995 | while ((res = getopt(argc, argv, "hp:o:r:L:tv")) >= 0) { |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 996 | switch (res) { |
Steven Moreland | f7fa068 | 2017-05-11 16:14:55 -0700 | [diff] [blame] | 997 | case 'p': |
| 998 | { |
Steven Moreland | 47792c4 | 2017-09-20 10:03:20 -0700 | [diff] [blame] | 999 | coordinator.setRootPath(optarg); |
Steven Moreland | f7fa068 | 2017-05-11 16:14:55 -0700 | [diff] [blame] | 1000 | break; |
| 1001 | } |
| 1002 | |
Steven Moreland | 37c57ee | 2017-09-25 19:08:56 -0700 | [diff] [blame] | 1003 | case 'v': |
| 1004 | { |
| 1005 | coordinator.setVerbose(true); |
| 1006 | break; |
| 1007 | } |
| 1008 | |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 1009 | case 'o': |
| 1010 | { |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 1011 | outputPath = optarg; |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 1012 | break; |
| 1013 | } |
| 1014 | |
Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 1015 | case 'r': |
| 1016 | { |
| 1017 | std::string val(optarg); |
| 1018 | auto index = val.find_first_of(':'); |
Steven Moreland | 4ff7420 | 2017-04-21 14:24:47 -0700 | [diff] [blame] | 1019 | if (index == std::string::npos) { |
| 1020 | fprintf(stderr, "ERROR: -r option must contain ':': %s\n", val.c_str()); |
| 1021 | exit(1); |
| 1022 | } |
Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 1023 | |
Steven Moreland | 13594d1 | 2017-09-28 23:27:50 +0000 | [diff] [blame] | 1024 | auto root = val.substr(0, index); |
| 1025 | auto path = val.substr(index + 1); |
Steven Moreland | 47792c4 | 2017-09-20 10:03:20 -0700 | [diff] [blame] | 1026 | |
| 1027 | std::string error; |
| 1028 | status_t err = coordinator.addPackagePath(root, path, &error); |
| 1029 | if (err != OK) { |
| 1030 | fprintf(stderr, "%s\n", error.c_str()); |
| 1031 | exit(1); |
| 1032 | } |
| 1033 | |
Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 1034 | break; |
| 1035 | } |
| 1036 | |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 1037 | case 'L': |
| 1038 | { |
Steven Moreland | dd58384 | 2017-04-19 13:09:57 -0700 | [diff] [blame] | 1039 | if (outputFormat != nullptr) { |
| 1040 | fprintf(stderr, |
| 1041 | "ERROR: only one -L option allowed. \"%s\" already specified.\n", |
| 1042 | outputFormat->name().c_str()); |
| 1043 | exit(1); |
| 1044 | } |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 1045 | for (auto &e : formats) { |
Steven Moreland | dd58384 | 2017-04-19 13:09:57 -0700 | [diff] [blame] | 1046 | if (e.name() == optarg) { |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 1047 | outputFormat = &e; |
| 1048 | break; |
| 1049 | } |
| 1050 | } |
Steven Moreland | dd58384 | 2017-04-19 13:09:57 -0700 | [diff] [blame] | 1051 | if (outputFormat == nullptr) { |
| 1052 | fprintf(stderr, |
| 1053 | "ERROR: unrecognized -L option: \"%s\".\n", |
| 1054 | optarg); |
| 1055 | exit(1); |
| 1056 | } |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 1057 | break; |
| 1058 | } |
| 1059 | |
Jiyong Park | 3728325 | 2017-08-29 14:11:48 +0900 | [diff] [blame] | 1060 | case 't': { |
| 1061 | generateForTest = true; |
| 1062 | break; |
| 1063 | } |
| 1064 | |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 1065 | case '?': |
| 1066 | case 'h': |
| 1067 | default: |
| 1068 | { |
Andreas Huber | 737080b | 2016-08-02 15:38:04 -0700 | [diff] [blame] | 1069 | usage(me); |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 1070 | exit(1); |
| 1071 | break; |
| 1072 | } |
| 1073 | } |
| 1074 | } |
| 1075 | |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 1076 | if (outputFormat == nullptr) { |
Steven Moreland | dd58384 | 2017-04-19 13:09:57 -0700 | [diff] [blame] | 1077 | fprintf(stderr, |
| 1078 | "ERROR: no -L option provided.\n"); |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 1079 | exit(1); |
| 1080 | } |
| 1081 | |
Jiyong Park | 3728325 | 2017-08-29 14:11:48 +0900 | [diff] [blame] | 1082 | if (generateForTest && outputFormat->name() != "androidbp") { |
| 1083 | fprintf(stderr, "ERROR: -t option is for -Landroidbp only.\n"); |
| 1084 | exit(1); |
| 1085 | } |
| 1086 | |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 1087 | argc -= optind; |
| 1088 | argv += optind; |
| 1089 | |
Steven Moreland | 3effa83 | 2017-06-16 16:17:41 -0700 | [diff] [blame] | 1090 | if (argc == 0) { |
| 1091 | fprintf(stderr, "ERROR: no fqname specified.\n"); |
| 1092 | usage(me); |
| 1093 | exit(1); |
| 1094 | } |
| 1095 | |
Andreas Huber | 737080b | 2016-08-02 15:38:04 -0700 | [diff] [blame] | 1096 | // Valid options are now in argv[0] .. argv[argc - 1]. |
| 1097 | |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 1098 | switch (outputFormat->mOutputMode) { |
| 1099 | case OutputHandler::NEEDS_DIR: |
| 1100 | case OutputHandler::NEEDS_FILE: |
| 1101 | { |
| 1102 | if (outputPath.empty()) { |
| 1103 | usage(me); |
| 1104 | exit(1); |
| 1105 | } |
| 1106 | |
| 1107 | if (outputFormat->mOutputMode == OutputHandler::NEEDS_DIR) { |
Howard Chen | 30f6b49 | 2017-08-24 16:50:12 +0800 | [diff] [blame] | 1108 | if (outputPath.back() != '/') { |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 1109 | outputPath += "/"; |
| 1110 | } |
| 1111 | } |
| 1112 | break; |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 1113 | } |
Steven Moreland | a171b56 | 2017-05-12 15:18:03 -0700 | [diff] [blame] | 1114 | case OutputHandler::NEEDS_SRC: |
| 1115 | { |
| 1116 | if (outputPath.empty()) { |
Steven Moreland | 47792c4 | 2017-09-20 10:03:20 -0700 | [diff] [blame] | 1117 | outputPath = coordinator.getRootPath(); |
Steven Moreland | a171b56 | 2017-05-12 15:18:03 -0700 | [diff] [blame] | 1118 | } |
Howard Chen | 30f6b49 | 2017-08-24 16:50:12 +0800 | [diff] [blame] | 1119 | if (outputPath.back() != '/') { |
| 1120 | outputPath += "/"; |
| 1121 | } |
Steven Moreland | a171b56 | 2017-05-12 15:18:03 -0700 | [diff] [blame] | 1122 | |
| 1123 | break; |
| 1124 | } |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 1125 | |
| 1126 | default: |
| 1127 | outputPath.clear(); // Unused. |
| 1128 | break; |
Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 1129 | } |
| 1130 | |
Steven Moreland | 25c8166 | 2017-05-12 14:57:36 -0700 | [diff] [blame] | 1131 | coordinator.addDefaultPackagePath("android.hardware", "hardware/interfaces"); |
| 1132 | coordinator.addDefaultPackagePath("android.hidl", "system/libhidl/transport"); |
| 1133 | coordinator.addDefaultPackagePath("android.frameworks", "frameworks/hardware/interfaces"); |
| 1134 | coordinator.addDefaultPackagePath("android.system", "system/hardware/interfaces"); |
Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 1135 | |
Andreas Huber | 737080b | 2016-08-02 15:38:04 -0700 | [diff] [blame] | 1136 | for (int i = 0; i < argc; ++i) { |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame] | 1137 | FQName fqName(argv[i]); |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame] | 1138 | |
Steven Moreland | bf71421 | 2017-10-27 18:29:01 -0700 | [diff] [blame] | 1139 | // TODO(b/65200821): remove |
| 1140 | gCurrentCompileName = "_" + StringHelper::Uppercase(fqName.tokenName()); |
| 1141 | |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 1142 | if (!fqName.isValid()) { |
Andreas Huber | e61e3f7 | 2016-08-03 10:22:03 -0700 | [diff] [blame] | 1143 | fprintf(stderr, |
Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 1144 | "ERROR: Invalid fully-qualified name.\n"); |
Iliyan Malchev | 5bb1402 | 2016-08-09 15:04:39 -0700 | [diff] [blame] | 1145 | exit(1); |
| 1146 | } |
Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 1147 | |
Steven Moreland | 05951b3 | 2017-05-12 17:22:22 -0700 | [diff] [blame] | 1148 | if (!outputFormat->validate(fqName, outputFormat->name())) { |
Steven Moreland | f2e4469 | 2017-04-18 20:19:09 -0700 | [diff] [blame] | 1149 | fprintf(stderr, |
| 1150 | "ERROR: output handler failed.\n"); |
Andreas Huber | e61e3f7 | 2016-08-03 10:22:03 -0700 | [diff] [blame] | 1151 | exit(1); |
| 1152 | } |
Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame] | 1153 | |
| 1154 | status_t err = |
Andreas Huber | 019d21d | 2016-10-03 12:59:47 -0700 | [diff] [blame] | 1155 | outputFormat->generate(fqName, me, &coordinator, outputPath); |
Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame] | 1156 | |
| 1157 | if (err != OK) { |
Steven Moreland | 261370a | 2016-08-29 15:36:59 -0700 | [diff] [blame] | 1158 | exit(1); |
Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame] | 1159 | } |
Andreas Huber | eb1081f | 2016-07-28 13:13:24 -0700 | [diff] [blame] | 1160 | } |
Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 1161 | |
Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame] | 1162 | return 0; |
Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 1163 | } |