1 // Copyright 2024 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gn/innerapis_publicinfo_generator.h"
6
7 #include <fstream>
8 #include <iostream>
9 #include <sys/stat.h>
10
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/json/json_reader.h"
14 #include "base/values.h"
15 #include "gn/build_settings.h"
16 #include "gn/config.h"
17 #include "gn/filesystem_utils.h"
18 #include "gn/functions.h"
19 #include "gn/ohos_components.h"
20 #include "gn/ohos_components_checker.h"
21 #include "gn/parse_tree.h"
22 #include "gn/settings.h"
23 #include "gn/substitution_writer.h"
24 #include "gn/target.h"
25 #include "gn/value.h"
26 #include "gn/standard_out.h"
27
28 InnerApiPublicInfoGenerator *InnerApiPublicInfoGenerator::instance_ = nullptr;
29
StartWith(const std::string & str,const std::string & prefix)30 static bool StartWith(const std::string &str, const std::string &prefix)
31 {
32 return (str.rfind(prefix, 0) == 0);
33 }
34
GetOutName(const Target * target,const std::string & module,const std::string & type,RustValues::CrateType crateType)35 static std::string GetOutName(const Target *target, const std::string &module, const std::string &type, RustValues::CrateType crateType)
36 {
37 std::string output = target->output_name();
38 std::string extension = target->output_extension();
39 if(extension != ""){
40 extension = "." + extension;
41 }else{
42 if (crateType == RustValues::CRATE_AUTO){
43 if (type == "shared_library") {
44 extension = ".z.so";
45 } else if (type == "static_library") {
46 extension = ".a";
47 }
48 }else{
49 if(crateType == RustValues::CRATE_RLIB){
50 extension = ".rlib";
51 }else if(crateType == RustValues::CRATE_DYLIB || crateType == RustValues::CRATE_PROC_MACRO){
52 extension = ".dylib.so";
53 } else if(crateType == RustValues::CRATE_STATICLIB){
54 extension = ".a";
55 } else if(crateType == RustValues::CRATE_CDYLIB){
56 extension = ".z.so";
57 }
58 }
59 }
60 if (output == "") {
61 output = module;
62 }
63 if (!StartWith(output , "lib") && crateType != RustValues::CRATE_BIN && type != "executable"){
64 output = "lib" + output ;
65 }
66 return output + extension;
67 }
68
GetRustCrateInfo(const Target * target,const Label & toolchain_label)69 static std::string GetRustCrateInfo(const Target* target, const Label& toolchain_label)
70 {
71 std::string info = "";
72 if (target->has_rust_values()) {
73 info += ",\n \"rust_crate_name\": \"" + target->rust_values().crate_name() + "\",";
74 info += "\n \"rust_crate_type\": \"" + RustValues::GetCrateTypeStr(RustValues::InferredCrateType(target)) + "\"";
75 auto private_deps = target->private_deps();
76 if (private_deps.size() > 0) {
77 info += ",\n \"rust_deps\": [\n ";
78 bool first = true;
79 for (const auto& dep : private_deps) {
80 std::string dep_str = dep.label.GetUserVisibleName(toolchain_label);
81 if (dep_str.find("__check") != std::string::npos ||
82 dep_str.find("__info") != std::string::npos ||
83 dep_str.find("__notice") != std::string::npos ||
84 dep_str.find("__collect") != std::string::npos) {
85 continue;
86 }
87 if (!first) {
88 info += ",\n ";
89 }
90 first = false;
91 info += "\"" + dep_str + "\"";
92 }
93 info += "\n ]";
94 }
95 }
96 return info;
97 }
98
TraverIncludeDirs(const Target * target,const OhosComponentChecker * checker,const std::string & label,Err * err)99 static bool TraverIncludeDirs(const Target *target, const OhosComponentChecker *checker,
100 const std::string &label, Err *err)
101 {
102 if (checker == nullptr) {
103 return true;
104 }
105
106 std::vector<SourceDir> dirs = target->include_dirs();
107 for (const SourceDir &dir : dirs) {
108 if (!checker->CheckIncludesAbsoluteDepsOther(target, label, dir.value(), err)) {
109 return false;
110 }
111 }
112 return true;
113 }
114
CheckIncludes(const Target * target,const OhosComponentChecker * checker,const std::string & dir,Err * err,bool isPublic)115 static bool CheckIncludes(const Target *target, const OhosComponentChecker *checker,
116 const std::string &dir, Err *err, bool isPublic)
117 {
118 std::string label = target->label().GetUserVisibleName(false);
119 if (isPublic) {
120 if (checker != nullptr) {
121 if (!checker->CheckInnerApiIncludesOverRange(target, label, dir, err)) {
122 return false;
123 }
124 }
125 }
126 if (checker != nullptr) {
127 if (!checker->CheckIncludesAbsoluteDepsOther(target, label, dir, err)) {
128 return false;
129 }
130 }
131 return true;
132 }
133
ReplaceDoubleQuotes(const std::string & input)134 static std::string ReplaceDoubleQuotes(const std::string &input) {
135 std::string result;
136 for (char c : input) {
137 if (c == '"') {
138 result += "\\\"";
139 } else {
140 result += c;
141 }
142 }
143 return result;
144 }
145
GetSingleFlagInfo(const std::string & name,const std::vector<std::string> & flags)146 static std::string GetSingleFlagInfo(const std::string &name, const std::vector<std::string> &flags)
147 {
148 std::string info;
149 if (!flags.empty()) {
150 info +=",\n \"";
151 info += name;
152 info += "\": [\n ";
153 bool first = true;
154 for (const std::string &flag : flags) {
155 if (!first) {
156 info += ",\n ";
157 }
158 first = false;
159 std::string str = ReplaceDoubleQuotes(flag);
160 info += "\"" + str + "\"";
161 }
162 info += "\n ]";
163 }
164 return info;
165 }
166
GetFlagsInfo(const Config * config)167 static std::string GetFlagsInfo(const Config *config)
168 {
169 std::string info;
170 info += GetSingleFlagInfo("arflags", config->own_values().arflags());
171 info += GetSingleFlagInfo("asmflags", config->own_values().asmflags());
172 info += GetSingleFlagInfo("cflags", config->own_values().cflags());
173 info += GetSingleFlagInfo("cflags_c", config->own_values().cflags_c());
174 info += GetSingleFlagInfo("cflags_cc", config->own_values().cflags_cc());
175 info += GetSingleFlagInfo("cflags_objc", config->own_values().cflags_objc());
176 info += GetSingleFlagInfo("cflags_objcc", config->own_values().cflags_objcc());
177 info += GetSingleFlagInfo("defines", config->own_values().defines());
178 info += GetSingleFlagInfo("frameworks", config->own_values().frameworks());
179 info += GetSingleFlagInfo("weak_frameworks", config->own_values().weak_frameworks());
180 info += GetSingleFlagInfo("ldflags", config->own_values().ldflags());
181 info += GetSingleFlagInfo("rustflags", config->own_values().rustflags());
182 info += GetSingleFlagInfo("rustenv", config->own_values().rustenv());
183 info += GetSingleFlagInfo("swiftflags", config->own_values().swiftflags());
184 info += "\n";
185 return info;
186 }
187
TraverLibDirs(const Target * target,const OhosComponentChecker * checker,const std::vector<SourceDir> & dirs,Err * err)188 static bool TraverLibDirs(const Target *target, const OhosComponentChecker *checker,
189 const std::vector<SourceDir> &dirs, Err *err)
190 {
191 if (checker == nullptr) {
192 return true;
193 }
194 std::string label = target->label().GetUserVisibleName(false);
195 for (const SourceDir &dir : dirs) {
196 if (!checker->CheckLibDir(target, label, dir.value(), err)) {
197 return false;
198 }
199 }
200 return true;
201 }
202
GetIncludeDirsInfo(const Target * target,const Config * config,const OhosComponentChecker * checker,Err * err,bool isPublic)203 static std::string GetIncludeDirsInfo(const Target *target, const Config *config,
204 const OhosComponentChecker *checker, Err *err, bool isPublic)
205 {
206 std::string info = ",\n \"include_dirs\": [\n ";
207 const std::vector<SourceDir> dirs = config->own_values().include_dirs();
208 bool first = true;
209 for (const SourceDir &dir : dirs) {
210 if (!first) {
211 info += ",\n ";
212 }
213 first = false;
214 info += "\"" + dir.value() + "\"";
215 if (!CheckIncludes(target, checker, dir.value(), err, isPublic)) {
216 return "";
217 }
218 }
219
220 info += "\n ]";
221 return info;
222 }
223
GetConfigInfo(const Target * target,const UniqueVector<LabelConfigPair> & configs,const OhosComponentChecker * checker,Err * err,bool isPublic)224 static std::string GetConfigInfo(const Target *target, const UniqueVector<LabelConfigPair> &configs,
225 const OhosComponentChecker *checker, Err *err, bool isPublic)
226 {
227 std::string info = "[{";
228 bool first = true;
229 for (const auto &config : configs) {
230 const std::vector<SourceDir> lib_dirs = config.ptr->own_values().lib_dirs();
231 if (!TraverLibDirs(target, checker, lib_dirs, err)) {
232 return "";
233 }
234 std::string label = config.label.GetUserVisibleName(false);
235 if (!first) {
236 info += ", {";
237 }
238 first = false;
239 info += "\n \"label\": \"" + label + "\"";
240 info += GetIncludeDirsInfo(target, config.ptr, checker, err, isPublic);
241 info += GetFlagsInfo(config.ptr);
242 info += " }";
243 }
244 info += "]";
245 return info;
246 }
247
GetPublicConfigsInfo(const Target * target,const OhosComponentChecker * checker,Err * err)248 static std::string GetPublicConfigsInfo(const Target *target, const OhosComponentChecker *checker, Err *err)
249 {
250 std::string info = "";
251 const UniqueVector<LabelConfigPair> configs = target->own_public_configs();
252 if (configs.size() > 0) {
253 info += ",\n \"public_configs\": ";
254 std::string tmp = GetConfigInfo(target, configs, checker, err, true);
255 if (tmp == "") {
256 return "";
257 }
258 info += tmp;
259 }
260 return info;
261 }
262
GetAllDependentConfigsInfo(const Target * target,const OhosComponentChecker * checker,Err * err)263 static std::string GetAllDependentConfigsInfo(const Target *target, const OhosComponentChecker *checker, Err *err)
264 {
265 std::string info = "";
266 const UniqueVector<LabelConfigPair> all_configs = target->own_all_dependent_configs();
267 if (all_configs.size() > 0) {
268 info += ",\n \"all_dependent_configs\": ";
269 std::string tmp = GetConfigInfo(target, all_configs, checker, err, true);
270 if (tmp == "") {
271 return "";
272 }
273 info += tmp;
274 if (checker != nullptr) {
275 if (!checker->CheckAllDepsConfigs(target, target->label().GetUserVisibleName(false), err)) {
276 return "";
277 }
278 }
279 }
280 return info;
281 }
282
TraverPrivateConfigsInfo(const Target * target,const OhosComponentChecker * checker,Err * err)283 static void TraverPrivateConfigsInfo(const Target *target, const OhosComponentChecker *checker, Err *err)
284 {
285 const UniqueVector<LabelConfigPair> private_configs = target->own_configs();
286 if (private_configs.size() > 0) {
287 (void)GetConfigInfo(target, private_configs, checker, err, false);
288 }
289 }
290
GetPublicHeadersInfo(const Target * target)291 static std::string GetPublicHeadersInfo(const Target *target)
292 {
293 std::string info = "";
294 const std::vector<SourceFile> &headers = target->public_headers();
295 if (headers.size() > 0) {
296 info += ",\n \"public\": [\n ";
297 bool first = true;
298 for (const auto &header : headers) {
299 if (!first) {
300 info += ",\n ";
301 }
302 first = false;
303 info += "\"" + header.value() + "\"";
304 }
305 info += " ]";
306 }
307 return info;
308 }
309
GetPublicDepsInfo(const Target * target,const std::string & label,const OhosComponentChecker * checker,Err * err)310 static std::string GetPublicDepsInfo(const Target *target, const std::string &label,
311 const OhosComponentChecker *checker, Err *err)
312 {
313 std::string info = "";
314 const LabelTargetVector deps = target->public_deps();
315 if (deps.size() > 0) {
316 info += ",\n \"public_deps\": [\n ";
317 bool first = true;
318 for (const auto &dep : deps) {
319 if (!first) {
320 info += ",\n ";
321 }
322 first = false;
323 std::string dep_str = dep.label.GetUserVisibleName(false);
324 info += "\"" + dep_str + "\"";
325 if (checker == nullptr) {
326 continue;
327 }
328 if (!checker->CheckInnerApiPublicDepsInner(target, label, dep_str, err)) {
329 return "";
330 }
331 if (!checker->CheckPublicDeps(target, label, dep_str, err)) {
332 return "";
333 }
334 }
335 info += "\n ]";
336 }
337 return info;
338 }
339
GetOutNameAndTypeInfo(const Target * target,const std::string & module)340 static std::string GetOutNameAndTypeInfo(const Target *target, const std::string &module)
341 {
342 std::string type(Target::GetStringForOutputType(target->output_type()));
343 std::string info = "";
344 RustValues::CrateType crate_type = target->has_rust_values() ? target->rust_values().crate_type() : RustValues::CrateType::CRATE_AUTO;
345 const std::string name = GetOutName(target, module, type, crate_type);
346 const std::vector<OutputFile>& outputFiles = target->computed_outputs();
347 if (outputFiles.size() > 0) {
348 info += ",\n \"outputs\": [\n ";
349 bool first = true;
350 for (const auto& outputFile : outputFiles) {
351 if (!first) {
352 info += ",\n ";
353 }
354 first = false;
355 info += "\"" + outputFile.value() + "\"";
356 }
357 info += "\n ]";
358 }
359 info += ",\n \"out_name\":\"" + name + "\"";
360 info += ",\n \"type\":\"" + type + "\"";
361 return info;
362 }
363
GetComponentInfo(const std::string & subsystem,const std::string & component,const std::string & path)364 static std::string GetComponentInfo(const std::string &subsystem, const std::string &component, const std::string &path)
365 {
366 std::string info = "";
367 info += ",\n \"subsystem\":\"" + subsystem + "\"";
368 info += ",\n \"component\":\"" + component + "\"";
369 info += ",\n \"path\":\"" + path + "\"";
370 return info;
371 }
372
GetPublicInfo(const Target * target,const std::string & label,const OhosComponentChecker * checker,Err * err)373 static std::string GetPublicInfo(const Target *target, const std::string &label,
374 const OhosComponentChecker *checker, Err *err)
375 {
376 std::string info = GetPublicConfigsInfo(target, checker, err);
377 info += GetAllDependentConfigsInfo(target, checker, err);
378 if (target->all_headers_public()) {
379 info += ",\n \"public\": [ \"*\" ]";
380 } else {
381 info += GetPublicHeadersInfo(target);
382 }
383 info += GetPublicDepsInfo(target, label, checker, err);
384 info += "\n}\n";
385 return info;
386 }
387
GetBaseInfo(const Target * target,const std::string & label,const std::string & module,const OhosComponent * component)388 static std::string GetBaseInfo(const Target *target, const std::string &label,
389 const std::string &module, const OhosComponent *component)
390 {
391 std::string info = "{\n";
392 info += " \"label\": \"" + label + "\"";
393 info += GetOutNameAndTypeInfo(target, module);
394 info += GetRustCrateInfo(target, target->settings()->default_toolchain_label());
395 if (component != nullptr) {
396 info += GetComponentInfo(component->subsystem(), component->name(), component->path());
397 }
398 return info;
399 }
400
WritePublicInfo(const std::string & build,const std::string & module,const OhosComponent * component,const std::string & info)401 static void WritePublicInfo(const std::string &build, const std::string &module,
402 const OhosComponent *component, const std::string &info)
403 {
404 const std::string dir = build + "/" + component->subsystem() + "/" + component->name() + "/publicinfo";
405 base::FilePath path(dir);
406 base::CreateDirectory(path);
407 std::ofstream file;
408 const std::string json = dir + "/" + module + ".json";
409 file.open(json, std::ios::out);
410 file << info;
411 file.close();
412 }
413
DoGeneratedInnerapiPublicInfo(const Target * target,const OhosComponentChecker * checker,Err * err)414 void InnerApiPublicInfoGenerator::DoGeneratedInnerapiPublicInfo(const Target *target,
415 const OhosComponentChecker *checker, Err *err)
416 {
417 if (target == nullptr || (ignoreTest_ && target->testonly())) {
418 return;
419 }
420 std::string label = target->label().GetUserVisibleName(false);
421 size_t pos = label.find(":");
422 if (pos == std::string::npos) {
423 return;
424 }
425 std::string module = label.substr(pos + 1, label.length() - 1);
426 const OhosComponent *component = target->ohos_component();
427 std::string info = GetBaseInfo(target, label, module, component);
428 info += GetPublicInfo(target, label, checker, err);
429 const std::vector<SourceDir> &lib_dirs = target->config_values().lib_dirs();
430 if (!TraverLibDirs(target, checker, lib_dirs, err)) {
431 return;
432 }
433 if (!TraverIncludeDirs(target, checker, label, err)) {
434 return;
435 }
436 TraverPrivateConfigsInfo(target, checker, err);
437
438 if (target->testonly() || component == nullptr || !component->isInnerApi(label)) {
439 return;
440 }
441
442 WritePublicInfo(build_dir_, module, component, info);
443 return;
444 }
445
GeneratedInnerapiPublicInfo(const std::vector<const Target * > & items,Err * err)446 bool InnerApiPublicInfoGenerator::GeneratedInnerapiPublicInfo(const std::vector<const Target*>& items, Err *err)
447 {
448 const OhosComponentChecker *checker = OhosComponentChecker::getInstance();
449 for (const Target *item : items) {
450 if (item->ohos_component()) {
451 DoGeneratedInnerapiPublicInfo(item, checker, err);
452 if (err->has_error()) {
453 return false;
454 }
455 }
456 }
457 return true;
458 }