| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 1 | #include "AST.h" | 
| Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 2 | #include "Coordinator.h" | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 3 | #include "Formatter.h" | 
| Andreas Huber | 84f89de | 2016-07-28 15:39:51 -0700 | [diff] [blame] | 4 | #include "FQName.h" | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 5 |  | 
| Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame] | 6 | #include <android-base/logging.h> | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 7 | #include <stdio.h> | 
| Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 8 | #include <string> | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 9 | #include <unistd.h> | 
| Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 10 | #include <vector> | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 11 |  | 
|  | 12 | using namespace android; | 
|  | 13 |  | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 14 | static void usage(const char *me) { | 
| Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 15 | fprintf(stderr, | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 16 | "usage: %s -o output-path [-m] (-r interface-root)+ fqname+\n", | 
| Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 17 | me); | 
|  | 18 |  | 
|  | 19 | fprintf(stderr, "         -o output path\n"); | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 20 | fprintf(stderr, "         -m generate makefile instead of sources\n"); | 
| Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 21 |  | 
|  | 22 | fprintf(stderr, | 
|  | 23 | "         -r package:path root " | 
|  | 24 | "(e.g., android.hardware:hardware/interfaces)\n"); | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 25 | } | 
|  | 26 |  | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 27 | static std::string makeLibraryName(const FQName &packageFQName) { | 
|  | 28 | std::vector<std::string> components; | 
|  | 29 | packageFQName.getPackageAndVersionComponents( | 
|  | 30 | &components, true /* cpp_compatible */); | 
|  | 31 |  | 
|  | 32 | const std::string libraryName = | 
|  | 33 | "lib_" + FQName::JoinStrings(components, "_"); | 
|  | 34 |  | 
|  | 35 | return libraryName; | 
|  | 36 | } | 
|  | 37 |  | 
|  | 38 | static status_t generateMakefileOrSourcesForPackage( | 
|  | 39 | Coordinator *coordinator, | 
|  | 40 | const std::string &outputDir, | 
|  | 41 | bool createMakefile, | 
|  | 42 | const FQName &packageFQName) { | 
|  | 43 | std::vector<FQName> packageInterfaces; | 
|  | 44 |  | 
|  | 45 | status_t err = | 
|  | 46 | coordinator->getPackageInterfaces(packageFQName, &packageInterfaces); | 
|  | 47 |  | 
|  | 48 | if (err != OK) { | 
|  | 49 | return err; | 
|  | 50 | } | 
|  | 51 |  | 
|  | 52 | std::set<FQName> importedPackages; | 
|  | 53 | for (const auto &fqName : packageInterfaces) { | 
|  | 54 | AST *ast = coordinator->parse(fqName); | 
|  | 55 |  | 
|  | 56 | if (ast == NULL) { | 
|  | 57 | fprintf(stderr, | 
|  | 58 | "Could not parse %s. Aborting.\n", | 
|  | 59 | fqName.string().c_str()); | 
|  | 60 |  | 
|  | 61 | return UNKNOWN_ERROR; | 
|  | 62 | } | 
|  | 63 |  | 
|  | 64 | if (!createMakefile) { | 
|  | 65 | status_t err = ast->generateCpp(outputDir); | 
|  | 66 |  | 
|  | 67 | if (err != OK) { | 
|  | 68 | return err; | 
|  | 69 | } | 
|  | 70 | } else { | 
|  | 71 | ast->addImportedPackages(&importedPackages); | 
|  | 72 | } | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | if (!createMakefile) { | 
|  | 76 | return OK; | 
|  | 77 | } | 
|  | 78 |  | 
|  | 79 | std::string path = | 
|  | 80 | coordinator->getPackagePath(packageFQName, false /* relative */); | 
|  | 81 |  | 
|  | 82 | path.append("Android.mk"); | 
|  | 83 |  | 
|  | 84 | CHECK(Coordinator::MakeParentHierarchy(path)); | 
|  | 85 | FILE *file = fopen(path.c_str(), "w"); | 
|  | 86 |  | 
|  | 87 | if (file == NULL) { | 
|  | 88 | return -errno; | 
|  | 89 | } | 
|  | 90 |  | 
|  | 91 | const std::string libraryName = makeLibraryName(packageFQName); | 
|  | 92 |  | 
|  | 93 | Formatter out(file); | 
|  | 94 |  | 
|  | 95 | out << "LOCAL_PATH := $(call my-dir)\n" | 
|  | 96 | << "include $(CLEAR_VARS)\n\n" | 
|  | 97 | << "LOCAL_MODULE := " | 
|  | 98 | << libraryName | 
|  | 99 | << "\n" | 
|  | 100 | << "LOCAL_MODULE_CLASS := SHARED_LIBRARIES\n\n" | 
|  | 101 | << "intermediates := $(local-generated-sources-dir)\n\n" | 
|  | 102 | << "GEN := \\\n"; | 
|  | 103 |  | 
|  | 104 | out.indent(); | 
|  | 105 | for (const auto &fqName : packageInterfaces) { | 
|  | 106 | out << "$(intermediates)/" | 
|  | 107 | << coordinator->convertPackageRootToPath(packageFQName) | 
|  | 108 | << coordinator->getPackagePath(packageFQName, true /* relative */); | 
|  | 109 |  | 
|  | 110 | if (fqName.name() == "types") { | 
|  | 111 | out << "types.cpp"; | 
|  | 112 | } else { | 
|  | 113 | out << fqName.name().substr(1) << "All.cpp"; | 
|  | 114 | } | 
|  | 115 |  | 
|  | 116 | out << " \\\n"; | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | out.unindent(); | 
|  | 120 |  | 
|  | 121 | out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)\n\n" | 
|  | 122 | << "$(GEN): PRIVATE_CUSTOM_TOOL = \\\n"; | 
|  | 123 |  | 
|  | 124 | out.indent(); | 
|  | 125 |  | 
|  | 126 | out << "nuhidl-gen -o $(PRIVATE_OUTPUT_DIR) " | 
|  | 127 | << packageFQName.string() | 
|  | 128 | << "\n"; | 
|  | 129 |  | 
|  | 130 | out.unindent(); | 
|  | 131 |  | 
|  | 132 | out << "\n$(GEN): "; | 
|  | 133 |  | 
|  | 134 | bool first = true; | 
|  | 135 | for (const auto &fqName : packageInterfaces) { | 
|  | 136 | if (!first) { | 
|  | 137 | out << " "; | 
|  | 138 | } | 
|  | 139 |  | 
|  | 140 | out << "$(LOCAL_PATH)/" << fqName.name() << ".hal"; | 
|  | 141 |  | 
|  | 142 | first = false; | 
|  | 143 | } | 
|  | 144 | out << "\n\t$(transform-generated-source)\n\n"; | 
|  | 145 |  | 
|  | 146 | out << "LOCAL_GENERATED_SOURCES += $(GEN)\n\n" | 
|  | 147 | << "LOCAL_EXPORT_C_INCLUDE_DIRS := $(intermediates)\n\n" | 
|  | 148 | << "LOCAL_SHARED_LIBRARIES := \\\n"; | 
|  | 149 |  | 
|  | 150 | out.indent(); | 
|  | 151 | out << "libhwbinder \\\n" | 
|  | 152 | << "libutils \\\n"; | 
|  | 153 |  | 
|  | 154 | for (const auto &importedPackage : importedPackages) { | 
|  | 155 | out << makeLibraryName(importedPackage) << " \\\n"; | 
|  | 156 | } | 
|  | 157 |  | 
|  | 158 | out.unindent(); | 
|  | 159 |  | 
|  | 160 | out << "\n" | 
|  | 161 | << "include $(BUILD_SHARED_LIBRARY)\n"; | 
|  | 162 |  | 
|  | 163 | return OK; | 
|  | 164 | } | 
|  | 165 |  | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 166 | int main(int argc, char **argv) { | 
|  | 167 | std::string outputDir; | 
| Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 168 | std::vector<std::string> packageRootPaths; | 
|  | 169 | std::vector<std::string> packageRoots; | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 170 | bool createMakefile = false; | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 171 |  | 
| Andreas Huber | 737080b | 2016-08-02 15:38:04 -0700 | [diff] [blame] | 172 | const char *me = argv[0]; | 
|  | 173 |  | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 174 | int res; | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 175 | while ((res = getopt(argc, argv, "hmo:r:")) >= 0) { | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 176 | switch (res) { | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 177 | case 'm': | 
|  | 178 | { | 
|  | 179 | createMakefile = true; | 
|  | 180 | break; | 
|  | 181 | } | 
|  | 182 |  | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 183 | case 'o': | 
|  | 184 | { | 
|  | 185 | outputDir = optarg; | 
|  | 186 | break; | 
|  | 187 | } | 
|  | 188 |  | 
| Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 189 | case 'r': | 
|  | 190 | { | 
|  | 191 | std::string val(optarg); | 
|  | 192 | auto index = val.find_first_of(':'); | 
|  | 193 | CHECK(index != std::string::npos); | 
|  | 194 |  | 
|  | 195 | auto package = val.substr(0, index); | 
|  | 196 | auto path = val.substr(index + 1); | 
|  | 197 | packageRootPaths.push_back(path); | 
|  | 198 | packageRoots.push_back(package); | 
|  | 199 | break; | 
|  | 200 | } | 
|  | 201 |  | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 202 | case '?': | 
|  | 203 | case 'h': | 
|  | 204 | default: | 
|  | 205 | { | 
| Andreas Huber | 737080b | 2016-08-02 15:38:04 -0700 | [diff] [blame] | 206 | usage(me); | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 207 | exit(1); | 
|  | 208 | break; | 
|  | 209 | } | 
|  | 210 | } | 
|  | 211 | } | 
|  | 212 |  | 
|  | 213 | argc -= optind; | 
|  | 214 | argv += optind; | 
|  | 215 |  | 
| Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 216 | if (packageRootPaths.empty()) { | 
|  | 217 | // Pick reasonable defaults. | 
|  | 218 |  | 
|  | 219 | packageRoots.push_back("android.hardware"); | 
|  | 220 |  | 
|  | 221 | const char *TOP = getenv("TOP"); | 
|  | 222 | CHECK(TOP != NULL); | 
|  | 223 |  | 
|  | 224 | std::string path = TOP; | 
|  | 225 | path.append("/hardware/interfaces"); | 
|  | 226 |  | 
|  | 227 | packageRootPaths.push_back(path); | 
|  | 228 | } | 
|  | 229 |  | 
| Andreas Huber | 737080b | 2016-08-02 15:38:04 -0700 | [diff] [blame] | 230 | // Valid options are now in argv[0] .. argv[argc - 1]. | 
|  | 231 |  | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 232 | if (createMakefile) { | 
|  | 233 | outputDir.clear();  // Unused. | 
|  | 234 | } else if (outputDir.empty()) { | 
| Andreas Huber | 737080b | 2016-08-02 15:38:04 -0700 | [diff] [blame] | 235 | usage(me); | 
| Andreas Huber | b82318c | 2016-08-02 14:45:54 -0700 | [diff] [blame] | 236 | exit(1); | 
|  | 237 | } else { | 
|  | 238 | const size_t len = outputDir.size(); | 
|  | 239 | if (outputDir[len - 1] != '/') { | 
|  | 240 | outputDir += "/"; | 
|  | 241 | } | 
|  | 242 | } | 
|  | 243 |  | 
| Andreas Huber | dca261f | 2016-08-04 13:47:51 -0700 | [diff] [blame] | 244 | Coordinator coordinator(packageRootPaths, packageRoots); | 
| Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 245 |  | 
| Andreas Huber | 737080b | 2016-08-02 15:38:04 -0700 | [diff] [blame] | 246 | for (int i = 0; i < argc; ++i) { | 
| Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame] | 247 | FQName fqName(argv[i]); | 
| Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame] | 248 |  | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 249 | if (!fqName.isValid() | 
|  | 250 | || fqName.package().empty() | 
|  | 251 | || fqName.version().empty() | 
|  | 252 | || !fqName.name().empty()) { | 
| Andreas Huber | e61e3f7 | 2016-08-03 10:22:03 -0700 | [diff] [blame] | 253 | fprintf(stderr, | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 254 | "Each fqname argument should specify a valid package.\n"); | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 255 |  | 
| Andreas Huber | e61e3f7 | 2016-08-03 10:22:03 -0700 | [diff] [blame] | 256 | exit(1); | 
|  | 257 | } | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 258 |  | 
|  | 259 | status_t err = | 
|  | 260 | generateMakefileOrSourcesForPackage( | 
|  | 261 | &coordinator, outputDir, createMakefile, fqName); | 
|  | 262 |  | 
|  | 263 | if (err != OK) { | 
|  | 264 | break; | 
|  | 265 | } | 
| Andreas Huber | eb1081f | 2016-07-28 13:13:24 -0700 | [diff] [blame] | 266 | } | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 267 |  | 
| Andreas Huber | d2943e1 | 2016-08-05 11:59:31 -0700 | [diff] [blame^] | 268 | return 0; | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 269 | } |