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 ¶ms)
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 ¶ms)
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 ¶ms, 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 }