|  | // Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "tools/gn/err.h" | 
|  | #include "tools/gn/filesystem_utils.h" | 
|  | #include "tools/gn/functions.h" | 
|  | #include "tools/gn/label.h" | 
|  | #include "tools/gn/parse_tree.h" | 
|  | #include "tools/gn/value.h" | 
|  |  | 
|  | namespace functions { | 
|  |  | 
|  | const char kGetLabelInfo[] = "get_label_info"; | 
|  | const char kGetLabelInfo_HelpShort[] = | 
|  | "get_label_info: Get an attribute from a target's label."; | 
|  | const char kGetLabelInfo_Help[] = | 
|  | R"*(get_label_info: Get an attribute from a target's label. | 
|  |  | 
|  | get_label_info(target_label, what) | 
|  |  | 
|  | Given the label of a target, returns some attribute of that target. The | 
|  | target need not have been previously defined in the same file, since none of | 
|  | the attributes depend on the actual target definition, only the label itself. | 
|  |  | 
|  | See also "gn help get_target_outputs". | 
|  |  | 
|  | Possible values for the "what" parameter | 
|  |  | 
|  | "name" | 
|  | The short name of the target. This will match the value of the | 
|  | "target_name" variable inside that target's declaration. For the label | 
|  | "//foo/bar:baz" this will return "baz". | 
|  |  | 
|  | "dir" | 
|  | The directory containing the target's definition, with no slash at the | 
|  | end. For the label "//foo/bar:baz" this will return "//foo/bar". | 
|  |  | 
|  | "target_gen_dir" | 
|  | The generated file directory for the target. This will match the value of | 
|  | the "target_gen_dir" variable when inside that target's declaration. | 
|  |  | 
|  | "root_gen_dir" | 
|  | The root of the generated file tree for the target. This will match the | 
|  | value of the "root_gen_dir" variable when inside that target's | 
|  | declaration. | 
|  |  | 
|  | "target_out_dir | 
|  | The output directory for the target. This will match the value of the | 
|  | "target_out_dir" variable when inside that target's declaration. | 
|  |  | 
|  | "root_out_dir" | 
|  | The root of the output file tree for the target. This will match the | 
|  | value of the "root_out_dir" variable when inside that target's | 
|  | declaration. | 
|  |  | 
|  | "label_no_toolchain" | 
|  | The fully qualified version of this label, not including the toolchain. | 
|  | For the input ":bar" it might return "//foo:bar". | 
|  |  | 
|  | "label_with_toolchain" | 
|  | The fully qualified version of this label, including the toolchain. For | 
|  | the input ":bar" it might return "//foo:bar(//toolchain:x64)". | 
|  |  | 
|  | "toolchain" | 
|  | The label of the toolchain. This will match the value of the | 
|  | "current_toolchain" variable when inside that target's declaration. | 
|  |  | 
|  | Examples | 
|  |  | 
|  | get_label_info(":foo", "name") | 
|  | # Returns string "foo". | 
|  |  | 
|  | get_label_info("//foo/bar:baz", "target_gen_dir") | 
|  | # Returns string "//out/Debug/gen/foo/bar". | 
|  | )*"; | 
|  |  | 
|  | Value RunGetLabelInfo(Scope* scope, | 
|  | const FunctionCallNode* function, | 
|  | const std::vector<Value>& args, | 
|  | Err* err) { | 
|  | if (args.size() != 2) { | 
|  | *err = Err(function, "Expected two arguments."); | 
|  | return Value(); | 
|  | } | 
|  |  | 
|  | // Resolve the requested label. | 
|  | Label label = Label::Resolve(scope->GetSourceDir(), | 
|  | ToolchainLabelForScope(scope), args[0], err); | 
|  | if (label.is_null()) | 
|  | return Value(); | 
|  |  | 
|  | // Extract the "what" parameter. | 
|  | if (!args[1].VerifyTypeIs(Value::STRING, err)) | 
|  | return Value(); | 
|  | const std::string& what = args[1].string_value(); | 
|  |  | 
|  | Value result(function, Value::STRING); | 
|  | if (what == "name") { | 
|  | result.string_value() = label.name(); | 
|  |  | 
|  | } else if (what == "dir") { | 
|  | result.string_value() = DirectoryWithNoLastSlash(label.dir()); | 
|  |  | 
|  | } else if (what == "target_gen_dir") { | 
|  | result.string_value() = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir( | 
|  | BuildDirContext(scope, label.GetToolchainLabel()), label.dir(), | 
|  | BuildDirType::GEN)); | 
|  |  | 
|  | } else if (what == "root_gen_dir") { | 
|  | result.string_value() = DirectoryWithNoLastSlash(GetBuildDirAsSourceDir( | 
|  | BuildDirContext(scope, label.GetToolchainLabel()), BuildDirType::GEN)); | 
|  |  | 
|  | } else if (what == "target_out_dir") { | 
|  | result.string_value() = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir( | 
|  | BuildDirContext(scope, label.GetToolchainLabel()), label.dir(), | 
|  | BuildDirType::OBJ)); | 
|  |  | 
|  | } else if (what == "root_out_dir") { | 
|  | result.string_value() = DirectoryWithNoLastSlash(GetBuildDirAsSourceDir( | 
|  | BuildDirContext(scope, label.GetToolchainLabel()), | 
|  | BuildDirType::TOOLCHAIN_ROOT)); | 
|  |  | 
|  | } else if (what == "toolchain") { | 
|  | result.string_value() = label.GetToolchainLabel().GetUserVisibleName(false); | 
|  |  | 
|  | } else if (what == "label_no_toolchain") { | 
|  | result.string_value() = | 
|  | label.GetWithNoToolchain().GetUserVisibleName(false); | 
|  |  | 
|  | } else if (what == "label_with_toolchain") { | 
|  | result.string_value() = label.GetUserVisibleName(true); | 
|  |  | 
|  | } else { | 
|  | *err = Err(args[1], "Unknown value for \"what\" parameter."); | 
|  | return Value(); | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | }  // namespace functions |