blob: eef9e5507ea00460326e4e88c05b874754d9cdb3 [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(
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 Huberb82318c2016-08-02 14:45:54 -0700166int main(int argc, char **argv) {
167 std::string outputDir;
Andreas Huberdca261f2016-08-04 13:47:51 -0700168 std::vector<std::string> packageRootPaths;
169 std::vector<std::string> packageRoots;
Andreas Huberd2943e12016-08-05 11:59:31 -0700170 bool createMakefile = false;
Andreas Huberb82318c2016-08-02 14:45:54 -0700171
Andreas Huber737080b2016-08-02 15:38:04 -0700172 const char *me = argv[0];
173
Andreas Huberb82318c2016-08-02 14:45:54 -0700174 int res;
Andreas Huberd2943e12016-08-05 11:59:31 -0700175 while ((res = getopt(argc, argv, "hmo:r:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -0700176 switch (res) {
Andreas Huberd2943e12016-08-05 11:59:31 -0700177 case 'm':
178 {
179 createMakefile = true;
180 break;
181 }
182
Andreas Huberb82318c2016-08-02 14:45:54 -0700183 case 'o':
184 {
185 outputDir = optarg;
186 break;
187 }
188
Andreas Huberdca261f2016-08-04 13:47:51 -0700189 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 Huberb82318c2016-08-02 14:45:54 -0700202 case '?':
203 case 'h':
204 default:
205 {
Andreas Huber737080b2016-08-02 15:38:04 -0700206 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -0700207 exit(1);
208 break;
209 }
210 }
211 }
212
213 argc -= optind;
214 argv += optind;
215
Andreas Huberdca261f2016-08-04 13:47:51 -0700216 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 Huber737080b2016-08-02 15:38:04 -0700230 // Valid options are now in argv[0] .. argv[argc - 1].
231
Andreas Huberd2943e12016-08-05 11:59:31 -0700232 if (createMakefile) {
233 outputDir.clear(); // Unused.
234 } else if (outputDir.empty()) {
Andreas Huber737080b2016-08-02 15:38:04 -0700235 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -0700236 exit(1);
237 } else {
238 const size_t len = outputDir.size();
239 if (outputDir[len - 1] != '/') {
240 outputDir += "/";
241 }
242 }
243
Andreas Huberdca261f2016-08-04 13:47:51 -0700244 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -0700245
Andreas Huber737080b2016-08-02 15:38:04 -0700246 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -0700247 FQName fqName(argv[i]);
Andreas Huber68f24592016-07-29 14:53:48 -0700248
Andreas Huberd2943e12016-08-05 11:59:31 -0700249 if (!fqName.isValid()
250 || fqName.package().empty()
251 || fqName.version().empty()
252 || !fqName.name().empty()) {
Andreas Hubere61e3f72016-08-03 10:22:03 -0700253 fprintf(stderr,
Andreas Huberd2943e12016-08-05 11:59:31 -0700254 "Each fqname argument should specify a valid package.\n");
Andreas Huber881227d2016-08-02 14:20:21 -0700255
Andreas Hubere61e3f72016-08-03 10:22:03 -0700256 exit(1);
257 }
Andreas Huberd2943e12016-08-05 11:59:31 -0700258
259 status_t err =
260 generateMakefileOrSourcesForPackage(
261 &coordinator, outputDir, createMakefile, fqName);
262
263 if (err != OK) {
264 break;
265 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700266 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700267
Andreas Huberd2943e12016-08-05 11:59:31 -0700268 return 0;
Andreas Huberc9410c72016-07-28 12:18:40 -0700269}