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