blob: 997699900fb0ffe7eceb1d055f57bc3cdd56b380 [file] [log] [blame]
Andreas Huberc9410c72016-07-28 12:18:40 -07001#include "AST.h"
Andreas Huber5345ec22016-07-29 13:33:27 -07002#include "Coordinator.h"
Andreas Huberd2943e12016-08-05 11:59:31 -07003#include "Formatter.h"
Andreas Huber84f89de2016-07-28 15:39:51 -07004#include "FQName.h"
Andreas Huberc9410c72016-07-28 12:18:40 -07005
Andreas Huber68f24592016-07-29 14:53:48 -07006#include <android-base/logging.h>
Andreas Huberc9410c72016-07-28 12:18:40 -07007#include <stdio.h>
Andreas Huberdca261f2016-08-04 13:47:51 -07008#include <string>
Andreas Huberb82318c2016-08-02 14:45:54 -07009#include <unistd.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070010#include <vector>
Andreas Huberc9410c72016-07-28 12:18:40 -070011
12using namespace android;
13
Andreas Huberb82318c2016-08-02 14:45:54 -070014static void usage(const char *me) {
Andreas Huberdca261f2016-08-04 13:47:51 -070015 fprintf(stderr,
Andreas Huberd2943e12016-08-05 11:59:31 -070016 "usage: %s -o output-path [-m] (-r interface-root)+ fqname+\n",
Andreas Huberdca261f2016-08-04 13:47:51 -070017 me);
18
19 fprintf(stderr, " -o output path\n");
Andreas Huberd2943e12016-08-05 11:59:31 -070020 fprintf(stderr, " -m generate makefile instead of sources\n");
Andreas Huberdca261f2016-08-04 13:47:51 -070021
22 fprintf(stderr,
23 " -r package:path root "
24 "(e.g., android.hardware:hardware/interfaces)\n");
Andreas Huberb82318c2016-08-02 14:45:54 -070025}
26
Andreas Huberd2943e12016-08-05 11:59:31 -070027static std::string makeLibraryName(const FQName &packageFQName) {
Iliyan Malcheve2c595a2016-08-07 21:20:04 -070028 return packageFQName.string();
Andreas Huberd2943e12016-08-05 11:59:31 -070029}
30
31static status_t generateMakefileOrSourcesForPackage(
Iliyan Malchevb66c3992016-08-07 21:18:13 -070032 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -070033 Coordinator *coordinator,
34 const std::string &outputDir,
35 bool createMakefile,
36 const FQName &packageFQName) {
37 std::vector<FQName> packageInterfaces;
38
39 status_t err =
40 coordinator->getPackageInterfaces(packageFQName, &packageInterfaces);
41
42 if (err != OK) {
43 return err;
44 }
45
46 std::set<FQName> importedPackages;
47 for (const auto &fqName : packageInterfaces) {
48 AST *ast = coordinator->parse(fqName);
49
50 if (ast == NULL) {
51 fprintf(stderr,
52 "Could not parse %s. Aborting.\n",
53 fqName.string().c_str());
54
55 return UNKNOWN_ERROR;
56 }
57
58 if (!createMakefile) {
59 status_t err = ast->generateCpp(outputDir);
60
61 if (err != OK) {
62 return err;
63 }
64 } else {
65 ast->addImportedPackages(&importedPackages);
66 }
67 }
68
69 if (!createMakefile) {
70 return OK;
71 }
72
73 std::string path =
74 coordinator->getPackagePath(packageFQName, false /* relative */);
75
76 path.append("Android.mk");
77
78 CHECK(Coordinator::MakeParentHierarchy(path));
79 FILE *file = fopen(path.c_str(), "w");
80
81 if (file == NULL) {
82 return -errno;
83 }
84
85 const std::string libraryName = makeLibraryName(packageFQName);
86
87 Formatter out(file);
88
89 out << "LOCAL_PATH := $(call my-dir)\n"
90 << "include $(CLEAR_VARS)\n\n"
91 << "LOCAL_MODULE := "
92 << libraryName
93 << "\n"
94 << "LOCAL_MODULE_CLASS := SHARED_LIBRARIES\n\n"
95 << "intermediates := $(local-generated-sources-dir)\n\n"
96 << "GEN := \\\n";
97
98 out.indent();
99 for (const auto &fqName : packageInterfaces) {
100 out << "$(intermediates)/"
101 << coordinator->convertPackageRootToPath(packageFQName)
102 << coordinator->getPackagePath(packageFQName, true /* relative */);
103
104 if (fqName.name() == "types") {
105 out << "types.cpp";
106 } else {
107 out << fqName.name().substr(1) << "All.cpp";
108 }
109
110 out << " \\\n";
111 }
112
113 out.unindent();
114
115 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)\n\n"
116 << "$(GEN): PRIVATE_CUSTOM_TOOL = \\\n";
117
118 out.indent();
119
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700120 out << hidl_gen << " -o $(PRIVATE_OUTPUT_DIR) "
Andreas Huberd2943e12016-08-05 11:59:31 -0700121 << packageFQName.string()
122 << "\n";
123
124 out.unindent();
125
126 out << "\n$(GEN): ";
127
128 bool first = true;
129 for (const auto &fqName : packageInterfaces) {
130 if (!first) {
131 out << " ";
132 }
133
134 out << "$(LOCAL_PATH)/" << fqName.name() << ".hal";
135
136 first = false;
137 }
138 out << "\n\t$(transform-generated-source)\n\n";
139
140 out << "LOCAL_GENERATED_SOURCES += $(GEN)\n\n"
141 << "LOCAL_EXPORT_C_INCLUDE_DIRS := $(intermediates)\n\n"
142 << "LOCAL_SHARED_LIBRARIES := \\\n";
143
144 out.indent();
145 out << "libhwbinder \\\n"
146 << "libutils \\\n";
147
148 for (const auto &importedPackage : importedPackages) {
149 out << makeLibraryName(importedPackage) << " \\\n";
150 }
151
152 out.unindent();
153
154 out << "\n"
155 << "include $(BUILD_SHARED_LIBRARY)\n";
156
157 return OK;
158}
159
Andreas Huberb82318c2016-08-02 14:45:54 -0700160int main(int argc, char **argv) {
161 std::string outputDir;
Andreas Huberdca261f2016-08-04 13:47:51 -0700162 std::vector<std::string> packageRootPaths;
163 std::vector<std::string> packageRoots;
Andreas Huberd2943e12016-08-05 11:59:31 -0700164 bool createMakefile = false;
Andreas Huberb82318c2016-08-02 14:45:54 -0700165
Andreas Huber737080b2016-08-02 15:38:04 -0700166 const char *me = argv[0];
167
Andreas Huberb82318c2016-08-02 14:45:54 -0700168 int res;
Andreas Huberd2943e12016-08-05 11:59:31 -0700169 while ((res = getopt(argc, argv, "hmo:r:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -0700170 switch (res) {
Andreas Huberd2943e12016-08-05 11:59:31 -0700171 case 'm':
172 {
173 createMakefile = true;
174 break;
175 }
176
Andreas Huberb82318c2016-08-02 14:45:54 -0700177 case 'o':
178 {
179 outputDir = optarg;
180 break;
181 }
182
Andreas Huberdca261f2016-08-04 13:47:51 -0700183 case 'r':
184 {
185 std::string val(optarg);
186 auto index = val.find_first_of(':');
187 CHECK(index != std::string::npos);
188
189 auto package = val.substr(0, index);
190 auto path = val.substr(index + 1);
191 packageRootPaths.push_back(path);
192 packageRoots.push_back(package);
193 break;
194 }
195
Andreas Huberb82318c2016-08-02 14:45:54 -0700196 case '?':
197 case 'h':
198 default:
199 {
Andreas Huber737080b2016-08-02 15:38:04 -0700200 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -0700201 exit(1);
202 break;
203 }
204 }
205 }
206
207 argc -= optind;
208 argv += optind;
209
Andreas Huberdca261f2016-08-04 13:47:51 -0700210 if (packageRootPaths.empty()) {
211 // Pick reasonable defaults.
212
213 packageRoots.push_back("android.hardware");
214
215 const char *TOP = getenv("TOP");
216 CHECK(TOP != NULL);
217
218 std::string path = TOP;
219 path.append("/hardware/interfaces");
220
221 packageRootPaths.push_back(path);
222 }
223
Andreas Huber737080b2016-08-02 15:38:04 -0700224 // Valid options are now in argv[0] .. argv[argc - 1].
225
Andreas Huberd2943e12016-08-05 11:59:31 -0700226 if (createMakefile) {
227 outputDir.clear(); // Unused.
228 } else if (outputDir.empty()) {
Andreas Huber737080b2016-08-02 15:38:04 -0700229 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -0700230 exit(1);
231 } else {
232 const size_t len = outputDir.size();
233 if (outputDir[len - 1] != '/') {
234 outputDir += "/";
235 }
236 }
237
Andreas Huberdca261f2016-08-04 13:47:51 -0700238 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -0700239
Andreas Huber737080b2016-08-02 15:38:04 -0700240 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -0700241 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -0700242
Andreas Huberd2943e12016-08-05 11:59:31 -0700243 if (!fqName.isValid()
244 || fqName.package().empty()
245 || fqName.version().empty()
246 || !fqName.name().empty()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -0700247 fprintf(stderr,
Andreas Huberd2943e12016-08-05 11:59:31 -0700248 "Each fqname argument should specify a valid package.\n");
Andreas Huber881227d2016-08-02 14:20:21 -0700249
Andreas Hubere61e3f72016-08-03 10:22:03 -0700250 exit(1);
251 }
Andreas Huberd2943e12016-08-05 11:59:31 -0700252
253 status_t err =
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700254 generateMakefileOrSourcesForPackage(me,
Andreas Huberd2943e12016-08-05 11:59:31 -0700255 &coordinator, outputDir, createMakefile, fqName);
256
257 if (err != OK) {
258 break;
259 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700260 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700261
Andreas Huberd2943e12016-08-05 11:59:31 -0700262 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -0700263}