• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 InnerApiPublicInfoGenerator *InnerApiPublicInfoGenerator::instance_ = nullptr;
28 
StartWith(const std::string & str,const std::string prefix)29 static bool StartWith(const std::string &str, const std::string prefix)
30 {
31     return (str.rfind(prefix, 0) == 0);
32 }
33 
IsFileExists(const std::string & path)34 static bool IsFileExists(const std::string &path)
35 {
36     if (access(path.c_str(), F_OK) == 0) {
37         return true;
38     }
39     return false;
40 }
41 
GetOutName(const Scope * scope,std::string targetName,const std::string type)42 static std::string GetOutName(const Scope *scope, std::string targetName, const std::string type)
43 {
44     std::string outputName = "";
45     std::string extension = "";
46     const Value *outputNameValue = scope->GetValue("output_name");
47     const Value *extensionValue = scope->GetValue("output_extension");
48     if (outputNameValue != nullptr) {
49         outputName = outputNameValue->string_value();
50     }
51     if (extensionValue != nullptr) {
52         extension = extensionValue->string_value();
53     }
54 
55     if (outputName == "") {
56         outputName = targetName;
57     }
58     if (type == "shared_library") {
59         if (extension == "") {
60             extension = ".z.so";
61         } else {
62             extension = "." + extension;
63         }
64         if (!StartWith(outputName, "lib")) {
65             outputName = "lib" + outputName;
66         }
67     } else if (type == "static_library") {
68         extension = ".a";
69         if (!StartWith(outputName, "lib")) {
70             outputName = "lib" + outputName;
71         }
72     } else if (type == "rust_library") {
73         if (extension == "") {
74             extension = ".dylib.so";
75         } else {
76             extension = "." + extension;
77         }
78         if (!StartWith(outputName, "lib")) {
79             outputName = "lib" + outputName;
80         }
81     }
82     return outputName + extension;
83 }
84 
TraverIncludeDirs(const OhosComponentChecker * checker,const Target * target,const Scope * scope,const std::string label,Err * err)85 static bool TraverIncludeDirs(const OhosComponentChecker *checker, const Target *target, const Scope *scope,
86     const std::string label, Err *err)
87 {
88     const Value *includes = scope->GetValue("include_dirs");
89     if (includes != nullptr) {
90         const std::vector<Value> &includes_list = includes->list_value();
91         for (size_t i = 0; i < includes_list.size(); i++) {
92             SourceDir real_dir = scope->GetSourceDir().ResolveRelativeDir(includes_list[i], err,
93                 scope->settings()->build_settings()->root_path_utf8());
94             if (!checker->CheckIncludesAbsoluteDepsOther(target, label, real_dir.value(), err)) {
95                 return false;
96             }
97         }
98     }
99     return true;
100 }
101 
CheckIncludes(const OhosComponentChecker * checker,const std::string dir,bool isPublic,const PublicConfigInfoParams & params)102 static bool CheckIncludes(const OhosComponentChecker *checker, const std::string dir, bool isPublic,
103     const PublicConfigInfoParams &params)
104 {
105     const Target *target = params.target;
106     const std::string label = params.label;
107     Err *err = params.err;
108     if (isPublic) {
109         if (checker != nullptr) {
110             if (!checker->CheckInnerApiIncludesOverRange(target, label, dir, err)) {
111                 return false;
112             }
113         }
114     }
115     if (checker != nullptr) {
116         if (!checker->CheckIncludesAbsoluteDepsOther(target, label, dir, err)) {
117             return false;
118         }
119     }
120     return true;
121 }
122 
GetIncludeDirsInfo(const Config * config,const OhosComponentChecker * checker,bool isPublic,const PublicConfigInfoParams & params)123 static std::string GetIncludeDirsInfo(const Config *config, const OhosComponentChecker *checker, bool isPublic,
124     const PublicConfigInfoParams &params)
125 {
126     std::string info = ",\n    \"include_dirs\": [\n      ";
127     const std::vector<SourceDir> dirs = config->own_values().include_dirs();
128     bool first = true;
129     for (const SourceDir &dir : dirs) {
130         if (!first) {
131             info += ",\n      ";
132         }
133         first = false;
134         info += "\"" + dir.value() + "\"";
135         if (!CheckIncludes(checker, dir.value(), isPublic, params)) {
136             return "";
137         }
138     }
139     info += "\n    ]\n";
140     return info;
141 }
142 
GetPublicConfigInfo(const PublicConfigInfoParams & params,Scope * scope,const UniqueVector<LabelConfigPair> & configs,const OhosComponentChecker * checker,bool isPublic)143 static std::string GetPublicConfigInfo(const PublicConfigInfoParams &params, Scope *scope,
144     const UniqueVector<LabelConfigPair> &configs, const OhosComponentChecker *checker, bool isPublic)
145 {
146     const Target *target = params.target;
147     const std::string label = params.label;
148     Err *err = params.err;
149     Scope::ItemVector *collector = scope->GetItemCollector();
150     std::string info = "[{";
151     bool firstConfig = true;
152     for (const auto &config : configs) {
153         if (!firstConfig) {
154             info += ", {";
155         }
156         firstConfig = false;
157         info += "\n    \"label\": \"" + config.label.GetUserVisibleName(false) + "\"";
158         for (auto &item : *collector) {
159             if (item->label() != config.label)
160                 continue;
161             Config *as_config = item->AsConfig();
162             if (!as_config) {
163                 continue;
164             }
165             PublicConfigInfoParams params = { target, label, err };
166             info += GetIncludeDirsInfo(as_config, checker, isPublic, params);
167         }
168         info += "  }";
169     }
170     info += "]";
171     return info;
172 }
173 
GetPublicConfigsInfo(const Target * target,const std::string & labelString,Scope * scope,const OhosComponentChecker * checker,Err * err)174 std::string GetPublicConfigsInfo(const Target *target, const std::string &labelString, Scope *scope,
175     const OhosComponentChecker *checker, Err *err)
176 {
177     std::string info = "";
178     const UniqueVector<LabelConfigPair> configs = target->public_configs();
179     if (configs.size() > 0) {
180         info += ",\n  \"public_configs\": ";
181         PublicConfigInfoParams params = { target, labelString, err };
182         std::string tmp = GetPublicConfigInfo(params, scope, configs, checker, true);
183         if (tmp == "") {
184             return "";
185         }
186         info += tmp;
187     }
188     return info;
189 }
190 
GetAllDependentConfigsInfo(const Target * target,const std::string & labelString,Scope * scope,const OhosComponentChecker * checker,Err * err)191 std::string GetAllDependentConfigsInfo(const Target *target, const std::string &labelString, Scope *scope,
192     const OhosComponentChecker *checker, Err *err)
193 {
194     std::string info = "";
195     const UniqueVector<LabelConfigPair> all_configs = target->all_dependent_configs();
196     if (all_configs.size() > 0) {
197         info += ",\n  \"all_dependent_configs\": ";
198         PublicConfigInfoParams params = { target, labelString, err };
199         std::string tmp = GetPublicConfigInfo(params, scope, all_configs, checker, true);
200         if (tmp == "") {
201             return "";
202         }
203         info += tmp;
204         if (checker != nullptr) {
205             if (!checker->CheckAllDepsConfigs(target, labelString, err)) {
206                 return "";
207             }
208         }
209     }
210     return info;
211 }
212 
GetPrivateConfigsInfo(const Target * target,const std::string & labelString,Scope * scope,const OhosComponentChecker * checker,Err * err)213 std::string GetPrivateConfigsInfo(const Target *target, const std::string &labelString, Scope *scope,
214     const OhosComponentChecker *checker, Err *err)
215 {
216     std::string info = "";
217     const UniqueVector<LabelConfigPair> private_configs = target->configs();
218     if (private_configs.size() > 0) {
219         PublicConfigInfoParams params = { target, labelString, err };
220         std::string tmp = GetPublicConfigInfo(params, scope, private_configs, checker, false);
221         if (tmp == "") {
222             return "";
223         }
224     }
225     return info;
226 }
227 
228 
GetPublicHeadersInfo(const Target * target)229 std::string GetPublicHeadersInfo(const Target *target)
230 {
231     std::string info = "";
232     const std::vector<SourceFile> &headers = target->public_headers();
233     if (headers.size() > 0) {
234         info += ",\n  \"public\": [\n    ";
235         bool first = true;
236         for (const auto &header : headers) {
237             if (!first) {
238                 info += ",\n    ";
239             }
240             first = false;
241             info += "\"" + header.value() + "\"";
242         }
243         info += "  ]";
244     }
245     return info;
246 }
247 
GetPublicDepsInfo(const Target * target,const std::string & labelString,const OhosComponentChecker * checker,Err * err)248 std::string GetPublicDepsInfo(const Target *target, const std::string &labelString,
249     const OhosComponentChecker *checker, Err *err)
250 {
251     std::string info = "";
252     const LabelTargetVector deps = target->public_deps();
253     if (deps.size() > 0) {
254         info += ",\n  \"public_deps\": [\n    ";
255         bool first = true;
256         for (const auto &dep : deps) {
257             if (!first) {
258                 info += ",\n    ";
259             }
260             first = false;
261             std::string dep_str = dep.label.GetUserVisibleName(false);
262             info += "\"" + dep_str + "\"";
263             if (checker == nullptr) {
264                 continue;
265             }
266             if (!checker->CheckInnerApiPublicDepsInner(target, labelString, dep_str, err)) {
267                 return "";
268             }
269         }
270         info += "\n  ]";
271     }
272     return info;
273 }
274 
GetOutNameAndTypeInfo(const Scope * scope,const std::string & targetName,const std::string & type)275 std::string GetOutNameAndTypeInfo(const Scope *scope, const std::string &targetName, const std::string &type)
276 {
277     std::string info = "";
278     const std::string name = GetOutName(scope, targetName, type);
279     info += ",\n  \"out_name\":\"" + name + "\"";
280     info += ",\n  \"type\":\"" + type + "\"";
281     return info;
282 }
283 
GetComponentInfo(const std::string & subsystem,const std::string & component,const std::string & path)284 std::string GetComponentInfo(const std::string &subsystem, const std::string &component, const std::string &path)
285 {
286     std::string info = "";
287     info += ",\n  \"subsystem\":\"" + subsystem + "\"";
288     info += ",\n  \"component\":\"" + component + "\"";
289     info += ",\n  \"path\":\"" + path + "\"";
290     info += "\n}\n";
291     return info;
292 }
293 
GeneratedInnerapiPublicInfo(Target * target,Label label,Scope * scope,const std::string type,Err * err)294 void InnerApiPublicInfoGenerator::GeneratedInnerapiPublicInfo(Target *target, Label label, Scope *scope,
295     const std::string type, Err *err)
296 {
297     if (target == nullptr || (ignoreTest_ && target->testonly())) {
298         return;
299     }
300     const OhosComponentChecker *checker = OhosComponentChecker::getInstance();
301 
302     std::string labelString = label.GetUserVisibleName(false);
303     std::string info = "{\n";
304 
305     info += "  \"label\": \"" + labelString + "\"";
306     info += GetPublicConfigsInfo(target, labelString, scope, checker, err);
307     info += GetAllDependentConfigsInfo(target, labelString, scope, checker, err);
308     info += GetPrivateConfigsInfo(target, labelString, scope, checker, err);
309 
310     if (checker != nullptr) {
311         if (!TraverIncludeDirs(checker, target, scope, labelString, err)) {
312             return;
313         }
314     }
315 
316     if (target->all_headers_public()) {
317         info += ",\n  \"public\": [ \"*\" ]";
318     } else {
319         info += GetPublicHeadersInfo(target);
320     }
321 
322     info += GetPublicDepsInfo(target, labelString, checker, err);
323 
324     const OhosComponent *component = target->ohos_component();
325     if (target->testonly() || component == nullptr || !component->isInnerApi(labelString)) {
326         return;
327     }
328     int pos = labelString.find(":");
329     std::string targetName = labelString.substr(pos + 1, labelString.length() - 1);
330     info += GetOutNameAndTypeInfo(scope, targetName, type);
331     info += GetComponentInfo(component->subsystem(), component->name(), component->path());
332 
333     const std::string dir = build_dir_ + "/" + component->subsystem() + "/" + component->name() + "/publicinfo";
334     base::FilePath path(dir);
335     base::CreateDirectory(path);
336     std::ofstream publicfile;
337     const std::string json_path = dir + "/" + targetName + ".json";
338     if (IsFileExists(json_path)) {
339         return;
340     }
341     publicfile.open(json_path, std::ios::out);
342     publicfile << info;
343     publicfile.close();
344     return;
345 }