1 // Copyright 2014 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 <regex>
6 #include "gn/err.h"
7 #include "gn/filesystem_utils.h"
8 #include "gn/functions.h"
9 #include "gn/label.h"
10 #include "gn/parse_tree.h"
11 #include "gn/value.h"
12 #include "ohos_components.h"
13
14 namespace functions {
15
16 const char kGetLabelInfo[] = "get_label_info";
17 const char kGetLabelInfo_HelpShort[] =
18 "get_label_info: Get an attribute from a target's label.";
19 const char kGetLabelInfo_Help[] =
20 R"*(get_label_info: Get an attribute from a target's label.
21
22 get_label_info(target_label, what)
23
24 Given the label of a target, returns some attribute of that target. The
25 target need not have been previously defined in the same file, since none of
26 the attributes depend on the actual target definition, only the label itself.
27
28 See also "gn help get_target_outputs".
29
30 Possible values for the "what" parameter
31
32 "name"
33 The short name of the target. This will match the value of the
34 "target_name" variable inside that target's declaration. For the label
35 "//foo/bar:baz" this will return "baz".
36
37 "dir"
38 The directory containing the target's definition, with no slash at the
39 end. For the label "//foo/bar:baz" this will return "//foo/bar".
40
41 "target_gen_dir"
42 The generated file directory for the target. This will match the value of
43 the "target_gen_dir" variable when inside that target's declaration.
44
45 "root_gen_dir"
46 The root of the generated file tree for the target. This will match the
47 value of the "root_gen_dir" variable when inside that target's
48 declaration.
49
50 "target_out_dir
51 The output directory for the target. This will match the value of the
52 "target_out_dir" variable when inside that target's declaration.
53
54 "root_out_dir"
55 The root of the output file tree for the target. This will match the
56 value of the "root_out_dir" variable when inside that target's
57 declaration.
58
59 "label_no_toolchain"
60 The fully qualified version of this label, not including the toolchain.
61 For the input ":bar" it might return "//foo:bar".
62
63 "label_with_toolchain"
64 The fully qualified version of this label, including the toolchain. For
65 the input ":bar" it might return "//foo:bar(//toolchain:x64)".
66
67 "toolchain"
68 The label of the toolchain. This will match the value of the
69 "current_toolchain" variable when inside that target's declaration.
70
71 Examples
72
73 get_label_info(":foo", "name")
74 # Returns string "foo".
75
76 get_label_info("//foo/bar:baz", "target_gen_dir")
77 # Returns string "//out/Debug/gen/foo/bar".
78 )*";
79
getComponentLabel(const std::string & target_label,const BuildSettings * settings)80 std::string getComponentLabel(const std::string& target_label,
81 const BuildSettings* settings) {
82 std::regex pattern("[A-Za-z0-9_]+:[A-Za-z0-9_.-]+");
83 if (std::regex_match(target_label, pattern)) {
84 size_t pos = target_label.find(':');
85 std::string component_str = target_label.substr(0, pos);
86 std::string innner_api_str = target_label.substr(pos + 1);
87 const OhosComponent* component =
88 settings->GetOhosComponentByName(component_str);
89 if (component) {
90 return component->getInnerApi(innner_api_str);
91 }
92 }
93 return {};
94 }
95
96 Value RunGetLabelInfo(Scope* scope,
97 const FunctionCallNode* function,
98 const std::vector<Value>& args,
99 Err* err) {
100 if (args.size() != 2) {
101 *err = Err(function, "Expected two arguments.");
102 return Value();
103 }
104
105 // Resolve the requested label.
106 const BuildSettings* buildSettings = scope->settings()->build_settings();
107 Label label;
108 std::string target = args[0].string_value();
109 bool resolved = false;
110 // [OHOS] Resolve component info first
111 if (!target.empty() && buildSettings->isOhosIndepCompilerEnable()) {
112 const std::string& label_str = getComponentLabel(target, buildSettings);
113 if (!label_str.empty()) {
114 const Value& value = Value(args[0].origin(), label_str);
115 label =
116 Label::Resolve(scope->GetSourceDir(), buildSettings->root_path_utf8(),
117 ToolchainLabelForScope(scope), value, err);
118 resolved = true;
119 }
120 }
121 if (!resolved) {
122 label =
123 Label::Resolve(scope->GetSourceDir(), buildSettings->root_path_utf8(),
124 ToolchainLabelForScope(scope), args[0], err);
125 }
126 if (label.is_null())
127 return Value();
128
129 // Extract the "what" parameter.
130 if (!args[1].VerifyTypeIs(Value::STRING, err))
131 return Value();
132 const std::string& what = args[1].string_value();
133
134 Value result(function, Value::STRING);
135 if (what == "name") {
136 result.string_value() = label.name();
137
138 } else if (what == "dir") {
139 result.string_value() = DirectoryWithNoLastSlash(label.dir());
140
141 } else if (what == "target_gen_dir") {
142 result.string_value() = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir(
143 BuildDirContext(scope, label.GetToolchainLabel()), label.dir(),
144 BuildDirType::GEN));
145
146 } else if (what == "root_gen_dir") {
147 result.string_value() = DirectoryWithNoLastSlash(GetBuildDirAsSourceDir(
148 BuildDirContext(scope, label.GetToolchainLabel()), BuildDirType::GEN));
149
150 } else if (what == "target_out_dir") {
151 result.string_value() = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir(
152 BuildDirContext(scope, label.GetToolchainLabel()), label.dir(),
153 BuildDirType::OBJ));
154
155 } else if (what == "root_out_dir") {
156 result.string_value() = DirectoryWithNoLastSlash(GetBuildDirAsSourceDir(
157 BuildDirContext(scope, label.GetToolchainLabel()),
158 BuildDirType::TOOLCHAIN_ROOT));
159
160 } else if (what == "toolchain") {
161 result.string_value() = label.GetToolchainLabel().GetUserVisibleName(false);
162
163 } else if (what == "label_no_toolchain") {
164 result.string_value() =
165 label.GetWithNoToolchain().GetUserVisibleName(false);
166
167 } else if (what == "label_with_toolchain") {
168 result.string_value() = label.GetUserVisibleName(true);
169
170 } else {
171 *err = Err(args[1], "Unknown value for \"what\" parameter.");
172 return Value();
173 }
174
175 return result;
176 }
177
178 } // namespace functions
179