blob: cf35b150dbe2e661e018887cc1906fce653caf47 [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) {
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
38static status_t generateMakefileOrSourcesForPackage(
Iliyan Malchevb66c3992016-08-07 21:18:13 -070039 const char *hidl_gen,
Andreas Huberd2943e12016-08-05 11:59:31 -070040 Coordinator *coordinator,
41 const std::string &outputDir,
42 bool createMakefile,
43 const FQName &packageFQName) {
44 std::vector<FQName> packageInterfaces;
45
46 status_t err =
47 coordinator->getPackageInterfaces(packageFQName, &packageInterfaces);
48
49 if (err != OK) {
50 return err;
51 }
52
53 std::set<FQName> importedPackages;
54 for (const auto &fqName : packageInterfaces) {
55 AST *ast = coordinator->parse(fqName);
56
57 if (ast == NULL) {
58 fprintf(stderr,
59 "Could not parse %s. Aborting.\n",
60 fqName.string().c_str());
61
62 return UNKNOWN_ERROR;
63 }
64
65 if (!createMakefile) {
66 status_t err = ast->generateCpp(outputDir);
67
68 if (err != OK) {
69 return err;
70 }
71 } else {
72 ast->addImportedPackages(&importedPackages);
73 }
74 }
75
76 if (!createMakefile) {
77 return OK;
78 }
79
80 std::string path =
81 coordinator->getPackagePath(packageFQName, false /* relative */);
82
83 path.append("Android.mk");
84
85 CHECK(Coordinator::MakeParentHierarchy(path));
86 FILE *file = fopen(path.c_str(), "w");
87
88 if (file == NULL) {
89 return -errno;
90 }
91
92 const std::string libraryName = makeLibraryName(packageFQName);
93
94 Formatter out(file);
95
96 out << "LOCAL_PATH := $(call my-dir)\n"
97 << "include $(CLEAR_VARS)\n\n"
98 << "LOCAL_MODULE := "
99 << libraryName
100 << "\n"
101 << "LOCAL_MODULE_CLASS := SHARED_LIBRARIES\n\n"
102 << "intermediates := $(local-generated-sources-dir)\n\n"
103 << "GEN := \\\n";
104
105 out.indent();
106 for (const auto &fqName : packageInterfaces) {
107 out << "$(intermediates)/"
108 << coordinator->convertPackageRootToPath(packageFQName)
109 << coordinator->getPackagePath(packageFQName, true /* relative */);
110
111 if (fqName.name() == "types") {
112 out << "types.cpp";
113 } else {
114 out << fqName.name().substr(1) << "All.cpp";
115 }
116
117 out << " \\\n";
118 }
119
120 out.unindent();
121
122 out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)\n\n"
123 << "$(GEN): PRIVATE_CUSTOM_TOOL = \\\n";
124
125 out.indent();
126
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700127 out << hidl_gen << " -o $(PRIVATE_OUTPUT_DIR) "
Andreas Huberd2943e12016-08-05 11:59:31 -0700128 << packageFQName.string()
129 << "\n";
130
131 out.unindent();
132
133 out << "\n$(GEN): ";
134
135 bool first = true;
136 for (const auto &fqName : packageInterfaces) {
137 if (!first) {
138 out << " ";
139 }
140
141 out << "$(LOCAL_PATH)/" << fqName.name() << ".hal";
142
143 first = false;
144 }
145 out << "\n\t$(transform-generated-source)\n\n";
146
147 out << "LOCAL_GENERATED_SOURCES += $(GEN)\n\n"
148 << "LOCAL_EXPORT_C_INCLUDE_DIRS := $(intermediates)\n\n"
149 << "LOCAL_SHARED_LIBRARIES := \\\n";
150
151 out.indent();
152 out << "libhwbinder \\\n"
153 << "libutils \\\n";
154
155 for (const auto &importedPackage : importedPackages) {
156 out << makeLibraryName(importedPackage) << " \\\n";
157 }
158
159 out.unindent();
160
161 out << "\n"
162 << "include $(BUILD_SHARED_LIBRARY)\n";
163
164 return OK;
165}
166
Andreas Huberb82318c2016-08-02 14:45:54 -0700167int main(int argc, char **argv) {
168 std::string outputDir;
Andreas Huberdca261f2016-08-04 13:47:51 -0700169 std::vector<std::string> packageRootPaths;
170 std::vector<std::string> packageRoots;
Andreas Huberd2943e12016-08-05 11:59:31 -0700171 bool createMakefile = false;
Andreas Huberb82318c2016-08-02 14:45:54 -0700172
Andreas Huber737080b2016-08-02 15:38:04 -0700173 const char *me = argv[0];
174
Andreas Huberb82318c2016-08-02 14:45:54 -0700175 int res;
Andreas Huberd2943e12016-08-05 11:59:31 -0700176 while ((res = getopt(argc, argv, "hmo:r:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -0700177 switch (res) {
Andreas Huberd2943e12016-08-05 11:59:31 -0700178 case 'm':
179 {
180 createMakefile = true;
181 break;
182 }
183
Andreas Huberb82318c2016-08-02 14:45:54 -0700184 case 'o':
185 {
186 outputDir = optarg;
187 break;
188 }
189
Andreas Huberdca261f2016-08-04 13:47:51 -0700190 case 'r':
191 {
192 std::string val(optarg);
193 auto index = val.find_first_of(':');
194 CHECK(index != std::string::npos);
195
196 auto package = val.substr(0, index);
197 auto path = val.substr(index + 1);
198 packageRootPaths.push_back(path);
199 packageRoots.push_back(package);
200 break;
201 }
202
Andreas Huberb82318c2016-08-02 14:45:54 -0700203 case '?':
204 case 'h':
205 default:
206 {
Andreas Huber737080b2016-08-02 15:38:04 -0700207 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -0700208 exit(1);
209 break;
210 }
211 }
212 }
213
214 argc -= optind;
215 argv += optind;
216
Andreas Huberdca261f2016-08-04 13:47:51 -0700217 if (packageRootPaths.empty()) {
218 // Pick reasonable defaults.
219
220 packageRoots.push_back("android.hardware");
221
222 const char *TOP = getenv("TOP");
223 CHECK(TOP != NULL);
224
225 std::string path = TOP;
226 path.append("/hardware/interfaces");
227
228 packageRootPaths.push_back(path);
229 }
230
Andreas Huber737080b2016-08-02 15:38:04 -0700231 // Valid options are now in argv[0] .. argv[argc - 1].
232
Andreas Huberd2943e12016-08-05 11:59:31 -0700233 if (createMakefile) {
234 outputDir.clear(); // Unused.
235 } else if (outputDir.empty()) {
Andreas Huber737080b2016-08-02 15:38:04 -0700236 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -0700237 exit(1);
238 } else {
239 const size_t len = outputDir.size();
240 if (outputDir[len - 1] != '/') {
241 outputDir += "/";
242 }
243 }
244
Andreas Huberdca261f2016-08-04 13:47:51 -0700245 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -0700246
Andreas Huber737080b2016-08-02 15:38:04 -0700247 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -0700248 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -0700249
Andreas Huberd2943e12016-08-05 11:59:31 -0700250 if (!fqName.isValid()
251 || fqName.package().empty()
252 || fqName.version().empty()
253 || !fqName.name().empty()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -0700254 fprintf(stderr,
Andreas Huberd2943e12016-08-05 11:59:31 -0700255 "Each fqname argument should specify a valid package.\n");
Andreas Huber881227d2016-08-02 14:20:21 -0700256
Andreas Hubere61e3f72016-08-03 10:22:03 -0700257 exit(1);
258 }
Andreas Huberd2943e12016-08-05 11:59:31 -0700259
260 status_t err =
Iliyan Malchevb66c3992016-08-07 21:18:13 -0700261 generateMakefileOrSourcesForPackage(me,
Andreas Huberd2943e12016-08-05 11:59:31 -0700262 &coordinator, outputDir, createMakefile, fqName);
263
264 if (err != OK) {
265 break;
266 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700267 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700268
Andreas Huberd2943e12016-08-05 11:59:31 -0700269 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -0700270}