Index: tools/gn/functions_target.cc |
diff --git a/tools/gn/functions_target.cc b/tools/gn/functions_target.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a5991e777ca9d903ab718d46763d2e8c66908ad7 |
--- /dev/null |
+++ b/tools/gn/functions_target.cc |
@@ -0,0 +1,221 @@ |
+// Copyright (c) 2013 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/functions.h" |
+ |
+#include "tools/gn/err.h" |
+#include "tools/gn/parse_tree.h" |
+#include "tools/gn/scope.h" |
+#include "tools/gn/target_generator.h" |
+#include "tools/gn/value.h" |
+ |
+namespace { |
+ |
+Value ExecuteGenericTarget(const char* target_type, |
+ Scope* scope, |
+ const FunctionCallNode* function, |
+ const std::vector<Value>& args, |
+ BlockNode* block, |
+ Err* err) { |
+ if (!EnsureNotProcessingImport(function, scope, err) || |
+ !EnsureNotProcessingBuildConfig(function, scope, err)) |
+ return Value(); |
+ Scope block_scope(scope); |
+ if (!FillTargetBlockScope(scope, function, target_type, block, |
+ args, &block_scope, err)) |
+ return Value(); |
+ |
+ block->ExecuteBlockInScope(&block_scope, err); |
+ if (err->has_error()) |
+ return Value(); |
+ |
+ TargetGenerator::GenerateTarget(&block_scope, function->function(), args, |
+ target_type, err); |
+ |
+ block_scope.CheckForUnusedVars(err); |
+ return Value(); |
+} |
+ |
+} // namespace |
+ |
+Value ExecuteComponent(Scope* scope, |
+ const FunctionCallNode* function, |
+ const std::vector<Value>& args, |
+ BlockNode* block, |
+ Err* err) { |
+ // A component is either a shared or static library, depending on the value |
+ // of |component_mode|. |
+ const Value* component_mode_value = scope->GetValue("component_mode"); |
+ |
+ static const char helptext[] = |
+ "You're declaring a component here but have not defined " |
+ "\"component_mode\" to\neither \"shared_library\" or \"static_library\"."; |
+ if (!component_mode_value) { |
+ *err = Err(function->function(), "No component mode set.", helptext); |
+ return Value(); |
+ } |
+ if (component_mode_value->type() != Value::STRING || |
+ (component_mode_value->string_value() != functions::kSharedLibrary && |
+ component_mode_value->string_value() != functions::kStaticLibrary)) { |
+ *err = Err(function->function(), "Invalid component mode set.", helptext); |
+ return Value(); |
+ } |
+ const std::string& component_mode = component_mode_value->string_value(); |
+ |
+ if (!EnsureNotProcessingImport(function, scope, err)) |
+ return Value(); |
+ Scope block_scope(scope); |
+ if (!FillTargetBlockScope(scope, function, component_mode.c_str(), block, |
+ args, &block_scope, err)) |
+ return Value(); |
+ |
+ block->ExecuteBlockInScope(&block_scope, err); |
+ if (err->has_error()) |
+ return Value(); |
+ |
+ TargetGenerator::GenerateTarget(&block_scope, function->function(), args, |
+ component_mode, err); |
+ return Value(); |
+} |
+ |
+Value ExecuteCopy(Scope* scope, |
+ const FunctionCallNode* function, |
+ const std::vector<Value>& args, |
+ Err* err) { |
+ if (!EnsureNotProcessingImport(function, scope, err) || |
+ !EnsureNotProcessingBuildConfig(function, scope, err)) |
+ return Value(); |
+ TargetGenerator::GenerateTarget(scope, function->function(), args, |
+ functions::kCopy, err); |
+ return Value(); |
+} |
+ |
+/* |
+custom: Declare a script-generated target. |
+ |
+ This target type allows you to run a script over a set of sources files and |
+ generate a set of output files. |
+ |
+ The script will be executed with the given arguments with the current |
+ directory being that of the current BUILD file. |
+ |
+ There are two modes. The first mode is the "per-file" mode where you |
+ specify a list of sources and the script is run once for each one as a build |
+ rule. In this case, each file specified in the |outputs| variable must be |
+ unique when applied to each source file (normally you would reference |
+ "{{source_name_part}}" from within each one) or the build system will get |
+ confused about how to build those files. You should use the |data| variable |
+ to list all additional dependencies of your script: these will be added |
+ as dependencies for each build step. |
+ |
+ The second mode is when you just want to run a script once rather than as a |
+ general rule over a set of files. In this case you don't list any sources. |
+ Dependencies of your script are specified only in the |data| variable and |
+ your |outputs| variable should just list all outputs. |
+ |
+Variables: |
+ |
+ args, data, deps, outputs, script*, sources |
+ * = required |
+ |
+ There are some special substrings that will be searched for when processing |
+ some variables: |
+ |
+ "{{source}}" |
+ Expanded in |args|, this is the name of the source file relative to the |
+ current directory when running the script. This is how you specify |
+ the current input file to your script. |
+ |
+ "{{source_name_part}}" |
+ Expanded in |args| and |outputs|, this is just the filename part of the |
+ current source file with no directory or extension. This is how you |
+ specify a name transoformation to the output. Normally you would |
+ write an output as "$target_output_dir/{{source_name_part}}.o". |
+ |
+ All |outputs| files must be inside the output directory of the build. You |
+ would generally use "$target_output_dir" or "$target_gen_dir" to reference |
+ the output or generated intermediate file directories, respectively. |
+ |
+Examples: |
+ |
+ custom("general_rule") { |
+ script = "do_processing.py" |
+ sources = [ "foo.idl" ] |
+ data = [ "my_configuration.txt" ] |
+ outputs = [ "$target_gen_dir/{{source_name_part}}.h" ] |
+ args = [ "{{source}}", |
+ "-o", "$relative_target_gen_dir/{{source_name_part}}.h" ] |
+ } |
+ |
+ custom("just_run_this_guy_once") { |
+ script = "doprocessing.py" |
+ data = [ "my_configuration.txt" ] |
+ outputs = [ "$target_gen_dir/insightful_output.txt" ] |
+ args = [ "--output_dir", $target_gen_dir ] |
+ } |
+*/ |
+Value ExecuteCustom(Scope* scope, |
+ const FunctionCallNode* function, |
+ const std::vector<Value>& args, |
+ BlockNode* block, |
+ Err* err) { |
+ return ExecuteGenericTarget(functions::kCustom, scope, function, args, |
+ block, err); |
+} |
+ |
+Value ExecuteExecutable(Scope* scope, |
+ const FunctionCallNode* function, |
+ const std::vector<Value>& args, |
+ BlockNode* block, |
+ Err* err) { |
+ return ExecuteGenericTarget(functions::kExecutable, scope, function, args, |
+ block, err); |
+} |
+ |
+Value ExecuteSharedLibrary(Scope* scope, |
+ const FunctionCallNode* function, |
+ const std::vector<Value>& args, |
+ BlockNode* block, |
+ Err* err) { |
+ return ExecuteGenericTarget(functions::kSharedLibrary, scope, function, args, |
+ block, err); |
+} |
+ |
+Value ExecuteStaticLibrary(Scope* scope, |
+ const FunctionCallNode* function, |
+ const std::vector<Value>& args, |
+ BlockNode* block, |
+ Err* err) { |
+ return ExecuteGenericTarget(functions::kStaticLibrary, scope, function, args, |
+ block, err); |
+} |
+ |
+/* |
+group: Declare a group of targets. |
+ |
+ This target type allows you to create meta-targets that just collect a set |
+ of dependencies into one named target. |
+ |
+Variables: |
+ |
+ deps |
+ |
+Example: |
+ |
+ group("all") { |
+ deps = [ |
+ "//project:runner", |
+ "//project:unit_tests", |
+ ] |
+ } |
+*/ |
+Value ExecuteGroup(Scope* scope, |
+ const FunctionCallNode* function, |
+ const std::vector<Value>& args, |
+ BlockNode* block, |
+ Err* err) { |
+ return ExecuteGenericTarget(functions::kGroup, scope, function, args, |
+ block, err); |
+} |
+ |