278 lines
10 KiB
C++
278 lines
10 KiB
C++
// 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 functions {
|
|
|
|
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
|
|
|
|
// component -------------------------------------------------------------------
|
|
|
|
const char kComponent[] = "component";
|
|
const char kComponent_Help[] =
|
|
"TODO(brettw) write this.";
|
|
|
|
Value RunComponent(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();
|
|
}
|
|
|
|
// copy ------------------------------------------------------------------------
|
|
|
|
const char kCopy[] = "copy";
|
|
const char kCopy_Help[] =
|
|
"TODO(brettw) write this.";
|
|
|
|
Value RunCopy(const FunctionCallNode* function,
|
|
const std::vector<Value>& args,
|
|
Scope* scope,
|
|
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 ----------------------------------------------------------------------
|
|
|
|
const char kCustom[] = "custom";
|
|
const char kCustom_Help[] =
|
|
"custom: Declare a script-generated target.\n"
|
|
"\n"
|
|
" This target type allows you to run a script over a set of source\n"
|
|
" files and generate a set of output files.\n"
|
|
"\n"
|
|
" The script will be executed with the given arguments with the current\n"
|
|
" directory being that of the current BUILD file.\n"
|
|
"\n"
|
|
" There are two modes. The first mode is the \"per-file\" mode where you\n"
|
|
" specify a list of sources and the script is run once for each one as a\n"
|
|
" build rule. In this case, each file specified in the |outputs|\n"
|
|
" variable must be unique when applied to each source file (normally you\n"
|
|
" would reference |{{source_name_part}}| from within each one) or the\n"
|
|
" build system will get confused about how to build those files. You\n"
|
|
" should use the |data| variable to list all additional dependencies of\n"
|
|
" your script: these will be added as dependencies for each build step.\n"
|
|
"\n"
|
|
" The second mode is when you just want to run a script once rather than\n"
|
|
" as a general rule over a set of files. In this case you don't list any\n"
|
|
" sources. Dependencies of your script are specified only in the |data|\n"
|
|
" variable and your |outputs| variable should just list all outputs.\n"
|
|
"\n"
|
|
"Variables:\n"
|
|
"\n"
|
|
" args, data, deps, outputs, script*, sources\n"
|
|
" * = required\n"
|
|
"\n"
|
|
" There are some special substrings that will be searched for when\n"
|
|
" processing some variables:\n"
|
|
"\n"
|
|
" {{source}}\n"
|
|
" Expanded in |args|, this is the name of the source file relative\n"
|
|
" to the current directory when running the script. This is how\n"
|
|
" you specify the current input file to your script.\n"
|
|
"\n"
|
|
" {{source_name_part}}\n"
|
|
" Expanded in |args| and |outputs|, this is just the filename part\n"
|
|
" of the current source file with no directory or extension. This\n"
|
|
" is how you specify a name transformation to the output. Normally\n"
|
|
" you would write an output as\n"
|
|
" \"$target_output_dir/{{source_name_part}}.o\".\n"
|
|
"\n"
|
|
" All |outputs| files must be inside the output directory of the build.\n"
|
|
" You would generally use |$target_output_dir| or |$target_gen_dir| to\n"
|
|
" reference the output or generated intermediate file directories,\n"
|
|
" respectively.\n"
|
|
"\n"
|
|
"Examples:\n"
|
|
"\n"
|
|
" custom(\"general_rule\") {\n"
|
|
" script = \"do_processing.py\"\n"
|
|
" sources = [ \"foo.idl\" ]\n"
|
|
" data = [ \"my_configuration.txt\" ]\n"
|
|
" outputs = [ \"$target_gen_dir/{{source_name_part}}.h\" ]\n"
|
|
" args = [ \"{{source}}\",\n"
|
|
" \"-o\",\n"
|
|
" \"$relative_target_gen_dir/{{source_name_part}}.h\" ]\n"
|
|
" }\n"
|
|
"\n"
|
|
" custom(\"just_run_this_guy_once\") {\n"
|
|
" script = \"doprocessing.py\"\n"
|
|
" data = [ \"my_configuration.txt\" ]\n"
|
|
" outputs = [ \"$target_gen_dir/insightful_output.txt\" ]\n"
|
|
" args = [ \"--output_dir\", $target_gen_dir ]\n"
|
|
" }\n";
|
|
|
|
Value RunCustom(Scope* scope,
|
|
const FunctionCallNode* function,
|
|
const std::vector<Value>& args,
|
|
BlockNode* block,
|
|
Err* err) {
|
|
return ExecuteGenericTarget(functions::kCustom, scope, function, args,
|
|
block, err);
|
|
}
|
|
|
|
// executable ------------------------------------------------------------------
|
|
|
|
const char kExecutable[] = "executable";
|
|
const char kExecutable_Help[] =
|
|
"TODO(brettw) write this.";
|
|
|
|
Value RunExecutable(Scope* scope,
|
|
const FunctionCallNode* function,
|
|
const std::vector<Value>& args,
|
|
BlockNode* block,
|
|
Err* err) {
|
|
return ExecuteGenericTarget(functions::kExecutable, scope, function, args,
|
|
block, err);
|
|
}
|
|
|
|
// group -----------------------------------------------------------------------
|
|
|
|
const char kGroup[] = "group";
|
|
const char kGroup_Help[] =
|
|
"group: Declare a named group of targets.\n"
|
|
"\n"
|
|
" This target type allows you to create meta-targets that just collect a\n"
|
|
" set of dependencies into one named target.\n"
|
|
"\n"
|
|
"Variables:\n"
|
|
"\n"
|
|
" deps\n"
|
|
"\n"
|
|
"Example:\n"
|
|
" group(\"all\") {\n"
|
|
" deps = [\n"
|
|
" \"//project:runner\",\n"
|
|
" \"//project:unit_tests\",\n"
|
|
" ]\n"
|
|
" }";
|
|
|
|
Value RunGroup(Scope* scope,
|
|
const FunctionCallNode* function,
|
|
const std::vector<Value>& args,
|
|
BlockNode* block,
|
|
Err* err) {
|
|
return ExecuteGenericTarget(functions::kGroup, scope, function, args,
|
|
block, err);
|
|
}
|
|
|
|
// shared_library --------------------------------------------------------------
|
|
|
|
const char kSharedLibrary[] = "shared_library";
|
|
const char kSharedLibrary_Help[] =
|
|
"TODO(brettw) write this.";
|
|
|
|
Value RunSharedLibrary(Scope* scope,
|
|
const FunctionCallNode* function,
|
|
const std::vector<Value>& args,
|
|
BlockNode* block,
|
|
Err* err) {
|
|
return ExecuteGenericTarget(functions::kSharedLibrary, scope, function, args,
|
|
block, err);
|
|
}
|
|
|
|
// static_library --------------------------------------------------------------
|
|
|
|
const char kStaticLibrary[] = "static_library";
|
|
const char kStaticLibrary_Help[] =
|
|
"TODO(brettw) write this.";
|
|
|
|
Value RunStaticLibrary(Scope* scope,
|
|
const FunctionCallNode* function,
|
|
const std::vector<Value>& args,
|
|
BlockNode* block,
|
|
Err* err) {
|
|
return ExecuteGenericTarget(functions::kStaticLibrary, scope, function, args,
|
|
block, err);
|
|
}
|
|
|
|
// test ------------------------------------------------------------------------
|
|
|
|
const char kTest[] = "test";
|
|
const char kTest_Help[] =
|
|
"TODO(brettw) write this.";
|
|
|
|
Value RunTest(Scope* scope,
|
|
const FunctionCallNode* function,
|
|
const std::vector<Value>& args,
|
|
BlockNode* block,
|
|
Err* err) {
|
|
return ExecuteGenericTarget(functions::kExecutable, scope, function, args,
|
|
block, err);
|
|
}
|
|
|
|
} // namespace functions
|