diff options
author | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-30 09:27:04 +0000 |
---|---|---|
committer | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-30 09:27:04 +0000 |
commit | 69a4548e0ab3fbb1531b4df89708bfab9cf0df20 (patch) | |
tree | ab77a5fe7f52b55970950374ceb22f4be8e4ea53 | |
parent | d5f9c7ceb6d59748ad07bb96194b44b516c3c1ad (diff) | |
download | chromium_src-69a4548e0ab3fbb1531b4df89708bfab9cf0df20.zip chromium_src-69a4548e0ab3fbb1531b4df89708bfab9cf0df20.tar.gz chromium_src-69a4548e0ab3fbb1531b4df89708bfab9cf0df20.tar.bz2 |
Revert 214254 "Add initial prototype for the GN meta-buildsystem."
It broke the check_licenses step on Android (see http://build.chromium.org/p/chromium.linux/builders/Android%20Builder%20%28dbg%29/builds/39904/steps/check_licenses/logs/stdio):
@@@BUILD_STEP check_licenses@@@
> /b/build/slave/Android_Builder__dbg_/build/src/android_webview/tools/webview_licenses.py scan
Got LicenseError "missing README.chromium or licenses.py SPECIAL_CASES entry" while scanning tools/gn/secondary/base/third_party/dynamic_annotations
Got LicenseError "missing README.chromium or licenses.py SPECIAL_CASES entry" while scanning tools/gn/secondary/third_party/modp_b64
< /b/build/slave/Android_Builder__dbg_/build/src/android_webview/tools/webview_licenses.py scan
ERROR: process exited with code 2
@@@STEP_FAILURE@@@
> Add initial prototype for the GN meta-buildsystem.
>
> This is currently not hooked into the build. To build, add a reference to the
> gn.gyp file to build/all.gyp
>
> R=darin@chromium.org, scottmg@chromium.org
>
> Review URL: https://codereview.chromium.org/21114002
TBR=brettw@chromium.org
Review URL: https://codereview.chromium.org/21084010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214325 0039d316-1c4b-4281-b951-d872f2087c98
140 files changed, 0 insertions, 18197 deletions
@@ -1,8 +0,0 @@ -# This file is used by the experimental meta-buildsystem in src/tools/gn to -# find the root of the source tree and to set startup options. - -# The location of the build configuration file. -buildconfig = "//build/config/BUILDCONFIG.gn" - -# The secondary source root is a parallel directory tree where -secondary_source = "//tools/gn/secondary/" diff --git a/tools/gn/BUILD.gn b/tools/gn/BUILD.gn deleted file mode 100644 index ccb5411..0000000 --- a/tools/gn/BUILD.gn +++ /dev/null @@ -1,153 +0,0 @@ -static_library("gn_lib") {
- sources = [
- "build_settings.cc",
- "build_settings.h",
- "command_desc.cc",
- "command_desc.h",
- "command_gen.cc",
- "command_gen.h",
- "command.cc",
- "config.cc",
- "config.h",
- "config_values.h",
- "config_values_extractors.cc",
- "config_values_extractors.h",
- "config_values_generator.cc",
- "config_values_generator.h",
- "err.cc",
- "err.h",
- "escape.cc",
- "escape.h",
- "file_template.cc",
- "file_template.h",
- "filesystem_utils.cc",
- "filesystem_utils.h",
- "functions.cc",
- "functions.h",
- "functions_target.cc",
- "function_exec_script.cc",
- "function_process_file_template.cc",
- "function_read_file.cc",
- "function_set_default_toolchain.cc",
- "function_template.cc",
- "function_toolchain.cc",
- "function_write_file.cc",
- "import_manager.cc",
- "import_manager.h",
- "input_conversion.cc",
- "input_conversion.h",
- "input_file.cc",
- "input_file.h",
- "input_file_manager.cc",
- "input_file_manager.h",
- "item.cc",
- "item.h",
- "item_node.cc",
- "item_node.h",
- "item_tree.cc",
- "item_tree.h",
- "label.cc",
- "label.h",
- "location.h",
- "ninja_build_writer.cc",
- "ninja_build_writer.h",
- "ninja_helper.cc",
- "ninja_helper.h",
- "ninja_target_writer.cc",
- "ninja_target_writer.h",
- "ninja_toolchain_writer.cc",
- "ninja_toolchain_writer.h",
- "ninja_writer.cc",
- "ninja_writer.h",
- "operators.cc",
- "operators.h",
- "output_file.h",
- "parse_tree.cc",
- "parse_tree.h",
- "parser.cc",
- "parser.h",
- "path_output.cc",
- "path_output.h",
- "pattern.cc",
- "pattern.h",
- "scheduler.cc",
- "scheduler.h",
- "scope.cc",
- "scope.h",
- "scope_per_file_provider.cc",
- "scope_per_file_provider.h",
- "settings.cc",
- "settings.h",
- "setup.cc",
- "setup.h",
- "source_dir.cc",
- "source_dir.h",
- "source_file.cc",
- "source_file.h",
- "standard_out.cc",
- "standard_out.h",
- "string_utils.cc",
- "string_utils.h",
- "target.cc",
- "target.h",
- "target_generator.cc",
- "target_generator.h",
- "target_manager.cc",
- "target_manager.h",
- "token.cc",
- "token.h",
- "tokenizer.cc",
- "tokenizer.h",
- "toolchain.cc",
- "toolchain.h",
- "toolchain_manager.cc",
- "toolchain_manager.h",
- "value.cc",
- "value.h",
- "value_extractors.cc",
- "value_extractors.h",
- ]
- deps = [
- "//base",
- "//base/third_party/dynamic_annotations",
- ]
-}
-
-executable("gn") {
- sources = [
- "gn_main.cc",
- ]
- deps = [
- ":gn_lib",
- ]
-}
-
-test("gn_unittests") {
- sources = [
- "escape_unittest.cc",
- "file_template_unittest.cc",
- "filesystem_utils_unittest.cc",
- "input_conversion_unittest.cc",
- "label_unittest.cc",
- "ninja_helper_unittest.cc",
- "parser_unittest.cc",
- "path_output_unittest.cc",
- "pattern_unittest.cc",
- "source_dir_unittest.cc",
- "string_utils_unittest.cc",
- "target_generator_unittest.cc",
- "target_manager_unittest.cc",
- "tokenizer_unittest.cc",
- ]
- deps = [
- ":gn_lib",
- "//base:run_all_unittests",
- "//base:test_support_base",
- "//testing:gtest",
- ]
-}
-
-executable("generate_test_gn_data") {
- sources = [ "generate_test_gn_data.cc" ]
- deps = [ "//base" ]
-}
diff --git a/tools/gn/OWNERS b/tools/gn/OWNERS deleted file mode 100644 index 06fefbf..0000000 --- a/tools/gn/OWNERS +++ /dev/null @@ -1 +0,0 @@ -brettw@chromium.org diff --git a/tools/gn/README.txt b/tools/gn/README.txt deleted file mode 100644 index 0a637bf..0000000 --- a/tools/gn/README.txt +++ /dev/null @@ -1,7 +0,0 @@ -GN "Generate Ninja" - -This tool is an experimental metabuildsystem. It is not currently in a state -where it is ready for public consumption. - -It is not currently used in the build and there are currently no plans to -replace GYP. diff --git a/tools/gn/build_settings.cc b/tools/gn/build_settings.cc deleted file mode 100644 index 09b4c99..0000000 --- a/tools/gn/build_settings.cc +++ /dev/null @@ -1,44 +0,0 @@ -// 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/build_settings.h" - -#include "tools/gn/filesystem_utils.h" - -BuildSettings::BuildSettings() - : item_tree_(), - target_manager_(this), - toolchain_manager_(this) { -} - -BuildSettings::~BuildSettings() { -} - -void BuildSettings::SetSecondarySourcePath(const SourceDir& d) { - secondary_source_path_ = GetFullPath(d); -} - -void BuildSettings::SetBuildDir(const SourceDir& d) { - build_dir_ = d; - build_to_source_dir_string_ = InvertDir(d); -} - -base::FilePath BuildSettings::GetFullPath(const SourceFile& file) const { - return file.Resolve(root_path_); -} - -base::FilePath BuildSettings::GetFullPath(const SourceDir& dir) const { - return dir.Resolve(root_path_); -} - -base::FilePath BuildSettings::GetFullPathSecondary( - const SourceFile& file) const { - return file.Resolve(secondary_source_path_); -} - -base::FilePath BuildSettings::GetFullPathSecondary( - const SourceDir& dir) const { - return dir.Resolve(secondary_source_path_); -} - diff --git a/tools/gn/build_settings.h b/tools/gn/build_settings.h deleted file mode 100644 index fe04266..0000000 --- a/tools/gn/build_settings.h +++ /dev/null @@ -1,110 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_BUILD_SETTINGS_H_ -#define TOOLS_GN_BUILD_SETTINGS_H_ - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/files/file_path.h" -#include "tools/gn/item_tree.h" -#include "tools/gn/scope.h" -#include "tools/gn/source_dir.h" -#include "tools/gn/source_file.h" -#include "tools/gn/target_manager.h" -#include "tools/gn/toolchain_manager.h" - -// Settings for one build, which is one toplevel output directory. There -// may be multiple Settings objects that refer to this, one for each toolchain. -class BuildSettings { - public: - typedef base::Callback<void(const Target*)> TargetResolvedCallback; - - BuildSettings(); - ~BuildSettings(); - - // Absolute path of the source root on the local system. Everything is - // relative to this. - const base::FilePath& root_path() const { return root_path_; } - void set_root_path(const base::FilePath& r) { root_path_ = r; } - - // When nonempty, specifies a parallel directory higherarchy in which to - // search for buildfiles if they're not found in the root higherarchy. This - // allows us to keep buildfiles in a separate tree during development. - const base::FilePath& secondary_source_path() const { - return secondary_source_path_; - } - void SetSecondarySourcePath(const SourceDir& d); - - // Path of the python executable to run scripts with. - base::FilePath python_path() const { return python_path_; } - void set_python_path(const base::FilePath& p) { python_path_ = p; } - - const SourceFile& build_config_file() const { return build_config_file_; } - void set_build_config_file(const SourceFile& f) { build_config_file_ = f; } - - // The build directory is the root of all output files. The default toolchain - // files go into here, and non-default toolchains will have separate - // toolchain-specific root directories inside this. - const SourceDir& build_dir() const { return build_dir_; } - void SetBuildDir(const SourceDir& dir); - - // The inverse of relative_build_dir, ending with a separator. - // Example: relative_build_dir_ = "out/Debug/" this will be "../../" - const std::string& build_to_source_dir_string() const { - return build_to_source_dir_string_; - } - - // These accessors do not return const objects since the resulting objects - // are threadsafe. In this setting, we use constness primarily to ensure - // that the Settings object is used in a threadsafe manner. Although this - // violates the concept of logical constness, that's less important in our - // application, and actually implementing this in a way that preserves - // logical constness is cumbersome. - ItemTree& item_tree() const { return item_tree_; } - TargetManager& target_manager() const { return target_manager_; } - ToolchainManager& toolchain_manager() const { return toolchain_manager_; } - - // Returns the full absolute OS path cooresponding to the given file in the - // root source tree. - base::FilePath GetFullPath(const SourceFile& file) const; - base::FilePath GetFullPath(const SourceDir& dir) const; - - // Returns the absolute OS path inside the secondary source path. Will return - // an empty FilePath if the secondary source path is empty. When loading a - // buildfile, the GetFullPath should always be consulted first. - base::FilePath GetFullPathSecondary(const SourceFile& file) const; - base::FilePath GetFullPathSecondary(const SourceDir& dir) const; - - // This is the callback to execute when a target is marked resolved. If we - // don't need to do anything, this will be null. When a target is resolved, - // this callback should be posted to the scheduler pool so the work is - // distributed properly. - const TargetResolvedCallback& target_resolved_callback() const { - return target_resolved_callback_; - } - void set_target_resolved_callback(const TargetResolvedCallback& cb) { - target_resolved_callback_ = cb; - } - - private: - base::FilePath root_path_; - base::FilePath secondary_source_path_; - base::FilePath python_path_; - - SourceFile build_config_file_; - SourceDir build_dir_; - std::string build_to_source_dir_string_; - - TargetResolvedCallback target_resolved_callback_; - - // See getters above. - mutable ItemTree item_tree_; - mutable TargetManager target_manager_; - mutable ToolchainManager toolchain_manager_; - - DISALLOW_COPY_AND_ASSIGN(BuildSettings); -}; - -#endif // TOOLS_GN_BUILD_SETTINGS_H_ diff --git a/tools/gn/command_desc.cc b/tools/gn/command_desc.cc deleted file mode 100644 index bf91776..0000000 --- a/tools/gn/command_desc.cc +++ /dev/null @@ -1,201 +0,0 @@ -// 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 <algorithm> -#include <set> - -#include "tools/gn/commands.h" -#include "tools/gn/config.h" -#include "tools/gn/item.h" -#include "tools/gn/item_node.h" -#include "tools/gn/label.h" -#include "tools/gn/setup.h" -#include "tools/gn/standard_out.h" -#include "tools/gn/target.h" - -namespace { - -struct CompareTargetLabel { - bool operator()(const Target* a, const Target* b) const { - return a->label() < b->label(); - } -}; - -const Target* GetTargetForDesc(const std::vector<std::string>& args) { - // Deliberately leaked to avoid expensive process teardown. - Setup* setup = new Setup; - if (!setup->DoSetup()) - return NULL; - - // FIXME(brettw): set the output dir to be a sandbox one to avoid polluting - // the real output dir with files written by the build scripts. - - // Do the actual load. This will also write out the target ninja files. - if (!setup->Run()) - return NULL; - - // Need to resolve the label after we know the default toolchain. - // TODO(brettw) find the current directory and resolve the input label - // relative to that. - Label default_toolchain = setup->build_settings().toolchain_manager() - .GetDefaultToolchainUnlocked(); - Value arg_value(NULL, args[0]); - Err err; - Label label = Label::Resolve(SourceDir(), default_toolchain, arg_value, &err); - if (err.has_error()) { - err.PrintToStdout(); - return NULL; - } - - ItemNode* node; - { - base::AutoLock lock(setup->build_settings().item_tree().lock()); - node = setup->build_settings().item_tree().GetExistingNodeLocked(label); - } - if (!node) { - Err(Location(), "", - "I don't know about this \"" + label.GetUserVisibleName(false) + - "\"").PrintToStdout(); - return NULL; - } - - const Target* target = node->item()->AsTarget(); - if (!target) { - Err(Location(), "Not a target.", - "The \"" + label.GetUserVisibleName(false) + "\" thing\n" - "is not a target. Somebody should probably implement this command for " - "other\nitem types."); - return NULL; - } - - return target; -} - -void RecursiveCollectDeps(const Target* target, std::set<Label>* result) { - if (result->find(target->label()) != result->end()) - return; // Already did this target. - result->insert(target->label()); - - const std::vector<const Target*>& deps = target->deps(); - for (size_t i = 0; i < deps.size(); i++) - RecursiveCollectDeps(deps[i], result); -} - -// Prints dependencies of the given target (not the target itself). -void RecursivePrintDeps(const Target* target, - const Label& default_toolchain, - int indent_level) { - std::vector<const Target*> sorted_deps = target->deps(); - std::sort(sorted_deps.begin(), sorted_deps.end(), CompareTargetLabel()); - - std::string indent(indent_level * 2, ' '); - for (size_t i = 0; i < sorted_deps.size(); i++) { - OutputString(indent + - sorted_deps[i]->label().GetUserVisibleName(default_toolchain) + "\n"); - RecursivePrintDeps(sorted_deps[i], default_toolchain, indent_level + 1); - } -} - -} // namespace - -int RunDescCommand(const std::vector<std::string>& args) { - if (args.size() != 1) { - Err(Location(), "You're holding it wrong.", - "Usage: \"gn desc <target_name>\"").PrintToStdout(); - return NULL; - } - - const Target* target = GetTargetForDesc(args); - if (!target) - return 1; - - // Generally we only want to display toolchains on labels when the toolchain - // is different than the default one for this target (which we always print - // in the header). - Label target_toolchain = target->label().GetToolchainLabel(); - - // Header. - std::string title_target = - "Target: " + target->label().GetUserVisibleName(false); - std::string title_toolchain = - "Toolchain: " + target_toolchain.GetUserVisibleName(false); - OutputString(title_target + "\n", DECORATION_YELLOW); - OutputString(title_toolchain + "\n", DECORATION_YELLOW); - OutputString(std::string( - std::max(title_target.size(), title_toolchain.size()), '=') + "\n"); - - OutputString("Sources:\n"); - const Target::FileList& sources = target->sources(); - for (size_t i = 0; i < sources.size(); i++) - OutputString(" " + sources[i].value() + "\n"); - - // Configs (don't sort since the order determines how things are processed). - OutputString("\nConfigs:\n"); - const std::vector<const Config*>& configs = target->configs(); - for (size_t i = 0; i < configs.size(); i++) { - OutputString(" " + - configs[i]->label().GetUserVisibleName(target_toolchain) + "\n"); - } - - // Deps. Sorted for convenience. Sort the labels rather than the strings so - // that "//foo:bar" comes before "//foo/third_party:bar". - OutputString("\nDirect dependencies:\n" - "(Use \"gn deps\" or \"gn tree\" to display recursive deps.)\n"); - const std::vector<const Target*>& deps = target->deps(); - std::vector<Label> sorted_deps; - for (size_t i = 0; i < deps.size(); i++) - sorted_deps.push_back(deps[i]->label()); - std::sort(sorted_deps.begin(), sorted_deps.end()); - for (size_t i = 0; i < sorted_deps.size(); i++) { - OutputString(" " + sorted_deps[i].GetUserVisibleName(target_toolchain) + - "\n"); - } - return 0; -} - -int RunDepsCommand(const std::vector<std::string>& args) { - if (args.size() != 1) { - Err(Location(), "You're holding it wrong.", - "Usage: \"gn deps <target_name>\"").PrintToStdout(); - return NULL; - } - - const Target* target = GetTargetForDesc(args); - if (!target) - return 1; - - // Generally we only want to display toolchains on labels when the toolchain - // is different than the default one for this target (which we always print - // in the header). - Label target_toolchain = target->label().GetToolchainLabel(); - - std::set<Label> all_deps; - RecursiveCollectDeps(target, &all_deps); - - OutputString("Recursive dependencies of " + - target->label().GetUserVisibleName(true) + "\n", - DECORATION_YELLOW); - - for (std::set<Label>::iterator i = all_deps.begin(); - i != all_deps.end(); ++i) - OutputString(" " + i->GetUserVisibleName(target_toolchain) + "\n"); - return 0; -} - -int RunTreeCommand(const std::vector<std::string>& args) { - if (args.size() != 1) { - Err(Location(), "You're holding it wrong.", - "Usage: \"gn tree <target_name>\"").PrintToStdout(); - return NULL; - } - - const Target* target = GetTargetForDesc(args); - if (!target) - return 1; - - OutputString(target->label().GetUserVisibleName(false) + "\n"); - RecursivePrintDeps(target, target->label().GetToolchainLabel(), 1); - - return 0; -} diff --git a/tools/gn/command_gen.cc b/tools/gn/command_gen.cc deleted file mode 100644 index ab64a8d..0000000 --- a/tools/gn/command_gen.cc +++ /dev/null @@ -1,66 +0,0 @@ -// 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 "base/bind.h" -#include "base/command_line.h" -#include "base/strings/string_number_conversions.h" -#include "base/time/time.h" -#include "tools/gn/build_settings.h" -#include "tools/gn/commands.h" -#include "tools/gn/ninja_target_writer.h" -#include "tools/gn/ninja_writer.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/setup.h" -#include "tools/gn/standard_out.h" - -namespace { - -// Suppress output on success. -const char kSwitchQuiet[] = "q"; - -} // namespace - -int RunGenCommand(const std::vector<std::string>& args) { - base::TimeTicks begin_time = base::TimeTicks::Now(); - - // Deliberately leaked to avoid expensive process teardown. - Setup* setup = new Setup; - if (!setup->DoSetup()) - return 1; - - // Cause the load to also generate the ninja files for each target. - setup->build_settings().set_target_resolved_callback( - base::Bind(&NinjaTargetWriter::RunAndWriteFile)); - - // Do the actual load. This will also write out the target ninja files. - if (!setup->Run()) - return 1; - - // Write the root ninja files. - if (!NinjaWriter::RunAndWriteFiles(&setup->build_settings())) { - Err(Location(), - "Couldn't open root buildfile(s) for writing").PrintToStdout(); - return 1; - } - - base::TimeTicks end_time = base::TimeTicks::Now(); - - if (!CommandLine::ForCurrentProcess()->HasSwitch(kSwitchQuiet)) { - OutputString("Done. ", DECORATION_GREEN); - - // TODO(brettw) get the number of targets without getting the entire list. - std::vector<const Target*> all_targets; - setup->build_settings().target_manager().GetAllTargets(&all_targets); - std::string stats = "Generated " + - base::IntToString(static_cast<int>(all_targets.size())) + - " targets from " + - base::IntToString( - setup->scheduler().input_file_manager()->GetInputFileCount()) + - " files in " + - base::IntToString((end_time - begin_time).InMilliseconds()) + "ms\n"; - OutputString(stats); - } - - return 0; -} diff --git a/tools/gn/commands.h b/tools/gn/commands.h deleted file mode 100644 index 1d4449c..0000000 --- a/tools/gn/commands.h +++ /dev/null @@ -1,18 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_COMMANDS_H_ -#define TOOLS_GN_COMMANDS_H_ - -#include <string> -#include <vector> - -// The different commands we have, returns the value we should return from -// main(). -int RunDepsCommand(const std::vector<std::string>& args); -int RunDescCommand(const std::vector<std::string>& args); -int RunGenCommand(const std::vector<std::string>& args); -int RunTreeCommand(const std::vector<std::string>& args); - -#endif // TOOLS_GN_COMMANDS_H_ diff --git a/tools/gn/config.cc b/tools/gn/config.cc deleted file mode 100644 index 1175d7f..0000000 --- a/tools/gn/config.cc +++ /dev/null @@ -1,78 +0,0 @@ -// 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/config.h" - -#include "tools/gn/err.h" -#include "tools/gn/input_file_manager.h" -#include "tools/gn/item_node.h" -#include "tools/gn/item_tree.h" -#include "tools/gn/scheduler.h" - -Config::Config(const Label& label) : Item(label) { -} - -Config::~Config() { -} - -Config* Config::AsConfig() { - return this; -} - -const Config* Config::AsConfig() const { - return this; -} - -// static -Config* Config::GetConfig(const Settings* settings, - const LocationRange& specified_from_here, - const Label& label, - Item* dep_from, - Err* err) { - DCHECK(!label.is_null()); - - ItemTree* tree = &settings->build_settings()->item_tree(); - base::AutoLock lock(tree->lock()); - - ItemNode* node = tree->GetExistingNodeLocked(label); - Config* config = NULL; - if (!node) { - config = new Config(label); - node = new ItemNode(config); - tree->AddNodeLocked(node); - - // Only schedule loading the given target if somebody is depending on it - // (and we optimize by not re-asking it to run the current file). - // Otherwise, we're probably generating it right now. - if (dep_from && dep_from->label().dir() != label.dir()) { - settings->build_settings()->toolchain_manager().ScheduleInvocationLocked( - specified_from_here, label.GetToolchainLabel(), label.dir(), - err); - } - } else if ((config = node->item()->AsConfig())) { - // Previously saw this item as a config. - - // If we have no dep_from, we're generating it. In this case, it had better - // not already be generated. - if (!dep_from && node->state() != ItemNode::REFERENCED) { - *err = Err(specified_from_here, "Duplicate config definition.", - "You already told me about a config with this name."); - return NULL; - } - } else { - // Previously saw this thing as a non-config. - *err = Err(specified_from_here, - "Config name already used.", - "Previously you specified a " + - node->item()->GetItemTypeName() + " with this name instead."); - return NULL; - } - - // Keep a record of the guy asking us for this dependency. We know if - // somebody is adding a dependency, that guy it himself not resolved. - if (dep_from && node->state() != ItemNode::RESOLVED) - tree->GetExistingNodeLocked(dep_from->label())->AddDependency(node); - - return config; -} diff --git a/tools/gn/config.h b/tools/gn/config.h deleted file mode 100644 index 0ee9b7b..0000000 --- a/tools/gn/config.h +++ /dev/null @@ -1,45 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_CONFIG_H_ -#define TOOLS_GN_CONFIG_H_ - -#include "base/compiler_specific.h" -#include "tools/gn/config_values.h" -#include "tools/gn/item.h" - -class Err; -class ItemTree; -class LocationRange; -class Settings; - -// Represents a named config in the dependency graph. -class Config : public Item { - public: - Config(const Label& label); - virtual ~Config(); - - virtual Config* AsConfig() OVERRIDE; - virtual const Config* AsConfig() const OVERRIDE; - - ConfigValues& config_values() { return config_values_; } - const ConfigValues& config_values() const { return config_values_; } - - // Gets or creates a config. - // - // This is like the TargetManager is for Targets, but Configs are so much - // simpler that this one function is all we need. - static Config* GetConfig(const Settings* settings, - const LocationRange& specified_from_here, - const Label& label, - Item* dep_from, - Err* err); - - private: - ConfigValues config_values_; - - DISALLOW_COPY_AND_ASSIGN(Config); -}; - -#endif // TOOLS_GN_CONFIG_H_ diff --git a/tools/gn/config_values.cc b/tools/gn/config_values.cc deleted file mode 100644 index 53466df..0000000 --- a/tools/gn/config_values.cc +++ /dev/null @@ -1,11 +0,0 @@ -// 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/config_values.h" - -ConfigValues::ConfigValues() { -} - -ConfigValues::~ConfigValues() { -} diff --git a/tools/gn/config_values.h b/tools/gn/config_values.h deleted file mode 100644 index e7c1712..0000000 --- a/tools/gn/config_values.h +++ /dev/null @@ -1,50 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_CONFIG_VALUES_H_ -#define TOOLS_GN_CONFIG_VALUES_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "tools/gn/source_dir.h" - -// Holds the values (includes, defines, compiler flags, etc.) for a given -// config or target. -class ConfigValues { - public: - ConfigValues(); - ~ConfigValues(); - - const std::vector<SourceDir>& includes() const { return includes_; } - void swap_in_includes(std::vector<SourceDir>* lo) { includes_.swap(*lo); } - - const std::vector<std::string>& defines() const { return defines_; } - void swap_in_defines(std::vector<std::string>* d) { defines_.swap(*d); } - - const std::vector<std::string>& cflags() const { return cflags_; } - void swap_in_cflags(std::vector<std::string>* lo) { cflags_.swap(*lo); } - - const std::vector<std::string>& cflags_c() const { return cflags_c_; } - void swap_in_cflags_c(std::vector<std::string>* lo) { cflags_c_.swap(*lo); } - - const std::vector<std::string>& cflags_cc() const { return cflags_cc_; } - void swap_in_cflags_cc(std::vector<std::string>* lo) { cflags_cc_.swap(*lo); } - - const std::vector<std::string>& ldflags() const { return ldflags_; } - void swap_in_ldflags(std::vector<std::string>* lo) { ldflags_.swap(*lo); } - - private: - std::vector<SourceDir> includes_; - std::vector<std::string> defines_; - std::vector<std::string> cflags_; - std::vector<std::string> cflags_c_; - std::vector<std::string> cflags_cc_; - std::vector<std::string> ldflags_; - - DISALLOW_COPY_AND_ASSIGN(ConfigValues); -}; - -#endif // TOOLS_GN_CONFIG_VALUES_H_ diff --git a/tools/gn/config_values_extractors.cc b/tools/gn/config_values_extractors.cc deleted file mode 100644 index 96b514a..0000000 --- a/tools/gn/config_values_extractors.cc +++ /dev/null @@ -1,22 +0,0 @@ -// 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/config_values_extractors.h" - -namespace { - -struct StringWriter { - void operator()(const std::string& s, std::ostream& out) const { - out << " " << s; - } -}; - -} // namespace - -void RecursiveTargetConfigStringsToStream( - const Target* target, - const std::vector<std::string>& (ConfigValues::* getter)() const, - std::ostream& out) { - RecursiveTargetConfigToStream(target, getter, StringWriter(), out); -} diff --git a/tools/gn/config_values_extractors.h b/tools/gn/config_values_extractors.h deleted file mode 100644 index 0eaa2c9..0000000 --- a/tools/gn/config_values_extractors.h +++ /dev/null @@ -1,50 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_ -#define TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_ - -#include <ostream> -#include <string> -#include <vector> - -#include "tools/gn/config.h" -#include "tools/gn/config_values.h" -#include "tools/gn/target.h" - -template<typename T, class Writer> -inline void ConfigValuesToStream( - const ConfigValues& values, - const std::vector<T>& (ConfigValues::* getter)() const, - const Writer& writer, - std::ostream& out) { - const std::vector<T>& v = (values.*getter)(); - for (size_t i = 0; i < v.size(); i++) - writer(v[i], out); -}; - -template<typename T, class Writer> -inline void RecursiveTargetConfigToStream( - const Target* target, - const std::vector<T>& (ConfigValues::* getter)() const, - const Writer& writer, - std::ostream& out) { - // Write all configs in reverse order (to get oldest first, which will look - // more normal in the output). - for (int i = static_cast<int>(target->configs().size() - 1); i >= 0; i--) { - ConfigValuesToStream(target->configs()[i]->config_values(), getter, - writer, out); - } - - // Last write from the config from the Target itself, if any. - ConfigValuesToStream(target->config_values(), getter, writer, out); -} - -// Writes the values out as strings with no transformation. -void RecursiveTargetConfigStringsToStream( - const Target* target, - const std::vector<std::string>& (ConfigValues::* getter)() const, - std::ostream& out); - -#endif // TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_ diff --git a/tools/gn/config_values_generator.cc b/tools/gn/config_values_generator.cc deleted file mode 100644 index 34c3f67..0000000 --- a/tools/gn/config_values_generator.cc +++ /dev/null @@ -1,89 +0,0 @@ -// 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/config_values_generator.h" - -#include "tools/gn/config_values.h" -#include "tools/gn/scope.h" -#include "tools/gn/value.h" -#include "tools/gn/value_extractors.h" - -namespace { - -void GetStringList( - const Scope* scope, - const char* var_name, - ConfigValues* config_values, - void (ConfigValues::* swapper_inner)(std::vector<std::string>*), - Err* err) { - const Value* value = scope->GetValue(var_name); - if (!value) - return; // No value, empty input and succeed. - - std::vector<std::string> result; - ExtractListOfStringValues(*value, &result, err); - (config_values->*swapper_inner)(&result); -} - -} // namespace - -ConfigValuesGenerator::ConfigValuesGenerator(ConfigValues* dest_values, - const Scope* scope, - const Token& function_token, - const SourceDir& input_dir, - Err* err) - : config_values_(dest_values), - scope_(scope), - function_token_(function_token), - input_dir_(input_dir), - err_(err) { -} - -ConfigValuesGenerator::~ConfigValuesGenerator() { -} - -void ConfigValuesGenerator::Run() { - FillDefines(); - FillIncludes(); - FillCflags(); - FillCflags_C(); - FillCflags_CC(); - FillLdflags(); -} - -void ConfigValuesGenerator::FillDefines() { - GetStringList(scope_, "defines", config_values_, - &ConfigValues::swap_in_defines, err_); -} - -void ConfigValuesGenerator::FillIncludes() { - const Value* value = scope_->GetValue("includes"); - if (!value) - return; // No value, empty input and succeed. - - std::vector<SourceDir> includes; - if (!ExtractListOfRelativeDirs(*value, input_dir_, &includes, err_)) - return; - config_values_->swap_in_includes(&includes); -} - -void ConfigValuesGenerator::FillCflags() { - GetStringList(scope_, "cflags", config_values_, - &ConfigValues::swap_in_cflags, err_); -} - -void ConfigValuesGenerator::FillCflags_C() { - GetStringList(scope_, "cflags_c", config_values_, - &ConfigValues::swap_in_cflags_c, err_); -} - -void ConfigValuesGenerator::FillCflags_CC() { - GetStringList(scope_, "cflags_cc", config_values_, - &ConfigValues::swap_in_cflags_cc, err_); -} - -void ConfigValuesGenerator::FillLdflags() { - GetStringList(scope_, "ldflags", config_values_, - &ConfigValues::swap_in_ldflags, err_); -} diff --git a/tools/gn/config_values_generator.h b/tools/gn/config_values_generator.h deleted file mode 100644 index 79d9067..0000000 --- a/tools/gn/config_values_generator.h +++ /dev/null @@ -1,48 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_CONFIG_VALUES_GENERATOR_H_ -#define TOOLS_GN_CONFIG_VALUES_GENERATOR_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "tools/gn/source_dir.h" - -class ConfigValues; -class Err; -class Scope; -class Token; - -class ConfigValuesGenerator { - public: - ConfigValuesGenerator(ConfigValues* dest_values, - const Scope* scope, - const Token& function_token, - const SourceDir& input_dir, - Err* err); - ~ConfigValuesGenerator(); - - // Sets the error passed to the constructor on failure. - void Run(); - - private: - void FillDefines(); - void FillIncludes(); - void FillCflags(); - void FillCflags_C(); - void FillCflags_CC(); - void FillLdflags(); - - ConfigValues* config_values_; - const Scope* scope_; - const Token& function_token_; - const SourceDir input_dir_; - Err* err_; - - DISALLOW_COPY_AND_ASSIGN(ConfigValuesGenerator); -}; - -#endif // TOOLS_GN_CONFIG_VALUES_GENERATOR_H_ diff --git a/tools/gn/err.cc b/tools/gn/err.cc deleted file mode 100644 index 068ea6d..0000000 --- a/tools/gn/err.cc +++ /dev/null @@ -1,196 +0,0 @@ -// 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/err.h" - -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/input_file.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/standard_out.h" -#include "tools/gn/tokenizer.h" -#include "tools/gn/value.h" - -namespace { - -std::string GetNthLine(const base::StringPiece& data, int n) { - size_t line_off = Tokenizer::ByteOffsetOfNthLine(data, n); - size_t end = line_off + 1; - while (end < data.size() && !Tokenizer::IsNewline(data, end)) - end++; - return data.substr(line_off, end - line_off).as_string(); -} - -void FillRangeOnLine(const LocationRange& range, int line_number, - std::string* line) { - // Only bother if the range's begin or end overlaps the line. If the entire - // line is highlighted as a result of this range, it's not very helpful. - if (range.begin().line_number() != line_number && - range.end().line_number() != line_number) - return; - - // Watch out, the char offsets in the location are 1-based, so we have to - // subtract 1. - int begin_char; - if (range.begin().line_number() < line_number) - begin_char = 0; - else - begin_char = range.begin().char_offset() - 1; - - int end_char; - if (range.end().line_number() > line_number) - end_char = line->size(); // Ending is non-inclusive. - else - end_char = range.end().char_offset() - 1; - - CHECK(end_char >= begin_char); - CHECK(begin_char >= 0 && begin_char <= static_cast<int>(line->size())); - CHECK(end_char >= 0 && end_char <= static_cast<int>(line->size())); - for (int i = begin_char; i < end_char; i++) - line->at(i) = '-'; -} - -// The line length is used to clip the maximum length of the markers we'll -// make if the error spans more than one line (like unterminated literals). -void OutputHighlighedPosition(const Location& location, - const Err::RangeList& ranges, - size_t line_length) { - // Make a buffer of the line in spaces. - std::string highlight; - highlight.resize(line_length); - for (size_t i = 0; i < line_length; i++) - highlight[i] = ' '; - - // Highlight all the ranges on the line. - for (size_t i = 0; i < ranges.size(); i++) - FillRangeOnLine(ranges[i], location.line_number(), &highlight); - - // Allow the marker to be one past the end of the line for marking the end. - highlight.push_back(' '); - CHECK(location.char_offset() - 1 >= 0 && - location.char_offset() - 1 < static_cast<int>(highlight.size())); - highlight[location.char_offset() - 1] = '^'; - - // Trim unused spaces from end of line. - while (!highlight.empty() && highlight[highlight.size() - 1] == ' ') - highlight.resize(highlight.size() - 1); - - highlight += "\n"; - OutputString(highlight, DECORATION_BLUE); -} - -} // namespace - -Err::Err() : has_error_(false) { -} - -Err::Err(const Location& location, - const std::string& msg, - const std::string& help) - : has_error_(true), - location_(location), - message_(msg), - help_text_(help) { -} - -Err::Err(const LocationRange& range, - const std::string& msg, - const std::string& help) - : has_error_(true), - location_(range.begin()), - message_(msg), - help_text_(help) { - ranges_.push_back(range); -} - -Err::Err(const Token& token, - const std::string& msg, - const std::string& help) - : has_error_(true), - location_(token.location()), - message_(msg), - help_text_(help) { - ranges_.push_back(token.range()); -} - -Err::Err(const ParseNode* node, - const std::string& msg, - const std::string& help_text) - : has_error_(true), - message_(msg), - help_text_(help_text) { - // Node will be null in certain tests. - if (node) { - LocationRange range = node->GetRange(); - location_ = range.begin(); - ranges_.push_back(range); - } -} - -Err::Err(const Value& value, - const std::string msg, - const std::string& help_text) - : has_error_(true), - message_(msg), - help_text_(help_text) { - if (value.origin()) { - LocationRange range = value.origin()->GetRange(); - location_ = range.begin(); - ranges_.push_back(range); - } -} - -Err::~Err() { -} - -void Err::PrintToStdout() const { - InternalPrintToStdout(false); -} - -void Err::AppendSubErr(const Err& err) { - sub_errs_.push_back(err); -} - -void Err::InternalPrintToStdout(bool is_sub_err) const { - DCHECK(has_error_); - - if (!is_sub_err) - OutputString("ERROR ", DECORATION_RED); - - // File name and location. - const InputFile* input_file = location_.file(); - std::string loc_str; - if (input_file) { - std::string path8; - path8.assign(input_file->name().value()); - - if (is_sub_err) - loc_str = "See "; - else - loc_str = "at "; - loc_str += path8 + ": " + - base::IntToString(location_.line_number()) + ":" + - base::IntToString(location_.char_offset()) + ": "; - } - OutputString(loc_str + message_ + "\n"); - - // Quoted line. - if (input_file) { - std::string line = GetNthLine(input_file->contents(), - location_.line_number()); - if (!ContainsOnlyWhitespaceASCII(line)) { - OutputString(line + "\n", DECORATION_BOLD); - OutputHighlighedPosition(location_, ranges_, line.size()); - } - } - - // Optional help text. - if (!help_text_.empty()) - OutputString(help_text_ + "\n"); - - // Sub errors. - for (size_t i = 0; i < sub_errs_.size(); i++) - sub_errs_[i].InternalPrintToStdout(true); -} diff --git a/tools/gn/err.h b/tools/gn/err.h deleted file mode 100644 index 3e077e9..0000000 --- a/tools/gn/err.h +++ /dev/null @@ -1,85 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_ERR_H_ -#define TOOLS_GN_ERR_H_ - -#include <string> -#include <vector> - -#include "tools/gn/location.h" -#include "tools/gn/token.h" - -class ParseNode; -class Value; - -// Result of doing some operation. Check has_error() to see if an error -// occurred. -// -// An error has a location and a message. Below that, is some optional help -// text to go with the annotation of the location. -// -// An error can also have sub-errors which are additionally printed out -// below. They can provide additional context. -class Err { - public: - typedef std::vector<LocationRange> RangeList; - - // Indicates no error. - Err(); - - // Error at a single point. - Err(const Location& location, - const std::string& msg, - const std::string& help = std::string()); - - // Error at a given range. - Err(const LocationRange& range, - const std::string& msg, - const std::string& help = std::string()); - - // Error at a given token. - Err(const Token& token, - const std::string& msg, - const std::string& help_text = std::string()); - - // Error at a given node. - Err(const ParseNode* node, - const std::string& msg, - const std::string& help_text = std::string()); - - // Error at a given value. - Err(const Value& value, - const std::string msg, - const std::string& help_text = std::string()); - - ~Err(); - - bool has_error() const { return has_error_; } - const Location& location() const { return location_; } - const std::string& message() const { return message_; } - const std::string& help_text() const { return help_text_; } - - void AppendRange(const LocationRange& range) { ranges_.push_back(range); } - const RangeList& ranges() const { return ranges_; } - - void AppendSubErr(const Err& err); - - void PrintToStdout() const; - - private: - void InternalPrintToStdout(bool is_sub_err) const; - - bool has_error_; - Location location_; - - std::vector<LocationRange> ranges_; - - std::string message_; - std::string help_text_; - - std::vector<Err> sub_errs_; -}; - -#endif // TOOLS_GN_ERR_H_ diff --git a/tools/gn/escape.cc b/tools/gn/escape.cc deleted file mode 100644 index 5fc7b6f..0000000 --- a/tools/gn/escape.cc +++ /dev/null @@ -1,77 +0,0 @@ -// 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/escape.h" - -#include "base/containers/stack_container.h" - -namespace { - -template<typename DestString> -void EscapeStringToString(const base::StringPiece& str, - const EscapeOptions& options, - DestString* dest) { - bool used_quotes = false; - - for (size_t i = 0; i < str.size(); i++) { - if (str[i] == '$' && options.mode == ESCAPE_NINJA) { - // Escape dollars signs since ninja treats these specially. - dest->push_back('$'); - dest->push_back('$'); - } else if (str[i] == '"' && options.mode == ESCAPE_SHELL) { - // Escape quotes with backslashes for the command-line (Ninja doesn't - // care). - dest->push_back('\\'); - dest->push_back('"'); - } else if (str[i] == ' ') { - if (options.mode == ESCAPE_NINJA) { - // For ninja just escape spaces with $. - dest->push_back('$'); - } else if (options.mode == ESCAPE_SHELL && !options.inhibit_quoting) { - // For the shell, quote the whole string. - if (!used_quotes) { - used_quotes = true; - dest->insert(dest->begin(), '"'); - } - } - dest->push_back(' '); -#if defined(OS_WIN) - } else if (str[i] == '/' && options.convert_slashes) { - // Convert slashes on Windows if requested. - dest->push_back('\\'); -#else - } else if (str[i] == '\\' && options.mode == ESCAPE_SHELL) { - // For non-Windows shell, escape backslashes. - dest->push_back('\\'); - dest->push_back('\\'); -#endif - } else { - dest->push_back(str[i]); - } - } - - if (used_quotes) - dest->push_back('"'); -} - -} // namespace - -std::string EscapeString(const base::StringPiece& str, - const EscapeOptions& options) { - std::string result; - result.reserve(str.size() + 4); // Guess we'll add a couple of extra chars. - EscapeStringToString(str, options, &result); - return result; -} - -void EscapeStringToStream(std::ostream& out, - const base::StringPiece& str, - const EscapeOptions& options) { - // Escape to a stack buffer and then write out to the stream. - base::StackVector<char, 256> result; - result->reserve(str.size() + 4); // Guess we'll add a couple of extra chars. - EscapeStringToString(str, options, &result.container()); - if (!result->empty()) - out.write(result->data(), result->size()); -} diff --git a/tools/gn/escape.h b/tools/gn/escape.h deleted file mode 100644 index 1791161..0000000 --- a/tools/gn/escape.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_ESCAPE_H_ -#define TOOLS_GN_ESCAPE_H_ - -#include <iosfwd> - -#include "base/strings/string_piece.h" - -// TODO(brettw) we may need to make this a bitfield. If we want to write a -// shell command in a ninja file, we need the shell characters to be escaped, -// and THEN the ninja characters. Or maybe we require the caller to do two -// passes. -enum EscapingMode { - ESCAPE_NONE, // No escaping. - ESCAPE_NINJA, // Ninja string escaping. - ESCAPE_SHELL, // Shell string escaping. -}; - -struct EscapeOptions { - EscapeOptions() - : mode(ESCAPE_NONE), - convert_slashes(false), - inhibit_quoting(false) { - } - - EscapingMode mode; - - // When set, converts forward-slashes to system-specific path separators. - bool convert_slashes; - - // When the escaping mode is ESCAPE_SHELL, the escaper will normally put - // quotes around things with spaces. If this value is set to true, we'll - // disable the quoting feature and just add the spaces. - // - // This mode is for when quoting is done at some higher-level. Defaults to - // false. - bool inhibit_quoting; -}; - -// Escapes the given input, returnining the result. -std::string EscapeString(const base::StringPiece& str, - const EscapeOptions& options); - -// Same as EscapeString but writes the results to the given stream, saving a -// copy. -void EscapeStringToStream(std::ostream& out, - const base::StringPiece& str, - const EscapeOptions& options); - -#endif // TOOLS_GN_ESCAPE_H_ diff --git a/tools/gn/escape_unittest.cc b/tools/gn/escape_unittest.cc deleted file mode 100644 index a7c19b3..0000000 --- a/tools/gn/escape_unittest.cc +++ /dev/null @@ -1,4 +0,0 @@ -// 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. - diff --git a/tools/gn/file_template.cc b/tools/gn/file_template.cc deleted file mode 100644 index 8b5d09f..0000000 --- a/tools/gn/file_template.cc +++ /dev/null @@ -1,125 +0,0 @@ -// 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/file_template.h" - -#include "tools/gn/filesystem_utils.h" - -const char FileTemplate::kSource[] = "{{source}}"; -const char FileTemplate::kSourceNamePart[] = "{{source_name_part}}"; - -FileTemplate::FileTemplate(const Value& t, Err* err) { - ParseInput(t, err); -} - -FileTemplate::FileTemplate(const std::vector<std::string>& t) { - for (size_t i = 0; i < t.size(); i++) - ParseOneTemplateString(t[i]); -} - -FileTemplate::~FileTemplate() { -} - -void FileTemplate::Apply(const Value& sources, - const ParseNode* origin, - std::vector<Value>* dest, - Err* err) const { - if (!sources.VerifyTypeIs(Value::LIST, err)) - return; - dest->reserve(sources.list_value().size() * templates_.container().size()); - - // Temporary holding place, allocate outside to re-use- buffer. - std::vector<std::string> string_output; - - const std::vector<Value>& sources_list = sources.list_value(); - for (size_t i = 0; i < sources_list.size(); i++) { - if (!sources_list[i].VerifyTypeIs(Value::STRING, err)) - return; - - ApplyString(sources_list[i].string_value(), &string_output); - for (size_t out_i = 0; out_i < string_output.size(); out_i++) - dest->push_back(Value(origin, string_output[i])); - } -} - -void FileTemplate::ApplyString(const std::string& str, - std::vector<std::string>* output) const { - // Compute all substitutions needed so we can just do substitutions below. - // We skip the LITERAL one since that varies each time. - std::string subst[Subrange::NUM_TYPES]; - if (types_required_[Subrange::SOURCE]) - subst[Subrange::SOURCE] = str; - if (types_required_[Subrange::NAME_PART]) - subst[Subrange::NAME_PART] = FindFilenameNoExtension(&str).as_string(); - - output->resize(templates_.container().size()); - for (size_t template_i = 0; - template_i < templates_.container().size(); template_i++) { - const Template& t = templates_[template_i]; - (*output)[template_i].clear(); - for (size_t subrange_i = 0; subrange_i < t.container().size(); - subrange_i++) { - if (t[subrange_i].type == Subrange::LITERAL) - (*output)[template_i].append(t[subrange_i].literal); - else - (*output)[template_i].append(subst[t[subrange_i].type]); - } - } -} - -void FileTemplate::ParseInput(const Value& value, Err* err) { - switch (value.type()) { - case Value::STRING: - ParseOneTemplateString(value.string_value()); - break; - case Value::LIST: - for (size_t i = 0; i < value.list_value().size(); i++) { - if (!value.list_value()[i].VerifyTypeIs(Value::STRING, err)) - return; - ParseOneTemplateString(value.list_value()[i].string_value()); - } - break; - default: - *err = Err(value, "File template must be a string or list.", - "A sarcastic comment about your skills goes here."); - } -} - -void FileTemplate::ParseOneTemplateString(const std::string& str) { - templates_.container().resize(templates_.container().size() + 1); - Template& t = templates_[templates_.container().size() - 1]; - - size_t cur = 0; - while (true) { - size_t next = str.find("{{", cur); - - // Pick up everything from the previous spot to here as a literal. - if (next == std::string::npos) { - if (cur != str.size()) - t.container().push_back(Subrange(Subrange::LITERAL, str.substr(cur))); - break; - } else if (next > cur) { - t.container().push_back( - Subrange(Subrange::LITERAL, str.substr(cur, next - cur))); - } - - // Decode the template param. - if (str.compare(next, arraysize(kSource) - 1, kSource) == 0) { - t.container().push_back(Subrange(Subrange::SOURCE)); - types_required_[Subrange::SOURCE] = true; - cur = next + arraysize(kSource) - 1; - } else if (str.compare(next, arraysize(kSourceNamePart) - 1, - kSourceNamePart) == 0) { - t.container().push_back(Subrange(Subrange::NAME_PART)); - types_required_[Subrange::NAME_PART] = true; - cur = next + arraysize(kSourceNamePart) - 1; - } else { - // If it's not a match, treat it like a one-char literal (this will be - // rare, so it's not worth the bother to add to the previous literal) so - // we can keep going. - t.container().push_back(Subrange(Subrange::LITERAL, "{")); - cur = next + 1; - } - } -} diff --git a/tools/gn/file_template.h b/tools/gn/file_template.h deleted file mode 100644 index 25d2251..0000000 --- a/tools/gn/file_template.h +++ /dev/null @@ -1,74 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_FILE_TEMPLATE_H_ -#define TOOLS_GN_FILE_TEMPLATE_H_ - -#include "base/basictypes.h" -#include "base/containers/stack_container.h" -#include "tools/gn/err.h" -#include "tools/gn/value.h" - -class ParseNode; - -class FileTemplate { - public: - struct Subrange { - enum Type { - LITERAL = 0, - SOURCE, - NAME_PART, - NUM_TYPES // Must be last - }; - Subrange(Type t, const std::string& l = std::string()) - : type(t), - literal(l) { - } - - Type type; - - // When type_ == LITERAL, this specifies the literal. - std::string literal; - }; - - // Constructs a template from the given value. On error, the err will be - // set. In this case you should not use this object. - FileTemplate(const Value& t, Err* err); - FileTemplate(const std::vector<std::string>& t); - ~FileTemplate(); - - // Applies this template to the given list of sources, appending all - // results to the given dest list. The sources must be a list for the - // one that takes a value as an input, otherwise the given error will be set. - void Apply(const Value& sources, - const ParseNode* origin, - std::vector<Value>* dest, - Err* err) const; - void ApplyString(const std::string& input, - std::vector<std::string>* output) const; - - // Known template types. - static const char kSource[]; - static const char kSourceNamePart[]; - - private: - typedef base::StackVector<Subrange, 8> Template; - typedef base::StackVector<Template, 8> TemplateVector; - - void ParseInput(const Value& value, Err* err); - - // Parses a template string and adds it to the templates_ list. - void ParseOneTemplateString(const std::string& str); - - TemplateVector templates_; - - // The corresponding value is set to true if the given subrange type is - // required. This allows us to precompute these types whem applying them - // to a given source file. - bool types_required_[Subrange::NUM_TYPES]; - - DISALLOW_COPY_AND_ASSIGN(FileTemplate); -}; - -#endif // TOOLS_GN_FILE_TEMPLATE_H_ diff --git a/tools/gn/file_template_unittest.cc b/tools/gn/file_template_unittest.cc deleted file mode 100644 index 47c84f0..0000000 --- a/tools/gn/file_template_unittest.cc +++ /dev/null @@ -1,45 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/file_template.h" - -TEST(FileTemplate, Static) { - std::vector<std::string> templates; - templates.push_back("something_static"); - FileTemplate t(templates); - - std::vector<std::string> result; - t.ApplyString("", &result); - ASSERT_EQ(1u, result.size()); - EXPECT_EQ("something_static", result[0]); - - t.ApplyString("lalala", &result); - ASSERT_EQ(1u, result.size()); - EXPECT_EQ("something_static", result[0]); -} - -TEST(FileTemplate, Typical) { - std::vector<std::string> templates; - templates.push_back("foo/{{source_name_part}}.cc"); - templates.push_back("foo/{{source_name_part}}.h"); - FileTemplate t(templates); - - std::vector<std::string> result; - t.ApplyString("sources/ha.idl", &result); - ASSERT_EQ(2u, result.size()); - EXPECT_EQ("foo/ha.cc", result[0]); - EXPECT_EQ("foo/ha.h", result[1]); -} - -TEST(FileTemplate, Weird) { - std::vector<std::string> templates; - templates.push_back("{{{source}}{{source}}{{"); - FileTemplate t(templates); - - std::vector<std::string> result; - t.ApplyString("foo/lalala.c", &result); - ASSERT_EQ(1u, result.size()); - EXPECT_EQ("{foo/lalala.cfoo/lalala.c{{", result[0]); -} diff --git a/tools/gn/filesystem_utils.cc b/tools/gn/filesystem_utils.cc deleted file mode 100644 index 625a358..0000000 --- a/tools/gn/filesystem_utils.cc +++ /dev/null @@ -1,350 +0,0 @@ -// 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/filesystem_utils.h" - -#include "base/logging.h" -#include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" -#include "tools/gn/location.h" -#include "tools/gn/source_dir.h" - -namespace { - -enum DotDisposition { - // The given dot is just part of a filename and is not special. - NOT_A_DIRECTORY, - - // The given dot is the current directory. - DIRECTORY_CUR, - - // The given dot is the first of a double dot that should take us up one. - DIRECTORY_UP -}; - -// When we find a dot, this function is called with the character following -// that dot to see what it is. The return value indicates what type this dot is -// (see above). This code handles the case where the dot is at the end of the -// input. -// -// |*consumed_len| will contain the number of characters in the input that -// express what we found. -DotDisposition ClassifyAfterDot(const std::string& path, - size_t after_dot, - size_t* consumed_len) { - if (after_dot == path.size()) { - // Single dot at the end. - *consumed_len = 1; - return DIRECTORY_CUR; - } - if (path[after_dot] == '/') { - // Single dot followed by a slash. - *consumed_len = 2; // Consume the slash - return DIRECTORY_CUR; - } - - if (path[after_dot] == '.') { - // Two dots. - if (after_dot + 1 == path.size()) { - // Double dot at the end. - *consumed_len = 2; - return DIRECTORY_UP; - } - if (path[after_dot + 1] == '/') { - // Double dot folowed by a slash. - *consumed_len = 3; - return DIRECTORY_UP; - } - } - - // The dots are followed by something else, not a directory. - *consumed_len = 1; - return NOT_A_DIRECTORY; -} - -} // namesapce - -SourceFileType GetSourceFileType(const SourceFile& file, - Settings::TargetOS os) { - base::StringPiece extension = FindExtension(&file.value()); - if (extension == "cc" || extension == "cpp" || extension == "cxx") - return SOURCE_CC; - if (extension == "h") - return SOURCE_H; - if (extension == "c") - return SOURCE_C; - - switch (os) { - case Settings::MAC: - if (extension == "m") - return SOURCE_M; - if (extension == "mm") - return SOURCE_MM; - break; - - case Settings::WIN: - if (extension == "rc") - return SOURCE_RC; - break; - - default: - break; - } - - // TODO(brettw) asm files. - // TODO(brettw) weird thing with .S on non-Windows platforms. - return SOURCE_UNKNOWN; -} - -const char* GetExtensionForOutputType(Target::OutputType type, - Settings::TargetOS os) { - switch (os) { - case Settings::WIN: - switch (type) { - case Target::NONE: - NOTREACHED(); - return ""; - case Target::EXECUTABLE: - return "exe"; - case Target::SHARED_LIBRARY: - return "dll.lib"; // Extension of import library. - case Target::STATIC_LIBRARY: - return "lib"; - case Target::LOADABLE_MODULE: - return "dll"; // TODO(brettw) what's this? - default: - NOTREACHED(); - } - break; - - default: - NOTREACHED(); - } - return ""; -} - -std::string FilePathToUTF8(const base::FilePath& path) { -#if defined(OS_WIN) - return WideToUTF8(path.value()); -#else - return path.value(); -#endif -} - -base::FilePath UTF8ToFilePath(const base::StringPiece& sp) { -#if defined(OS_WIN) - return base::FilePath(UTF8ToWide(sp)); -#else - return base::FilePath(sp.as_string()); -#endif -} - -size_t FindExtensionOffset(const std::string& path) { - for (int i = static_cast<int>(path.size()); i >= 0; i--) { - if (path[i] == '/') - break; - if (path[i] == '.') - return i + 1; - } - return std::string::npos; -} - -base::StringPiece FindExtension(const std::string* path) { - size_t extension_offset = FindExtensionOffset(*path); - if (extension_offset == std::string::npos) - return base::StringPiece(); - return base::StringPiece(&path->data()[extension_offset], - path->size() - extension_offset); -} - -size_t FindFilenameOffset(const std::string& path) { - for (int i = static_cast<int>(path.size()) - 1; i >= 0; i--) { - if (path[i] == '/') - return i + 1; - } - return 0; // No filename found means everything was the filename. -} - -base::StringPiece FindFilename(const std::string* path) { - size_t filename_offset = FindFilenameOffset(*path); - if (filename_offset == 0) - return base::StringPiece(*path); // Everything is the file name. - return base::StringPiece(&(*path).data()[filename_offset], - path->size() - filename_offset); -} - -base::StringPiece FindFilenameNoExtension(const std::string* path) { - if (path->empty()) - return base::StringPiece(); - size_t filename_offset = FindFilenameOffset(*path); - size_t extension_offset = FindExtensionOffset(*path); - - size_t name_len; - if (extension_offset == std::string::npos) - name_len = path->size() - filename_offset; - else - name_len = extension_offset - filename_offset - 1; - - return base::StringPiece(&(*path).data()[filename_offset], name_len); -} - -void RemoveFilename(std::string* path) { - path->resize(FindFilenameOffset(*path)); -} - -bool EndsWithSlash(const std::string& s) { - return !s.empty() && s[s.size() - 1] == '/'; -} - -base::StringPiece FindDir(const std::string* path) { - size_t filename_offset = FindFilenameOffset(*path); - if (filename_offset == 0u) - return base::StringPiece(); - return base::StringPiece(path->data(), filename_offset); -} - -bool EnsureStringIsInOutputDir(const SourceDir& dir, - const std::string& str, - const Value& originating, - Err* err) { - // The last char of the dir will be a slash. We don't care if the input ends - // in a slash or not, so just compare up until there. - // - // This check will be wrong for all proper prefixes "e.g. "/output" will - // match "/out" but we don't really care since this is just a sanity check. - const std::string& dir_str = dir.value(); - if (str.compare(0, dir_str.length() - 1, dir_str, 0, dir_str.length() - 1) - != 0) { - *err = Err(originating, "File not inside output directory.", - "The given file should be in the output directory. Normally you would " - "specify\n\"$target_output_dir/foo\" or " - "\"$target_gen_dir/foo\". I interpreted this as\n\"" - + str + "\"."); - return false; - } - return true; -} - -std::string InvertDir(const SourceDir& path) { - const std::string value = path.value(); - if (value.empty()) - return std::string(); - - DCHECK(value[0] == '/'); - size_t begin_index = 1; - - // If the input begins with two slashes, skip over both (this is a - // source-relative dir). - if (value.size() > 1 && value[1] == '/') - begin_index = 2; - - std::string ret; - for (size_t i = begin_index; i < value.size(); i++) { - if (value[i] == '/') - ret.append("../"); - } - return ret; -} - -void NormalizePath(std::string* path) { - char* pathbuf = path->empty() ? NULL : &(*path)[0]; - - // top_index is the first character we can modify in the path. Anything - // before this indicates where the path is relative to. - size_t top_index = 0; - bool is_relative = true; - if (!path->empty() && pathbuf[0] == '/') { - is_relative = false; - - if (path->size() > 1 && pathbuf[1] == '/') { - // Two leading slashes, this is a path into the source dir. - top_index = 2; - } else { - // One leading slash, this is a system-absolute path. - top_index = 1; - } - } - - size_t dest_i = top_index; - for (size_t src_i = top_index; src_i < path->size(); /* nothing */) { - if (pathbuf[src_i] == '.') { - if (src_i == 0 || pathbuf[src_i - 1] == '/') { - // Slash followed by a dot, see if it's something special. - size_t consumed_len; - switch (ClassifyAfterDot(*path, src_i + 1, &consumed_len)) { - case NOT_A_DIRECTORY: - // Copy the dot to the output, it means nothing special. - pathbuf[dest_i++] = pathbuf[src_i++]; - break; - case DIRECTORY_CUR: - // Current directory, just skip the input. - src_i += consumed_len; - break; - case DIRECTORY_UP: - // Back up over previous directory component. If we're already - // at the top, preserve the "..". - if (dest_i > top_index) { - // The previous char was a slash, remove it. - dest_i--; - } - - if (dest_i == top_index) { - if (is_relative) { - // We're already at the beginning of a relative input, copy the - // ".." and continue. We need the trailing slash if there was - // one before (otherwise we're at the end of the input). - pathbuf[dest_i++] = '.'; - pathbuf[dest_i++] = '.'; - if (consumed_len == 3) - pathbuf[dest_i++] = '/'; - - // This also makes a new "root" that we can't delete by going - // up more levels. Otherwise "../.." would collapse to - // nothing. - top_index = dest_i; - } - // Otherwise we're at the beginning of an absolute path. Don't - // allow ".." to go up another level and just eat it. - } else { - // Just find the previous slash or the beginning of input. - while (dest_i > 0 && pathbuf[dest_i - 1] != '/') - dest_i--; - } - src_i += consumed_len; - } - } else { - // Dot not preceeded by a slash, copy it literally. - pathbuf[dest_i++] = pathbuf[src_i++]; - } - } else if (pathbuf[src_i] == '/') { - if (src_i > 0 && pathbuf[src_i - 1] == '/') { - // Two slashes in a row, skip over it. - src_i++; - } else { - // Just one slash, copy it. - pathbuf[dest_i++] = pathbuf[src_i++]; - } - } else { - // Input nothing special, just copy it. - pathbuf[dest_i++] = pathbuf[src_i++]; - } - } - path->resize(dest_i); -} - -void ConvertPathToSystem(std::string* path) { -#if defined(OS_WIN) - for (size_t i = 0; i < path->size(); i++) { - if ((*path)[i] == '/') - (*path)[i] = '\\'; - } -#endif -} - -std::string PathToSystem(const std::string& path) { - std::string ret(path); - ConvertPathToSystem(&ret); - return ret; -} - diff --git a/tools/gn/filesystem_utils.h b/tools/gn/filesystem_utils.h deleted file mode 100644 index 19139f8..0000000 --- a/tools/gn/filesystem_utils.h +++ /dev/null @@ -1,115 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_FILESYSTEM_UTILS_H_ -#define TOOLS_GN_FILESYSTEM_UTILS_H_ - -#include <string> - -#include "base/files/file_path.h" -#include "base/strings/string_piece.h" -#include "tools/gn/settings.h" -#include "tools/gn/target.h" - -class Err; -class Location; -class Value; - -enum SourceFileType { - SOURCE_UNKNOWN, - SOURCE_ASM, - SOURCE_C, - SOURCE_CC, - SOURCE_H, - SOURCE_M, - SOURCE_MM, - //SOURCE_S, // TODO(brettw) what is this? - SOURCE_RC, -}; - -SourceFileType GetSourceFileType(const SourceFile& file, - Settings::TargetOS os); - -// Returns the extension, not including the dot, for the given file type on the -// given system. -// -// Some targets make multiple files (like a .dll and an import library). This -// function returns the name of the file other targets should depend on and -// link to (so in this example, the import library). -const char* GetExtensionForOutputType(Target::OutputType type, - Settings::TargetOS os); - -std::string FilePathToUTF8(const base::FilePath& path); -base::FilePath UTF8ToFilePath(const base::StringPiece& sp); - -// Extensions ----------------------------------------------------------------- - -// Returns the index of the extension (character after the last dot not after a -// slash). Returns std::string::npos if not found. Returns path.size() if the -// file ends with a dot. -size_t FindExtensionOffset(const std::string& path); - -// Returns a string piece pointing into the input string identifying the -// extension. Note that the input pointer must outlive the output. -base::StringPiece FindExtension(const std::string* path); - -// Filename parts ------------------------------------------------------------- - -// Returns the offset of the character following the last slash, or -// 0 if no slash was found. Returns path.size() if the path ends with a slash. -// Note that the input pointer must outlive the output. -size_t FindFilenameOffset(const std::string& path); - -// Returns a string piece pointing into the input string identifying the -// file name (following the last slash, including the extension). Note that the -// input pointer must outlive the output. -base::StringPiece FindFilename(const std::string* path); - -// Like FindFilename but does not include the extension. -base::StringPiece FindFilenameNoExtension(const std::string* path); - -// Removes everything after the last slash. The last slash, if any, will be -// preserved. -void RemoveFilename(std::string* path); - -// Returns true if the given path ends with a slash. -bool EndsWithSlash(const std::string& s); - -// Path parts ----------------------------------------------------------------- - -// Returns a string piece pointing into the input string identifying the -// directory name of the given path, including the last slash. Note that the -// input pointer must outlive the output. -base::StringPiece FindDir(const std::string* path); - -// Verifies that the given string references a file inside of the given -// directory. This is pretty stupid and doesn't handle "." and "..", etc., -// it is designed for a sanity check to keep people from writing output files -// to the source directory accidentally. -// -// The originating value will be blamed in the error. -// -// If the file isn't in the dir, returns false and sets the error. Otherwise -// returns true and leaves the error untouched. -bool EnsureStringIsInOutputDir(const SourceDir& dir, - const std::string& str, - const Value& originating, - Err* err); - -// ---------------------------------------------------------------------------- - -// Converts a directory to its inverse (e.g. "/foo/bar/" -> "../../"). -// This will be the empty string for the root directories ("/" and "//"), and -// in all other cases, this is guaranteed to end in a slash. -std::string InvertDir(const SourceDir& dir); - -// Collapses "." and sequential "/"s and evaluates "..". -void NormalizePath(std::string* path); - -// Converts slashes to backslashes for Windows. Keeps the string unchanged -// for other systems. -void ConvertPathToSystem(std::string* path); -std::string PathToSystem(const std::string& path); - -#endif // TOOLS_GN_FILESYSTEM_UTILS_H_ diff --git a/tools/gn/filesystem_utils_unittest.cc b/tools/gn/filesystem_utils_unittest.cc deleted file mode 100644 index 75bf7cd..0000000 --- a/tools/gn/filesystem_utils_unittest.cc +++ /dev/null @@ -1,146 +0,0 @@ -// 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 "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/filesystem_utils.h" - -TEST(FilesystemUtils, FileExtensionOffset) { - EXPECT_EQ(std::string::npos, FindExtensionOffset("")); - EXPECT_EQ(std::string::npos, FindExtensionOffset("foo/bar/baz")); - EXPECT_EQ(4u, FindExtensionOffset("foo.")); - EXPECT_EQ(4u, FindExtensionOffset("f.o.bar")); - EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/")); - EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/baz")); -} - -TEST(FilesystemUtils, FindExtension) { - std::string input; - EXPECT_EQ("", FindExtension(&input).as_string()); - input = "foo/bar/baz"; - EXPECT_EQ("", FindExtension(&input).as_string()); - input = "foo."; - EXPECT_EQ("", FindExtension(&input).as_string()); - input = "f.o.bar"; - EXPECT_EQ("bar", FindExtension(&input).as_string()); - input = "foo.bar/"; - EXPECT_EQ("", FindExtension(&input).as_string()); - input = "foo.bar/baz"; - EXPECT_EQ("", FindExtension(&input).as_string()); -} - -TEST(FilesystemUtils, FindFilenameOffset) { - EXPECT_EQ(0u, FindFilenameOffset("")); - EXPECT_EQ(0u, FindFilenameOffset("foo")); - EXPECT_EQ(4u, FindFilenameOffset("foo/")); - EXPECT_EQ(4u, FindFilenameOffset("foo/bar")); -} - -TEST(FilesystemUtils, RemoveFilename) { - std::string s; - - RemoveFilename(&s); - EXPECT_STREQ("", s.c_str()); - - s = "foo"; - RemoveFilename(&s); - EXPECT_STREQ("", s.c_str()); - - s = "/"; - RemoveFilename(&s); - EXPECT_STREQ("/", s.c_str()); - - s = "foo/bar"; - RemoveFilename(&s); - EXPECT_STREQ("foo/", s.c_str()); - - s = "foo/bar/baz.cc"; - RemoveFilename(&s); - EXPECT_STREQ("foo/bar/", s.c_str()); -} - -TEST(FilesystemUtils, FindDir) { - std::string input; - EXPECT_EQ("", FindDir(&input)); - input = "/"; - EXPECT_EQ("/", FindDir(&input)); - input = "foo/"; - EXPECT_EQ("foo/", FindDir(&input)); - input = "foo/bar/baz"; - EXPECT_EQ("foo/bar/", FindDir(&input)); -} - -TEST(FilesystemUtils, InvertDir) { - EXPECT_TRUE(InvertDir(SourceDir()) == ""); - EXPECT_TRUE(InvertDir(SourceDir("/")) == ""); - EXPECT_TRUE(InvertDir(SourceDir("//")) == ""); - - EXPECT_TRUE(InvertDir(SourceDir("//foo/bar")) == "../../"); - EXPECT_TRUE(InvertDir(SourceDir("/foo/bar/")) == "../../"); -} - -TEST(FilesystemUtils, NormalizePath) { - std::string input; - - NormalizePath(&input); - EXPECT_EQ("", input); - - input = "foo/bar.txt"; - NormalizePath(&input); - EXPECT_EQ("foo/bar.txt", input); - - input = "."; - NormalizePath(&input); - EXPECT_EQ("", input); - - input = ".."; - NormalizePath(&input); - EXPECT_EQ("..", input); - - input = "foo//bar"; - NormalizePath(&input); - EXPECT_EQ("foo/bar", input); - - input = "//foo"; - NormalizePath(&input); - EXPECT_EQ("//foo", input); - - input = "foo/..//bar"; - NormalizePath(&input); - EXPECT_EQ("bar", input); - - input = "foo/../../bar"; - NormalizePath(&input); - EXPECT_EQ("../bar", input); - - input = "/../foo"; // Don't go aboe the root dir. - NormalizePath(&input); - EXPECT_EQ("/foo", input); - - input = "//../foo"; // Don't go aboe the root dir. - NormalizePath(&input); - EXPECT_EQ("//foo", input); - - input = "../foo"; - NormalizePath(&input); - EXPECT_EQ("../foo", input); - - input = ".."; - NormalizePath(&input); - EXPECT_EQ("..", input); - - input = "./././."; - NormalizePath(&input); - EXPECT_EQ("", input); - - input = "../../.."; - NormalizePath(&input); - EXPECT_EQ("../../..", input); - - input = "../"; - NormalizePath(&input); - EXPECT_EQ("../", input); -} diff --git a/tools/gn/function_define_rule.cc b/tools/gn/function_define_rule.cc deleted file mode 100644 index afbed9e..0000000 --- a/tools/gn/function_define_rule.cc +++ /dev/null @@ -1,37 +0,0 @@ -// 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/parse_tree.h" -#include "tools/gn/scope.h" -#include "tools/gn/value.h" - -Value ExecuteDefineRule(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err) { - // TODO(brettw) determine if the function is built-in and throw an error if - // it is. - if (args.size() != 1) { - *err = Err(function->function(), - "Need exactly one string arg to define_rule."); - return Value(); - } - if (!args[0].VerifyTypeIs(Value::STRING, err)) - return Value(); - std::string rule_name = args[0].string_value(); - - const FunctionCallNode* existing_rule = scope->GetRule(rule_name); - if (existing_rule) { - *err = Err(function, "Duplicate rule definition.", - "A rule with this name was already defined."); - err->AppendSubErr(Err(existing_rule->function(), "Previous definition.")); - return Value(); - } - - scope->AddRule(rule_name, function); - return Value(); -} diff --git a/tools/gn/function_exec_script.cc b/tools/gn/function_exec_script.cc deleted file mode 100644 index a950909..0000000 --- a/tools/gn/function_exec_script.cc +++ /dev/null @@ -1,254 +0,0 @@ -// 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 "base/command_line.h" -#include "base/file_util.h" -#include "base/strings/string_number_conversions.h" -#include "build/build_config.h" -#include "tools/gn/err.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/functions.h" -#include "tools/gn/input_conversion.h" -#include "tools/gn/input_file.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/value.h" - -#if defined(OS_WIN) -#include <windows.h> - -#include "base/win/scoped_handle.h" -#include "base/win/scoped_process_information.h" -#endif - -/* -exec_script: Synchronously run a script and return the output. - - exec_script(filename, arguments, input_conversion, [file_dependencies]) - - Runs the given script, returning the stdout of the script. The build - generation will fail if the script does not exist or returns a nonzero - exit code. - -Arguments: - - filename: - File name of python script to execute, relative to the build file. - - arguments: - A list of strings to be passed to the scripe as arguments. - - input_conversion: - Controls how the file is read and parsed. See "help input_conversion". - - dependencies: - (Optional) A list of files that this script reads or otherwise depends - on. These dependencies will be added to the build result such that if - any of them change, the build will be regenerated and the script will - be re-run. - - The script itself will be an implicit dependency so you do not need to - list it. - -Example: - - all_lines = exec_script("myscript.py", [some_input], "list lines", - ["data_file.txt"]) -*/ - -namespace { - -#if defined(OS_WIN) -bool ExecProcess(const CommandLine& cmdline, - const base::FilePath& startup_dir, - std::string* std_out, - std::string* std_err, - int* exit_code) { - SECURITY_ATTRIBUTES sa_attr; - // Set the bInheritHandle flag so pipe handles are inherited. - sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES); - sa_attr.bInheritHandle = TRUE; - sa_attr.lpSecurityDescriptor = NULL; - - // Create the pipe for the child process's STDOUT. - HANDLE out_read = NULL; - HANDLE out_write = NULL; - if (!CreatePipe(&out_read, &out_write, &sa_attr, 0)) { - NOTREACHED() << "Failed to create pipe"; - return false; - } - base::win::ScopedHandle scoped_out_read(out_read); - base::win::ScopedHandle scoped_out_write(out_write); - - // Create the pipe for the child process's STDERR. - HANDLE err_read = NULL; - HANDLE err_write = NULL; - if (!CreatePipe(&err_read, &err_write, &sa_attr, 0)) { - NOTREACHED() << "Failed to create pipe"; - return false; - } - base::win::ScopedHandle scoped_err_read(err_read); - base::win::ScopedHandle scoped_err_write(err_write); - - // Ensure the read handle to the pipe for STDOUT/STDERR is not inherited. - if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) { - NOTREACHED() << "Failed to disabled pipe inheritance"; - return false; - } - if (!SetHandleInformation(err_read, HANDLE_FLAG_INHERIT, 0)) { - NOTREACHED() << "Failed to disabled pipe inheritance"; - return false; - } - - base::FilePath::StringType cmdline_str(cmdline.GetCommandLineString()); - - base::win::ScopedProcessInformation proc_info; - STARTUPINFO start_info = { 0 }; - - start_info.cb = sizeof(STARTUPINFO); - start_info.hStdOutput = out_write; - // Keep the normal stdin. - start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - // FIXME(brettw) set stderr here when we actually read it below. - //start_info.hStdError = err_write; - start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); - start_info.dwFlags |= STARTF_USESTDHANDLES; - - // Create the child process. - if (!CreateProcess(NULL, - &cmdline_str[0], - NULL, NULL, - TRUE, // Handles are inherited. - 0, NULL, - startup_dir.value().c_str(), - &start_info, proc_info.Receive())) { - return false; - } - - // Close our writing end of pipes now. Otherwise later read would not be able - // to detect end of child's output. - scoped_out_write.Close(); - scoped_err_write.Close(); - - // Read output from the child process's pipe for STDOUT - const int kBufferSize = 1024; - char buffer[kBufferSize]; - - // FIXME(brettw) read from stderr here! This is complicated because we want - // to read both of them at the same time, probably need overlapped I/O. - // Also uncomment start_info code above. - for (;;) { - DWORD bytes_read = 0; - BOOL success = ReadFile(out_read, buffer, kBufferSize, &bytes_read, NULL); - if (!success || bytes_read == 0) - break; - std_out->append(buffer, bytes_read); - } - - // Let's wait for the process to finish. - WaitForSingleObject(proc_info.process_handle(), INFINITE); - - DWORD dw_exit_code; - GetExitCodeProcess(proc_info.process_handle(), &dw_exit_code); - *exit_code = static_cast<int>(dw_exit_code); - - return true; -} -#else -bool ExecProcess(const CommandLine& cmdline, - const base::FilePath& startup_dir, - std::string* std_out, - std::string* std_err, - int* exit_code) { - //NOTREACHED() << "Implement me."; - return false; -} -#endif - -} // namespace - -Value ExecuteExecScript(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - if (args.size() != 3 && args.size() != 4) { - *err = Err(function->function(), "Wrong number of args to write_file", - "I expected three or four arguments."); - return Value(); - } - - const Settings* settings = scope->settings(); - const BuildSettings* build_settings = settings->build_settings(); - const SourceDir& cur_dir = SourceDirForFunctionCall(function); - - // Find the python script to run. - if (!args[0].VerifyTypeIs(Value::STRING, err)) - return Value(); - SourceFile script_source = - cur_dir.ResolveRelativeFile(args[0].string_value()); - base::FilePath script_path = build_settings->GetFullPath(script_source); - if (!build_settings->secondary_source_path().empty() && - !base::PathExists(script_path)) { - // Fall back to secondary source root when the file doesn't exist. - script_path = build_settings->GetFullPathSecondary(script_source); - } - - // Add all dependencies of this script, including the script itself, to the - // build deps. - g_scheduler->AddGenDependency(script_source); - if (args.size() == 4) { - const Value& deps_value = args[3]; - if (!deps_value.VerifyTypeIs(Value::LIST, err)) - return Value(); - - for (size_t i = 0; i < deps_value.list_value().size(); i++) { - if (!deps_value.list_value()[0].VerifyTypeIs(Value::STRING, err)) - return Value(); - g_scheduler->AddGenDependency(cur_dir.ResolveRelativeFile( - deps_value.list_value()[0].string_value())); - } - } - - // Make the command line. - const base::FilePath& python_path = build_settings->python_path(); - CommandLine cmdline(python_path); - cmdline.AppendArgPath(script_path); - - const Value& script_args = args[1]; - if (!script_args.VerifyTypeIs(Value::LIST, err)) - return Value(); - for (size_t i = 0; i < script_args.list_value().size(); i++) { - if (!script_args.list_value()[i].VerifyTypeIs(Value::STRING, err)) - return Value(); - cmdline.AppendArg(script_args.list_value()[i].string_value()); - } - - // Execute the process. - // TODO(brettw) set the environment block. - std::string output; - std::string stderr_output; // TODO(brettw) not hooked up, see above. - int exit_code = 0; - if (!ExecProcess(cmdline, build_settings->GetFullPath(cur_dir), - &output, &stderr_output, &exit_code)) { - *err = Err(function->function(), "Could not execute python.", - "I was trying to execute \"" + FilePathToUTF8(python_path) + "\"."); - return Value(); - } - - // TODO(brettw) maybe we need stderr also for reasonable stack dumps. - if (exit_code != 0) { - std::string msg = - std::string("I was running \"") + FilePathToUTF8(script_path) + "\"\n" - "and it returned " + base::IntToString(exit_code); - if (!output.empty()) - msg += " and printed out:\n\n" + output; - else - msg += "."; - *err = Err(function->function(), "Script returned non-zero exit code.", - msg); - return Value(); - } - - return ConvertInputToValue(output, function, args[2], err); -} diff --git a/tools/gn/function_process_file_template.cc b/tools/gn/function_process_file_template.cc deleted file mode 100644 index 18e1425..0000000 --- a/tools/gn/function_process_file_template.cc +++ /dev/null @@ -1,65 +0,0 @@ -// 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/file_template.h" -#include "tools/gn/functions.h" -#include "tools/gn/parse_tree.h" - -/* -process_file_template: Do template expansion over a list of files. - - process_file_template(source_list, template) - - process_file_template applies a template list to a source file list, - returning the result of applying each template to each source. This is - typically used for computing output file names from input files. - -Arguments: - - The source_list is a list of file names. - - The template can be a string or a list. If it is a list, multiple output - strings are generated for each input. - - The following template substrings are used in the template arguments - and are replaced with the corresponding part of the input file name: - - "{{source}}": The entire source name. - - "{{source_name_part}}": The source name with no path or extension. - -Example: - - sources = [ - "foo.idl", - "bar.idl", - ] - myoutputs = process_file_template( - sources, - [ "$target_gen_dir/{{source_name_part}}.cc", - "$target_gen_dir/{{source_name_part}}.h" ]) - - The result in this case will be: - [ "/out/Debug/foo.cc" - "/out/Debug/foo.h" - "/out/Debug/bar.cc" - "/out/Debug/bar.h" ] -*/ -Value ExecuteProcessFileTemplate(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - if (args.size() != 2) { - *err = Err(function->function(), "Expected two arguments"); - return Value(); - } - - FileTemplate file_template(args[1], err); - if (err->has_error()) - return Value(); - - Value ret(function, Value::LIST); - file_template.Apply(args[0], function, &ret.list_value(), err); - return ret; -} diff --git a/tools/gn/function_read_file.cc b/tools/gn/function_read_file.cc deleted file mode 100644 index db981ad..0000000 --- a/tools/gn/function_read_file.cc +++ /dev/null @@ -1,67 +0,0 @@ -// 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 "base/file_util.h" -#include "tools/gn/err.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/functions.h" -#include "tools/gn/input_conversion.h" -#include "tools/gn/input_file.h" -#include "tools/gn/scheduler.h" - -// TODO(brettw) consider removing this. I originally wrote it for making the -// WebKit bindings but misundersood what was required, and didn't need to -// use this. This seems to have a high potential for misuse. - -/* -read_file: Read a file into a variable. - - read_file(filename, how_to_read) - - Whitespace will be trimmed from the end of the file. Throws an error if the - file can not be opened. - -Arguments: - - filename: - Filename to read, relative to the build file. - - input_conversion: - Controls how the file is read and parsed. See "help input_conversion". - -Example: - - lines = read_file("foo.txt", "list lines") -*/ -Value ExecuteReadFile(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - if (args.size() != 2) { - *err = Err(function->function(), "Wrong number of args to read_file", - "I expected two arguments."); - return Value(); - } - if (!args[0].VerifyTypeIs(Value::STRING, err)) - return Value(); - - // Compute the file name. - const SourceDir& cur_dir = SourceDirForFunctionCall(function); - SourceFile source_file = cur_dir.ResolveRelativeFile(args[0].string_value()); - base::FilePath file_path = - scope->settings()->build_settings()->GetFullPath(source_file); - - // Ensure that everything is recomputed if the read file changes. - g_scheduler->AddGenDependency(source_file); - - // Read contents. - std::string file_contents; - if (!file_util::ReadFileToString(file_path, &file_contents)) { - *err = Err(args[0], "Could not read file.", - "I resolved this to \"" + FilePathToUTF8(file_path) + "\"."); - return Value(); - } - - return ConvertInputToValue(file_contents, function, args[1], err); -} diff --git a/tools/gn/function_set_default_toolchain.cc b/tools/gn/function_set_default_toolchain.cc deleted file mode 100644 index 4939ac8..0000000 --- a/tools/gn/function_set_default_toolchain.cc +++ /dev/null @@ -1,70 +0,0 @@ -// 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/build_settings.h" -#include "tools/gn/functions.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/scope.h" -#include "tools/gn/settings.h" -#include "tools/gn/toolchain_manager.h" - -/* -set_default_toolchain: Sets the default toolchain name. - - set_default_toolchain(toolchain_label) - - The given label should identify a toolchain definition (see "toolchain"). - This toolchain will be used for all targets unless otherwise specified. - - This function is only valid to call during the processing of the build - configuration file. Since the build configuration file is processed - separately for each toolchain, this function will be a no-op when called - under any non-default toolchains. - - For example, the default toolchain should be appropriate for the current - environment. If the current environment is 32-bit and somebody references - a target with a 64-bit toolchain, we wouldn't want processing of the build - config file for the 64-bit toolchain to reset the default toolchain to - 64-bit, we want to keep it 32-bits. - -Argument: - - toolchain_label: - Toolchain name. - -Example: - - set_default_toolchain("//build/config/win:vs32") -*/ - -Value ExecuteSetDefaultToolchain(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - if (!scope->IsProcessingBuildConfig()) { - *err = Err(function->function(), "Must be called from build config.", - "set_default_toolchain can only be called from the build configuration " - "file."); - return Value(); - } - - // Ignore non-default-build-config invocations. - if (!scope->IsProcessingDefaultBuildConfig()) - return Value(); - - const SourceDir& current_dir = SourceDirForFunctionCall(function); - const Label& default_toolchain = ToolchainLabelForScope(scope); - - if (!EnsureSingleStringArg(function, args, err)) - return Value(); - Label toolchain_label( - Label::Resolve(current_dir, default_toolchain, args[0], err)); - if (toolchain_label.is_null()) - return Value(); - - ToolchainManager& mgr = - scope->settings()->build_settings()->toolchain_manager(); - mgr.SetDefaultToolchainUnlocked(toolchain_label, function->GetRange(), err); - return Value(); -} diff --git a/tools/gn/function_template.cc b/tools/gn/function_template.cc deleted file mode 100644 index a85a40f..0000000 --- a/tools/gn/function_template.cc +++ /dev/null @@ -1,38 +0,0 @@ -// 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/parse_tree.h" -#include "tools/gn/scope.h" -#include "tools/gn/value.h" - -Value ExecuteTemplate(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err) { - // TODO(brettw) determine if the function is built-in and throw an error if - // it is. - if (args.size() != 1) { - *err = Err(function->function(), - "Need exactly one string arg to template."); - return Value(); - } - if (!args[0].VerifyTypeIs(Value::STRING, err)) - return Value(); - std::string template_name = args[0].string_value(); - - const FunctionCallNode* existing_template = scope->GetTemplate(template_name); - if (existing_template) { - *err = Err(function, "Duplicate template definition.", - "A template with this name was already defined."); - err->AppendSubErr(Err(existing_template->function(), - "Previous definition.")); - return Value(); - } - - scope->AddTemplate(template_name, function); - return Value(); -} diff --git a/tools/gn/function_toolchain.cc b/tools/gn/function_toolchain.cc deleted file mode 100644 index b78c639..0000000 --- a/tools/gn/function_toolchain.cc +++ /dev/null @@ -1,126 +0,0 @@ -// 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/err.h" -#include "tools/gn/functions.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/scope.h" -#include "tools/gn/settings.h" -#include "tools/gn/toolchain.h" - -namespace { - -// This is jsut a unique value to take the address of to use as the key for -// the toolchain property on a scope. -const int kToolchainPropertyKey = 0; - -// Reads the given string from the scope (if present) and puts the result into -// dest. If the value is not a string, sets the error and returns false. -bool ReadString(Scope& scope, const char* var, std::string* dest, Err* err) { - const Value* v = scope.GetValue(var, true); - if (!v) - return true; // Not present is fine. - - if (!v->VerifyTypeIs(Value::STRING, err)) - return false; - *dest = v->string_value(); - return true; -} - -} // namespace - -Value ExecuteToolchain(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(); - - // Note that we don't want to use MakeLabelForScope since that will include - // the toolchain name in the label, and toolchain labels don't themselves - // have toolchain names. - const SourceDir& input_dir = SourceDirForFunctionCall(function); - Label label(input_dir, args[0].string_value(), SourceDir(), std::string()); - if (g_scheduler->verbose_logging()) - g_scheduler->Log("Generating toolchain", label.GetUserVisibleName(true)); - - // This object will actually be copied into the one owned by the toolchain - // manager, but that has to be done in the lock. - Toolchain toolchain(label); - - Scope block_scope(scope); - block_scope.SetProperty(&kToolchainPropertyKey, &toolchain); - block->ExecuteBlockInScope(&block_scope, err); - block_scope.SetProperty(&kToolchainPropertyKey, NULL); - if (err->has_error()) - return Value(); - if (!block_scope.CheckForUnusedVars(err)) - return Value(); - - const BuildSettings* build_settings = scope->settings()->build_settings(); - { - // Save the toolchain definition in the toolchain manager and mark the - // corresponding item in the dependency tree resolved so that targets - // that depend on this toolchain know it's ready. - base::AutoLock lock(build_settings->item_tree().lock()); - build_settings->toolchain_manager().SetToolchainDefinitionLocked( - toolchain, function->GetRange(), err); - build_settings->item_tree().MarkItemGeneratedLocked(label); - } - return Value(); -} - -Value ExecuteTool(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err) { - // Find the toolchain definition we're executing inside of. The toolchain - // function will set a property pointing to it that we'll pick up. - Toolchain* toolchain = reinterpret_cast<Toolchain*>( - scope->GetProperty(&kToolchainPropertyKey, NULL)); - if (!toolchain) { - *err = Err(function->function(), "tool() called outside of toolchain().", - "The tool() function can only be used inside a toolchain() " - "definition."); - return Value(); - } - - if (!EnsureSingleStringArg(function, args, err)) - return Value(); - const std::string& tool_name = args[0].string_value(); - Toolchain::ToolType tool_type = Toolchain::ToolNameToType(tool_name); - if (tool_type == Toolchain::TYPE_NONE) { - *err = Err(args[0], "Unknown tool type"); - return Value(); - } - - // Run the tool block. - Scope block_scope(scope); - block->ExecuteBlockInScope(&block_scope, err); - if (err->has_error()) - return Value(); - - // Extract the stuff we need. - Toolchain::Tool t; - if (!ReadString(block_scope, "command", &t.command, err) || - !ReadString(block_scope, "depfile", &t.depfile, err) || - !ReadString(block_scope, "deps", &t.deps, err) || - !ReadString(block_scope, "description", &t.description, err) || - !ReadString(block_scope, "pool", &t.pool, err) || - !ReadString(block_scope, "restat", &t.restat, err) || - !ReadString(block_scope, "rspfile", &t.rspfile, err) || - !ReadString(block_scope, "rspfile_content", &t.rspfile_content, err)) - return Value(); - - // Make sure there weren't any vars set in this tool that were unused. - if (!block_scope.CheckForUnusedVars(err)) - return Value(); - - toolchain->SetTool(tool_type, t); - return Value(); -} diff --git a/tools/gn/function_write_file.cc b/tools/gn/function_write_file.cc deleted file mode 100644 index 9356feb..0000000 --- a/tools/gn/function_write_file.cc +++ /dev/null @@ -1,84 +0,0 @@ -// 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 <iostream> -#include <sstream> - -#include "base/file_util.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "tools/gn/err.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/functions.h" -#include "tools/gn/input_file.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/scheduler.h" - -/* -write_file: Read a file into a variable. - - write_file(filename, data) - - If data is a list, the list will be written one-item-per-line with no - quoting or brackets. - - TODO(brettw) we probably need an optional third argument to control list - formatting. - -Arguments: - - filename: - Filename to write. This must be within the output directory. - - data: - The list or string to write. -*/ -Value ExecuteWriteFile(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - if (args.size() != 2) { - *err = Err(function->function(), "Wrong number of args to write_file", - "I expected two arguments."); - return Value(); - } - - // Compute the file name and make sure it's in the output dir. - if (!args[0].VerifyTypeIs(Value::STRING, err)) - return Value(); - const SourceDir& cur_dir = SourceDirForFunctionCall(function); - SourceFile source_file = cur_dir.ResolveRelativeFile(args[0].string_value()); - if (!EnsureStringIsInOutputDir( - scope->settings()->build_settings()->build_dir(), - source_file.value(), args[0], err)) - return Value(); - - // Compute output. - std::ostringstream contents; - if (args[1].type() == Value::LIST) { - const std::vector<Value>& list = args[1].list_value(); - for (size_t i = 0; i < list.size(); i++) - contents << list[i].ToString() << std::endl; - } else { - contents << args[1].ToString(); - } - - // Write file, creating the directory if necessary. - base::FilePath file_path = - scope->settings()->build_settings()->GetFullPath(source_file); - const std::string& contents_string = contents.str(); - if (!file_util::CreateDirectory(file_path.DirName())) { - *err = Err(function->function(), "Unable to create directory.", - "I was using \"" + FilePathToUTF8(file_path.DirName()) + "\"."); - return Value(); - } - if (file_util::WriteFile(file_path, - contents_string.c_str(), contents_string.size()) - != static_cast<int>(contents_string.size())) { - *err = Err(function->function(), "Unable to write file.", - "I was writing \"" + FilePathToUTF8(file_path) + "\"."); - return Value(); - } - return Value(); -} diff --git a/tools/gn/functions.cc b/tools/gn/functions.cc deleted file mode 100644 index 7f32db2..0000000 --- a/tools/gn/functions.cc +++ /dev/null @@ -1,443 +0,0 @@ -// 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 <iostream> - -#include "base/strings/string_util.h" -#include "tools/gn/config.h" -#include "tools/gn/config_values_generator.h" -#include "tools/gn/err.h" -#include "tools/gn/input_file.h" -#include "tools/gn/item_tree.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/scope.h" -#include "tools/gn/settings.h" -#include "tools/gn/target_manager.h" -#include "tools/gn/token.h" -#include "tools/gn/value.h" - -namespace { - -void FillNeedsBlockError(const FunctionCallNode* function, Err* err) { - *err = Err(function->function(), "This function call requires a block.", - "The block's \"{\" must be on the same line as the function " - "call's \")\"."); -} - -Value ExecuteAssert(const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - if (args.size() != 1) { - *err = Err(function->function(), "Wrong number of arguments.", - "assert() takes one argument, " - "were you expecting somethig else?"); - } else if (args[0].InterpretAsInt() == 0) { - *err = Err(function->function(), "Assertion failed."); - if (args[0].origin()) { - // If you do "assert(foo)" we'd ideally like to show you where foo was - // set, and in this case the origin of the args will tell us that. - // However, if you do "assert(foo && bar)" the source of the value will - // be the assert like, which isn't so helpful. - // - // So we try to see if the args are from the same line or not. This will - // break if you do "assert(\nfoo && bar)" and we may show the second line - // as the source, oh well. The way around this is to check to see if the - // origin node is inside our function call block. - Location origin_location = args[0].origin()->GetRange().begin(); - if (origin_location.file() != function->function().location().file() || - origin_location.line_number() != - function->function().location().line_number()) { - err->AppendSubErr(Err(args[0].origin()->GetRange(), "", - "This is where it was set.")); - } - } - } - return Value(); -} - -Value ExecuteConfig(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - if (!EnsureSingleStringArg(function, args, err) || - !EnsureNotProcessingImport(function, scope, err)) - return Value(); - - Label label(MakeLabelForScope(scope, function, args[0].string_value())); - - if (g_scheduler->verbose_logging()) - g_scheduler->Log("Generating config", label.GetUserVisibleName(true)); - - // Create the empty config object. - ItemTree* tree = &scope->settings()->build_settings()->item_tree(); - Config* config = Config::GetConfig(scope->settings(), function->GetRange(), - label, NULL, err); - if (err->has_error()) - return Value(); - - // Fill it. - const SourceDir input_dir = SourceDirForFunctionCall(function); - ConfigValuesGenerator gen(&config->config_values(), scope, - function->function(), input_dir, err); - gen.Run(); - if (err->has_error()) - return Value(); - - // Mark as complete. - { - base::AutoLock lock(tree->lock()); - tree->MarkItemGeneratedLocked(label); - } - return Value(); -} - -Value ExecuteDeclareArgs(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - // Only allow this to be called once. We use a variable in the current scope - // with a name the parser will reject if the user tried to type it. - const char did_declare_args_var[] = "@@declared_args"; - if (scope->GetValue(did_declare_args_var)) { - *err = Err(function->function(), "Duplicate call to declared_args."); - err->AppendSubErr( - Err(scope->GetValue(did_declare_args_var)->origin()->GetRange(), - "See the original call.")); - return Value(); - } - - // Find the root scope where the values will be set. - Scope* root = scope->mutable_containing(); - if (!root || root->containing() || !scope->IsProcessingBuildConfig()) { - *err = Err(function->function(), "declare_args called incorrectly." - "It must be called only from the build config script and in the " - "root scope."); - return Value(); - } - - // Take all variables set in the current scope as default values and put - // them in the parent scope. The values in the current scope are the defaults, - // then we apply the external args to this list. - Scope::KeyValueVector values; - scope->GetCurrentScopeValues(&values); - for (size_t i = 0; i < values.size(); i++) { - // TODO(brettw) actually import the arguments from the command line rather - // than only using the defaults. - root->SetValue(values[i].first, values[i].second, - values[i].second.origin()); - } - - scope->SetValue(did_declare_args_var, Value(function, 1), NULL); - return Value(); -} - -Value ExecuteImport(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - if (!EnsureSingleStringArg(function, args, err) || - !EnsureNotProcessingImport(function, scope, err)) - return Value(); - - const SourceDir input_dir = SourceDirForFunctionCall(function); - SourceFile import_file = - input_dir.ResolveRelativeFile(args[0].string_value()); - scope->settings()->import_manager().DoImport(import_file, function, - scope, err); - return Value(); -} - -Value ExecuteTemplate(Scope* scope, - const FunctionCallNode* invocation, - const std::vector<Value>& args, - BlockNode* block, - const FunctionCallNode* rule, - Err* err) { - if (!EnsureNotProcessingImport(invocation, scope, err)) - return Value(); - Scope block_scope(scope); - if (!FillTargetBlockScope(scope, invocation, - invocation->function().value().data(), - block, args, &block_scope, err)) - return Value(); - - // Run the block for the rule invocation. - block->ExecuteBlockInScope(&block_scope, err); - if (err->has_error()) - return Value(); - - // Now run the rule itself with that block as the current scope. - rule->block()->ExecuteBlockInScope(&block_scope, err); - if (err->has_error()) - return Value(); - - return Value(); -} - -Value ExecuteSetDefaults(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err) { - if (!EnsureSingleStringArg(function, args, err)) - return Value(); - const std::string& target_type(args[0].string_value()); - - // Ensure there aren't defaults already set. - if (scope->GetTargetDefaults(target_type)) { - *err = Err(function->function(), - "This target type defaults were already set."); - return Value(); - } - - // Execute the block in a new scope that has a parent of the containing - // scope. - Scope block_scope(scope); - if (!FillTargetBlockScope(scope, function, - function->function().value().data(), - block, args, &block_scope, err)) - return Value(); - - // Run the block for the rule invocation. - block->ExecuteBlockInScope(&block_scope, err); - if (err->has_error()) - return Value(); - - // Now copy the values set on the scope we made into the free-floating one - // (with no containing scope) used to hold the target defaults. - Scope* dest = scope->MakeTargetDefaults(target_type); - block_scope.NonRecursiveMergeTo(dest, function, "<SHOULD NOT FAIL>", err); - return Value(); -} - -Value ExecuteSetSourcesAssignmentFilter(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - if (args.size() != 1) { - *err = Err(function, "set_sources_assignment_filter takes one argument."); - } else { - scoped_ptr<PatternList> f(new PatternList); - f->SetFromValue(args[0], err); - if (!err->has_error()) - scope->set_sources_assignment_filter(f.Pass()); - } - return Value(); -} - -// void print(...) -// prints all arguments to the console separated by spaces. -Value ExecutePrint(const std::vector<Value>& args, Err* err) { - for (size_t i = 0; i < args.size(); i++) { - if (i != 0) - std::cout << " "; - std::cout << args[i].ToString(); - } - std::cout << std::endl; - return Value(); -} - -} // namespace - -// ---------------------------------------------------------------------------- - -namespace functions { - -const char kAssert[] = "assert"; -const char kComponent[] = "component"; -const char kConfig[] = "config"; -const char kCopy[] = "copy"; -const char kCustom[] = "custom"; -const char kDeclareArgs[] = "declare_args"; -const char kExecScript[] = "exec_script"; -const char kExecutable[] = "executable"; -const char kGroup[] = "group"; -const char kImport[] = "import"; -const char kPrint[] = "print"; -const char kProcessFileTemplate[] = "process_file_template"; -const char kReadFile[] = "read_file"; -const char kSetDefaults[] = "set_defaults"; -const char kSetDefaultToolchain[] = "set_default_toolchain"; -const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter"; -const char kSharedLibrary[] = "shared_library"; -const char kStaticLibrary[] = "static_library"; -const char kTemplate[] = "template"; -const char kTool[] = "tool"; -const char kToolchain[] = "toolchain"; -const char kTest[] = "test"; -const char kWriteFile[] = "write_file"; - -} // namespace functions - -// ---------------------------------------------------------------------------- - -bool EnsureNotProcessingImport(const ParseNode* node, - const Scope* scope, - Err* err) { - if (scope->IsProcessingImport()) { - *err = Err(node, "Not valid from an import.", - "We need to talk about this thing you are doing here. Doing this\n" - "kind of thing from an imported file makes me feel like you are\n" - "abusing me. Imports are for defining defaults, variables, and rules.\n" - "The appropriate place for this kind of thing is really in a normal\n" - "BUILD file."); - return false; - } - return true; -} - -bool EnsureNotProcessingBuildConfig(const ParseNode* node, - const Scope* scope, - Err* err) { - if (scope->IsProcessingBuildConfig()) { - *err = Err(node, "Not valid from the build config.", - "You can't do this kind of thing from the build config script, " - "silly!\nPut it in a regular BUILD file."); - return false; - } - return true; -} - -bool FillTargetBlockScope(const Scope* scope, - const FunctionCallNode* function, - const char* target_type, - const BlockNode* block, - const std::vector<Value>& args, - Scope* block_scope, - Err* err) { - if (!block) { - FillNeedsBlockError(function, err); - return false; - } - - // Copy the target defaults, if any, into the scope we're going to execute - // the block in. - const Scope* default_scope = scope->GetTargetDefaults(target_type); - if (default_scope) { - if (!default_scope->NonRecursiveMergeTo(block_scope, function, - "target defaults", err)) - return false; - } - - // The name is the single argument to the target function. - if (!EnsureSingleStringArg(function, args, err)) - return false; - - // Set the target name variable to the current target, and mark it used - // because we don't want to issue an error if the script ignores it. - const base::StringPiece target_name("target_name"); - block_scope->SetValue(target_name, Value(function, args[0].string_value()), - function); - block_scope->MarkUsed(target_name); - return true; -} - -bool EnsureSingleStringArg(const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err) { - if (args.size() != 1) { - *err = Err(function->function(), "Incorrect arguments.", - "This function requires a single string argument."); - return false; - } - return args[0].VerifyTypeIs(Value::STRING, err); -} - -const SourceDir& SourceDirForFunctionCall(const FunctionCallNode* function) { - return function->function().location().file()->dir(); -} - -const Label& ToolchainLabelForScope(const Scope* scope) { - return scope->settings()->toolchain()->label(); -} - -Label MakeLabelForScope(const Scope* scope, - const FunctionCallNode* function, - const std::string& name) { - const SourceDir& input_dir = SourceDirForFunctionCall(function); - const Label& toolchain_label = ToolchainLabelForScope(scope); - return Label(input_dir, name, toolchain_label.dir(), toolchain_label.name()); -} - -Value ExecuteFunction(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err) { - const Token& name = function->function(); - if (block) { - // These target generators need to execute the block themselves. - if (name.IsIdentifierEqualTo(functions::kComponent)) - return ExecuteComponent(scope, function, args, block, err); - if (name.IsIdentifierEqualTo(functions::kCustom)) - return ExecuteCustom(scope, function, args, block, err); - if (name.IsIdentifierEqualTo(functions::kExecutable)) - return ExecuteExecutable(scope, function, args, block, err); - if (name.IsIdentifierEqualTo(functions::kSetDefaults)) - return ExecuteSetDefaults(scope, function, args, block, err); - if (name.IsIdentifierEqualTo(functions::kSharedLibrary)) - return ExecuteSharedLibrary(scope, function, args, block, err); - if (name.IsIdentifierEqualTo(functions::kStaticLibrary)) - return ExecuteStaticLibrary(scope, function, args, block, err); - if (name.IsIdentifierEqualTo(functions::kGroup)) - return ExecuteGroup(scope, function, args, block, err); - if (name.IsIdentifierEqualTo(functions::kTest)) - return ExecuteExecutable(scope, function, args, block, err); - if (name.IsIdentifierEqualTo(functions::kTemplate)) - return ExecuteTemplate(scope, function, args, block, err); - if (name.IsIdentifierEqualTo(functions::kTool)) - return ExecuteTool(scope, function, args, block, err); - if (name.IsIdentifierEqualTo(functions::kToolchain)) - return ExecuteToolchain(scope, function, args, block, err); - - const FunctionCallNode* rule = - scope->GetTemplate(function->function().value().as_string()); - if (rule) - return ExecuteTemplate(scope, function, args, block, rule, err); - - // FIXME(brettw) This is not right, what if you specify a function that - // doesn't take a block but specify one?!?!? - - // The rest of the functions can take a pre-executed block for simplicity. - Scope block_scope(scope); - block->ExecuteBlockInScope(&block_scope, err); - if (err->has_error()) - return Value(); - - if (name.IsIdentifierEqualTo(functions::kConfig)) - return ExecuteConfig(&block_scope, function, args, err); - if (name.IsIdentifierEqualTo(functions::kCopy)) - return ExecuteCopy(&block_scope, function, args, err); - if (name.IsIdentifierEqualTo(functions::kDeclareArgs)) - return ExecuteDeclareArgs(&block_scope, function, args, err); - - *err = Err(name, "Unknown function."); - return Value(); - } - - if (name.IsIdentifierEqualTo(functions::kAssert)) - return ExecuteAssert(function, args, err); - if (name.IsIdentifierEqualTo(functions::kExecScript)) - return ExecuteExecScript(scope, function, args, err); - if (name.IsIdentifierEqualTo(functions::kImport)) - return ExecuteImport(scope, function, args, err); - if (name.IsIdentifierEqualTo(functions::kPrint)) - return ExecutePrint(args, err); - if (name.IsIdentifierEqualTo(functions::kProcessFileTemplate)) - return ExecuteProcessFileTemplate(scope, function, args, err); - if (name.IsIdentifierEqualTo(functions::kReadFile)) - return ExecuteReadFile(scope, function, args, err); - if (name.IsIdentifierEqualTo(functions::kSetDefaultToolchain)) - return ExecuteSetDefaultToolchain(scope, function, args, err); - if (name.IsIdentifierEqualTo(functions::kSetSourcesAssignmentFilter)) - return ExecuteSetSourcesAssignmentFilter(scope, function, args, err); - if (name.IsIdentifierEqualTo(functions::kWriteFile)) - return ExecuteWriteFile(scope, function, args, err); - - *err = Err(function, "Unknown function."); - return Value(); -} diff --git a/tools/gn/functions.h b/tools/gn/functions.h deleted file mode 100644 index 806de1d..0000000 --- a/tools/gn/functions.h +++ /dev/null @@ -1,182 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_FUNCTIONS_H_ -#define TOOLS_GN_FUNCTIONS_H_ - -#include <string> -#include <vector> - -class Err; -class BlockNode; -class FunctionCallNode; -class Label; -class ListNode; -class ParseNode; -class Scope; -class SourceDir; -class Token; -class Value; - -Value ExecuteFunction(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, // Optional. - Err* err); - -// Function executing functions ----------------------------------------------- - -Value ExecuteTemplate(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err); -Value ExecuteExecScript(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err); -Value ExecuteProcessFileTemplate(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err); -Value ExecuteReadFile(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err); -Value ExecuteSetDefaultToolchain(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err); -Value ExecuteTool(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err); -Value ExecuteToolchain(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err); -Value ExecuteWriteFile(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err); - -// Target-generating functions. -Value ExecuteComponent(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err); -Value ExecuteCopy(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err); -Value ExecuteCustom(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err); -Value ExecuteExecutable(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err); -Value ExecuteSharedLibrary(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err); -Value ExecuteStaticLibrary(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err); -Value ExecuteGroup(Scope* scope, - const FunctionCallNode* function, - const std::vector<Value>& args, - BlockNode* block, - Err* err); - -// Helper functions ----------------------------------------------------------- - -// Verifies that the current scope is not processing an import. If it is, it -// will set the error, blame the given parse node for it, and return false. -bool EnsureNotProcessingImport(const ParseNode* node, - const Scope* scope, - Err* err); - -// Like EnsureNotProcessingImport but checks for running the build config. -bool EnsureNotProcessingBuildConfig(const ParseNode* node, - const Scope* scope, - Err* err); - -// Sets up the |block_scope| for executing a target (or something like it). -// The |scope| is the containing scope. It should have been already set as the -// parent for the |block_scope| when the |block_scope| was created. -// -// This will set up the target defaults and set the |target_name| variable in -// the block scope to the current target name, which is assumed to be the first -// argument to the function. -// -// On success, returns true. On failure, sets the error and returns false. -bool FillTargetBlockScope(const Scope* scope, - const FunctionCallNode* function, - const char* target_type, - const BlockNode* block, - const std::vector<Value>& args, - Scope* block_scope, - Err* err); - -// Validates that the given function call has one string argument. This is -// the most common function signature, so it saves space to have this helper. -// Returns false and sets the error on failure. -bool EnsureSingleStringArg(const FunctionCallNode* function, - const std::vector<Value>& args, - Err* err); - -// Returns the source directory for the file comtaining the given function -// invocation. -const SourceDir& SourceDirForFunctionCall(const FunctionCallNode* function); - -// Returns the name of the toolchain for the given scope. -const Label& ToolchainLabelForScope(const Scope* scope); - -// Generates a label for the given scope, using the current directory and -// toolchain, and the given name. -Label MakeLabelForScope(const Scope* scope, - const FunctionCallNode* function, - const std::string& name); - -// Function name constants ---------------------------------------------------- - -namespace functions { - -extern const char kAssert[]; -extern const char kComponent[]; -extern const char kConfig[]; -extern const char kCopy[]; -extern const char kCustom[]; -extern const char kDeclareArgs[]; -extern const char kExecScript[]; -extern const char kExecutable[]; -extern const char kGroup[]; -extern const char kImport[]; -extern const char kPrint[]; -extern const char kProcessFileTemplate[]; -extern const char kReadFile[]; -extern const char kSetDefaults[]; -extern const char kSetDefaultToolchain[]; -extern const char kSetSourcesAssignmentFilter[]; -extern const char kSharedLibrary[]; -extern const char kStaticLibrary[]; -extern const char kTemplate[]; -extern const char kTest[]; -extern const char kTool[]; -extern const char kToolchain[]; -extern const char kWriteFile[]; - -} // namespace functions - -#endif // TOOLS_GN_FUNCTIONS_H_ diff --git a/tools/gn/functions_target.cc b/tools/gn/functions_target.cc deleted file mode 100644 index a5991e77..0000000 --- a/tools/gn/functions_target.cc +++ /dev/null @@ -1,221 +0,0 @@ -// 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); -} - diff --git a/tools/gn/generate_test_gn_data.cc b/tools/gn/generate_test_gn_data.cc deleted file mode 100644 index 017c4c4..0000000 --- a/tools/gn/generate_test_gn_data.cc +++ /dev/null @@ -1,129 +0,0 @@ -// 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 <fstream> -#include <iostream> - -#include "base/file_util.h" -#include "base/files/file_path.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" - -// Usage: just run in the directory where you want your test source root to be. - -int files_written = 0; -int targets_written = 0; - -base::FilePath UTF8ToFilePath(const std::string& s) { -#if defined(OS_WIN) - return base::FilePath(UTF8ToWide(s)); -#else - return base::FilePath(s); -#endif -} - -std::string FilePathToUTF8(const base::FilePath& path) { -#if defined(OS_WIN) - return WideToUTF8(path.value()); -#else - return path.value(); -#endif -} - -base::FilePath RepoPathToPathName(const std::vector<int>& repo_path) { - base::FilePath ret; - for (size_t i = 0; i < repo_path.size(); i++) { - ret = ret.Append(UTF8ToFilePath(base::IntToString(repo_path[i]))); - } - return ret; -} - -std::string TargetIndexToLetter(int target_index) { - char ret[2]; - ret[0] = 'a' + target_index; - ret[1] = 0; - return ret; -} - -std::string RepoPathToTargetName(const std::vector<int>& repo_path, - int target_index) { - std::string ret; - for (size_t i = 0; i < repo_path.size(); i++) { - if (i != 0) - ret.push_back('_'); - ret.append(base::IntToString(repo_path[i])); - } - ret += TargetIndexToLetter(target_index); - return ret; -} - -std::string RepoPathToFullTargetName(const std::vector<int>& repo_path, - int target_index) { - std::string ret; - for (size_t i = 0; i < repo_path.size(); i++) { - ret.push_back('/'); - ret.append(base::IntToString(repo_path[i])); - } - - ret += ":" + RepoPathToTargetName(repo_path, target_index); - return ret; -} - -void WriteLevel(const std::vector<int>& repo_path, - int spread, - int max_depth, - int targets_per_level, - int files_per_target) { - base::FilePath dirname = RepoPathToPathName(repo_path); - base::FilePath filename = dirname.AppendASCII("BUILD.gn"); - std::cout << "Writing " << FilePathToUTF8(filename) << "\n"; - - // Don't keep the file open while recursing. - { - file_util::CreateDirectory(dirname); - - std::ofstream file; - file.open(FilePathToUTF8(filename).c_str(), - std::ios_base::out | std::ios_base::binary); - files_written++; - - for (int i = 0; i < targets_per_level; i++) { - targets_written++; - file << "executable(\"" << RepoPathToTargetName(repo_path, i) - << "\") {\n"; - file << " sources = [\n"; - for (int f = 0; f < files_per_target; f++) - file << " \"" << base::IntToString(f) << ".cc\",\n"; - - if (repo_path.size() < (size_t)max_depth) { - file << " ]\n"; - file << " deps = [\n"; - for (int d = 0; d < spread; d++) { - std::vector<int> cur = repo_path; - cur.push_back(d); - for (int t = 0; t < targets_per_level; t++) - file << " \"" << RepoPathToFullTargetName(cur, t) << "\",\n"; - } - } - file << " ]\n}\n\n"; - } - } - if (repo_path.size() < (size_t)max_depth) { - // Recursively generate subdirs. - for (int i = 0; i < spread; i++) { - std::vector<int> cur = repo_path; - cur.push_back(i); - WriteLevel(cur, spread, max_depth, targets_per_level, files_per_target); - } - } -} - -int main() { - WriteLevel(std::vector<int>(), 5, 4, 3, 50); // 781 files, 2343 targets - //WriteLevel(std::vector<int>(), 6, 4, 2, 50); - std::cout << "Wrote " << files_written << " files and " - << targets_written << " targets.\n"; - return 0; -} diff --git a/tools/gn/gn.gyp b/tools/gn/gn.gyp deleted file mode 100644 index 4904e3d..0000000 --- a/tools/gn/gn.gyp +++ /dev/null @@ -1,171 +0,0 @@ -{
- 'variables': {
- 'chromium_code': 1,
- },
- 'targets': [
- {
- 'target_name': 'gn_lib',
- 'type': 'static_library',
- 'dependencies': [
- '../../base/base.gyp:base',
- ],
- 'sources': [
- 'build_settings.cc',
- 'build_settings.h',
- 'command_desc.cc',
- 'command_desc.h',
- 'command_gen.cc',
- 'command_gen.h',
- 'commands.h',
- 'config.cc',
- 'config.h',
- 'config_values.cc',
- 'config_values.h',
- 'config_values_extractors.cc',
- 'config_values_extractors.h',
- 'config_values_generator.cc',
- 'config_values_generator.h',
- 'err.cc',
- 'err.h',
- 'escape.cc',
- 'escape.h',
- 'file_template.cc',
- 'file_template.h',
- 'filesystem_utils.cc',
- 'filesystem_utils.h',
- 'functions_target.cc',
- 'functions.cc',
- 'functions.h',
- 'function_exec_script.cc',
- 'function_process_file_template.cc',
- 'function_read_file.cc',
- 'function_set_default_toolchain.cc',
- 'function_template.cc',
- 'function_toolchain.cc',
- 'function_write_file.cc',
- 'import_manager.cc',
- 'import_manager.h',
- 'input_conversion.cc',
- 'input_conversion.h',
- 'input_file.cc',
- 'input_file.h',
- 'input_file_manager.cc',
- 'input_file_manager.h',
- 'item.cc',
- 'item.h',
- 'item_node.cc',
- 'item_node.h',
- 'item_tree.cc',
- 'item_tree.h',
- 'label.cc',
- 'label.h',
- 'location.h',
- 'ninja_build_writer.cc',
- 'ninja_build_writer.h',
- 'ninja_helper.cc',
- 'ninja_helper.h',
- 'ninja_target_writer.cc',
- 'ninja_target_writer.h',
- 'ninja_toolchain_writer.cc',
- 'ninja_toolchain_writer.h',
- 'ninja_writer.cc',
- 'ninja_writer.h',
- 'operators.cc',
- 'operators.h',
- 'output_file.h',
- 'parse_tree.cc',
- 'parse_tree.h',
- 'parser.cc',
- 'parser.h',
- 'path_output.cc',
- 'path_output.h',
- 'pattern.cc',
- 'pattern.h',
- 'scheduler.cc',
- 'scheduler.h',
- 'scope.cc',
- 'scope.h',
- 'scope_per_file_provider.cc',
- 'scope_per_file_provider.h',
- 'settings.cc',
- 'settings.h',
- 'setup.cc',
- 'setup.h',
- 'source_dir.cc',
- 'source_dir.h',
- 'source_file.cc',
- 'source_file.h',
- 'standard_out.cc',
- 'standard_out.h',
- 'string_utils.cc',
- 'string_utils.h',
- 'target.cc',
- 'target.h',
- 'target_generator.cc',
- 'target_generator.h',
- 'target_manager.cc',
- 'target_manager.h',
- 'token.cc',
- 'token.h',
- 'tokenizer.cc',
- 'tokenizer.h',
- 'toolchain.cc',
- 'toolchain.h',
- 'toolchain_manager.cc',
- 'toolchain_manager.h',
- 'value.cc',
- 'value.h',
- 'value_extractors.cc',
- 'value_extractors.h',
- ],
- },
- {
- 'target_name': 'gn',
- 'type': 'executable',
- 'sources': [
- 'gn_main.cc',
- ],
- 'dependencies': [
- 'gn_lib',
- '../../base/base.gyp:base',
- '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- ],
- },
- {
- 'target_name': 'gn_unittests',
- 'type': '<(gtest_target_type)',
- 'sources': [
- 'escape_unittest.cc',
- 'file_template_unittest.cc',
- 'filesystem_utils_unittest.cc',
- 'input_conversion_unittest.cc',
- 'label_unittest.cc',
- 'ninja_helper_unittest.cc',
- 'parser_unittest.cc',
- 'path_output_unittest.cc',
- 'pattern_unittest.cc',
- 'source_dir_unittest.cc',
- 'string_utils_unittest.cc',
- 'target_generator_unittest.cc',
- 'target_manager_unittest.cc',
- 'tokenizer_unittest.cc',
- ],
- 'dependencies': [
- 'gn_lib',
- '../../base/base.gyp:run_all_unittests',
- '../../base/base.gyp:test_support_base',
- '../../testing/gtest.gyp:gtest',
- ],
- },
- {
- 'target_name': 'generate_test_gn_data',
- 'type': 'executable',
- 'sources': [
- 'generate_test_gn_data.cc',
- ],
- 'dependencies': [
- '../../base/base.gyp:base',
- ],
- }
- ],
-}
diff --git a/tools/gn/gn_main.cc b/tools/gn/gn_main.cc deleted file mode 100644 index 6f5b31e..0000000 --- a/tools/gn/gn_main.cc +++ /dev/null @@ -1,59 +0,0 @@ -// 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 "base/at_exit.h" -#include "base/command_line.h" -#include "base/strings/utf_string_conversions.h" -#include "tools/gn/commands.h" -#include "tools/gn/err.h" -#include "tools/gn/location.h" - -namespace { - -std::vector<std::string> GetArgs(const CommandLine& cmdline) { - CommandLine::StringVector in_args = cmdline.GetArgs(); -#if defined(OS_WIN) - std::vector<std::string> out_args; - for (size_t i = 0; i < in_args.size(); i++) - out_args.push_back(base::WideToUTF8(in_args[i])); - return out_args; -#else - return in_args; -#endif -} - -} // namespace - -int main(int argc, char** argv) { - base::AtExitManager at_exit; - CommandLine::Init(argc, argv); - - std::vector<std::string> args = GetArgs(*CommandLine::ForCurrentProcess()); - - std::string command; - if (args.empty()) { - command = "gen"; - } else { - command = args[0]; - args.erase(args.begin()); - } - - int retval = 0; - if (command == "gen") { - retval = RunGenCommand(args); - } else if (command == "desc" || command == "wtf") { - retval = RunDescCommand(args); - } else if (command == "deps") { - retval = RunDepsCommand(args); - } else if (command == "tree") { - retval = RunTreeCommand(args); - } else { - Err(Location(), - "Command \"" + command + "\" unknown.").PrintToStdout(); - retval = 1; - } - - exit(retval); // Don't free memory, it can be really slow! - return retval; -} diff --git a/tools/gn/import_manager.cc b/tools/gn/import_manager.cc deleted file mode 100644 index 774f866..0000000 --- a/tools/gn/import_manager.cc +++ /dev/null @@ -1,83 +0,0 @@ -// 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/import_manager.h" - -#include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/scheduler.h" - -namespace { - -// Returns a newly-allocated scope on success, null on failure. -Scope* UncachedImport(const Settings* settings, - const SourceFile& file, - const ParseNode* node_for_err, - Err* err) { - const ParseNode* node = g_scheduler->input_file_manager()->SyncLoadFile( - node_for_err->GetRange(), settings->build_settings(), file, err); - if (!node) - return NULL; - const BlockNode* block = node->AsBlock(); - CHECK(block); - - scoped_ptr<Scope> scope(new Scope(settings->base_config())); - scope->SetProcessingImport(); - block->ExecuteBlockInScope(scope.get(), err); - if (err->has_error()) - return NULL; - scope->ClearProcessingImport(); - - return scope.release(); -} - -} // namesapce - -ImportManager::ImportManager() { -} - -ImportManager::~ImportManager() { - STLDeleteContainerPairSecondPointers(imports_.begin(), imports_.end()); -} - -bool ImportManager::DoImport(const SourceFile& file, - const ParseNode* node_for_err, - Scope* scope, - Err* err) { - // See if we have a cached import, but be careful to actually do the scope - // copying outside of the lock. - const Scope* imported_scope = NULL; - { - base::AutoLock lock(lock_); - ImportMap::const_iterator found = imports_.find(file); - if (found != imports_.end()) - imported_scope = found->second; - } - - if (!imported_scope) { - // Do a new import of the file. - imported_scope = UncachedImport(scope->settings(), file, - node_for_err, err); - if (!imported_scope) - return false; - - // We loaded the file outside the lock. This means that there could be a - // race and the file was already loaded on a background thread. Recover - // from this and use the existing one if that happens. - { - base::AutoLock lock(lock_); - ImportMap::const_iterator found = imports_.find(file); - if (found != imports_.end()) { - delete imported_scope; - imported_scope = found->second; - } else { - imports_[file] = imported_scope; - } - } - } - - return imported_scope->NonRecursiveMergeTo(scope, node_for_err, - "import", err); -} diff --git a/tools/gn/import_manager.h b/tools/gn/import_manager.h deleted file mode 100644 index 725a5b2..0000000 --- a/tools/gn/import_manager.h +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_IMPORT_MANAGER_H_ -#define TOOLS_GN_IMPORT_MANAGER_H_ - -#include <map> - -#include "base/synchronization/lock.h" - -class Err; -class ParseNode; -class Scope; -class SourceFile; - -// Provides a cache of the results of importing scopes so the results can -// be re-used rather than running the imported files multiple times. -class ImportManager { - public: - ImportManager(); - ~ImportManager(); - - // Does an import of the given file into the given scope. On error, sets the - // error and returns false. - bool DoImport(const SourceFile& file, - const ParseNode* node_for_err, - Scope* scope, - Err* err); - - private: - base::Lock lock_; - - // Owning pointers to the scopes. - typedef std::map<SourceFile, const Scope*> ImportMap; - ImportMap imports_; - - DISALLOW_COPY_AND_ASSIGN(ImportManager); -}; - -#endif // TOOLS_GN_IMPORT_MANAGER_H_ diff --git a/tools/gn/input_conversion.cc b/tools/gn/input_conversion.cc deleted file mode 100644 index c0a0685..0000000 --- a/tools/gn/input_conversion.cc +++ /dev/null @@ -1,205 +0,0 @@ -// 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 "input_conversion.h" - -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "tools/gn/build_settings.h" -#include "tools/gn/err.h" -#include "tools/gn/input_file.h" -#include "tools/gn/label.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/parser.h" -#include "tools/gn/scope.h" -#include "tools/gn/settings.h" -#include "tools/gn/tokenizer.h" -#include "tools/gn/value.h" - -namespace { - -// Returns the "first bit" of some script output for writing to error messages. -std::string GetExampleOfBadInput(const std::string& input) { - std::string result(input); - - // Maybe the result starts with a blank line or something, which we don't - // want. - TrimWhitespaceASCII(result, TRIM_ALL, &result); - - // Now take the first line, or the first set of chars, whichever is shorter. - bool trimmed = false; - size_t newline_offset = result.find('\n'); - if (newline_offset != std::string::npos) { - trimmed = true; - result.resize(newline_offset); - } - TrimWhitespaceASCII(result, TRIM_ALL, &result); - - const int kMaxSize = 50; - if (result.size() > kMaxSize) { - trimmed = true; - result.resize(kMaxSize); - } - - if (trimmed) - result.append("..."); - return result; -} - -// When parsing the result as a value, we may get various types of errors. -// This creates an error message for this case with an optional nested error -// message to reference. If there is no nested err, pass Err(). -// -// This code also takes care to rewrite the original error which will reference -// the temporary InputFile which won't exist when the error is propogated -// out to a higher level. -Err MakeParseErr(const std::string& input, - const ParseNode* origin, - const Err& nested) { - std::string help_text = - "When parsing a result as a \"value\" it should look like a list:\n" - " [ \"a\", \"b\", 5 ]\n" - "or a single literal:\n" - " \"my result\"\n" - "but instead I got this, which I find very confusing:\n"; - help_text.append(input); - if (nested.has_error()) - help_text.append("\nThe exact error was:"); - - Err result(origin, "Script result wasn't a valid value.", help_text); - if (nested.has_error()) { - result.AppendSubErr(Err(LocationRange(), nested.message(), - nested.help_text())); - } - return result; -} - -// Sets the origin of the value and any nested values with the given node. -void RecursivelySetOrigin(Value* value, const ParseNode* origin) { - value->set_origin(origin); - if (value->type() == Value::LIST) { - std::vector<Value>& list_value = value->list_value(); - for (size_t i = 0; i < list_value.size(); i++) - RecursivelySetOrigin(&list_value[i], origin); - } -} - -Value ParseString(const std::string& input, - const ParseNode* origin, - Err* err) { - SourceFile empty_source_for_most_vexing_parse; - InputFile input_file(empty_source_for_most_vexing_parse); - input_file.SetContents(input); - - std::vector<Token> tokens = Tokenizer::Tokenize(&input_file, err); - if (err->has_error()) { - *err = MakeParseErr(input, origin, *err); - return Value(); - } - - scoped_ptr<ParseNode> expression = Parser::ParseExpression(tokens, err); - if (err->has_error()) { - *err = MakeParseErr(input, origin, *err); - return Value(); - } - - // It's valid for the result to be a null pointer, this just means that the - // script returned nothing. - if (!expression) - return Value(); - - // The result should either be a list or a literal, anything else is - // invalid. - if (!expression->AsList() && !expression->AsLiteral()) { - *err = MakeParseErr(input, origin, Err()); - return Value(); - } - - BuildSettings build_settings; - Label empty_label; - Toolchain toolchain(empty_label); - Settings settings(&build_settings, &toolchain, std::string()); - Scope scope(&settings); - - Err nested_err; - Value result = expression->Execute(&scope, &nested_err); - if (nested_err.has_error()) { - *err = MakeParseErr(input, origin, nested_err); - return Value(); - } - - // The returned value will have references to the temporary parse nodes we - // made on the stack. If the values are used in an error message in the - // future, this will crash. Reset the origin of all values to be our - // containing origin. - RecursivelySetOrigin(&result, origin); - return result; -} - -Value ParseList(const std::string& input, - const ParseNode* origin, - Err* err) { - Value ret(origin, Value::LIST); - std::vector<std::string> as_lines; - base::SplitString(input, '\n', &as_lines); - - // Trim empty lines from the end. - // Do we want to make this configurable? - while (!as_lines.empty() && as_lines[as_lines.size() - 1].empty()) - as_lines.resize(as_lines.size() - 1); - - ret.list_value().reserve(as_lines.size()); - for (size_t i = 0; i < as_lines.size(); i++) - ret.list_value().push_back(Value(origin, as_lines[i])); - return ret; -} - -} // namespace - -/* -input_conversion: Specifies how to transform input to a variable. - - input_conversion is an argument to read_file and exec_script that specifies - how the result of the read operation should be converted into a variable. - - "list lines": - Return the file contents as a list, with a string for each line. The - newlines will not be present in the result. Empty newlines will be - trimmed from the trailing end of the returned list. - - "value": - Parse the input as if it was a literal rvalue in a buildfile. - Examples of typical program output using this mode: - [ "foo", "bar" ] (result will be a list) - or - "foo bar" (result will be a string) - or - 5 (result will be an integer) - - Note that if the input is empty, the result will be a null value which - will produce an error if assigned to a variable. - - "string": - Return the file contents into a single string. -*/ - -Value ConvertInputToValue(const std::string& input, - const ParseNode* origin, - const Value& input_conversion_value, - Err* err) { - if (!input_conversion_value.VerifyTypeIs(Value::STRING, err)) - return Value(); - const std::string& input_conversion = input_conversion_value.string_value(); - - if (input_conversion == "value") - return ParseString(input, origin, err); - if (input_conversion == "string") - return Value(origin, input); - if (input_conversion == "list lines") - return ParseList(input, origin, err); - - *err = Err(input_conversion_value, "Not a valid read file mode.", - "Have you considered a career in retail?"); - return Value(); -} diff --git a/tools/gn/input_conversion.h b/tools/gn/input_conversion.h deleted file mode 100644 index d15e513..0000000 --- a/tools/gn/input_conversion.h +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_INPUT_CONVERSION_H_ -#define TOOLS_GN_INPUT_CONVERSION_H_ - -#include <string> - -class Err; -class ParseNode; -class Value; - -// Converts the given input string (is read from a file or output from a -// script) to a Value. Conversions as specified in the input_conversion string -// will be performed. The given origin will be used for constructing the -// resulting Value. -// -// If the conversion string is invalid, the error will be set and an empty -// value will be returned. -Value ConvertInputToValue(const std::string& input, - const ParseNode* origin, - const Value& input_conversion_value, - Err* err); - -#endif // TOOLS_GN_INPUT_CONVERSION_H_ diff --git a/tools/gn/input_conversion_unittest.cc b/tools/gn/input_conversion_unittest.cc deleted file mode 100644 index 59c0123..0000000 --- a/tools/gn/input_conversion_unittest.cc +++ /dev/null @@ -1,81 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/err.h" -#include "tools/gn/input_conversion.h" -#include "tools/gn/value.h" - -TEST(InputConversion, String) { - Err err; - std::string input("\nfoo bar \n"); - Value result = ConvertInputToValue(input, NULL, Value(NULL, "string"), &err); - EXPECT_FALSE(err.has_error()); - EXPECT_EQ(Value::STRING, result.type()); - EXPECT_EQ(input, result.string_value()); -} - -TEST(InputConversion, ListLines) { - Err err; - std::string input("\nfoo\nbar \n"); - Value result = ConvertInputToValue(input, NULL, Value(NULL, "list lines"), - &err); - EXPECT_FALSE(err.has_error()); - EXPECT_EQ(Value::LIST, result.type()); - ASSERT_EQ(3u, result.list_value().size()); - EXPECT_EQ("", result.list_value()[0].string_value()); - EXPECT_EQ("foo", result.list_value()[1].string_value()); - EXPECT_EQ("bar", result.list_value()[2].string_value()); -} - -TEST(InputConversion, ValueString) { - Err err; - std::string input("\"str\""); - Value result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err); - EXPECT_FALSE(err.has_error()); - EXPECT_EQ(Value::STRING, result.type()); - EXPECT_EQ("str", result.string_value()); -} - -TEST(InputConversion, ValueInt) { - Err err; - std::string input("\n\n 6 \n "); - Value result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err); - EXPECT_FALSE(err.has_error()); - EXPECT_EQ(Value::INTEGER, result.type()); - EXPECT_EQ(6, result.int_value()); -} - -TEST(InputConversion, ValueList) { - Err err; - std::string input("\n [ \"a\", 5]"); - Value result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err); - EXPECT_FALSE(err.has_error()); - ASSERT_EQ(Value::LIST, result.type()); - ASSERT_EQ(2u, result.list_value().size()); - EXPECT_EQ("a", result.list_value()[0].string_value()); - EXPECT_EQ(5, result.list_value()[1].int_value()); -} - -TEST(InputConversion, ValueEmpty) { - Err err; - ConvertInputToValue("", NULL, Value(NULL, "value"), &err); -} - -TEST(InputConversion, ValueError) { - Err err; - std::string input("\n [ \"a\", 5\nfoo bar"); - Value result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err); - EXPECT_TRUE(err.has_error()); - - // Blocks not allowed. - input = "{ foo = 5 }"; - result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err); - EXPECT_TRUE(err.has_error()); - - // Function calls not allowed. - input = "print(5)"; - result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err); - EXPECT_TRUE(err.has_error()); -} diff --git a/tools/gn/input_file.cc b/tools/gn/input_file.cc deleted file mode 100644 index b2c3c0b..0000000 --- a/tools/gn/input_file.cc +++ /dev/null @@ -1,30 +0,0 @@ -// 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/input_file.h" - -#include "base/file_util.h" - -InputFile::InputFile(const SourceFile& name) - : name_(name), - dir_(name_.GetDir()), - contents_loaded_(false) { -} - -InputFile::~InputFile() { -} - -void InputFile::SetContents(const std::string& c) { - contents_loaded_ = true; - contents_ = c; -} - -bool InputFile::Load(const base::FilePath& system_path) { - if (file_util::ReadFileToString(system_path, &contents_)) { - contents_loaded_ = true; - return true; - } - return false; -} - diff --git a/tools/gn/input_file.h b/tools/gn/input_file.h deleted file mode 100644 index 66cf55c..0000000 --- a/tools/gn/input_file.h +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_INPUT_FILE_H_ -#define TOOLS_GN_INPUT_FILE_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "tools/gn/source_dir.h" -#include "tools/gn/source_file.h" - -class InputFile { - public: - InputFile(const SourceFile& name); - - // Constructor for testing. Uses an empty file path and a given contents. - //InputFile(const char* contents); - ~InputFile(); - - const SourceFile& name() const { return name_; } - - // The directory is just a cached version of name_->GetDir() but we get this - // a lot so computing it once up front saves a bunch of work. - const SourceDir& dir() const { return dir_; } - - const std::string& contents() const { - DCHECK(contents_loaded_); - return contents_; - } - - // For testing and in cases where this input doesn't actually refer to - // "a file". - void SetContents(const std::string& c); - - // Loads the given file synchronously, returning true on success. This - bool Load(const base::FilePath& system_path); - - private: - SourceFile name_; - SourceDir dir_; - - bool contents_loaded_; - std::string contents_; - - DISALLOW_COPY_AND_ASSIGN(InputFile); -}; - -#endif // TOOLS_GN_INPUT_FILE_H_ diff --git a/tools/gn/input_file_manager.cc b/tools/gn/input_file_manager.cc deleted file mode 100644 index e840ba0..0000000 --- a/tools/gn/input_file_manager.cc +++ /dev/null @@ -1,254 +0,0 @@ -// 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/input_file_manager.h" - -#include "base/bind.h" -#include "base/stl_util.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/parser.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/scope_per_file_provider.h" -#include "tools/gn/tokenizer.h" - -namespace { - -void InvokeFileLoadCallback(const InputFileManager::FileLoadCallback& cb, - const ParseNode* node) { - cb.Run(node); -} - -} // namespace - -InputFileManager::InputFileData::InputFileData(const SourceFile& file_name) - : file(file_name), - loaded(false), - sync_invocation(false) { -} - -InputFileManager::InputFileData::~InputFileData() { -} - -InputFileManager::InputFileManager() { -} - -InputFileManager::~InputFileManager() { - // Should be single-threaded by now. - STLDeleteContainerPairSecondPointers(input_files_.begin(), - input_files_.end()); -} - -bool InputFileManager::AsyncLoadFile(const LocationRange& origin, - const BuildSettings* build_settings, - const SourceFile& file_name, - const FileLoadCallback& callback, - Err* err) { - // Try not to schedule callbacks while holding the lock. All cases that don't - // want to schedule should return early. Otherwise, this will be scheduled - // after we leave the lock. - base::Closure schedule_this; - { - base::AutoLock lock(lock_); - - InputFileMap::const_iterator found = input_files_.find(file_name); - if (found == input_files_.end()) { - // New file, schedule load. - InputFileData* data = new InputFileData(file_name); - data->scheduled_callbacks.push_back(callback); - input_files_[file_name] = data; - - schedule_this = base::Bind(&InputFileManager::BackgroundLoadFile, - this, - origin, - build_settings, - file_name, - &data->file); - } else { - InputFileData* data = found->second; - - // Prevent mixing async and sync loads. See SyncLoadFile for discussion. - if (data->sync_invocation) { - g_scheduler->FailWithError(Err( - origin, "Load type mismatch.", - "The file \"" + file_name.value() + "\" was previously loaded\n" - "synchronously (via an import) and now you're trying to load it " - "asynchronously\n(via a deps rule). This is a class 2 misdemeanor: " - "a single input file must\nbe loaded the same way each time to " - "avoid blowing my tiny, tiny mind.")); - return false; - } - - if (data->loaded) { - // Can just directly issue the callback on the background thread. - schedule_this = base::Bind(&InvokeFileLoadCallback, callback, - data->parsed_root.get()); - } else { - // Load is pending on this file, schedule the invoke. - data->scheduled_callbacks.push_back(callback); - return true; - } - } - } - g_scheduler->pool()->PostWorkerTaskWithShutdownBehavior( - FROM_HERE, schedule_this, - base::SequencedWorkerPool::BLOCK_SHUTDOWN); - return true; -} - -const ParseNode* InputFileManager::SyncLoadFile( - const LocationRange& origin, - const BuildSettings* build_settings, - const SourceFile& file_name, - Err* err) { - base::AutoLock lock(lock_); - - InputFileData* data = NULL; - InputFileMap::iterator found = input_files_.find(file_name); - if (found == input_files_.end()) { - base::AutoUnlock unlock(lock_); - - // Haven't seen this file yet, start loading right now. - data = new InputFileData(file_name); - data->sync_invocation = true; - input_files_[file_name] = data; - - if (!LoadFile(origin, build_settings, file_name, &data->file, err)) - return NULL; - } else { - // This file has either been loaded or is pending loading. - data = found->second; - - if (!data->sync_invocation) { - // Don't allow mixing of sync and async loads. If an async load is - // scheduled and then a bunch of threads need to load it synchronously - // and block on it loading, it could deadlock or at least cause a lot - // of wasted CPU while those threads wait for the load to complete (which - // may be far back in the input queue). - // - // We could work around this by promoting the load to a sync load. This - // requires a bunch of extra code to either check flags and likely do - // extra locking (bad) or to just do both types of load on the file and - // deal with the race condition. - // - // I have no practical way to test this, and generally we should have - // all include files processed synchronously and all build files - // processed asynchronously, so it doesn't happen in practice. - *err = Err( - origin, "Load type mismatch.", - "The file \"" + file_name.value() + "\" was previously loaded\n" - "asynchronously (via a deps rule) and now you're trying to load it " - "synchronously.\nThis is a class 2 misdemeanor: a single input file " - "must be loaded the same way\neach time to avoid blowing my tiny, " - "tiny mind."); - return NULL; - } - - if (!data->loaded) { - // Wait for the already-pending sync load to complete. - if (!data->completion_event) - data->completion_event.reset(new base::WaitableEvent(false, false)); - { - base::AutoUnlock unlock(lock_); - data->completion_event->Wait(); - } - } - } - - // The other load could have failed. In this case that error will be printed - // to the console, but we need to return something here, so make up a - // dummy error. - if (!data->parsed_root) - *err = Err(origin, "File parse failed"); - return data->parsed_root.get(); -} - -int InputFileManager::GetInputFileCount() const { - base::AutoLock lock(lock_); - return input_files_.size(); -} - -void InputFileManager::GetAllInputFileNames( - std::vector<SourceFile>* result) const { - base::AutoLock lock(lock_); - result->reserve(input_files_.size()); - for (InputFileMap::const_iterator i = input_files_.begin(); - i != input_files_.end(); ++i) { - result->push_back(i->second->file.name()); - } -} - -void InputFileManager::BackgroundLoadFile(const LocationRange& origin, - const BuildSettings* build_settings, - const SourceFile& name, - InputFile* file) { - Err err; - if (!LoadFile(origin, build_settings, name, file, &err)) - g_scheduler->FailWithError(err); -} - -bool InputFileManager::LoadFile(const LocationRange& origin, - const BuildSettings* build_settings, - const SourceFile& name, - InputFile* file, - Err* err) { - // Do all of this stuff outside the lock. We should not give out file - // pointers until the read is complete. - if (g_scheduler->verbose_logging()) - g_scheduler->Log("Loading", name.value()); - - // Read. - base::FilePath primary_path = build_settings->GetFullPath(name); - if (!file->Load(primary_path)) { - if (!build_settings->secondary_source_path().empty()) { - // Fall back to secondary source tree. - base::FilePath secondary_path = - build_settings->GetFullPathSecondary(name); - if (!file->Load(secondary_path)) { - *err = Err(origin, "Can't load input file.", - "Unable to load either \n" + - FilePathToUTF8(primary_path) + " or \n" + - FilePathToUTF8(secondary_path)); - return false; - } - } else { - *err = Err(origin, - "Unable to load \"" + FilePathToUTF8(primary_path) + "\"."); - return false; - } - } - - if (g_scheduler->verbose_logging()) - g_scheduler->Log("Parsing", name.value()); - - // Tokenize. - std::vector<Token> tokens = Tokenizer::Tokenize(file, err); - if (err->has_error()) - return false; - - // Parse. - scoped_ptr<ParseNode> root = Parser::Parse(tokens, err); - if (err->has_error()) - return false; - ParseNode* unowned_root = root.get(); - - std::vector<FileLoadCallback> callbacks; - { - base::AutoLock lock(lock_); - DCHECK(input_files_.find(name) != input_files_.end()); - - InputFileData* data = input_files_[name]; - data->loaded = true; - data->tokens.swap(tokens); - data->parsed_root = root.Pass(); - - callbacks.swap(data->scheduled_callbacks); - } - - // Run pending invocations. Theoretically we could schedule each of these - // separately to get some parallelism. But normally there will only be one - // item in the list, so that's extra overhead and complexity for no gain. - for (size_t i = 0; i < callbacks.size(); i++) - callbacks[i].Run(unowned_root); - return true; -} diff --git a/tools/gn/input_file_manager.h b/tools/gn/input_file_manager.h deleted file mode 100644 index 0f708d5..0000000 --- a/tools/gn/input_file_manager.h +++ /dev/null @@ -1,123 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_INPUT_FILE_MANAGER_H_ -#define TOOLS_GN_INPUT_FILE_MANAGER_H_ - -#include <set> -#include <utility> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/containers/hash_tables.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "tools/gn/build_settings.h" -#include "tools/gn/input_file.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/settings.h" - -class Err; -class LocationRange; -class ParseNode; -class Token; - -// Manages loading and parsing files from disk. This doesn't actually have -// any context for executing the results, so potentially multiple configs -// could use the same input file (saving parsing). -// -// This class is threadsafe. -// -// InputFile objects must never be deleted while the program is running since -// various state points into them. -class InputFileManager : public base::RefCountedThreadSafe<InputFileManager> { - public: - // Callback issued when a file is laoded. On auccess, the parse node will - // refer to the root block of the file. On failure, this will be NULL. - typedef base::Callback<void(const ParseNode*)> FileLoadCallback; - - InputFileManager(); - - // Loads the given file and executes the callback on the worker pool. - // - // There are two types of errors. For errors known synchronously, the error - // will be set, it will return false, and no work will be scheduled. - // - // For parse errors and such that happen in the future, the error will be - // logged to the scheduler and the callback will be invoked with a null - // ParseNode pointer. The given |origin| will be blamed for the invocation. - bool AsyncLoadFile(const LocationRange& origin, - const BuildSettings* build_settings, - const SourceFile& file_name, - const FileLoadCallback& callback, - Err* err); - - // Loads and parses the given file synchronously, returning the root block - // corresponding to the parsed result. On error, return NULL and the given - // Err is set. - const ParseNode* SyncLoadFile(const LocationRange& origin, - const BuildSettings* build_settings, - const SourceFile& file_name, - Err* err); - - int GetInputFileCount() const; - - void GetAllInputFileNames(std::vector<SourceFile>* result) const; - - private: - friend class base::RefCountedThreadSafe<InputFileManager>; - - struct InputFileData { - InputFileData(const SourceFile& file_name); - ~InputFileData(); - - // Don't touch this outside the lock until it's marked loaded. - InputFile file; - - bool loaded; - - bool sync_invocation; - - // Lists all invocations that need to be executed when the file completes - // loading. - std::vector<FileLoadCallback> scheduled_callbacks; - - // Event to signal when the load is complete (or fails). This is lazily - // created only when a thread is synchronously waiting for this load (which - // only happens for imports). - scoped_ptr<base::WaitableEvent> completion_event; - - std::vector<Token> tokens; - - // Null before the file is loaded or if loading failed. - scoped_ptr<ParseNode> parsed_root; - }; - - virtual ~InputFileManager(); - - void BackgroundLoadFile(const LocationRange& origin, - const BuildSettings* build_settings, - const SourceFile& name, - InputFile* file); - - // Loads the given file. On error, sets the Err and return false. - bool LoadFile(const LocationRange& origin, - const BuildSettings* build_settings, - const SourceFile& name, - InputFile* file, - Err* err); - - mutable base::Lock lock_; - - // Maps repo-relative filenames to the corresponding owned pointer. - typedef base::hash_map<SourceFile, InputFileData*> InputFileMap; - InputFileMap input_files_; - - DISALLOW_COPY_AND_ASSIGN(InputFileManager); -}; - -#endif // TOOLS_GN_INPUT_FILE_MANAGER_H_ diff --git a/tools/gn/item.cc b/tools/gn/item.cc deleted file mode 100644 index 747183cb..0000000 --- a/tools/gn/item.cc +++ /dev/null @@ -1,31 +0,0 @@ -// 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/item.h" - -#include "base/logging.h" - -Item::Item(const Label& label) : label_(label) { -} - -Item::~Item() { -} - -Config* Item::AsConfig() { return NULL; } -const Config* Item::AsConfig() const { return NULL; } -Target* Item::AsTarget() { return NULL; } -const Target* Item::AsTarget() const { return NULL; } -Toolchain* Item::AsToolchain() { return NULL; } -const Toolchain* Item::AsToolchain() const { return NULL; } - -std::string Item::GetItemTypeName() const { - if (AsConfig()) - return "config"; - if (AsTarget()) - return "target"; - if (AsToolchain()) - return "toolchain"; - NOTREACHED(); - return "this thing that I have no idea what it is"; -} diff --git a/tools/gn/item.h b/tools/gn/item.h deleted file mode 100644 index aa71544..0000000 --- a/tools/gn/item.h +++ /dev/null @@ -1,45 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_ITEM_H_ -#define TOOLS_GN_ITEM_H_ - -#include <string> - -#include "tools/gn/label.h" - -class Config; -class Target; -class Toolchain; - -// A named item (target, config, etc.) that participates in the dependency -// graph. -class Item { - public: - Item(const Label& label); - virtual ~Item(); - - const Label& label() const { return label_; } - - // Manual RTTI. - virtual Config* AsConfig(); - virtual const Config* AsConfig() const; - virtual Target* AsTarget(); - virtual const Target* AsTarget() const; - virtual Toolchain* AsToolchain(); - virtual const Toolchain* AsToolchain() const; - - // Returns a name like "target" or "config" for the type of item this is, to - // be used in logging and error messages. - std::string GetItemTypeName() const; - - // Called when this item is resolved, meaning it and all of its dependents - // have no unresolved deps. - virtual void OnResolved() {} - - private: - Label label_; -}; - -#endif // TOOLS_GN_ITEM_H_ diff --git a/tools/gn/item_node.cc b/tools/gn/item_node.cc deleted file mode 100644 index 776a126..0000000 --- a/tools/gn/item_node.cc +++ /dev/null @@ -1,51 +0,0 @@ -// 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/item_node.h" - -#include <algorithm> - -#include "base/callback.h" -#include "base/logging.h" -#include "tools/gn/item.h" - -ItemNode::ItemNode(Item* i) - : state_(REFERENCED), - item_(i) { -} - -ItemNode::~ItemNode() { -} - -void ItemNode::AddDependency(ItemNode* node) { - if (direct_dependencies_.find(node) != direct_dependencies_.end()) - return; // Already have this dep. - direct_dependencies_.insert(node); - - if (node->state() != RESOLVED) { - // Wire up the pending resolution info. - unresolved_dependencies_.insert(node); - node->waiting_on_resolution_.insert(this); - } -} - -void ItemNode::MarkDirectDependencyResolved(ItemNode* node) { - DCHECK(unresolved_dependencies_.find(node) != unresolved_dependencies_.end()); - unresolved_dependencies_.erase(node); -} - -void ItemNode::SwapOutWaitingDependencySet(ItemNodeSet* out_set) { - waiting_on_resolution_.swap(*out_set); -} - -void ItemNode::SetGenerated() { - state_ = GENERATED; -} - -void ItemNode::SetResolved() { - state_ = RESOLVED; - - if (!resolved_closure_.is_null()) - resolved_closure_.Run(); -} diff --git a/tools/gn/item_node.h b/tools/gn/item_node.h deleted file mode 100644 index 297010f..0000000 --- a/tools/gn/item_node.h +++ /dev/null @@ -1,119 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_ITEM_NODE_H_ -#define TOOLS_GN_ITEM_NODE_H_ - -#include <set> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "tools/gn/location.h" - -class Item; - -// Represents a node in the depdency tree. It references an Item which is -// the actual thing. -// -// The items and nodes are split apart so that the ItemTree can manipulate -// the dependencies one one thread while the Item itself is been modified on -// another. -class ItemNode { - public: - enum State { - // Another item has referenced this one by name, but we have not yet - // encountered this item to know what it is. - REFERENCED, - - // This item has been defined but some of the dependencies it references - // have not been. - GENERATED, - - // All of this item's transitive dependencies have been found and - // resolved. - RESOLVED, - }; - - typedef std::set<ItemNode*> ItemNodeSet; - - // Takes ownership of the pointer. - // Initial state will be REFERENCED. - ItemNode(Item* i); - ~ItemNode(); - - State state() const { return state_; } - - // This closure will be executed when the item is resolved. - void set_resolved_closure(const base::Closure& closure) { - resolved_closure_ = closure; - } - - const Item* item() const { return item_.get(); } - Item* item() { return item_.get(); } - - // Where this was created from, which might be when it was generated or - // when it was first referenced from another target. - const LocationRange& originally_referenced_from_here() const { - return originally_referenced_from_here_; - } - void set_originally_referenced_from_here(const LocationRange& r) { - originally_referenced_from_here_ = r; - } - - // Where this was generated from. This will be empty for items that have - // been referenced but not generated. Note that this has to be one the - // ItemNode because it can be changing from multiple threads and we need - // to be sure that access is serialized. - const LocationRange& generated_from_here() const { - return generated_from_here_; - } - void set_generated_from_here(const LocationRange& r) { - generated_from_here_ = r; - } - - const ItemNodeSet& direct_dependencies() const { - return direct_dependencies_; - } - const ItemNodeSet& unresolved_dependencies() const { - return unresolved_dependencies_; - } - - void AddDependency(ItemNode* node); - - // Removes the given dependency from the unresolved list. Does not do - // anything else to update waiters. - void MarkDirectDependencyResolved(ItemNode* node); - - // Destructively retrieve the set of waiting nodes. - void SwapOutWaitingDependencySet(ItemNodeSet* out_set); - - void SetGenerated(); - void SetResolved(); - - private: - State state_; - scoped_ptr<Item> item_; - - LocationRange originally_referenced_from_here_; - LocationRange generated_from_here_; - - // What to run when this item is resolved. - base::Closure resolved_closure_; - - // Everything this item directly depends on. - ItemNodeSet direct_dependencies_; - - // Unresolved things this item directly depends on. - ItemNodeSet unresolved_dependencies_; - - // These items are waiting on us to be resolved before they can be - // resolved. This is the backpointer for unresolved_dependencies_. - ItemNodeSet waiting_on_resolution_; - - DISALLOW_COPY_AND_ASSIGN(ItemNode); -}; - -#endif // TOOLS_GN_ITEM_NODE_H_ diff --git a/tools/gn/item_tree.cc b/tools/gn/item_tree.cc deleted file mode 100644 index a4d1181..0000000 --- a/tools/gn/item_tree.cc +++ /dev/null @@ -1,193 +0,0 @@ -// 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/item_tree.h" - -#include <algorithm> - -#include "base/stl_util.h" -#include "tools/gn/err.h" -#include "tools/gn/item.h" -#include "tools/gn/item_node.h" - -namespace { - -// Recursively looks in the tree for a given node, returning true if it -// was found in the dependecy graph. This is used to see if a given node -// participates in a cycle. -// -// Note that "look_for" and "search_in" will be the same node when starting the -// search, so we don't want to return true in that case. -// -// If a cycle is found, the return value will be true and the cycle vector will -// be filled with the path (in reverse order). -bool RecursiveFindCycle(const ItemNode* look_for, - const ItemNode* search_in, - std::vector<const ItemNode*>* cycle) { - const ItemNode::ItemNodeSet& unresolved = - search_in->unresolved_dependencies(); - for (ItemNode::ItemNodeSet::const_iterator i = unresolved.begin(); - i != unresolved.end(); ++i) { - if (*i == look_for) { - cycle->push_back(*i); - return true; - } - - if (RecursiveFindCycle(look_for, *i, cycle)) { - // Found a cycle inside this one, record our path and return. - cycle->push_back(*i); - return true; - } - } - return false; -} - -} // namespace - -ItemTree::ItemTree() { -} - -ItemTree::~ItemTree() { - STLDeleteContainerPairSecondPointers(items_.begin(), items_.end()); -} - -ItemNode* ItemTree::GetExistingNodeLocked(const Label& label) { - lock_.AssertAcquired(); - StringToNodeHash::iterator found = items_.find(label); - if (found == items_.end()) - return NULL; - return found->second; -} - -void ItemTree::AddNodeLocked(ItemNode* node) { - lock_.AssertAcquired(); - DCHECK(items_.find(node->item()->label()) == items_.end()); - items_[node->item()->label()] = node; -} - -Err ItemTree::MarkItemGeneratedLocked(const Label& label) { - lock_.AssertAcquired(); - DCHECK(items_.find(label) != items_.end()); - - ItemNode* node = items_[label]; - - if (!node->unresolved_dependencies().empty()) { - // Still some pending dependencies, wait for those to be resolved. - node->SetGenerated(); - return Err(); - } - return MarkItemResolvedLocked(node); -} - -void ItemTree::GetAllItemsLocked(std::vector<const Item*>* dest) const { - lock_.AssertAcquired(); - dest->reserve(items_.size()); - for (StringToNodeHash::const_iterator i = items_.begin(); - i != items_.end(); ++i) { - dest->push_back(i->second->item()); - } -} - -Err ItemTree::CheckForBadItems() const { - base::AutoLock lock(lock_); - - // Look for errors where we find a GENERATED node that refers to a REFERENCED - // one. There may be other nodes depending on the GENERATED one, but listing - // all of those isn't helpful, we want to find the broken link. - // - // This finds normal "missing dependency" errors but does not find circular - // dependencies because in this case all items in the cycle will be GENERATED - // but none will be resolved. If this happens, we'll check explicitly for - // that below. - std::vector<const ItemNode*> bad_nodes; - std::string depstring; - for (StringToNodeHash::const_iterator i = items_.begin(); - i != items_.end(); ++i) { - const ItemNode* src = i->second; - - if (src->state() == ItemNode::GENERATED) { - bad_nodes.push_back(src); - - // Check dependencies. - for (ItemNode::ItemNodeSet::const_iterator dest = - src->unresolved_dependencies().begin(); - dest != src->unresolved_dependencies().end(); - ++dest) { - if ((*dest)->state() == ItemNode::REFERENCED) { - depstring += "\"" + src->item()->label().GetUserVisibleName(false) + - "\" needs " + (*dest)->item()->GetItemTypeName() + - " \"" + (*dest)->item()->label().GetUserVisibleName(false) + - "\"\n"; - } - } - } - } - - if (!bad_nodes.empty() && depstring.empty()) { - // Our logic above found a bad node but didn't identify the problem. This - // normally means a circular dependency. - depstring = CheckForCircularDependenciesLocked(bad_nodes); - if (depstring.empty()) { - // Something's very wrong, just dump out the bad nodes. - depstring = "I have no idea what went wrong, but these are unresolved, " - "possible due to an\ninternal error:"; - for (size_t i = 0; i < bad_nodes.size(); i++) { - depstring += "\n\"" + - bad_nodes[i]->item()->label().GetUserVisibleName(false) + "\""; - } - } - } - - if (depstring.empty()) - return Err(); - return Err(Location(), "Unresolved dependencies.", depstring); -} - -Err ItemTree::MarkItemResolvedLocked(ItemNode* node) { - node->SetResolved(); - node->item()->OnResolved(); - - // Now update our waiters, pushing the "resolved" bit. - ItemNode::ItemNodeSet waiting; - node->SwapOutWaitingDependencySet(&waiting); - for (ItemNode::ItemNodeSet::iterator i = waiting.begin(); - i != waiting.end(); ++i) { - ItemNode* waiter = *i; - - // Our node should be unresolved in the waiter. - DCHECK(waiter->unresolved_dependencies().find(node) != - waiter->unresolved_dependencies().end()); - waiter->MarkDirectDependencyResolved(node); - - // Recursively mark nodes as resolved. - if (waiter->state() == ItemNode::GENERATED && - waiter->unresolved_dependencies().empty()) { - Err err = MarkItemResolvedLocked(waiter); - if (err.has_error()) - return err; - } - } - - return Err(); -} - -std::string ItemTree::CheckForCircularDependenciesLocked( - const std::vector<const ItemNode*>& bad_nodes) const { - std::vector<const ItemNode*> cycle; - if (!RecursiveFindCycle(bad_nodes[0], bad_nodes[0], &cycle)) - return std::string(); // Didn't find a cycle, something else is wrong. - - cycle.push_back(bad_nodes[0]); - std::string ret = "There is a dependency cycle:"; - - // Walk backwards since the dependency arrows point in the reverse direction. - for (int i = static_cast<int>(cycle.size()) - 1; i >= 0; i--) { - ret += "\n \"" + cycle[i]->item()->label().GetUserVisibleName(false) + - "\""; - if (i != 0) - ret += " ->"; - } - - return ret; -} diff --git a/tools/gn/item_tree.h b/tools/gn/item_tree.h deleted file mode 100644 index f2ac4ae..0000000 --- a/tools/gn/item_tree.h +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_ITEM_TREE_H_ -#define TOOLS_GN_ITEM_TREE_H_ - -#include "base/containers/hash_tables.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" -#include "tools/gn/label.h" - -class Err; -class Item; -class ItemNode; - -// Represents the full dependency tree if labeled items in the system. -// Generally you will interact with this through the target manager, etc. -class ItemTree { - public: - ItemTree(); - ~ItemTree(); - - // This lock must be held when calling the "Locked" functions below. - base::Lock& lock() { return lock_; } - - // Returns NULL if the item is not found. - // - // The lock must be held. - ItemNode* GetExistingNodeLocked(const Label& label); - - // There must not be an item with this label in the tree already. Takes - // ownership of the pointer. - // - // The lock must be held. - void AddNodeLocked(ItemNode* node); - - // Mark the given item as being generated. If it has no unresolved - // dependencies, it will be marked resolved, and the resolved state will be - // recursively pushed into the dependency tree. Returns an error if there was - // an error. - Err MarkItemGeneratedLocked(const Label& label); - - // Fills the given vector with all known items. - void GetAllItemsLocked(std::vector<const Item*>* dest) const; - - // Returns an error if there are unresolved dependencies, or no error if - // there aren't. - // - // The lock should not be held. - Err CheckForBadItems() const; - - private: - Err MarkItemResolvedLocked(ItemNode* node); - - // Given a set of unresolved nodes, looks for cycles and returns the error - // message describing any cycles it found. - std::string CheckForCircularDependenciesLocked( - const std::vector<const ItemNode*>& bad_nodes) const; - - mutable base::Lock lock_; - - typedef base::hash_map<Label, ItemNode*> StringToNodeHash; - StringToNodeHash items_; // Owning pointer. - - DISALLOW_COPY_AND_ASSIGN(ItemTree); -}; - -#endif // TOOLS_GN_ITEM_TREE_H_ diff --git a/tools/gn/label.cc b/tools/gn/label.cc deleted file mode 100644 index f9b48da..0000000 --- a/tools/gn/label.cc +++ /dev/null @@ -1,263 +0,0 @@ -// 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/label.h" - -#include "base/logging.h" -#include "tools/gn/err.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/value.h" - -namespace { - -// We print user visible label names with no trailing slash after the -// directory name. -std::string DirWithNoTrailingSlash(const SourceDir& dir) { - // Be careful not to trim if the input is just "/" or "//". - if (dir.value().size() > 2) - return dir.value().substr(0, dir.value().size() - 1); - return dir.value(); -} - -// Given the separate-out input (everything before the colon) in the dep rule, -// computes the final build rule. Sets err on failure. On success, -// |*used_implicit| will be set to whether the implicit current directory was -// used. The value is used only for generating error messages. -bool ComputeBuildLocationFromDep(const Value& input_value, - const SourceDir& current_dir, - const base::StringPiece& input, - SourceDir* result, - Err* err) { - // No rule, use the current locaton. - if (input.empty()) { - *result = current_dir; - return true; - } - - // Don't allow directories to start with a single slash. All labels must be - // in the source root. - if (input[0] == '/' && (input.size() == 1 || input[1] != '/')) { - *err = Err(input_value, "Label can't start with a single slash", - "Labels must be either relative (no slash at the beginning) or be " - "absolute\ninside the source root (two slashes at the beginning)."); - return false; - } - - *result = current_dir.ResolveRelativeDir(input); - return true; -} - -// Given the separated-out target name (after the colon) computes the final -// name, using the implicit name from the previously-generated -// computed_location if necessary. The input_value is used only for generating -// error messages. -bool ComputeTargetNameFromDep(const Value& input_value, - const SourceDir& computed_location, - const base::StringPiece& input, - std::string* result, - Err* err) { - if (!input.empty()) { - // Easy case: input is specified, just use it. - result->assign(input.data(), input.size()); - return true; - } - - const std::string& loc = computed_location.value(); - - // Use implicit name. The path will be "//", "//base/", "//base/i18n/", etc. - if (loc.size() <= 1) { - *err = Err(input_value, "This dependency name is empty"); - return false; - } - - size_t next_to_last_slash = loc.rfind('/', loc.size() - 2); - DCHECK(next_to_last_slash != std::string::npos); - result->assign(&loc[next_to_last_slash + 1], - loc.size() - next_to_last_slash - 2); - return true; -} - -// The original value is used only for error reporting, use the |input| as the -// input to this function (which may be a substring of the original value when -// we're parsing toolchains. -// -// If the output toolchain vars are NULL, then we'll report an error if we -// find a toolchain specified (this is used when recursively parsing toolchain -// labels which themselves can't have toolchain specs). -// -// We assume that the output variables are initialized to empty so we don't -// write them unless we need them to contain something. -// -// Returns true on success. On failure, the out* variables might be written to -// but shouldn't be used. -bool Resolve(const SourceDir& current_dir, - const Label& current_toolchain, - const Value& original_value, - const base::StringPiece& input, - SourceDir* out_dir, - std::string* out_name, - SourceDir* out_toolchain_dir, - std::string* out_toolchain_name, - Err* err) { - // To workaround the problem that StringPiece operator[] doesn't return a ref. - const char* input_str = input.data(); - - size_t path_separator = input.find_first_of(":("); - base::StringPiece location_piece; - base::StringPiece name_piece; - base::StringPiece toolchain_piece; - if (path_separator == std::string::npos) { - location_piece = input; - // Leave name & toolchain piece null. - } else { - location_piece = base::StringPiece(&input_str[0], path_separator); - - size_t toolchain_separator = input.find('(', path_separator); - if (toolchain_separator == std::string::npos) { - name_piece = base::StringPiece(&input_str[path_separator + 1], - input.size() - path_separator - 1); - // Leave location piece null. - } else if (!out_toolchain_dir) { - // Toolchain specified but not allows in this context. - *err = Err(original_value, "Toolchain has a toolchain.", - "Your toolchain definition (inside the parens) seems to itself " - "have a\ntoolchain. Don't do this."); - return false; - } else { - // Name piece is everything between the two separators. Note that the - // separators may be the same (e.g. "//foo(bar)" which means empty name. - if (toolchain_separator > path_separator) { - name_piece = base::StringPiece( - &input_str[path_separator + 1], - toolchain_separator - path_separator - 1); - } - - // Toolchain name should end in a ) and this should be the end of the - // string. - if (input[input.size() - 1] != ')') { - *err = Err(original_value, "Bad toolchain name.", - "Toolchain name must end in a \")\" at the end of the label."); - return false; - } - - // Subtract off the two parens to just get the toolchain name. - toolchain_piece = base::StringPiece( - &input_str[toolchain_separator + 1], - input.size() - toolchain_separator - 2); - } - } - - // Everything before the separator is the filename. - // We allow three cases: - // Absolute: "//foo:bar" -> /foo:bar - // Target in current file: ":foo" -> <currentdir>:foo - // Path with implicit name: "/foo" -> /foo:foo - if (location_piece.empty() && name_piece.empty()) { - // Can't use both implicit filename and name (":"). - *err = Err(original_value, "This doesn't specify a dependency."); - return false; - } - - if (!ComputeBuildLocationFromDep(original_value, current_dir, location_piece, - out_dir, err)) - return false; - - if (!ComputeTargetNameFromDep(original_value, *out_dir, name_piece, - out_name, err)) - return false; - - // Last, do the toolchains. - if (out_toolchain_dir) { - // Handle empty toolchain strings. We don't allow normal labels to be - // empty so we can't allow the recursive call of this function to do this - // check. - if (toolchain_piece.empty()) { - *out_toolchain_dir = current_toolchain.dir(); - *out_toolchain_name = current_toolchain.name(); - return true; - } else { - return Resolve(current_dir, current_toolchain, - original_value, toolchain_piece, - out_toolchain_dir, out_toolchain_name, NULL, NULL, err); - } - } - return true; -} - -} // namespace - -Label::Label() { -} - -Label::Label(const SourceDir& dir, - const base::StringPiece& name, - const SourceDir& toolchain_dir, - const base::StringPiece& toolchain_name) - : dir_(dir), - toolchain_dir_(toolchain_dir) { - name_.assign(name.data(), name.size()); - toolchain_name_.assign(toolchain_name.data(), toolchain_name.size()); -} - -Label::~Label() { -} - -// static -Label Label::Resolve(const SourceDir& current_dir, - const Label& current_toolchain, - const Value& input, - Err* err) { - Label ret; - if (input.type() != Value::STRING) { - *err = Err(input, "Dependency is not a string."); - return ret; - } - const std::string& input_string = input.string_value(); - if (input_string.empty()) { - *err = Err(input, "Dependency string is empty."); - return ret; - } - - if (!::Resolve(current_dir, current_toolchain, input, input_string, - &ret.dir_, &ret.name_, - &ret.toolchain_dir_, &ret.toolchain_name_, - err)) - return Label(); - return ret; -} - -Label Label::GetToolchainLabel() const { - return Label(toolchain_dir_, toolchain_name_, - SourceDir(), base::StringPiece()); -} - -std::string Label::GetUserVisibleName(bool include_toolchain) const { - std::string ret; - ret.reserve(dir_.value().size() + name_.size() + 1); - - if (dir_.is_null()) - return ret; - - ret = DirWithNoTrailingSlash(dir_); - ret.push_back(':'); - ret.append(name_); - - if (include_toolchain) { - ret.push_back('('); - if (!toolchain_dir_.is_null() && !toolchain_name_.empty()) { - ret.append(DirWithNoTrailingSlash(toolchain_dir_)); - ret.push_back(':'); - ret.append(toolchain_name_); - } - ret.push_back(')'); - } - return ret; -} - -std::string Label::GetUserVisibleName(const Label& default_toolchain) const { - bool include_toolchain = - default_toolchain.dir() != toolchain_dir_ || - default_toolchain.name() != toolchain_name_; - return GetUserVisibleName(include_toolchain); -} diff --git a/tools/gn/label.h b/tools/gn/label.h deleted file mode 100644 index b31117a..0000000 --- a/tools/gn/label.h +++ /dev/null @@ -1,116 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_LABEL_H_ -#define TOOLS_GN_LABEL_H_ - -#include "base/containers/hash_tables.h" -#include "build/build_config.h" -#include "tools/gn/source_dir.h" - -class Err; -class Value; - -// A label represents the name of a target or some other named thing in -// the source path. The label is always absolute and always includes a name -// part, so it starts with a slash, and has one colon. -class Label { - public: - Label(); - - // Makes a label given an already-separate out path and name. - // See also Resolve(). - Label(const SourceDir& dir, - const base::StringPiece& name, - const SourceDir& toolchain_dir, - const base::StringPiece& toolchain_name); - ~Label(); - - // Resolives a string from a build file that may be relative to the - // current directory into a fully qualified label. On failure returns an - // is_null() label and sets the error. - static Label Resolve(const SourceDir& current_dir, - const Label& current_toolchain, - const Value& input, - Err* err); - - bool is_null() const { return dir_.is_null(); } - - const SourceDir& dir() const { return dir_; } - const std::string& name() const { return name_; } - - const SourceDir& toolchain_dir() const { return toolchain_dir_; } - const std::string& toolchain_name() const { return toolchain_name_; } - Label GetToolchainLabel() const; - - // Formats this label in a way that we can present to the user or expose to - // other parts of the system. SourceDirs end in slashes, but the user - // expects names like "//chrome/renderer:renderer_config" when printed. The - // toolchain is optionally included. - std::string GetUserVisibleName(bool include_toolchain) const; - - // Like the above version, but automatically includes the toolchain if it's - // not the default one. Normally the user only cares about the toolchain for - // non-default ones, so this can make certain output more clear. - std::string GetUserVisibleName(const Label& default_toolchain) const; - - bool operator==(const Label& other) const { - return name_ == other.name_ && dir_ == other.dir_ && - toolchain_dir_ == other.toolchain_dir_ && - toolchain_name_ == other.toolchain_name_; - } - bool operator!=(const Label& other) const { - return !operator==(other); - } - bool operator<(const Label& other) const { - // TODO(brettw) could be optimized to avoid an extra full string check - // (one for operator==, one for <). - if (dir_ != other.dir_) - return dir_ < other.dir_; - if (name_ != other.name_) - return name_ < other.name_; - if (toolchain_dir_ != other.toolchain_dir_) - return toolchain_dir_ < other.toolchain_dir_; - return toolchain_name_ < other.toolchain_name_; - } - - // Returns true if the toolchain dir/name of this object matches some - // other object. - bool ToolchainsEqual(const Label& other) const { - return toolchain_dir_ == other.toolchain_dir_ && - toolchain_name_ == other.toolchain_name_; - } - - private: - SourceDir dir_; - std::string name_; - - SourceDir toolchain_dir_; - std::string toolchain_name_; -}; - -namespace BASE_HASH_NAMESPACE { - -#if defined(COMPILER_GCC) -template<> struct hash<Label> { - std::size_t operator()(const Label& v) const { - hash<std::string> stringhash; - return ((stringhash(v.dir().value()) * 131 + - stringhash(v.name())) * 131 + - stringhash(v.toolchain_dir().value())) * 131 + - stringhash(v.toolchain_name()); - } -}; -#elif defined(COMPILER_MSVC) -inline size_t hash_value(const Label& v) { - return ((hash_value(v.dir().value()) * 131 + - hash_value(v.name())) * 131 + - hash_value(v.toolchain_dir().value())) * 131 + - hash_value(v.toolchain_name()); -} -#endif // COMPILER... - -} // namespace BASE_HASH_NAMESPACE - -#endif // TOOLS_GN_LABEL_H_ diff --git a/tools/gn/label_unittest.cc b/tools/gn/label_unittest.cc deleted file mode 100644 index 74eb3da..0000000 --- a/tools/gn/label_unittest.cc +++ /dev/null @@ -1,88 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/err.h" -#include "tools/gn/label.h" -#include "tools/gn/value.h" - -namespace { - -struct ParseDepStringCase { - const char* cur_dir; - const char* str; - bool success; - const char* expected_dir; - const char* expected_name; - const char* expected_toolchain_dir; - const char* expected_toolchain_name; -}; - -} // namespace - -TEST(Label, Resolve) { - ParseDepStringCase cases[] = { - // cur input succ expected dir name tc dir tc name - { "//chrome/", "", false, "", "", "", "" }, - { "//chrome/", "/", false, "", "", "", "" }, - { "//chrome/", ":", false, "", "", "", "" }, - { "//chrome/", "/:", false, "", "", "", "" }, - { "//chrome/", "blah", true, "//chrome/blah/", "blah", "//t/", "d" }, - { "//chrome/", "blah:bar", true, "//chrome/blah/", "bar", "//t/", "d" }, - // No single-leading slash. - { "//chrome/", "/chrome:bar", false, "", "", "", "" }, - // No trailing slash. - { "//chrome/", "/chrome/:bar", false, "", "", "", "" }, - // Refers to root dir. - { "//chrome/", "//:bar", true, "//", "bar", "//t/", "d" }, - // Implicit directory - { "//chrome/", ":bar", true, "//chrome/", "bar", "//t/", "d" }, - { "//chrome/renderer/", ":bar", true, "//chrome/renderer/", "bar", "//t/", "d" }, - // Implicit names. - { "//chrome/", "//base", true, "//base/", "base", "//t/", "d" }, - { "//chrome/", "//base/i18n", true, "//base/i18n/", "i18n", "//t/", "d" }, - { "//chrome/", "//base/i18n:foo", true, "//base/i18n/", "foo", "//t/", "d" }, - // Toolchain parsing. - { "//chrome/", "//chrome:bar(//t:n)", true, "//chrome/", "bar", "//t/", "n" }, - { "//chrome/", "//chrome:bar(//t)", true, "//chrome/", "bar", "//t/", "t" }, - { "//chrome/", "//chrome:bar(//t:)", true, "//chrome/", "bar", "//t/", "t" }, - { "//chrome/", "//chrome:bar()", true, "//chrome/", "bar", "//t/", "d" }, - { "//chrome/", "//chrome:bar(foo)", true, "//chrome/", "bar", "//chrome/foo/", "foo" }, - { "//chrome/", "//chrome:bar(:foo)", true, "//chrome/", "bar", "//chrome/", "foo" }, - // TODO(brettw) it might be nice to make this an error: - //{ "//chrome/", "//chrome:bar())", false, "", "", "", "" }, - { "//chrome/", "//chrome:bar(//t:bar(tc))", false, "", "", "", "" }, - { "//chrome/", "//chrome:bar(()", false, "", "", "", "" }, - { "//chrome/", "(t:b)", false, "", "", "", "" }, - { "//chrome/", ":bar(//t/b)", true, "//chrome/", "bar", "//t/b/", "b" }, - { "//chrome/", ":bar(/t/b)", false, "", "", "", "" }, - { "//chrome/", ":bar(t/b)", true, "//chrome/", "bar", "//chrome/t/b/", "b" }, - }; - - Label default_toolchain(SourceDir("//t/"), "d", - SourceDir(), std::string()); - - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) { - const ParseDepStringCase& cur = cases[i]; - - std::string location, name; - Err err; - Value v(NULL, Value::STRING); - v.string_value() = cur.str; - Label result = - Label::Resolve(SourceDir(cur.cur_dir), default_toolchain, v, &err); - EXPECT_EQ(cur.success, !err.has_error()) << i << " " << cur.str; - if (!err.has_error() && cur.success) { - EXPECT_EQ(cur.expected_dir, result.dir().value()) - << i << " " << cur.str; - EXPECT_EQ(cur.expected_name, result.name()) - << i << " " << cur.str; - EXPECT_EQ(cur.expected_toolchain_dir, - result.toolchain_dir().value()) - << i << " " << cur.str; - EXPECT_EQ(cur.expected_toolchain_name, result.toolchain_name()) - << i << " " << cur.str; - } - } -} diff --git a/tools/gn/location.h b/tools/gn/location.h deleted file mode 100644 index 2055125..0000000 --- a/tools/gn/location.h +++ /dev/null @@ -1,77 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_LOCATION_H_ -#define TOOLS_GN_LOCATION_H_ - -#include <algorithm> - -#include "base/logging.h" - -class InputFile; - -// Represents a place in a source file. Used for error reporting. -class Location { - public: - Location() - : file_(NULL), - line_number_(-1), - char_offset_(-1) { - } - Location(const InputFile* file, int line_number, int char_offset) - : file_(file), - line_number_(line_number), - char_offset_(char_offset) { - } - - const InputFile* file() const { return file_; } - int line_number() const { return line_number_; } - int char_offset() const { return char_offset_; } - - bool operator==(const Location& other) const { - return other.file_ == file_ && - other.line_number_ == line_number_ && - other.char_offset_ == char_offset_; - } - - bool operator<(const Location& other) const { - DCHECK(file_ == other.file_); - if (line_number_ != other.line_number_) - return line_number_ < other.line_number_; - return char_offset_ < other.char_offset_; - } - - private: - const InputFile* file_; // Null when unset. - int line_number_; // -1 when unset. - int char_offset_; // -1 when unset. -}; - -// Represents a range in a source file. Used for error reporting. -// The end is exclusive i.e. [begin, end) -class LocationRange { - public: - LocationRange() {} - LocationRange(const Location& begin, const Location& end) - : begin_(begin), - end_(end) { - DCHECK(begin_.file() == end_.file()); - } - - const Location& begin() const { return begin_; } - const Location& end() const { return end_; } - - LocationRange Union(const LocationRange& other) const { - DCHECK(begin_.file() == other.begin_.file()); - return LocationRange( - begin_ < other.begin_ ? begin_ : other.begin_, - end_ < other.end_ ? other.end_ : end_); - } - - private: - Location begin_; - Location end_; -}; - -#endif // TOOLS_GN_LOCATION_H_ diff --git a/tools/gn/ninja_build_writer.cc b/tools/gn/ninja_build_writer.cc deleted file mode 100644 index a63765c..0000000 --- a/tools/gn/ninja_build_writer.cc +++ /dev/null @@ -1,165 +0,0 @@ -// 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/ninja_build_writer.h" - -#include <fstream> - -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/process/process_handle.h" -#include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" -#include "tools/gn/build_settings.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/input_file_manager.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/target.h" - -#if defined(OS_WIN) -#include <windows.h> -#endif - -namespace { - -std::string GetSelfInvocationCommand(const BuildSettings* build_settings) { -#if defined(OS_WIN) - wchar_t module[MAX_PATH]; - GetModuleFileName(NULL, module, MAX_PATH); - //result = "\"" + WideToUTF8(module) + "\""; - base::FilePath executable(module); -#elif defined(OS_MACOSX) - // FIXME(brettw) write this on Mac! - base::FilePath executable("gn"); -#else - base::FilePath executable = - base::GetProcessExecutablePath(base::GetCurrentProcessHandle()); -#endif - -/* - // Append the root path. - CommandLine* cmdline = CommandLine::ForCurrentProcess(); - result += " --root=\"" + FilePathToUTF8(settings->root_path()) + "\""; -*/ - - CommandLine cmdline(executable); - cmdline.AppendSwitchPath("--root", build_settings->root_path()); - - // TODO(brettw) append other parameters. - -#if defined(OS_WIN) - return WideToUTF8(cmdline.GetCommandLineString()); -#else - return cmdline.GetCommandLineString(); -#endif -} - -} // namespace - -NinjaBuildWriter::NinjaBuildWriter( - const BuildSettings* build_settings, - const std::vector<const Settings*>& all_settings, - const std::vector<const Target*>& default_toolchain_targets, - std::ostream& out) - : build_settings_(build_settings), - all_settings_(all_settings), - default_toolchain_targets_(default_toolchain_targets), - out_(out), - path_output_(build_settings->build_dir(), ESCAPE_NINJA, true), - helper_(build_settings) { -} - -NinjaBuildWriter::~NinjaBuildWriter() { -} - -void NinjaBuildWriter::Run() { - WriteNinjaRules(); - WriteSubninjas(); - WritePhonyAndAllRules(); -} - -// static -bool NinjaBuildWriter::RunAndWriteFile( - const BuildSettings* build_settings, - const std::vector<const Settings*>& all_settings, - const std::vector<const Target*>& default_toolchain_targets) { - base::FilePath ninja_file(build_settings->GetFullPath( - SourceFile(build_settings->build_dir().value() + "build.ninja"))); - file_util::CreateDirectory(ninja_file.DirName()); - - std::ofstream file; - file.open(FilePathToUTF8(ninja_file).c_str(), - std::ios_base::out | std::ios_base::binary); - if (file.fail()) - return false; - - NinjaBuildWriter gen(build_settings, all_settings, - default_toolchain_targets, file); - gen.Run(); - return true; -} - -void NinjaBuildWriter::WriteNinjaRules() { - out_ << "rule gn\n"; - out_ << " command = " << GetSelfInvocationCommand(build_settings_) << "\n"; - out_ << " description = GN the world\n\n"; - - out_ << "build build.ninja: gn"; - - // Input build files. - std::vector<SourceFile> input_files; - g_scheduler->input_file_manager()->GetAllInputFileNames(&input_files); - for (size_t i = 0; i < input_files.size(); i++) { - out_ << " "; - path_output_.WriteFile(out_, input_files[i]); - } - - // Other files read by the build. - std::vector<SourceFile> other_files = g_scheduler->GetGenDependencies(); - for (size_t i = 0; i < other_files.size(); i++) { - out_ << " "; - path_output_.WriteFile(out_, other_files[i]); - } - - out_ << std::endl << std::endl; -} - -void NinjaBuildWriter::WriteSubninjas() { - for (size_t i = 0; i < all_settings_.size(); i++) { - out_ << "subninja "; - path_output_.WriteFile(out_, - helper_.GetNinjaFileForToolchain(all_settings_[i])); - out_ << std::endl; - } - out_ << std::endl; -} - -void NinjaBuildWriter::WritePhonyAndAllRules() { - std::string all_rules; - - // Write phony rules for the default toolchain (don't do other toolchains or - // we'll get naming conflicts). - for (size_t i = 0; i < default_toolchain_targets_.size(); i++) { - const Target* target = default_toolchain_targets_[i]; - if (target->output_type() == Target::NONE) - continue; // Nothing to generate. - - OutputFile target_file = helper_.GetTargetOutputFile(target); - if (target_file.value() != target->label().name()) { - out_ << "build " << target->label().name() << ": phony "; - path_output_.WriteFile(out_, target_file); - out_ << std::endl; - } - - if (!all_rules.empty()) - all_rules.append(" $\n "); - all_rules.append(target_file.value()); - } - - if (!all_rules.empty()) { - out_ << "\nbuild all: phony " << all_rules << std::endl; - out_ << "default all" << std::endl; - } -} - diff --git a/tools/gn/ninja_build_writer.h b/tools/gn/ninja_build_writer.h deleted file mode 100644 index 85548df..0000000 --- a/tools/gn/ninja_build_writer.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_NINJA_BUILD_WRITER_H_ -#define TOOLS_GN_NINJA_BUILD_WRITER_H_ - -#include <iosfwd> -#include <vector> - -#include "tools/gn/ninja_helper.h" -#include "tools/gn/path_output.h" - -class BuildSettings; -class Settings; -class Target; - -// Generates the toplevel "build.ninja" file. This references the individual -// toolchain files and lists all input .gn files as dependencies of the -// build itself. -class NinjaBuildWriter { - public: - static bool RunAndWriteFile( - const BuildSettings* settings, - const std::vector<const Settings*>& all_settings, - const std::vector<const Target*>& default_toolchain_targets); - - private: - NinjaBuildWriter(const BuildSettings* settings, - const std::vector<const Settings*>& all_settings, - const std::vector<const Target*>& default_toolchain_targets, - std::ostream& out); - ~NinjaBuildWriter(); - - void Run(); - - void WriteNinjaRules(); - void WriteSubninjas(); - void WritePhonyAndAllRules(); - - const BuildSettings* build_settings_; - std::vector<const Settings*> all_settings_; - std::vector<const Target*> default_toolchain_targets_; - std::ostream& out_; - PathOutput path_output_; - - NinjaHelper helper_; - - DISALLOW_COPY_AND_ASSIGN(NinjaBuildWriter); -}; - -#endif // TOOLS_GN_NINJA_BUILD_GENERATOR_H_ - diff --git a/tools/gn/ninja_helper.cc b/tools/gn/ninja_helper.cc deleted file mode 100644 index c27c0e4..0000000 --- a/tools/gn/ninja_helper.cc +++ /dev/null @@ -1,165 +0,0 @@ -// 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/ninja_helper.h" - -#include "base/logging.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/string_utils.h" -#include "tools/gn/target.h" - -namespace { - -const char kLibDirWithSlash[] = "lib"; -const char kObjectDirNoSlash[] = "obj"; - -} // namespace - -NinjaHelper::NinjaHelper(const BuildSettings* build_settings) - : build_settings_(build_settings) { - build_to_src_no_last_slash_ = build_settings->build_to_source_dir_string(); - if (!build_to_src_no_last_slash_.empty() && - build_to_src_no_last_slash_[build_to_src_no_last_slash_.size() - 1] == - '/') - build_to_src_no_last_slash_.resize(build_to_src_no_last_slash_.size() - 1); - - build_to_src_system_no_last_slash_ = build_to_src_no_last_slash_; - ConvertPathToSystem(&build_to_src_system_no_last_slash_); -} - -NinjaHelper::~NinjaHelper() { -} - -std::string NinjaHelper::GetTopleveOutputDir() const { - return kObjectDirNoSlash; -} - -std::string NinjaHelper::GetTargetOutputDir(const Target* target) const { - return kObjectDirNoSlash + target->label().dir().SourceAbsoluteWithOneSlash(); -} - -OutputFile NinjaHelper::GetNinjaFileForTarget(const Target* target) const { - OutputFile ret(target->settings()->toolchain_output_subdir()); - ret.value().append(kObjectDirNoSlash); - AppendStringPiece(&ret.value(), - target->label().dir().SourceAbsoluteWithOneSlash()); - ret.value().append(target->label().name()); - ret.value().append(".ninja"); - return ret; -} - -OutputFile NinjaHelper::GetNinjaFileForToolchain( - const Settings* settings) const { - OutputFile ret; - ret.value().append(settings->toolchain_output_subdir().value()); - ret.value().append("toolchain.ninja"); - return ret; -} - -// In Python, GypPathToUniqueOutput does the qualification. The only case where -// the Python version doesn't qualify the name is for target outputs, which we -// handle in a separate function. -OutputFile NinjaHelper::GetOutputFileForSource( - const Target* target, - const SourceFile& source, - SourceFileType type) const { - // Extract the filename and remove the extension (keep the dot). - base::StringPiece filename = FindFilename(&source.value()); - std::string name(filename.data(), filename.size()); - size_t extension_offset = FindExtensionOffset(name); - CHECK(extension_offset != std::string::npos); - name.resize(extension_offset); - - // Append the new extension. - switch (type) { - case SOURCE_ASM: - case SOURCE_C: - case SOURCE_CC: - case SOURCE_M: - case SOURCE_MM: - name.append(target->settings()->IsWin() ? "obj" : "o"); - break; - - case SOURCE_RC: - name.append("res"); - break; - - case SOURCE_H: - case SOURCE_UNKNOWN: - NOTREACHED(); - return OutputFile(); - } - - // Use the scheme <path>/<target>.<name>.<extension> so that all output - // names are unique to different targets. - OutputFile ret(kObjectDirNoSlash); - - // Find the directory, assume it starts with two slashes, and trim to one. - base::StringPiece dir = FindDir(&source.value()); - CHECK(dir.size() >= 2 && dir[0] == '/' && dir[1] == '/') - << "Source file isn't in the source repo: " << dir; - AppendStringPiece(&ret.value(), dir.substr(1)); - - ret.value().append(target->label().name()); - ret.value().append("."); - ret.value().append(name); - return ret; -} - -OutputFile NinjaHelper::GetTargetOutputFile(const Target* target) const { - OutputFile ret; - if (target->output_type() == Target::NONE) { - NOTREACHED(); - return ret; - } - - const char* extension; - if (target->output_type() == Target::NONE || - target->output_type() == Target::COPY_FILES || - target->output_type() == Target::CUSTOM) { - extension = "stamp"; - } else { - extension = GetExtensionForOutputType(target->output_type(), - target->settings()->target_os()); - } - - // Everything goes into the toolchain directory (which will be empty for the - // default toolchain, and will end in a slash otherwise). - ret.value().append(target->settings()->toolchain_output_subdir().value()); - - // Binaries and loadable libraries go into the toolchain root. - if (target->output_type() == Target::EXECUTABLE || - target->output_type() == Target::LOADABLE_MODULE || - (target->settings()->IsMac() && - (target->output_type() == Target::SHARED_LIBRARY || - target->output_type() == Target::STATIC_LIBRARY)) || - (target->settings()->IsWin() && - target->output_type() == Target::SHARED_LIBRARY)) { - // Generate a name like "<toolchain>/<name>.<extension>". - ret.value().append(target->label().name()); - ret.value().push_back('.'); - ret.value().append(extension); - return ret; - } - - // Libraries go into the library subdirectory like - // "<toolchain>/lib/<name>.<extension>". - if (target->output_type() == Target::SHARED_LIBRARY) { - ret.value().append(kLibDirWithSlash); - ret.value().append(target->label().name()); - ret.value().push_back('.'); - ret.value().append(extension); - return ret; - } - - // Everything else goes next to the target's .ninja file like - // "<toolchain>/obj/<path>/<name>.<extension>". - ret.value().append(kObjectDirNoSlash); - AppendStringPiece(&ret.value(), - target->label().dir().SourceAbsoluteWithOneSlash()); - ret.value().append(target->label().name()); - ret.value().push_back('.'); - ret.value().append(extension); - return ret; -} diff --git a/tools/gn/ninja_helper.h b/tools/gn/ninja_helper.h deleted file mode 100644 index 5bea29e..0000000 --- a/tools/gn/ninja_helper.h +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_NINJA_HELPER_H_ -#define TOOLS_GN_NINJA_HELPER_H_ - -#include <iosfwd> -#include <string> - -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/output_file.h" - -class BuildSettings; -class SourceDir; -class SourceFile; -class Target; - -// NinjaHelper ----------------------------------------------------------------- - -class NinjaHelper { - public: - NinjaHelper(const BuildSettings* build_settings); - ~NinjaHelper(); - - // Ends in a slash. - std::string GetTopleveOutputDir() const; - - // Ends in a slash. - std::string GetTargetOutputDir(const Target* target) const; - - // Example: "base/base.ninja". The string version will not be escaped, and - // will always have slashes for path separators. - OutputFile GetNinjaFileForTarget(const Target* target) const; - - // Returns the name of the root .ninja file for the given toolchain. - OutputFile GetNinjaFileForToolchain(const Settings* settings) const; - - // Given a source file relative to the source root, returns the output - // filename. - OutputFile GetOutputFileForSource(const Target* target, - const SourceFile& source, - SourceFileType type) const; - - // Returns the filename produced by the given output. - // - // Some targets make multiple files (like a .dll and an import library). This - // function returns the name of the file other targets should depend on and - // link to (so in this example, the import library). - OutputFile GetTargetOutputFile(const Target* target) const; - - // Returns the relative directory in either slashes or the system separator - // from the ninja directory (e.g. "out/Debug") to the source root (e.g. - // "../.."). It has no terminating slash. - const std::string& build_to_src_no_last_slash() const { - return build_to_src_no_last_slash_; - } - const std::string& build_to_src_system_no_last_slash() const { - return build_to_src_system_no_last_slash_; - } - - private: - const BuildSettings* build_settings_; - - std::string build_to_src_no_last_slash_; - std::string build_to_src_system_no_last_slash_; - - DISALLOW_COPY_AND_ASSIGN(NinjaHelper); -}; - -#endif // TOOLS_GN_NINJA_HELPER_H_ diff --git a/tools/gn/ninja_helper_unittest.cc b/tools/gn/ninja_helper_unittest.cc deleted file mode 100644 index 4aec032..0000000 --- a/tools/gn/ninja_helper_unittest.cc +++ /dev/null @@ -1,73 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" - -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/ninja_helper.h" -#include "tools/gn/settings.h" -#include "tools/gn/target.h" -#include "tools/gn/toolchain.h" - -namespace { - -class HelperSetterUpper { - public: - HelperSetterUpper() - : build_settings(), - toolchain(Label(SourceDir("//"), "tc", SourceDir(), std::string())), - settings(&build_settings, &toolchain, std::string()), - target(&settings, - Label(SourceDir("//tools/gn/"), "name", - SourceDir(), std::string())) { - settings.set_target_os(Settings::WIN); - - // Output going to "out/Debug". - build_settings.SetBuildDir(SourceDir("/out/Debug/")); - - // Our source target is in "tools/gn". - target.set_output_type(Target::EXECUTABLE); - } - - BuildSettings build_settings; - Toolchain toolchain; - Settings settings; - Target target; -}; - -} // namespace - -TEST(NinjaHelper, GetNinjaFileForTarget) { - HelperSetterUpper setup; - NinjaHelper helper(&setup.build_settings); - - // Default toolchain. - EXPECT_EQ(OutputFile("obj/tools/gn/name.ninja").value(), - helper.GetNinjaFileForTarget(&setup.target).value()); -} - -TEST(NinjaHelper, GetOutputFileForSource) { - HelperSetterUpper setup; - NinjaHelper helper(&setup.build_settings); - - // On Windows, expect ".obj" - EXPECT_EQ(OutputFile("obj/tools/gn/name.foo.obj").value(), - helper.GetOutputFileForSource(&setup.target, - SourceFile("//tools/gn/foo.cc"), - SOURCE_CC).value()); -} - -TEST(NinjaHelper, GetTargetOutputFile) { - HelperSetterUpper setup; - NinjaHelper helper(&setup.build_settings); - EXPECT_EQ(OutputFile("name.exe"), - helper.GetTargetOutputFile(&setup.target)); - - // Static library on Windows goes alongside the object files. - setup.target.set_output_type(Target::STATIC_LIBRARY); - EXPECT_EQ(OutputFile("obj/tools/gn/name.lib"), - helper.GetTargetOutputFile(&setup.target)); - - // TODO(brettw) test output to library and other OS types. -} diff --git a/tools/gn/ninja_target_writer.cc b/tools/gn/ninja_target_writer.cc deleted file mode 100644 index ed2d09d..0000000 --- a/tools/gn/ninja_target_writer.cc +++ /dev/null @@ -1,550 +0,0 @@ -// 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/ninja_target_writer.h" - -#include <fstream> -#include <sstream> - -#include "base/file_util.h" -#include "base/logging.h" -#include "base/strings/string_util.h" -#include "tools/gn/config_values_extractors.h" -#include "tools/gn/err.h" -#include "tools/gn/escape.h" -#include "tools/gn/file_template.h" -#include "tools/gn/location.h" -#include "tools/gn/path_output.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/string_utils.h" -#include "tools/gn/target.h" - -namespace { - -static const char kCustomTargetSourceKey[] = "{{source}}"; -static const char kCustomTargetSourceNamePartKey[] = "{{source_name_part}}"; - -struct DefineWriter { - void operator()(const std::string& s, std::ostream& out) const { - out << " -D" << s; - } -}; - -struct IncludeWriter { - IncludeWriter(PathOutput& path_output, - const NinjaHelper& h) - : helper(h), - path_output_(path_output), - old_inhibit_quoting_(path_output.inhibit_quoting()) { - // Inhibit quoting since we'll put quotes around the whole thing ourselves. - // Since we're writing in NINJA escaping mode, this won't actually do - // anything, but I think we may need to change to shell-and-then-ninja - // escaping for this in the future. - path_output_.set_inhibit_quoting(true); - } - ~IncludeWriter() { - path_output_.set_inhibit_quoting(old_inhibit_quoting_); - } - - void operator()(const SourceDir& d, std::ostream& out) const { - out << " \"-I"; - // It's important not to include the trailing slash on directories or on - // Windows it will be a backslash and the compiler might think we're - // escaping the quote! - path_output_.WriteDir(out, d, PathOutput::DIR_NO_LAST_SLASH); - out << "\""; - } - - const NinjaHelper& helper; - PathOutput& path_output_; - bool old_inhibit_quoting_; // So we can put the PathOutput back. -}; - -} // namespace - -NinjaTargetWriter::NinjaTargetWriter(const Target* target, std::ostream& out) - : settings_(target->settings()), - target_(target), - out_(out), - path_output_(settings_->build_settings()->build_dir(), - ESCAPE_NINJA, true), - helper_(settings_->build_settings()) { -} - -NinjaTargetWriter::~NinjaTargetWriter() { -} - -void NinjaTargetWriter::Run() { - out_ << "arch = environment.x86\n"; - - if (target_->output_type() == Target::COPY_FILES) { - WriteCopyRules(); - } else if (target_->output_type() == Target::CUSTOM) { - WriteCustomRules(); - } else { - WriteCompilerVars(); - - std::vector<OutputFile> obj_files; - WriteSources(&obj_files); - - WriteLinkerStuff(obj_files); - } -} - -// static -void NinjaTargetWriter::RunAndWriteFile(const Target* target) { - if (target->output_type() == Target::NONE) - return; - - const Settings* settings = target->settings(); - NinjaHelper helper(settings->build_settings()); - - base::FilePath ninja_file(settings->build_settings()->GetFullPath( - helper.GetNinjaFileForTarget(target).GetSourceFile( - settings->build_settings()))); - - file_util::CreateDirectory(ninja_file.DirName()); - - // It's rediculously faster to write to a string and then write that to - // disk in one operation than to use an fstream here. - std::stringstream file; - if (file.fail()) { - g_scheduler->FailWithError( - Err(Location(), "Error writing ninja file.", - "Unable to open \"" + FilePathToUTF8(ninja_file) + "\"\n" - "for writing.")); - return; - } - - NinjaTargetWriter gen(target, file); - gen.Run(); - - std::string contents = file.str(); - file_util::WriteFile(ninja_file, contents.c_str(), contents.size()); -} - -void NinjaTargetWriter::WriteCopyRules() { - // The dest dir should be inside the output dir so we can just remove the - // prefix and get ninja-relative paths. - const std::string& output_dir = - settings_->build_settings()->build_dir().value(); - const std::string& dest_dir = target_->destdir().value(); - DCHECK(StartsWithASCII(dest_dir, output_dir, true)); - std::string relative_dest_dir(&dest_dir[output_dir.size()], - dest_dir.size() - output_dir.size()); - - const Target::FileList& sources = target_->sources(); - std::vector<OutputFile> dest_files; - dest_files.reserve(sources.size()); - - // Write out rules for each file copied. - for (size_t i = 0; i < sources.size(); i++) { - const SourceFile& input_file = sources[i]; - - // The files should have the same name but in the dest dir. - base::StringPiece name_part = FindFilename(&input_file.value()); - OutputFile dest_file(relative_dest_dir); - AppendStringPiece(&dest_file.value(), name_part); - - dest_files.push_back(dest_file); - - out_ << "build "; - path_output_.WriteFile(out_, dest_file); - out_ << ": copy "; - path_output_.WriteFile(out_, input_file); - out_ << std::endl; - } - - // Write out the rule for the target to copy all of them. - out_ << std::endl << "build "; - path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_)); - out_ << ": stamp"; - for (size_t i = 0; i < dest_files.size(); i++) { - out_ << " "; - path_output_.WriteFile(out_, dest_files[i]); - } - out_ << std::endl; - - // TODO(brettw) need some kind of stamp file for depending on this, as well - // as order_only=prebuild. -} - -void NinjaTargetWriter::WriteCustomRules() { - // Make a unique name for this rule. - std::string target_label = target_->label().GetUserVisibleName(true); - std::string custom_rule_name(target_label); - ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name); - custom_rule_name.append("_rule"); - - // Run the script from the dir of the BUILD file. This has no trailing - // slash. - const SourceDir& script_cd = target_->label().dir(); - std::string script_cd_to_root = InvertDir(script_cd); - if (script_cd_to_root.empty()) { - script_cd_to_root = "."; - } else { - // Remove trailing slash - DCHECK(script_cd_to_root[script_cd_to_root.size() - 1] == '/'); - script_cd_to_root.resize(script_cd_to_root.size() - 1); - } - - std::string script_relative_to_cd = - script_cd_to_root + target_->script().value(); - - bool no_sources = target_->sources().empty(); - - // Use a unique name for the response file when there are multiple build - // steps so that they don't stomp on each other. - std::string rspfile = custom_rule_name; - if (!no_sources) - rspfile += ".$unique_name"; - rspfile += ".rsp"; - - // First write the custom rule. - out_ << "rule " << custom_rule_name << std::endl; - out_ << " command = $pythonpath gyp-win-tool action-wrapper $arch " - << rspfile << " "; - path_output_.WriteDir(out_, script_cd, PathOutput::DIR_NO_LAST_SLASH); - out_ << std::endl; - out_ << " description = CUSTOM " << target_label << std::endl; - out_ << " restat = 1" << std::endl; - out_ << " rspfile = " << rspfile << std::endl; - - // The build command goes in the rsp file. - out_ << " rspfile_content = $pythonpath " << script_relative_to_cd; - for (size_t i = 0; i < target_->script_args().size(); i++) { - const std::string& arg = target_->script_args()[i]; - out_ << " "; - WriteCustomArg(arg); - } - out_ << std::endl << std::endl; - - // Precompute the common dependencies for each step. This includes the - // script itself (changing the script should force a rebuild) and any data - // files. - std::ostringstream common_deps_stream; - path_output_.WriteFile(common_deps_stream, target_->script()); - const Target::FileList& datas = target_->data(); - for (size_t i = 0; i < datas.size(); i++) { - common_deps_stream << " "; - path_output_.WriteFile(common_deps_stream, datas[i]); - } - const std::string& common_deps = common_deps_stream.str(); - - // Collects all output files for writing below. - std::vector<OutputFile> output_files; - - if (no_sources) { - // No sources, write a rule that invokes the script once with the - // outputs as outputs, and the data as inputs. - out_ << "build"; - const Target::FileList& outputs = target_->outputs(); - for (size_t i = 0; i < outputs.size(); i++) { - OutputFile output_path( - RemovePrefix(outputs[i].value(), - settings_->build_settings()->build_dir().value())); - output_files.push_back(output_path); - out_ << " "; - path_output_.WriteFile(out_, output_path); - } - out_ << ": " << custom_rule_name << " " << common_deps << std::endl; - } else { - // Write separate rules for each input source file. - WriteCustomSourceRules(custom_rule_name, common_deps, script_cd, - script_cd_to_root, &output_files); - } - out_ << std::endl; - - // Last write a stamp rule to collect all outputs. - out_ << "build "; - path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_)); - out_ << ": stamp"; - for (size_t i = 0; i < output_files.size(); i++) { - out_ << " "; - path_output_.WriteFile(out_, output_files[i]); - } - out_ << std::endl; -} - -void NinjaTargetWriter::WriteCustomArg(const std::string& arg) { - // This can be optimized if it's called a lot. - EscapeOptions options; - options.mode = ESCAPE_NINJA; - std::string output_str = EscapeString(arg, options); - - // Do this substitution after escaping our our $ will be escaped (which we - // don't want). - ReplaceSubstringsAfterOffset(&output_str, 0, FileTemplate::kSource, - "${source}"); - ReplaceSubstringsAfterOffset(&output_str, 0, FileTemplate::kSourceNamePart, - "${source_name_part}"); - out_ << output_str; -} - -void NinjaTargetWriter::WriteCustomSourceRules( - const std::string& custom_rule_name, - const std::string& common_deps, - const SourceDir& script_cd, - const std::string& script_cd_to_root, - std::vector<OutputFile>* output_files) { - // Construct the template for generating the output files from each source. - const Target::FileList& outputs = target_->outputs(); - std::vector<std::string> output_template_args; - for (size_t i = 0; i < outputs.size(); i++) { - // All outputs should be in the output dir. - output_template_args.push_back( - RemovePrefix(outputs[i].value(), - settings_->build_settings()->build_dir().value())); - } - FileTemplate output_template(output_template_args); - - // Prevent re-allocating each time by initializing outside the loop. - std::vector<std::string> output_template_result; - - // Path output formatter for wrigin source paths passed to the script. - PathOutput script_source_path_output(script_cd, ESCAPE_SHELL, true); - - const Target::FileList& sources = target_->sources(); - for (size_t i = 0; i < sources.size(); i++) { - // Write outputs for this source file computed by the template. - out_ << "build"; - output_template.ApplyString(sources[i].value(), &output_template_result); - for (size_t out_i = 0; out_i < output_template_result.size(); out_i++) { - OutputFile output_path(output_template_result[out_i]); - output_files->push_back(output_path); - out_ << " "; - path_output_.WriteFile(out_, output_path); - } - - out_ << ": " << custom_rule_name - << " " << common_deps - << " "; - path_output_.WriteFile(out_, sources[i]); - out_ << std::endl; - - out_ << " unique_name = " << i << std::endl; - - // The source file here should be relative to the script directory since - // this is the variable passed to the script. Here we slightly abuse the - // OutputFile object by putting a non-output-relative path in it to signal - // that the PathWriter should not prepend directories. - out_ << " source = "; - script_source_path_output.WriteFile(out_, sources[i]); - out_ << std::endl; - - out_ << " source_name_part = " - << FindFilenameNoExtension(&sources[i].value()).as_string() - << std::endl; - } -} - -void NinjaTargetWriter::WriteCompilerVars() { - // Defines. - out_ << "defines ="; - RecursiveTargetConfigToStream(target_, &ConfigValues::defines, - DefineWriter(), out_); - out_ << std::endl; - - // Includes. - out_ << "includes ="; - RecursiveTargetConfigToStream(target_, &ConfigValues::includes, - IncludeWriter(path_output_, helper_), out_); - - out_ << std::endl; - - // C flags and friends. - out_ << "cflags ="; - RecursiveTargetConfigStringsToStream(target_, &ConfigValues::cflags, out_); - out_ << std::endl; - out_ << "cflags_c ="; - RecursiveTargetConfigStringsToStream(target_, &ConfigValues::cflags_c, out_); - out_ << std::endl; - out_ << "cflags_cc ="; - RecursiveTargetConfigStringsToStream(target_, &ConfigValues::cflags_cc, out_); - out_ << std::endl; - - out_ << std::endl; -} - -void NinjaTargetWriter::WriteSources( - std::vector<OutputFile>* object_files) { - const Target::FileList& sources = target_->sources(); - object_files->reserve(sources.size()); - - for (size_t i = 0; i < sources.size(); i++) { - const SourceFile& input_file = sources[i]; - - SourceFileType input_file_type = GetSourceFileType(input_file, - settings_->target_os()); - if (input_file_type == SOURCE_UNKNOWN) - continue; // Skip unknown file types. - const char* command = GetCommandForSourceType(input_file_type); - if (!command) - continue; // Skip files not needing compilation. - - OutputFile output_file = helper_.GetOutputFileForSource( - target_, input_file, input_file_type); - object_files->push_back(output_file); - - out_ << "build "; - path_output_.WriteFile(out_, output_file); - out_ << ": " << command << " "; - path_output_.WriteFile(out_, input_file); - out_ << std::endl; - } - out_ << std::endl; -} - -void NinjaTargetWriter::WriteLinkerStuff( - const std::vector<OutputFile>& object_files) { - // Manifest file on Windows. - // TODO(brettw) this seems not to be necessary for static libs, skip in - // that case? - OutputFile windows_manifest; - if (settings_->IsWin()) { - windows_manifest.value().assign(helper_.GetTargetOutputDir(target_)); - windows_manifest.value().append(target_->label().name()); - windows_manifest.value().append(".intermediate.manifest"); - out_ << "manifests = "; - path_output_.WriteFile(out_, windows_manifest); - out_ << std::endl; - } - - // Linker flags, append manifest flag on Windows to reference our file. - out_ << "ldflags ="; - RecursiveTargetConfigStringsToStream(target_, &ConfigValues::ldflags, out_); - if (settings_->IsWin()) - out_ << " /MANIFEST /ManifestFile:"; - path_output_.WriteFile(out_, windows_manifest); - { // HACK ERASEME BRETTW FIXME - out_ << " /DEBUG /MACHINE:X86 /LIBPATH:\"C:\\Program Files (x86)\\Windows Kits\\8.0\\Lib\\win8\\um\\x86\" /DELAYLOAD:dbghelp.dll /DELAYLOAD:dwmapi.dll /DELAYLOAD:shell32.dll /DELAYLOAD:uxtheme.dll /safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat /SUBSYSTEM:CONSOLE /INCREMENTAL /FIXED:NO /DYNAMICBASE:NO wininet.lib dnsapi.lib version.lib msimg32.lib ws2_32.lib usp10.lib psapi.lib dbghelp.lib winmm.lib shlwapi.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib user32.lib uuid.lib odbc32.lib odbccp32.lib delayimp.lib /NXCOMPAT"; - } - out_ << std::endl; - - // Libraries to link. - out_ << "libs =" << std::endl; - - // The external output file is the one that other libs depend on. - OutputFile external_output_file = helper_.GetTargetOutputFile(target_); - - // The internal output file is the "main thing" we think we're making. In - // the case of shared libraries, this is the shared library and the external - // output file is the import library. In other cases, the internal one and - // the external one are the same. - OutputFile internal_output_file; - if (target_->output_type() == Target::SHARED_LIBRARY) { - if (settings_->IsWin()) { - internal_output_file = OutputFile(target_->label().name() + ".dll"); - } else { - NOTREACHED(); // TODO(brettw) write this. - } - } else { - internal_output_file = external_output_file; - } - - // TODO(brettw) should we append data files to this? - - // In Python see "self.ninja.build(output, command, input," - out_ << "build "; - path_output_.WriteFile(out_, internal_output_file); - if (external_output_file != internal_output_file) { - out_ << " "; - path_output_.WriteFile(out_, external_output_file); - } - out_ << ": " << GetCommandForTargetType(); - for (size_t i = 0; i < object_files.size(); i++) { - out_ << " "; - path_output_.WriteFile(out_, object_files[i]); - } - - if (target_->output_type() == Target::EXECUTABLE || - target_->output_type() == Target::SHARED_LIBRARY || - target_->output_type() == Target::LOADABLE_MODULE) { - const std::vector<const Target*>& deps = target_->deps(); - const std::set<const Target*>& inherited = target_->inherited_libraries(); - - // Now append linkable libraries to the linker command. - for (size_t i = 0; i < deps.size(); i++) { - if (deps[i]->IsLinkable() && - inherited.find(deps[i]) == inherited.end()) { - out_ << " "; - path_output_.WriteFile(out_, - helper_.GetTargetOutputFile(target_->deps()[i])); - } - } - for (std::set<const Target*>::const_iterator i = inherited.begin(); - i != inherited.end(); ++i) { - out_ << " "; - path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i)); - } - } - out_ << std::endl; - - if (target_->output_type() == Target::SHARED_LIBRARY) { - out_ << " soname = "; - path_output_.WriteFile(out_, internal_output_file); - out_ << std::endl; - - out_ << " lib = "; - path_output_.WriteFile(out_, internal_output_file); - out_ << std::endl; - - out_ << " dll = "; - path_output_.WriteFile(out_, internal_output_file); - out_ << std::endl; - - if (settings_->IsWin()) { - out_ << " implibflag = /IMPLIB:"; - path_output_.WriteFile(out_, external_output_file); - out_ << std::endl; - } - } - - // TODO(brettw) postbuild steps here. - - out_ << std::endl; -} - -const char* NinjaTargetWriter::GetCommandForSourceType( - SourceFileType type) const { - if (type == SOURCE_C) - return "cc"; - if (type == SOURCE_CC) - return "cxx"; - - // TODO(brettw) asm files. - - if (settings_->IsMac()) { - if (type == SOURCE_M) - return "objc"; - if (type == SOURCE_MM) - return "objcxx"; - } - - if (settings_->IsWin()) { - if (type == SOURCE_RC) - return "rc"; - } - - // TODO(brettw) stuff about "S" files on non-Windows. - return NULL; -} - -const char* NinjaTargetWriter::GetCommandForTargetType() const { - if (target_->output_type() == Target::NONE) { - NOTREACHED(); - return ""; - } - - if (target_->output_type() == Target::STATIC_LIBRARY) { - // TODO(brettw) stuff about standalong static libraryes on Unix in - // WriteTarget in the Python one, and lots of postbuild steps. - return "alink"; - } - - if (target_->output_type() == Target::SHARED_LIBRARY) - return "solink"; - - return "link"; -} diff --git a/tools/gn/ninja_target_writer.h b/tools/gn/ninja_target_writer.h deleted file mode 100644 index 5e6827d..0000000 --- a/tools/gn/ninja_target_writer.h +++ /dev/null @@ -1,67 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_NINJA_TARGET_WRITER_H_ -#define TOOLS_GN_NINJA_TARGET_WRITER_H_ - -#include <iosfwd> -#include <string> - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/ninja_helper.h" -#include "tools/gn/path_output.h" -#include "tools/gn/settings.h" - -class Target; - -// Generates one target's ".ninja" file. The toplevel "build.ninja" file is -// generated by the NinjaBuildGenerator. -class NinjaTargetWriter { - public: - NinjaTargetWriter(const Target* target, std::ostream& out); - ~NinjaTargetWriter(); - - void Run(); - - static void RunAndWriteFile(const Target* target); - - private: - void WriteCopyRules(); - - void WriteCustomRules(); - void WriteCustomArg(const std::string& arg); - - // Writs the rules for compiling each source, writing all output files - // to the given vector. - // - // common_deps is a precomputed string of all ninja files that are common - // to each build step. This is added to each one. - void WriteCustomSourceRules(const std::string& custom_rule_name, - const std::string& common_deps, - const SourceDir& script_cd, - const std::string& script_cd_to_root, - std::vector<OutputFile>* output_files); - - void WriteCompilerVars(); - void WriteSources(std::vector<OutputFile>* object_files); - void WriteLinkerStuff(const std::vector<OutputFile>& object_files); - - // Returns NULL if the source type should not be compiled on this target. - const char* GetCommandForSourceType(SourceFileType type) const; - - const char* GetCommandForTargetType() const; - - const Settings* settings_; // Non-owning. - const Target* target_; // Non-owning. - std::ostream& out_; - PathOutput path_output_; - - NinjaHelper helper_; - - DISALLOW_COPY_AND_ASSIGN(NinjaTargetWriter); -}; - -#endif // TOOLS_GN_NINJA_TARGET_WRITER_H_ diff --git a/tools/gn/ninja_toolchain_writer.cc b/tools/gn/ninja_toolchain_writer.cc deleted file mode 100644 index 0e38b8c..0000000 --- a/tools/gn/ninja_toolchain_writer.cc +++ /dev/null @@ -1,94 +0,0 @@ -// 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/ninja_toolchain_writer.h" - -#include <fstream> - -#include "base/file_util.h" -#include "base/strings/stringize_macros.h" -#include "tools/gn/build_settings.h" -#include "tools/gn/settings.h" -#include "tools/gn/target.h" -#include "tools/gn/toolchain.h" - -NinjaToolchainWriter::NinjaToolchainWriter( - const Settings* settings, - const std::vector<const Target*>& targets, - std::ostream& out) - : settings_(settings), - targets_(targets), - out_(out), - path_output_(settings_->build_settings()->build_dir(), - ESCAPE_NINJA, true), - helper_(settings->build_settings()) { -} - -NinjaToolchainWriter::~NinjaToolchainWriter() { -} - -void NinjaToolchainWriter::Run() { - WriteRules(); - WriteSubninjas(); -} - -// static -bool NinjaToolchainWriter::RunAndWriteFile( - const Settings* settings, - const std::vector<const Target*>& targets) { - NinjaHelper helper(settings->build_settings()); - base::FilePath ninja_file(settings->build_settings()->GetFullPath( - helper.GetNinjaFileForToolchain(settings).GetSourceFile( - settings->build_settings()))); - file_util::CreateDirectory(ninja_file.DirName()); - - std::ofstream file; - file.open(FilePathToUTF8(ninja_file).c_str(), - std::ios_base::out | std::ios_base::binary); - if (file.fail()) - return false; - - NinjaToolchainWriter gen(settings, targets, file); - gen.Run(); - return true; -} - -void NinjaToolchainWriter::WriteRules() { - const Toolchain* tc = settings_->toolchain(); - std::string indent(" "); - - for (int i = Toolchain::TYPE_NONE + 1; i < Toolchain::TYPE_NUMTYPES; i++) { - Toolchain::ToolType tool_type = static_cast<Toolchain::ToolType>(i); - const Toolchain::Tool& tool = tc->GetTool(tool_type); - if (tool.empty()) - continue; - - out_ << "rule " << Toolchain::ToolTypeToName(tool_type) << std::endl; - - #define WRITE_ARG(name) \ - if (!tool.name.empty()) \ - out_ << indent << " " STRINGIZE(name) " = " << tool.name << std::endl; - WRITE_ARG(command); - WRITE_ARG(depfile); - WRITE_ARG(deps); - WRITE_ARG(description); - WRITE_ARG(pool); - WRITE_ARG(restat); - WRITE_ARG(rspfile); - WRITE_ARG(rspfile_content); - #undef WRITE_ARG - } - out_ << std::endl; -} - -void NinjaToolchainWriter::WriteSubninjas() { - for (size_t i = 0; i < targets_.size(); i++) { - if (targets_[i]->output_type() != Target::NONE) { - out_ << "subninja "; - path_output_.WriteFile(out_, helper_.GetNinjaFileForTarget(targets_[i])); - out_ << std::endl; - } - } - out_ << std::endl; -} diff --git a/tools/gn/ninja_toolchain_writer.h b/tools/gn/ninja_toolchain_writer.h deleted file mode 100644 index 71759ef..0000000 --- a/tools/gn/ninja_toolchain_writer.h +++ /dev/null @@ -1,46 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_NINJA_TOOLCHAIN_WRITER_H_ -#define TOOLS_GN_NINJA_TOOLCHAIN_WRITER_H_ - -#include <iosfwd> -#include <vector> - -#include "tools/gn/ninja_helper.h" -#include "tools/gn/path_output.h" - -class BuildSettings; -class Settings; -class Target; - -class NinjaToolchainWriter { - public: - // Takes the settings for the toolchain, as well as the list of all targets - // assicoated with the toolchain. - static bool RunAndWriteFile(const Settings* settings, - const std::vector<const Target*>& targets); - - private: - NinjaToolchainWriter(const Settings* settings, - const std::vector<const Target*>& targets, - std::ostream& out); - ~NinjaToolchainWriter(); - - void Run(); - - void WriteRules(); - void WriteSubninjas(); - - const Settings* settings_; - std::vector<const Target*> targets_; - std::ostream& out_; - PathOutput path_output_; - - NinjaHelper helper_; - - DISALLOW_COPY_AND_ASSIGN(NinjaToolchainWriter); -}; - -#endif // TOOLS_GN_NINJA_TOOLCHAIN_WRITER_H_ diff --git a/tools/gn/ninja_writer.cc b/tools/gn/ninja_writer.cc deleted file mode 100644 index 8b69a3f..0000000 --- a/tools/gn/ninja_writer.cc +++ /dev/null @@ -1,64 +0,0 @@ -// 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/ninja_writer.h" - -#include "tools/gn/location.h" -#include "tools/gn/ninja_build_writer.h" -#include "tools/gn/ninja_toolchain_writer.h" - - -NinjaWriter::NinjaWriter(const BuildSettings* build_settings) - : build_settings_(build_settings) { -} - -NinjaWriter::~NinjaWriter() { -} - -// static -bool NinjaWriter::RunAndWriteFiles(const BuildSettings* build_settings) { - NinjaWriter writer(build_settings); - return writer.WriteRootBuildfiles(); -} - -bool NinjaWriter::WriteRootBuildfiles() { - // Categorize all targets by toolchain. - typedef std::map<Label, std::vector<const Target*> > CategorizedMap; - CategorizedMap categorized; - - std::vector<const Target*> all_targets; - build_settings_->target_manager().GetAllTargets(&all_targets); - for (size_t i = 0; i < all_targets.size(); i++) { - categorized[all_targets[i]->label().GetToolchainLabel()].push_back( - all_targets[i]); - } - - Label default_label = - build_settings_->toolchain_manager().GetDefaultToolchainUnlocked(); - - // Write out the toolchain buildfiles, and also accumulate the set of - // all settings and find the list of targets in the default toolchain. - std::vector<const Settings*> all_settings; - const std::vector<const Target*>* default_targets = NULL; - for (CategorizedMap::const_iterator i = categorized.begin(); - i != categorized.end(); ++i) { - const Settings* settings; - { - base::AutoLock lock(build_settings_->item_tree().lock()); - Err ignored; - settings = - build_settings_->toolchain_manager().GetSettingsForToolchainLocked( - LocationRange(), i->first, &ignored); - } - if (i->first == default_label) - default_targets = &i->second; - all_settings.push_back(settings); - if (!NinjaToolchainWriter::RunAndWriteFile(settings, i->second)) - return false; - } - - // Write the root buildfile. - return NinjaBuildWriter::RunAndWriteFile(build_settings_, all_settings, - *default_targets); -} diff --git a/tools/gn/ninja_writer.h b/tools/gn/ninja_writer.h deleted file mode 100644 index 9b6d2c1..0000000 --- a/tools/gn/ninja_writer.h +++ /dev/null @@ -1,27 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_NINJA_WRITER_H_ -#define TOOLS_GN_NINJA_WRITER_H_ - -#include "base/basictypes.h" - -class BuildSettings; - -class NinjaWriter { - public: - static bool RunAndWriteFiles(const BuildSettings* build_settings); - - private: - NinjaWriter(const BuildSettings* build_settings); - ~NinjaWriter(); - - bool WriteRootBuildfiles(); - - const BuildSettings* build_settings_; - - DISALLOW_COPY_AND_ASSIGN(NinjaWriter); -}; - -#endif // TOOLS_GN_NINJA_WRITER_H_ diff --git a/tools/gn/operators.cc b/tools/gn/operators.cc deleted file mode 100644 index afded9f..0000000 --- a/tools/gn/operators.cc +++ /dev/null @@ -1,573 +0,0 @@ -// 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/operators.h" - -#include "base/strings/string_number_conversions.h" -#include "tools/gn/err.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/scope.h" -#include "tools/gn/token.h" -#include "tools/gn/value.h" - -namespace { - -const char kSourcesName[] = "sources"; - -// Applies the sources assignment filter from the given scope to each element -// of source (can be a list or a string), appending it to dest if it doesn't -// match. -void AppendFilteredSourcesToValue(const Scope* scope, - const Value& source, - Value* dest) { - const PatternList* filter = scope->GetSourcesAssignmentFilter(); - - const std::vector<Value>& source_list = source.list_value(); - - if (source.type() == Value::STRING) { - if (!filter || filter->is_empty() || - !filter->MatchesValue(source)) - dest->list_value().push_back(source); - return; - } - - // Otherwise source is a list. - DCHECK(source.type() == Value::LIST); - if (!filter || filter->is_empty()) { - // No filter, append everything. - for (size_t i = 0; i < source_list.size(); i++) - dest->list_value().push_back(source_list[i]); - return; - } - - // Note: don't reserve() the dest vector here since that actually hurts - // the allocation pattern when the build script is doing multiple small - // additions. - for (size_t i = 0; i < source_list.size(); i++) { - if (!filter->MatchesValue(source_list[i])) - dest->list_value().push_back(source_list[i]); - } -} - -void RemoveMatchesFromList(const BinaryOpNode* op_node, - Value* list, - const Value& to_remove, - Err* err) { - std::vector<Value>& v = list->list_value(); - switch (to_remove.type()) { - case Value::INTEGER: // Filter out the individual int/string. - case Value::STRING: { - bool found_match = false; - for (size_t i = 0; i < v.size(); /* nothing */) { - if (v[i] == to_remove) { - found_match = true; - v.erase(v.begin() + i); - } else { - i++; - } - } - if (!found_match) { - *err = Err(to_remove.origin()->GetRange(), "Item not found", - "You were trying to remove \"" + to_remove.ToString() + - "\"\nfrom the list but it wasn't there."); - } - break; - } - - case Value::LIST: // Filter out each individual thing. - for (size_t i = 0; i < to_remove.list_value().size(); i++) { - // TODO(brettw) if the nested item is a list, we may want to search - // for the literal list rather than remote the items in it. - RemoveMatchesFromList(op_node, list, to_remove.list_value()[i], err); - if (err->has_error()) - return; - } - break; - - default: - break; - } -} - -// Assignment ----------------------------------------------------------------- - -Value ExecuteEquals(Scope* scope, - const BinaryOpNode* op_node, - const Token& left, - const Value& right, - Err* err) { - const Value* old_value = scope->GetValue(left.value(), false); - if (old_value) { - if (scope->IsSetButUnused(left.value())) { - // Throw an error for re-assigning without using the value first. The - // exception is that you can overwrite an empty list with another list - // since this is the way to get around the "can't overwrite a nonempty - // list with another nonempty list" restriction. - if (old_value->type() != Value::LIST || - !old_value->list_value().empty()) { - *err = Err(op_node->left()->GetRange(), "Overwriting unused variable.", - "This overwrites a previous assignment to \"" + - left.value().as_string() + "\" that had no effect."); - err->AppendSubErr(Err(*scope->GetValue(left.value()), - "Previously set here.", - "Maybe you wanted \"+=\" to append instead?")); - return Value(); - } - } else { - // Throw an error when overwriting a nonempty list with another nonempty - // list item. This is to detect the case where you write - // defines = ["FOO"] - // and you overwrote inherited ones, when instead you mean to append: - // defines += ["FOO"] - if (old_value->type() == Value::LIST && - !old_value->list_value().empty() && - right.type() == Value::LIST && - !right.list_value().empty()) { - *err = Err(op_node->left()->GetRange(), "Replacing nonempty list.", - std::string("This overwrites a previously-defined nonempty list ") + - "(length " + base::IntToString(old_value->list_value().size()) + - ")."); - err->AppendSubErr(Err(*old_value, "for previous definition", - "with another one (length " + - base::IntToString(right.list_value().size()) + "). Did you mean " + - "\"+=\" to append instead? If you\nreally want to do this, do\n " + - left.value().as_string() + " = []\nbefore reassigning.")); - return Value(); - } - } - } - if (err->has_error()) - return Value(); - - if (right.type() == Value::LIST && left.value() == kSourcesName) { - // Assigning to sources, filter the list. Here we do the filtering and - // copying in one step to save an extra list copy (the lists may be - // long). - Value* set_value = scope->SetValue(left.value(), - Value(op_node, Value::LIST), op_node); - set_value->list_value().reserve(right.list_value().size()); - AppendFilteredSourcesToValue(scope, right, set_value); - } else { - // Normal value set, just copy it. - scope->SetValue(left.value(), right, op_node->right()); - } - return Value(); -} - -// allow_type_conversion indicates if we're allowed to change the type of the -// left value. This is set to true when doing +, and false when doing +=. -void ValuePlusEquals(const Scope* scope, - const BinaryOpNode* op_node, - const Token& left_token, - Value* left, - const Value& right, - bool allow_type_conversion, - Err* err) { - switch (left->type()) { - // Left-hand-side int. - case Value::INTEGER: - switch (right.type()) { - case Value::INTEGER: // int + int -> addition. - left->int_value() += right.int_value(); - return; - - case Value::STRING: // int + string -> string concat. - if (allow_type_conversion) { - *left = Value(op_node, - base::Int64ToString(left->int_value()) + right.string_value()); - return; - } - break; - - default: - break; - } - break; - - // Left-hand-side string. - case Value::STRING: - switch (right.type()) { - case Value::INTEGER: // string + int -> string concat. - left->string_value().append(base::Int64ToString(right.int_value())); - return; - - case Value::STRING: // string + string -> string contat. - left->string_value().append(right.string_value()); - return; - - default: - break; - } - break; - - // Left-hand-side list. - case Value::LIST: - switch (right.type()) { - case Value::INTEGER: // list + integer -> list append. - case Value::STRING: // list + string -> list append. - if (left_token.value() == kSourcesName) - AppendFilteredSourcesToValue(scope, right, left); - else - left->list_value().push_back(right); - return; - - case Value::LIST: // list + list -> list concat. - if (left_token.value() == kSourcesName) { - // Filter additions through the assignment filter. - AppendFilteredSourcesToValue(scope, right, left); - } else { - // Normal list concat. - for (size_t i = 0; i < right.list_value().size(); i++) - left->list_value().push_back(right.list_value()[i]); - } - return; - - default: - break; - } - - default: - break; - } - - *err = Err(op_node->op(), "Incompatible types to add.", - std::string("I see a ") + Value::DescribeType(left->type()) + " and a " + - Value::DescribeType(right.type()) + "."); -} - -Value ExecutePlusEquals(Scope* scope, - const BinaryOpNode* op_node, - const Token& left, - const Value& right, - Err* err) { - // We modify in-place rather than doing read-modify-write to avoid - // copying large lists. - Value* left_value = - scope->GetValueForcedToCurrentScope(left.value(), op_node); - if (!left_value) { - *err = Err(left, "Undefined variable for +=.", - "I don't have something with this name in scope now."); - return Value(); - } - ValuePlusEquals(scope, op_node, left, left_value, right, false, err); - left_value->set_origin(op_node); - scope->MarkUnused(left.value()); - return Value(); -} - -void ValueMinusEquals(const BinaryOpNode* op_node, - Value* left, - const Value& right, - bool allow_type_conversion, - Err* err) { - switch (left->type()) { - // Left-hand-side int. - case Value::INTEGER: - switch (right.type()) { - case Value::INTEGER: // int - int -> subtraction. - left->int_value() -= right.int_value(); - return; - - default: - break; - } - break; - - // Left-hand-side string. - case Value::STRING: - break; // All are errors. - - // Left-hand-side list. - case Value::LIST: - RemoveMatchesFromList(op_node, left, right, err); - return; - - default: - break; - } - - *err = Err(op_node->op(), "Incompatible types to add.", - std::string("I see a ") + Value::DescribeType(left->type()) + " and a " + - Value::DescribeType(right.type()) + "."); -} - -Value ExecuteMinusEquals(Scope* scope, - const BinaryOpNode* op_node, - const Token& left, - const Value& right, - Err* err) { - Value* left_value = - scope->GetValueForcedToCurrentScope(left.value(), op_node); - if (!left_value) { - *err = Err(left, "Undefined variable for -=.", - "I don't have something with this name in scope now."); - return Value(); - } - ValueMinusEquals(op_node, left_value, right, false, err); - left_value->set_origin(op_node); - scope->MarkUnused(left.value()); - return Value(); -} - -// Plus/Minus ----------------------------------------------------------------- - -Value ExecutePlus(Scope* scope, - const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - Value ret = left; - ValuePlusEquals(scope, op_node, Token(), &ret, right, true, err); - ret.set_origin(op_node); - return ret; -} - -Value ExecuteMinus(Scope* scope, - const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - Value ret = left; - ValueMinusEquals(op_node, &ret, right, true, err); - ret.set_origin(op_node); - return ret; -} - -// Comparison ----------------------------------------------------------------- - -Value ExecuteEqualsEquals(Scope* scope, - const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - if (left == right) - return Value(op_node, 1); - return Value(op_node, 0); -} - -Value ExecuteNotEquals(Scope* scope, - const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - // Evaluate in terms of ==. - Value result = ExecuteEqualsEquals(scope, op_node, left, right, err); - result.int_value() = static_cast<int64>(!result.int_value()); - return result; -} - -Value FillNeedsToIntegersError(const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - *err = Err(op_node, "Comparison requires two integers.", - "This operator can only compare two integers."); - err->AppendRange(left.origin()->GetRange()); - err->AppendRange(right.origin()->GetRange()); - return Value(); -} - -Value ExecuteLessEquals(Scope* scope, - const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - if (left.type() != Value::INTEGER || right.type() != Value::INTEGER) - return FillNeedsToIntegersError(op_node, left, right, err); - return Value(op_node, left.int_value() <= right.int_value()); -} - -Value ExecuteGreaterEquals(Scope* scope, - const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - if (left.type() != Value::INTEGER || right.type() != Value::INTEGER) - return FillNeedsToIntegersError(op_node, left, right, err); - return Value(op_node, left.int_value() >= right.int_value()); -} - -Value ExecuteGreater(Scope* scope, - const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - if (left.type() != Value::INTEGER || right.type() != Value::INTEGER) - return FillNeedsToIntegersError(op_node, left, right, err); - return Value(op_node, left.int_value() > right.int_value()); -} - -Value ExecuteLess(Scope* scope, - const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - if (left.type() != Value::INTEGER || right.type() != Value::INTEGER) - return FillNeedsToIntegersError(op_node, left, right, err); - return Value(op_node, left.int_value() < right.int_value()); -} - -// Binary ---------------------------------------------------------------------- - -Value ExecuteOr(Scope* scope, - const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - return Value(op_node, - static_cast<int64>(left.InterpretAsInt() || right.InterpretAsInt())); -} - -Value ExecuteAnd(Scope* scope, - const BinaryOpNode* op_node, - const Value& left, - const Value& right, - Err* err) { - return Value(op_node, - static_cast<int64>(left.InterpretAsInt() && right.InterpretAsInt())); -} - -} // namespace - -// ---------------------------------------------------------------------------- - -bool IsUnaryOperator(const Token& token) { - if (token.type() != Token::OPERATOR) - return false; - return token.value() == "!"; -} - -bool IsBinaryOperator(const Token& token) { - if (token.type() != Token::OPERATOR) - return false; - return token.value() == "=" || - token.value() == "+=" || - token.value() == "-=" || - token.value() == "+" || - token.value() == "-" || - token.value() == "==" || - token.value() == "!=" || - token.value() == "<=" || - token.value() == ">=" || - token.value() == "<" || - token.value() == ">" || - token.value() == "&&" || - token.value() == "||"; -} - -bool IsFunctionCallArgBeginScoper(const Token& token) { - return token.IsScoperEqualTo("("); -} - -bool IsFunctionCallArgEndScoper(const Token& token) { - return token.IsScoperEqualTo(")"); -} - -bool IsScopeBeginScoper(const Token& token) { - return token.IsScoperEqualTo("{"); -} - -bool IsScopeEndScoper(const Token& token) { - return token.IsScoperEqualTo("}"); -} - -Value ExecuteUnaryOperator(Scope* scope, - const UnaryOpNode* op_node, - const Value& expr, - Err* err) { - DCHECK(op_node->op().IsOperatorEqualTo("!")); - return Value(op_node, !expr.InterpretAsInt()); -} - -Value ExecuteBinaryOperator(Scope* scope, - const BinaryOpNode* op_node, - const ParseNode* left, - const ParseNode* right, - Err* err) { - const Token& op = op_node->op(); - - // First handle the ones that take an lvalue. - if (op.IsOperatorEqualTo("=") || - op.IsOperatorEqualTo("+=") || - op.IsOperatorEqualTo("-=")) { - const IdentifierNode* left_id = left->AsIdentifier(); - if (!left_id) { - *err = Err(op, "Operator requires an lvalue.", - "This thing on the left is not an idenfitier."); - err->AppendRange(left->GetRange()); - return Value(); - } - const Token& dest = left_id->value(); - - Value right_value = right->Execute(scope, err); - if (err->has_error()) - return Value(); - if (right_value.type() == Value::NONE) { - *err = Err(op, "Operator requires an rvalue.", - "This thing on the right does not evaluate to a value."); - err->AppendRange(right->GetRange()); - return Value(); - } - - if (op.IsOperatorEqualTo("=")) - return ExecuteEquals(scope, op_node, dest, right_value, err); - if (op.IsOperatorEqualTo("+=")) - return ExecutePlusEquals(scope, op_node, dest, right_value, err); - if (op.IsOperatorEqualTo("-=")) - return ExecuteMinusEquals(scope, op_node, dest, right_value, err); - NOTREACHED(); - return Value(); - } - - // Left value. - Value left_value = left->Execute(scope, err); - if (err->has_error()) - return Value(); - if (left_value.type() == Value::NONE) { - *err = Err(op, "Operator requires an value.", - "This thing on the left does not evaluate to a value."); - err->AppendRange(left->GetRange()); - return Value(); - } - - // Right value. Note: don't move this above to share code with the lvalue - // version since in this case we want to execute the left side first. - Value right_value = right->Execute(scope, err); - if (err->has_error()) - return Value(); - if (right_value.type() == Value::NONE) { - *err = Err(op, "Operator requires an value.", - "This thing on the right does not evaluate to a value."); - err->AppendRange(right->GetRange()); - return Value(); - } - - // +, -. - if (op.IsOperatorEqualTo("-")) - return ExecuteMinus(scope, op_node, left_value, right_value, err); - if (op.IsOperatorEqualTo("+")) - return ExecutePlus(scope, op_node, left_value, right_value, err); - - // Comparisons. - if (op.IsOperatorEqualTo("==")) - return ExecuteEqualsEquals(scope, op_node, left_value, right_value, err); - if (op.IsOperatorEqualTo("!=")) - return ExecuteNotEquals(scope, op_node, left_value, right_value, err); - if (op.IsOperatorEqualTo(">=")) - return ExecuteGreaterEquals(scope, op_node, left_value, right_value, err); - if (op.IsOperatorEqualTo("<=")) - return ExecuteLessEquals(scope, op_node, left_value, right_value, err); - if (op.IsOperatorEqualTo(">")) - return ExecuteGreater(scope, op_node, left_value, right_value, err); - if (op.IsOperatorEqualTo("<")) - return ExecuteLess(scope, op_node, left_value, right_value, err); - - // ||, &&. - if (op.IsOperatorEqualTo("||")) - return ExecuteOr(scope, op_node, left_value, right_value, err); - if (op.IsOperatorEqualTo("&&")) - return ExecuteAnd(scope, op_node, left_value, right_value, err); - - return Value(); -} diff --git a/tools/gn/operators.h b/tools/gn/operators.h deleted file mode 100644 index 3401c22..0000000 --- a/tools/gn/operators.h +++ /dev/null @@ -1,35 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_OPERATORS_H_ -#define TOOLS_GN_OPERATORS_H_ - -class BinaryOpNode; -class Err; -class ParseNode; -class Scope; -class Token; -class UnaryOpNode; -class Value; - -bool IsUnaryOperator(const Token& token); -bool IsBinaryOperator(const Token& token); - -bool IsFunctionCallArgBeginScoper(const Token& token); // "(" -bool IsFunctionCallArgEndScoper(const Token& token); // ")" - -bool IsScopeBeginScoper(const Token& token); // "{" -bool IsScopeEndScoper(const Token& token); // "}" - -Value ExecuteUnaryOperator(Scope* scope, - const UnaryOpNode* op_node, - const Value& value, - Err* err); -Value ExecuteBinaryOperator(Scope* scope, - const BinaryOpNode* op_node, - const ParseNode* left, - const ParseNode* right, - Err* err); - -#endif // TOOLS_GN_OPERATORS_H_ diff --git a/tools/gn/output_file.h b/tools/gn/output_file.h deleted file mode 100644 index 9c5e4b2..0000000 --- a/tools/gn/output_file.h +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_OUTPUT_FILE_H_ -#define TOOLS_GN_OUTPUT_FILE_H_ - -#include <string> - -#include "tools/gn/build_settings.h" -#include "tools/gn/source_file.h" - -// A simple wrapper around a string that indicates the string is a path -// relative to the output directory. -class OutputFile { - public: - OutputFile() : value_() {} - explicit OutputFile(const base::StringPiece& str) - : value_(str.data(), str.size()) { - } - - std::string& value() { return value_; } - const std::string& value() const { return value_; } - - // Converts to a SourceFile by prepending the build directory to the file. - SourceFile GetSourceFile(const BuildSettings* build_settings) const { - return SourceFile(build_settings->build_dir().value() + value_); - } - - bool operator==(const OutputFile& other) const { - return value_ == other.value_; - } - bool operator!=(const OutputFile& other) const { - return value_ != other.value_; - } - - private: - std::string value_; -}; - -#endif diff --git a/tools/gn/output_stream.h b/tools/gn/output_stream.h deleted file mode 100644 index 6f39c86..0000000 --- a/tools/gn/output_stream.h +++ /dev/null @@ -1,42 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_OUTPUT_STREAM_H_ -#define TOOLS_GN_OUTPUT_STREAM_H_ - -class OutputStream { - public: - - - - OutputStream& WriteBuffer(const char* buf, size_t len); - OutputStream& WriteInt(int i); - - // Write a literal. - // This template expansion prevents having to look for nulls. - template<size_t size> OutputStream& Write(const char (&buf)[size]) { - return WriteBuffer(buf, size); - } - - // Write a literal string. - OutputStream& Write(const std::string& str) { - return WriteBuffer(str.c_str(), str.size()); - } - - // Quotes if necessary, and does necessary escaping. If more than one - // input is provided, the results will be concatenated together (useful - // for constructing paths without a temporary buffer). - OutputStream& WritePath(const std::string& s); - OutputStream& WritePath(const std::string& s0, - const std::string& s1); - OutputStream& WritePath(const std::string& s0, - const std::string& s1, - const std::string& s2); - - OutputStream& EndLine() { - return WriteBuffer("\n", 1); - } -}; - -#endif // TOOLS_GN_OUTPUT_STREAM_H_ diff --git a/tools/gn/parse_tree.cc b/tools/gn/parse_tree.cc deleted file mode 100644 index 0f84970..0000000 --- a/tools/gn/parse_tree.cc +++ /dev/null @@ -1,472 +0,0 @@ -// 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/parse_tree.h" - -#include <string> - -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "tools/gn/functions.h" -#include "tools/gn/operators.h" -#include "tools/gn/scope.h" -#include "tools/gn/string_utils.h" - -namespace { - -std::string IndentFor(int value) { - std::string ret; - for (int i = 0; i < value; i++) - ret.append(" "); - return ret; -} - -} // namespace - -ParseNode::ParseNode() { -} - -ParseNode::~ParseNode() { -} - -const AccessorNode* ParseNode::AsAccessor() const { return NULL; } -const BinaryOpNode* ParseNode::AsBinaryOp() const { return NULL; } -const BlockNode* ParseNode::AsBlock() const { return NULL; } -const ConditionNode* ParseNode::AsConditionNode() const { return NULL; } -const FunctionCallNode* ParseNode::AsFunctionCall() const { return NULL; } -const IdentifierNode* ParseNode::AsIdentifier() const { return NULL; } -const ListNode* ParseNode::AsList() const { return NULL; } -const LiteralNode* ParseNode::AsLiteral() const { return NULL; } -const UnaryOpNode* ParseNode::AsUnaryOp() const { return NULL; } - -// AccessorNode --------------------------------------------------------------- - -AccessorNode::AccessorNode() { -} - -AccessorNode::~AccessorNode() { -} - -const AccessorNode* AccessorNode::AsAccessor() const { - return this; -} - -Value AccessorNode::Execute(Scope* scope, Err* err) const { - Value index_value = index_->Execute(scope, err); - if (err->has_error()) - return Value(); - if (!index_value.VerifyTypeIs(Value::INTEGER, err)) - return Value(); - - const Value* base_value = scope->GetValue(base_.value(), true); - if (!base_value) { - *err = MakeErrorDescribing("Undefined identifier."); - return Value(); - } - if (!base_value->VerifyTypeIs(Value::LIST, err)) - return Value(); - - int64 index_int = index_value.int_value(); - if (index_int < 0) { - *err = Err(index_->GetRange(), "Negative array subscript.", - "You gave me " + base::Int64ToString(index_int) + "."); - return Value(); - } - size_t index_sizet = static_cast<size_t>(index_int); - if (index_sizet >= base_value->list_value().size()) { - *err = Err(index_->GetRange(), "Array subscript out of range.", - "You gave me " + base::Int64ToString(index_int) + - " but I was expecting something from 0 to " + - base::Int64ToString( - static_cast<int64>(base_value->list_value().size()) - 1) + - ", inclusive."); - return Value(); - } - - // Doing this assumes that there's no way in the language to do anything - // between the time the reference is created and the time that the reference - // is used. If there is, this will crash! Currently, this is just used for - // array accesses where this "shouldn't" happen. - return base_value->list_value()[index_sizet]; -} - -LocationRange AccessorNode::GetRange() const { - return LocationRange(base_.location(), index_->GetRange().end()); -} - -Err AccessorNode::MakeErrorDescribing(const std::string& msg, - const std::string& help) const { - return Err(GetRange(), msg, help); -} - -void AccessorNode::Print(std::ostream& out, int indent) const { - out << IndentFor(indent) << "ACCESSOR\n"; - out << IndentFor(indent + 1) << base_.value() << "\n"; - index_->Print(out, indent + 1); -} - -// BinaryOpNode --------------------------------------------------------------- - -BinaryOpNode::BinaryOpNode() { -} - -BinaryOpNode::~BinaryOpNode() { -} - -const BinaryOpNode* BinaryOpNode::AsBinaryOp() const { - return this; -} - -Value BinaryOpNode::Execute(Scope* scope, Err* err) const { - return ExecuteBinaryOperator(scope, this, left_.get(), right_.get(), err); -} - -LocationRange BinaryOpNode::GetRange() const { - return left_->GetRange().Union(right_->GetRange()); -} - -Err BinaryOpNode::MakeErrorDescribing(const std::string& msg, - const std::string& help) const { - return Err(op_, msg, help); -} - -void BinaryOpNode::Print(std::ostream& out, int indent) const { - out << IndentFor(indent) << "BINARY(" << op_.value() << ")\n"; - left_->Print(out, indent + 1); - right_->Print(out, indent + 1); -} - -// BlockNode ------------------------------------------------------------------ - -BlockNode::BlockNode(bool has_scope) - : has_scope_(has_scope), - begin_token_(NULL), - end_token_(NULL) { -} - -BlockNode::~BlockNode() { - STLDeleteContainerPointers(statements_.begin(), statements_.end()); -} - -const BlockNode* BlockNode::AsBlock() const { - return this; -} - -Value BlockNode::Execute(Scope* containing_scope, Err* err) const { - if (has_scope_) { - Scope our_scope(containing_scope); - Value ret = ExecuteBlockInScope(&our_scope, err); - if (err->has_error()) - return Value(); - - // Check for unused vars in the scope. - //our_scope.CheckForUnusedVars(err); - return ret; - } - return ExecuteBlockInScope(containing_scope, err); -} - -LocationRange BlockNode::GetRange() const { - if (begin_token_ && end_token_) { - return begin_token_->range().Union(end_token_->range()); - } - return LocationRange(); // TODO(brettw) indicate the entire file somehow. -} - -Err BlockNode::MakeErrorDescribing(const std::string& msg, - const std::string& help) const { - if (begin_token_) - return Err(*begin_token_, msg, help); - // TODO(brettw) this should have the beginning of the file in it or something. - return Err(Location(NULL, 1, 1), msg, help); -} - -void BlockNode::Print(std::ostream& out, int indent) const { - out << IndentFor(indent) << "BLOCK\n"; - for (size_t i = 0; i < statements_.size(); i++) - statements_[i]->Print(out, indent + 1); -} - -Value BlockNode::ExecuteBlockInScope(Scope* our_scope, Err* err) const { - for (size_t i = 0; i < statements_.size() && !err->has_error(); i++) { - // Check for trying to execute things with no side effects in a block. - const ParseNode* cur = statements_[i]; - if (cur->AsList() || cur->AsLiteral() || cur->AsUnaryOp() || - cur->AsIdentifier()) { - *err = cur->MakeErrorDescribing( - "This statment has no effect.", - "Either delete it or do something with the result."); - return Value(); - } - cur->Execute(our_scope, err); - } - return Value(); -} - -// ConditionNode -------------------------------------------------------------- - -ConditionNode::ConditionNode() { -} - -ConditionNode::~ConditionNode() { -} - -const ConditionNode* ConditionNode::AsConditionNode() const { - return this; -} - -Value ConditionNode::Execute(Scope* scope, Err* err) const { - Value condition_result = condition_->Execute(scope, err); - if (err->has_error()) - return Value(); - if (condition_result.type() == Value::NONE) { - *err = condition_->MakeErrorDescribing( - "This does not evaluate to a value.", - "Please give me something to work with for the if statement."); - err->AppendRange(if_token_.range()); - return Value(); - } - - if (condition_result.InterpretAsInt()) { - if_true_->ExecuteBlockInScope(scope, err); - } else if (if_false_) { - // The else block is optional. It's either another condition (for an - // "else if" and we can just Execute it and the condition will handle - // the scoping) or it's a block indicating an "else" in which ase we - // need to be sure it inherits our scope. - const BlockNode* if_false_block = if_false_->AsBlock(); - if (if_false_block) - if_false_block->ExecuteBlockInScope(scope, err); - else - if_false_->Execute(scope, err); - } - - return Value(); -} - -LocationRange ConditionNode::GetRange() const { - if (if_false_) - return if_token_.range().Union(if_false_->GetRange()); - return if_token_.range().Union(if_true_->GetRange()); -} - -Err ConditionNode::MakeErrorDescribing(const std::string& msg, - const std::string& help) const { - return Err(if_token_, msg, help); -} - -void ConditionNode::Print(std::ostream& out, int indent) const { - out << IndentFor(indent) << "CONDITION\n"; - condition_->Print(out, indent + 1); - if_true_->Print(out, indent + 1); - if (if_false_) - if_false_->Print(out, indent + 1); -} - -// FunctionCallNode ----------------------------------------------------------- - -FunctionCallNode::FunctionCallNode() { -} - -FunctionCallNode::~FunctionCallNode() { -} - -const FunctionCallNode* FunctionCallNode::AsFunctionCall() const { - return this; -} - -Value FunctionCallNode::Execute(Scope* scope, Err* err) const { - Value args = args_->Execute(scope, err); - if (err->has_error()) - return Value(); - return ExecuteFunction(scope, this, args.list_value(), block_.get(), err); -} - -LocationRange FunctionCallNode::GetRange() const { - if (block_) - return function_.range().Union(block_->GetRange()); - return function_.range().Union(args_->GetRange()); -} - -Err FunctionCallNode::MakeErrorDescribing(const std::string& msg, - const std::string& help) const { - return Err(function_, msg, help); -} - -void FunctionCallNode::Print(std::ostream& out, int indent) const { - out << IndentFor(indent) << "FUNCTION(" << function_.value() << ")\n"; - args_->Print(out, indent + 1); - if (block_) - block_->Print(out, indent + 1); -} - -// IdentifierNode -------------------------------------------------------------- - -IdentifierNode::IdentifierNode() { -} - -IdentifierNode::IdentifierNode(const Token& token) : value_(token) { -} - -IdentifierNode::~IdentifierNode() { -} - -const IdentifierNode* IdentifierNode::AsIdentifier() const { - return this; -} - -Value IdentifierNode::Execute(Scope* scope, Err* err) const { - const Value* result = scope->GetValue(value_.value(), true); - if (!result) { - *err = MakeErrorDescribing("Undefined identifier"); - return Value(); - } - return *result; -} - -LocationRange IdentifierNode::GetRange() const { - return value_.range(); -} - -Err IdentifierNode::MakeErrorDescribing(const std::string& msg, - const std::string& help) const { - return Err(value_, msg, help); -} - -void IdentifierNode::Print(std::ostream& out, int indent) const { - out << IndentFor(indent) << "IDENTIFIER(" << value_.value() << ")\n"; -} - -// ListNode ------------------------------------------------------------------- - -ListNode::ListNode() { -} - -ListNode::~ListNode() { - STLDeleteContainerPointers(contents_.begin(), contents_.end()); -} - -const ListNode* ListNode::AsList() const { - return this; -} - -Value ListNode::Execute(Scope* scope, Err* err) const { - Value result_value(this, Value::LIST); - std::vector<Value>& results = result_value.list_value(); - results.resize(contents_.size()); - - for (size_t i = 0; i < contents_.size(); i++) { - const ParseNode* cur = contents_[i]; - results[i] = cur->Execute(scope, err); - if (err->has_error()) - return Value(); - if (results[i].type() == Value::NONE) { - *err = cur->MakeErrorDescribing( - "This does not evaluate to a value.", - "I can't do something with nothing."); - return Value(); - } - } - return result_value; -} - -LocationRange ListNode::GetRange() const { - return LocationRange(begin_token_.location(), end_token_.location()); -} - -Err ListNode::MakeErrorDescribing(const std::string& msg, - const std::string& help) const { - return Err(begin_token_, msg, help); -} - -void ListNode::Print(std::ostream& out, int indent) const { - out << IndentFor(indent) << "LIST\n"; - for (size_t i = 0; i < contents_.size(); i++) - contents_[i]->Print(out, indent + 1); -} - -// LiteralNode ----------------------------------------------------------------- - -LiteralNode::LiteralNode() { -} - -LiteralNode::LiteralNode(const Token& token) : value_(token) { -} - -LiteralNode::~LiteralNode() { -} - -const LiteralNode* LiteralNode::AsLiteral() const { - return this; -} - -Value LiteralNode::Execute(Scope* scope, Err* err) const { - switch (value_.type()) { - case Token::INTEGER: { - int64 result_int; - if (!base::StringToInt64(value_.value(), &result_int)) { - *err = MakeErrorDescribing("This does not look like an integer"); - return Value(); - } - return Value(this, result_int); - } - case Token::STRING: { - // TODO(brettw) Unescaping probably needs to be moved & improved. - // The input value includes the quotes around the string, strip those - // off and unescape. - Value v(this, Value::STRING); - ExpandStringLiteral(scope, value_, &v, err); - return v; - } - default: - NOTREACHED(); - return Value(); - } -} - -LocationRange LiteralNode::GetRange() const { - return value_.range(); -} - -Err LiteralNode::MakeErrorDescribing(const std::string& msg, - const std::string& help) const { - return Err(value_, msg, help); -} - -void LiteralNode::Print(std::ostream& out, int indent) const { - out << IndentFor(indent) << "LITERAL(" << value_.value() << ")\n"; -} - -// UnaryOpNode ---------------------------------------------------------------- - -UnaryOpNode::UnaryOpNode() { -} - -UnaryOpNode::~UnaryOpNode() { -} - -const UnaryOpNode* UnaryOpNode::AsUnaryOp() const { - return this; -} - -Value UnaryOpNode::Execute(Scope* scope, Err* err) const { - Value operand_value = operand_->Execute(scope, err); - if (err->has_error()) - return Value(); - return ExecuteUnaryOperator(scope, this, operand_value, err); -} - -LocationRange UnaryOpNode::GetRange() const { - return op_.range().Union(operand_->GetRange()); -} - -Err UnaryOpNode::MakeErrorDescribing(const std::string& msg, - const std::string& help) const { - return Err(op_, msg, help); -} - -void UnaryOpNode::Print(std::ostream& out, int indent) const { - out << IndentFor(indent) << "UNARY(" << op_.value() << ")\n"; - operand_->Print(out, indent + 1); -} diff --git a/tools/gn/parse_tree.h b/tools/gn/parse_tree.h deleted file mode 100644 index 09646e5..0000000 --- a/tools/gn/parse_tree.h +++ /dev/null @@ -1,366 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_PARSE_TREE_H_ -#define TOOLS_GN_PARSE_TREE_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "tools/gn/err.h" -#include "tools/gn/token.h" -#include "tools/gn/value.h" - -class AccessorNode; -class BinaryOpNode; -class BlockNode; -class ConditionNode; -class FunctionCallNode; -class IdentifierNode; -class ListNode; -class LiteralNode; -class Scope; -class UnaryOpNode; - -// ParseNode ------------------------------------------------------------------- - -// A node in the AST. -class ParseNode { - public: - ParseNode(); - virtual ~ParseNode(); - - virtual const AccessorNode* AsAccessor() const; - virtual const BinaryOpNode* AsBinaryOp() const; - virtual const BlockNode* AsBlock() const; - virtual const ConditionNode* AsConditionNode() const; - virtual const FunctionCallNode* AsFunctionCall() const; - virtual const IdentifierNode* AsIdentifier() const; - virtual const ListNode* AsList() const; - virtual const LiteralNode* AsLiteral() const; - virtual const UnaryOpNode* AsUnaryOp() const; - - virtual Value Execute(Scope* scope, Err* err) const = 0; - - virtual LocationRange GetRange() const = 0; - - // Returns an error with the given messages and the range set to something - // that indicates this node. - virtual Err MakeErrorDescribing( - const std::string& msg, - const std::string& help = std::string()) const = 0; - - // Prints a representation of this node to the given string, indenting - // by the given number of spaces. - virtual void Print(std::ostream& out, int indent) const = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(ParseNode); -}; - -// AccessorNode ---------------------------------------------------------------- - -// Access an array element. -// -// If we need to add support for member variables like "variable.len" I was -// thinking this would also handle that case. -class AccessorNode : public ParseNode { - public: - AccessorNode(); - virtual ~AccessorNode(); - - virtual const AccessorNode* AsAccessor() const OVERRIDE; - virtual Value Execute(Scope* scope, Err* err) const OVERRIDE; - virtual LocationRange GetRange() const OVERRIDE; - virtual Err MakeErrorDescribing( - const std::string& msg, - const std::string& help = std::string()) const OVERRIDE; - virtual void Print(std::ostream& out, int indent) const OVERRIDE; - - // Base is the thing on the left of the [], currently always required to be - // an identifier token. - const Token& base() const { return base_; } - void set_base(const Token& b) { base_ = b; } - - // Index is the expression inside the []. - const ParseNode* index() const { return index_.get(); } - void set_index(scoped_ptr<ParseNode> i) { index_ = i.Pass(); } - - private: - Token base_; - scoped_ptr<ParseNode> index_; - - DISALLOW_COPY_AND_ASSIGN(AccessorNode); -}; - -// BinaryOpNode ---------------------------------------------------------------- - -class BinaryOpNode : public ParseNode { - public: - BinaryOpNode(); - virtual ~BinaryOpNode(); - - virtual const BinaryOpNode* AsBinaryOp() const OVERRIDE; - virtual Value Execute(Scope* scope, Err* err) const OVERRIDE; - virtual LocationRange GetRange() const OVERRIDE; - virtual Err MakeErrorDescribing( - const std::string& msg, - const std::string& help = std::string()) const OVERRIDE; - virtual void Print(std::ostream& out, int indent) const OVERRIDE; - - const Token& op() const { return op_; } - void set_op(const Token& t) { op_ = t; } - - const ParseNode* left() const { return left_.get(); } - void set_left(scoped_ptr<ParseNode> left) { - left_ = left.Pass(); - } - - const ParseNode* right() const { return right_.get(); } - void set_right(scoped_ptr<ParseNode> right) { - right_ = right.Pass(); - } - - private: - scoped_ptr<ParseNode> left_; - Token op_; - scoped_ptr<ParseNode> right_; - - DISALLOW_COPY_AND_ASSIGN(BinaryOpNode); -}; - -// BlockNode ------------------------------------------------------------------- - -class BlockNode : public ParseNode { - public: - // Set has_scope if this block introduces a nested scope. - BlockNode(bool has_scope); - virtual ~BlockNode(); - - virtual const BlockNode* AsBlock() const OVERRIDE; - virtual Value Execute(Scope* scope, Err* err) const OVERRIDE; - virtual LocationRange GetRange() const OVERRIDE; - virtual Err MakeErrorDescribing( - const std::string& msg, - const std::string& help = std::string()) const OVERRIDE; - virtual void Print(std::ostream& out, int indent) const OVERRIDE; - - void set_begin_token(const Token* t) { begin_token_ = t; } - void set_end_token(const Token* t) { end_token_ = t; } - - const std::vector<ParseNode*>& statements() const { return statements_; } - void append_statement(scoped_ptr<ParseNode> s) { - statements_.push_back(s.release()); - } - - // Doesn't create a nested scope. - Value ExecuteBlockInScope(Scope* our_scope, Err* err) const; - - private: - bool has_scope_; - - // Tokens corresponding to { and }, if any (may be NULL). - const Token* begin_token_; - const Token* end_token_; - - // Owning pointers, use unique_ptr when we can use C++11. - std::vector<ParseNode*> statements_; - - DISALLOW_COPY_AND_ASSIGN(BlockNode); -}; - -// ConditionNode --------------------------------------------------------------- - -class ConditionNode : public ParseNode { - public: - ConditionNode(); - virtual ~ConditionNode(); - - virtual const ConditionNode* AsConditionNode() const OVERRIDE; - virtual Value Execute(Scope* scope, Err* err) const OVERRIDE; - virtual LocationRange GetRange() const OVERRIDE; - virtual Err MakeErrorDescribing( - const std::string& msg, - const std::string& help = std::string()) const OVERRIDE; - virtual void Print(std::ostream& out, int indent) const OVERRIDE; - - void set_if_token(const Token& token) { if_token_ = token; } - - const ParseNode* condition() const { return condition_.get(); } - void set_condition(scoped_ptr<ParseNode> c) { - condition_ = c.Pass(); - } - - const BlockNode* if_true() const { return if_true_.get(); } - void set_if_true(scoped_ptr<BlockNode> t) { - if_true_ = t.Pass(); - } - - // This is either empty, a block (for the else clause), or another - // condition. - const ParseNode* if_false() const { return if_false_.get(); } - void set_if_false(scoped_ptr<ParseNode> f) { - if_false_ = f.Pass(); - } - - private: - // Token corresponding to the "if" string. - Token if_token_; - - scoped_ptr<ParseNode> condition_; // Always non-null. - scoped_ptr<BlockNode> if_true_; // Always non-null. - scoped_ptr<ParseNode> if_false_; // May be null. - - DISALLOW_COPY_AND_ASSIGN(ConditionNode); -}; - -// FunctionCallNode ------------------------------------------------------------ - -class FunctionCallNode : public ParseNode { - public: - FunctionCallNode(); - virtual ~FunctionCallNode(); - - virtual const FunctionCallNode* AsFunctionCall() const OVERRIDE; - virtual Value Execute(Scope* scope, Err* err) const OVERRIDE; - virtual LocationRange GetRange() const OVERRIDE; - virtual Err MakeErrorDescribing( - const std::string& msg, - const std::string& help = std::string()) const OVERRIDE; - virtual void Print(std::ostream& out, int indent) const OVERRIDE; - - const Token& function() const { return function_; } - void set_function(Token t) { function_ = t; } - - const ListNode* args() const { return args_.get(); } - void set_args(scoped_ptr<ListNode> a) { args_ = a.Pass(); } - - const BlockNode* block() const { return block_.get(); } - void set_block(scoped_ptr<BlockNode> b) { block_ = b.Pass(); } - - private: - Token function_; - scoped_ptr<ListNode> args_; - scoped_ptr<BlockNode> block_; // May be null. - - DISALLOW_COPY_AND_ASSIGN(FunctionCallNode); -}; - -// IdentifierNode -------------------------------------------------------------- - -class IdentifierNode : public ParseNode { - public: - IdentifierNode(); - IdentifierNode(const Token& token); - virtual ~IdentifierNode(); - - virtual const IdentifierNode* AsIdentifier() const OVERRIDE; - virtual Value Execute(Scope* scope, Err* err) const OVERRIDE; - virtual LocationRange GetRange() const OVERRIDE; - virtual Err MakeErrorDescribing( - const std::string& msg, - const std::string& help = std::string()) const OVERRIDE; - virtual void Print(std::ostream& out, int indent) const OVERRIDE; - - const Token& value() const { return value_; } - void set_value(const Token& t) { value_ = t; } - - private: - Token value_; - - DISALLOW_COPY_AND_ASSIGN(IdentifierNode); -}; - -// ListNode -------------------------------------------------------------------- - -class ListNode : public ParseNode { - public: - ListNode(); - virtual ~ListNode(); - - virtual const ListNode* AsList() const OVERRIDE; - virtual Value Execute(Scope* scope, Err* err) const OVERRIDE; - virtual LocationRange GetRange() const OVERRIDE; - virtual Err MakeErrorDescribing( - const std::string& msg, - const std::string& help = std::string()) const OVERRIDE; - virtual void Print(std::ostream& out, int indent) const OVERRIDE; - - void set_begin_token(const Token& t) { begin_token_ = t; } - void set_end_token(const Token& t) { end_token_ = t; } - - void append_item(scoped_ptr<ParseNode> s) { - contents_.push_back(s.release()); - } - const std::vector<ParseNode*>& contents() const { return contents_; } - - private: - // Tokens corresponding to the [ and ]. - Token begin_token_; - Token end_token_; - - // Owning pointers, use unique_ptr when we can use C++11. - std::vector<ParseNode*> contents_; - - DISALLOW_COPY_AND_ASSIGN(ListNode); -}; - -// LiteralNode ----------------------------------------------------------------- - -class LiteralNode : public ParseNode { - public: - LiteralNode(); - LiteralNode(const Token& token); - virtual ~LiteralNode(); - - virtual const LiteralNode* AsLiteral() const OVERRIDE; - virtual Value Execute(Scope* scope, Err* err) const OVERRIDE; - virtual LocationRange GetRange() const OVERRIDE; - virtual Err MakeErrorDescribing( - const std::string& msg, - const std::string& help = std::string()) const OVERRIDE; - virtual void Print(std::ostream& out, int indent) const OVERRIDE; - - const Token& value() const { return value_; } - void set_value(const Token& t) { value_ = t; } - - private: - Token value_; - - DISALLOW_COPY_AND_ASSIGN(LiteralNode); -}; - -// UnaryOpNode ----------------------------------------------------------------- - -class UnaryOpNode : public ParseNode { - public: - UnaryOpNode(); - virtual ~UnaryOpNode(); - - virtual const UnaryOpNode* AsUnaryOp() const OVERRIDE; - virtual Value Execute(Scope* scope, Err* err) const OVERRIDE; - virtual LocationRange GetRange() const OVERRIDE; - virtual Err MakeErrorDescribing( - const std::string& msg, - const std::string& help = std::string()) const OVERRIDE; - virtual void Print(std::ostream& out, int indent) const OVERRIDE; - - const Token& op() const { return op_; } - void set_op(const Token& t) { op_ = t; } - - const ParseNode* operand() const { return operand_.get(); } - void set_operand(scoped_ptr<ParseNode> operand) { - operand_ = operand.Pass(); - } - - private: - Token op_; - scoped_ptr<ParseNode> operand_; - - DISALLOW_COPY_AND_ASSIGN(UnaryOpNode); -}; - -#endif // TOOLS_GN_PARSE_TREE_H_ diff --git a/tools/gn/parser.cc b/tools/gn/parser.cc deleted file mode 100644 index 385aa34..0000000 --- a/tools/gn/parser.cc +++ /dev/null @@ -1,470 +0,0 @@ -// 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/parser.h" - -#include "base/logging.h" -#include "tools/gn/functions.h" -#include "tools/gn/operators.h" -#include "tools/gn/token.h" - -namespace { - -// Returns true if the two tokens are on the same line. We assume they're in -// the same file. -bool IsSameLine(const Token& a, const Token& b) { - DCHECK(a.location().file() == b.location().file()); - return a.location().line_number() == b.location().line_number(); -} - -} // namespace - -Parser::Parser(const std::vector<Token>& tokens, Err* err) - : tokens_(tokens), - err_(err), - cur_(0) { -} - -Parser::~Parser() { -} - -// static -scoped_ptr<ParseNode> Parser::Parse(const std::vector<Token>& tokens, - Err* err) { - Parser p(tokens, err); - return p.ParseBlock(false).PassAs<ParseNode>(); -} - -// static -scoped_ptr<ParseNode> Parser::ParseExpression(const std::vector<Token>& tokens, - Err* err) { - Parser p(tokens, err); - return p.ParseExpression().Pass(); -} - -bool Parser::IsToken(Token::Type type, char* str) const { - if (at_end()) - return false; - return cur_token().type() == type || cur_token().value() == str; -} - -scoped_ptr<AccessorNode> Parser::ParseAccessor() { - scoped_ptr<AccessorNode> accessor(new AccessorNode); - - DCHECK(cur_token().type() == Token::IDENTIFIER); - accessor->set_base(cur_token()); - cur_++; // Skip identifier. - cur_++; // Skip "[" (we know this exists because the existance of this - // token is how the caller knows it's an accessor. - - if (at_end()) { - *err_ = MakeEOFError("Got EOF when looking for list index."); - return scoped_ptr<AccessorNode>(); - } - - // Get the expression. - scoped_ptr<ParseNode> expr = ParseExpression().Pass(); - if (has_error()) - return scoped_ptr<AccessorNode>(); - if (at_end()) { - *err_ = MakeEOFError("Got EOF when looking for list accessor ]"); - return scoped_ptr<AccessorNode>(); - } - accessor->set_index(expr.Pass()); - - // Skip over "]" - if (!cur_token().IsScoperEqualTo("]")) { - *err_ = Err(cur_token(), "Expecting ]", - "You started a list access but didn't terminate it, and instead " - "I fould this\nstupid thing."); - return scoped_ptr<AccessorNode>(); - } - cur_++; - - return accessor.Pass(); -} - -// Blocks at the file scope don't need {} so we have the option to ignore -// them. When need_braces is set, we'll expect a begin an end brace. -// -// block := "{" block_contents "}" -// block_contents := (expression | conditional | block)* -scoped_ptr<BlockNode> Parser::ParseBlock(bool need_braces) { - scoped_ptr<BlockNode> block(new BlockNode(true)); - - // Eat initial { if necessary. - const Token* opening_curly_brace; - if (need_braces) { - if (at_end()) { - *err_ = MakeEOFError("Got EOF when looking for { for block.", - "It should have been after here."); - return scoped_ptr<BlockNode>(); - } else if(!IsScopeBeginScoper(cur_token())) { - *err_ = Err(cur_token(), "Expecting { instead of this thing.", - "THOU SHALT USE CURLY BRACES FOR ALL BLOCKS."); - return scoped_ptr<BlockNode>(); - } - opening_curly_brace = &cur_token(); - block->set_begin_token(opening_curly_brace); - cur_++; - } - - // Loop until EOF or end brace found. - while (!at_end() && !IsScopeEndScoper(cur_token())) { - if (cur_token().IsIdentifierEqualTo("if")) { - // Conditional. - block->append_statement(ParseCondition().PassAs<ParseNode>()); - } else if (IsScopeBeginScoper(cur_token())) { - // Nested block. - block->append_statement(ParseBlock(true).PassAs<ParseNode>()); - } else { - // Everything else is an expression. - block->append_statement(ParseExpression().PassAs<ParseNode>()); - } - if (has_error()) - return scoped_ptr<BlockNode>(); - } - - // Eat the ending "}" if necessary. - if (need_braces) { - if (at_end() || !IsScopeEndScoper(cur_token())) { - *err_ = Err(*opening_curly_brace, "Expecting }", - "I ran headlong into the end of the file looking for the " - "closing brace\ncorresponding to this one."); - return scoped_ptr<BlockNode>(); - } - block->set_end_token(&cur_token()); - cur_++; // Skip past "}". - } - - return block.Pass(); -} - -// conditional := "if (" expression ")" block [else_conditional] -// else_conditional := ("else" block) | ("else" conditional) -scoped_ptr<ConditionNode> Parser::ParseCondition() { - scoped_ptr<ConditionNode> cond(new ConditionNode); - - // Skip past "if". - const Token& if_token = cur_token(); - cond->set_if_token(if_token); - DCHECK(if_token.IsIdentifierEqualTo("if")); - cur_++; - - if (at_end() || !IsFunctionCallArgBeginScoper(cur_token())) { - *err_ = Err(if_token, "Expecting \"(\" after \"if\"", - "Did you think this was Python or something?"); - return scoped_ptr<ConditionNode>(); - } - - // Skip over (. - const Token& open_paren_token = cur_token(); - cur_++; - if (at_end()) { - *err_ = Err(if_token, "Unexpected EOF inside if condition"); - return scoped_ptr<ConditionNode>(); - } - - // Condition inside (). - cond->set_condition(ParseExpression().Pass()); - if (has_error()) - return scoped_ptr<ConditionNode>(); - - if (at_end() || !IsFunctionCallArgEndScoper(cur_token())) { - *err_ = Err(open_paren_token, "Expecting \")\" for \"if\" condition", - "You didn't finish the thought you started here."); - return scoped_ptr<ConditionNode>(); - } - cur_++; // Skip over ) - - // Contents of {}. - cond->set_if_true(ParseBlock(true).Pass()); - if (has_error()) - return scoped_ptr<ConditionNode>(); - - // Optional "else" at the end. - if (!at_end() && cur_token().IsIdentifierEqualTo("else")) { - cur_++; - - // The else may be followed by an if or a block. - if (at_end()) { - *err_ = MakeEOFError("Ran into end of file after \"else\".", - "else, WHAT?!?!?"); - return scoped_ptr<ConditionNode>(); - } - if (cur_token().IsIdentifierEqualTo("if")) { - // "else if() {" - cond->set_if_false(ParseCondition().PassAs<ParseNode>()); - } else if (IsScopeBeginScoper(cur_token())) { - // "else {" - cond->set_if_false(ParseBlock(true).PassAs<ParseNode>()); - } else { - // else <anything else> - *err_ = Err(cur_token(), "Expected \"if\" or \"{\" after \"else\".", - "This is neither of those things."); - return scoped_ptr<ConditionNode>(); - } - } - - if (has_error()) - return scoped_ptr<ConditionNode>(); - return cond.Pass(); -} - -// expression := paren_expression | accessor | identifier | literal | -// funccall | unary_expression | binary_expression -// -// accessor := identifier <non-newline-whitespace>* "[" expression "]" -// -// The "non-newline-whitespace is used to differentiate between this case: -// a[1] -// and this one: -// a -// [1] -// The second one is kind of stupid (since it does nothing with the values) -// but is still legal. -scoped_ptr<ParseNode> Parser::ParseExpression() { - scoped_ptr<ParseNode> expr = ParseExpressionExceptBinaryOperators(); - if (has_error()) - return scoped_ptr<ParseNode>(); - - // That may have hit EOF, in which case we can't have any binary operators. - if (at_end()) - return expr.Pass(); - - // TODO(brettw) handle operator precidence! - // Gobble up all subsequent expressions as long as there are binary - // operators. - - if (IsBinaryOperator(cur_token())) { - scoped_ptr<BinaryOpNode> binary_op(new BinaryOpNode); - binary_op->set_left(expr.Pass()); - const Token& operator_token = cur_token(); - binary_op->set_op(operator_token); - cur_++; - if (at_end()) { - *err_ = Err(operator_token, "Unexpected EOF in expression.", - "I was looking for the right-hand-side of this operator."); - return scoped_ptr<ParseNode>(); - } - binary_op->set_right(ParseExpression().Pass()); - if (has_error()) - return scoped_ptr<ParseNode>(); - return binary_op.PassAs<ParseNode>(); - } - - return expr.Pass(); -} - - -// This internal one does not handle binary operators, since it requires -// looking at the "next" thing. The regular ParseExpression above handles it. -scoped_ptr<ParseNode> Parser::ParseExpressionExceptBinaryOperators() { - if (at_end()) - return scoped_ptr<ParseNode>(); - - const Token& token = cur_token(); - - // Unary expression. - if (IsUnaryOperator(token)) - return ParseUnaryOp().PassAs<ParseNode>(); - - // Parenthesized expressions. - if (token.IsScoperEqualTo("(")) - return ParseParenExpression(); - - // Function calls. - if (token.type() == Token::IDENTIFIER) { - if (has_next_token() && IsFunctionCallArgBeginScoper(next_token())) - return ParseFunctionCall().PassAs<ParseNode>(); - } - - // Lists. - if (token.IsScoperEqualTo("[")) { - return ParseList(Token(Location(), Token::SCOPER, "["), - Token(Location(), Token::SCOPER, "]")).PassAs<ParseNode>(); - } - - // Literals. - if (token.type() == Token::STRING || token.type() == Token::INTEGER) { - cur_++; - return scoped_ptr<ParseNode>(new LiteralNode(token)); - } - - // Accessors. - if (token.type() == Token::IDENTIFIER && - has_next_token() && next_token().IsScoperEqualTo("[") && - IsSameLine(token, next_token())) { - return ParseAccessor().PassAs<ParseNode>(); - } - - // Identifiers. - if (token.type() == Token::IDENTIFIER) { - cur_++; - return scoped_ptr<ParseNode>(new IdentifierNode(token)); - } - - // Handle errors. - if (token.type() == Token::SEPARATOR) { - *err_ = Err(token, "Unexpected comma.", - "You can't put a comma here, it must be in list separating " - "complete\nthoughts."); - } else if (IsScopeBeginScoper(token)) { - *err_ = Err(token, "Unexpected token.", - "You can't put a \"{\" scope here, it must be in a block."); - } else { - *err_ = Err(token, "Unexpected token.", - "I was really hoping for something else here and you let me down."); - } - return scoped_ptr<ParseNode>(); -} - -// function_call := identifier "(" list_contents ")" -// [<non-newline-whitespace>* block] -scoped_ptr<FunctionCallNode> Parser::ParseFunctionCall() { - scoped_ptr<FunctionCallNode> func(new FunctionCallNode); - - const Token& function_token = cur_token(); - func->set_function(function_token); - - // This function should only get called when we know we have a function, - // which only happens when there is a paren following the name. Skip past it. - DCHECK(has_next_token()); - cur_++; // Skip past function name to (. - const Token& open_paren_token = cur_token(); - DCHECK(IsFunctionCallArgBeginScoper(open_paren_token)); - - if (at_end()) { - *err_ = Err(open_paren_token, "Unexpected EOF for function call.", - "You didn't finish the thought you started here."); - return scoped_ptr<FunctionCallNode>(); - } - - // Arguments. - func->set_args(ParseList(Token(Location(), Token::SCOPER, "("), - Token(Location(), Token::SCOPER, ")"))); - if (has_error()) - return scoped_ptr<FunctionCallNode>(); - - // Optional {} after function call for certain functions. The "{" must be on - // the same line as the ")" to disambiguate the case of a function followed - // by a random block just used for scoping purposes. - if (!at_end() && IsScopeBeginScoper(cur_token())) { - const Token& args_end_token = tokens_[cur_ - 1]; - DCHECK(args_end_token.IsScoperEqualTo(")")); - if (IsSameLine(args_end_token, cur_token())) - func->set_block(ParseBlock(true).Pass()); - } - - if (has_error()) - return scoped_ptr<FunctionCallNode>(); - return func.Pass(); -} - -// list := "[" expression* "]" -// list_contents := [(expression ",")* expression [","]] -// -// The list_contents is also used in function calls surrounded by parens, so -// this function takes the tokens that are expected to surround the list. -scoped_ptr<ListNode> Parser::ParseList(const Token& expected_begin, - const Token& expected_end) { - scoped_ptr<ListNode> list(new ListNode); - - const Token& open_bracket_token = cur_token(); - list->set_begin_token(open_bracket_token); - cur_++; // Skip "[" or "(". - - bool need_separator = false; - while(true) { - if (at_end()) { - *err_ = Err(open_bracket_token, "EOF found when parsing list.", - "I expected a \"" + expected_end.value().as_string() + - "\" corresponding to this one."); - return scoped_ptr<ListNode>(); - } - if (cur_token().type() == expected_end.type() && - cur_token().value() == expected_end.value()) { - list->set_end_token(cur_token()); - cur_++; - break; - } - - if (need_separator) { - DCHECK(!list->contents().empty()); - LocationRange prev_item_range = - list->contents().at(list->contents().size() - 1)->GetRange(); - *err_ = Err(prev_item_range.end(), - "Need comma separating items in list.", - "You probably need a comma after this thingy."); - err_->AppendRange(prev_item_range); - return scoped_ptr<ListNode>(); - } - scoped_ptr<ParseNode> expr = ParseExpression().Pass(); - if (has_error()) - return scoped_ptr<ListNode>(); - list->append_item(expr.Pass()); - - need_separator = true; - if (!at_end()) { - // Skip over the separator, marking that we found it. - if (cur_token().type() == Token::SEPARATOR) { - cur_++; - need_separator = false; - } - } - } - return list.Pass(); -} - -// paren_expression := "(" expression ")" -scoped_ptr<ParseNode> Parser::ParseParenExpression() { - const Token& open_paren_token = cur_token(); - cur_++; // Skip over ( - - scoped_ptr<ParseNode> ret = ParseExpression(); - if (has_error()) - return scoped_ptr<ParseNode>(); - - if (at_end()) { - *err_ = Err(open_paren_token, "EOF found when parsing expression.", - "I was looking for a \")\" corresponding to this one."); - return scoped_ptr<ParseNode>(); - } - if (!cur_token().IsScoperEqualTo(")")) { - *err_ = Err(open_paren_token, "Expected \")\" for expression", - "I was looking for a \")\" corresponding to this one."); - return scoped_ptr<ParseNode>(); - } - cur_++; // Skip over ) - return ret.Pass(); -} - -// unary_expression := "!" expression -scoped_ptr<UnaryOpNode> Parser::ParseUnaryOp() { - scoped_ptr<UnaryOpNode> unary(new UnaryOpNode); - - DCHECK(!at_end() && IsUnaryOperator(cur_token())); - const Token& op_token = cur_token(); - unary->set_op(op_token); - cur_++; - - if (at_end()) { - *err_ = Err(op_token, "Expected expression.", - "This operator needs something to operate on."); - return scoped_ptr<UnaryOpNode>(); - } - unary->set_operand(ParseExpression().Pass()); - if (has_error()) - return scoped_ptr<UnaryOpNode>(); - return unary.Pass(); -} - -Err Parser::MakeEOFError(const std::string& message, - const std::string& help) const { - if (tokens_.empty()) - return Err(Location(NULL, 1, 1), message, help); - - const Token& last = tokens_[tokens_.size() - 1]; - return Err(last, message, help); -} diff --git a/tools/gn/parser.h b/tools/gn/parser.h deleted file mode 100644 index 252b801..0000000 --- a/tools/gn/parser.h +++ /dev/null @@ -1,81 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_PARSER_H_ -#define TOOLS_GN_PARSER_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "tools/gn/err.h" -#include "tools/gn/parse_tree.h" - -// Parses a series of tokens. The resulting AST will refer to the tokens passed -// to the input, so the tokens an the file data they refer to must outlive your -// use of the ParseNode. -class Parser { - public: - // Will return a null pointer and set the err on error. - static scoped_ptr<ParseNode> Parse(const std::vector<Token>& tokens, - Err* err); - - // Alternative to parsing that assumes the input is an expression. - static scoped_ptr<ParseNode> ParseExpression(const std::vector<Token>& tokens, - Err* err); - - private: - // Vector must be valid for lifetime of call. - Parser(const std::vector<Token>& tokens, Err* err); - ~Parser(); - - scoped_ptr<AccessorNode> ParseAccessor(); - scoped_ptr<BlockNode> ParseBlock(bool need_braces); - scoped_ptr<ConditionNode> ParseCondition(); - scoped_ptr<ParseNode> ParseExpression(); - scoped_ptr<ParseNode> ParseExpressionExceptBinaryOperators(); - scoped_ptr<FunctionCallNode> ParseFunctionCall(); - scoped_ptr<ListNode> ParseList(const Token& expected_begin, - const Token& expected_end); - scoped_ptr<ParseNode> ParseParenExpression(); - scoped_ptr<UnaryOpNode> ParseUnaryOp(); - - bool IsToken(Token::Type type, char* str) const; - - // Gets an error corresponding to the last token. When we hit an EOF - // usually we've already gone beyond the end (or maybe there are no tokens) - // so there is some tricky logic to report this. - Err MakeEOFError(const std::string& message, - const std::string& help = std::string()) const; - - const Token& cur_token() const { return tokens_[cur_]; } - - bool done() const { return at_end() || has_error(); } - bool at_end() const { return cur_ >= tokens_.size(); } - bool has_error() const { return err_->has_error(); } - - const Token& next_token() const { return tokens_[cur_ + 1]; } - bool has_next_token() const { return cur_ + 1 < tokens_.size(); } - - const std::vector<Token>& tokens_; - - Err* err_; - - // Current index into the tokens. - size_t cur_; - - FRIEND_TEST_ALL_PREFIXES(Parser, BinaryOp); - FRIEND_TEST_ALL_PREFIXES(Parser, Block); - FRIEND_TEST_ALL_PREFIXES(Parser, Condition); - FRIEND_TEST_ALL_PREFIXES(Parser, Expression); - FRIEND_TEST_ALL_PREFIXES(Parser, FunctionCall); - FRIEND_TEST_ALL_PREFIXES(Parser, List); - FRIEND_TEST_ALL_PREFIXES(Parser, ParenExpression); - FRIEND_TEST_ALL_PREFIXES(Parser, UnaryOp); - - DISALLOW_COPY_AND_ASSIGN(Parser); -}; - -#endif // TOOLS_GN_PARSER_H_ diff --git a/tools/gn/parser_unittest.cc b/tools/gn/parser_unittest.cc deleted file mode 100644 index 3fd8ebe..0000000 --- a/tools/gn/parser_unittest.cc +++ /dev/null @@ -1,329 +0,0 @@ -// 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 <iostream> -#include <sstream> - -#include "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/input_file.h" -#include "tools/gn/parser.h" -#include "tools/gn/tokenizer.h" - -namespace { - -bool GetTokens(const InputFile* input, std::vector<Token>* result) { - result->clear(); - Err err; - *result = Tokenizer::Tokenize(input, &err); - return !err.has_error(); -} - -bool IsIdentifierEqual(const ParseNode* node, const char* val) { - if (!node) - return false; - const IdentifierNode* ident = node->AsIdentifier(); - if (!ident) - return false; - return ident->value().value() == val; -} - -bool IsLiteralEqual(const ParseNode* node, const char* val) { - if (!node) - return false; - const LiteralNode* lit = node->AsLiteral(); - if (!lit) - return false; - return lit->value().value() == val; -} - -// Returns true if the given node as a simple assignment to a given value. -bool IsAssignment(const ParseNode* node, const char* ident, const char* value) { - if (!node) - return false; - const BinaryOpNode* binary = node->AsBinaryOp(); - if (!binary) - return false; - return binary->op().IsOperatorEqualTo("=") && - IsIdentifierEqual(binary->left(), ident) && - IsLiteralEqual(binary->right(), value); -} - -// Returns true if the given node is a block with one assignment statement. -bool IsBlockWithAssignment(const ParseNode* node, - const char* ident, const char* value) { - if (!node) - return false; - const BlockNode* block = node->AsBlock(); - if (!block) - return false; - if (block->statements().size() != 1) - return false; - return IsAssignment(block->statements()[0], ident, value); -} - -void DoParserPrintTest(const char* input, const char* expected) { - std::vector<Token> tokens; - InputFile input_file(SourceFile("/test")); - input_file.SetContents(input); - ASSERT_TRUE(GetTokens(&input_file, &tokens)); - - Err err; - scoped_ptr<ParseNode> result = Parser::Parse(tokens, &err); - ASSERT_TRUE(result); - - std::ostringstream collector; - result->Print(collector, 0); - - EXPECT_EQ(expected, collector.str()); -} - -// Expects the tokenizer or parser to identify an error at the given line and -// character. -void DoParserErrorTest(const char* input, int err_line, int err_char) { - InputFile input_file(SourceFile("/test")); - input_file.SetContents(input); - - Err err; - std::vector<Token> tokens = Tokenizer::Tokenize(&input_file, &err); - if (!err.has_error()) { - scoped_ptr<ParseNode> result = Parser::Parse(tokens, &err); - ASSERT_FALSE(result); - ASSERT_TRUE(err.has_error()); - } - - EXPECT_EQ(err_line, err.location().line_number()); - EXPECT_EQ(err_char, err.location().char_offset()); -} - -} // namespace - -TEST(Parser, BinaryOp) { - std::vector<Token> tokens; - - // Simple set expression. - InputFile expr_input(SourceFile("/test")); - expr_input.SetContents("a=2"); - ASSERT_TRUE(GetTokens(&expr_input, &tokens)); - Err err; - Parser set(tokens, &err); - scoped_ptr<ParseNode> expr = set.ParseExpression(); - ASSERT_TRUE(expr); - - const BinaryOpNode* binary_op = expr->AsBinaryOp(); - ASSERT_TRUE(binary_op); - - EXPECT_TRUE(binary_op->left()->AsIdentifier()); - - EXPECT_TRUE(binary_op->op().type() == Token::OPERATOR); - EXPECT_TRUE(binary_op->op().value() == "="); - - EXPECT_TRUE(binary_op->right()->AsLiteral()); -} - -TEST(Parser, Condition) { - std::vector<Token> tokens; - - InputFile cond_input(SourceFile("/test")); - cond_input.SetContents("if(1) { a = 2 }"); - ASSERT_TRUE(GetTokens(&cond_input, &tokens)); - Err err; - Parser simple_if(tokens, &err); - scoped_ptr<ConditionNode> cond = simple_if.ParseCondition(); - ASSERT_TRUE(cond); - - EXPECT_TRUE(IsLiteralEqual(cond->condition(), "1")); - EXPECT_FALSE(cond->if_false()); // No else block. - EXPECT_TRUE(IsBlockWithAssignment(cond->if_true(), "a", "2")); - - // Now try a complicated if/else if/else one. - InputFile complex_if_input(SourceFile("/test")); - complex_if_input.SetContents( - "if(1) { a = 2 } else if (0) { a = 3 } else { a = 4 }"); - ASSERT_TRUE(GetTokens(&complex_if_input, &tokens)); - Parser complex_if(tokens, &err); - cond = complex_if.ParseCondition(); - ASSERT_TRUE(cond); - - EXPECT_TRUE(IsLiteralEqual(cond->condition(), "1")); - EXPECT_TRUE(IsBlockWithAssignment(cond->if_true(), "a", "2")); - - ASSERT_TRUE(cond->if_false()); - const ConditionNode* nested_cond = cond->if_false()->AsConditionNode(); - ASSERT_TRUE(nested_cond); - EXPECT_TRUE(IsLiteralEqual(nested_cond->condition(), "0")); - EXPECT_TRUE(IsBlockWithAssignment(nested_cond->if_true(), "a", "3")); - EXPECT_TRUE(IsBlockWithAssignment(nested_cond->if_false(), "a", "4")); -} - -TEST(Parser, FunctionCall) { - const char* input = "foo(a, 1, 2,) bar()"; - const char* expected = - "BLOCK\n" - " FUNCTION(foo)\n" - " LIST\n" - " IDENTIFIER(a)\n" - " LITERAL(1)\n" - " LITERAL(2)\n" - " FUNCTION(bar)\n" - " LIST\n"; - DoParserPrintTest(input, expected); -} - -TEST(Parser, ParenExpression) { - const char* input = "(foo(1)) + (a + b)"; - const char* expected = - "BLOCK\n" - " BINARY(+)\n" - " FUNCTION(foo)\n" - " LIST\n" - " LITERAL(1)\n" - " BINARY(+)\n" - " IDENTIFIER(a)\n" - " IDENTIFIER(b)\n"; - DoParserPrintTest(input, expected); - DoParserErrorTest("(a +", 1, 4); -} - -TEST(Parser, UnaryOp) { - std::vector<Token> tokens; - - InputFile ident_input(SourceFile("/test")); - ident_input.SetContents("!foo"); - ASSERT_TRUE(GetTokens(&ident_input, &tokens)); - Err err; - Parser ident(tokens, &err); - scoped_ptr<UnaryOpNode> op = ident.ParseUnaryOp(); - - ASSERT_TRUE(op); - EXPECT_TRUE(op->op().type() == Token::OPERATOR); - EXPECT_TRUE(op->op().value() == "!"); -} - -TEST(Parser, CompleteFunction) { - const char* input = - "cc_test(\"foo\") {\n" - " sources = [\n" - " \"foo.cc\",\n" - " \"foo.h\"\n" - " ]\n" - " dependencies = [\n" - " \"base\"\n" - " ]\n" - "}\n"; - const char* expected = - "BLOCK\n" - " FUNCTION(cc_test)\n" - " LIST\n" - " LITERAL(\"foo\")\n" - " BLOCK\n" - " BINARY(=)\n" - " IDENTIFIER(sources)\n" - " LIST\n" - " LITERAL(\"foo.cc\")\n" - " LITERAL(\"foo.h\")\n" - " BINARY(=)\n" - " IDENTIFIER(dependencies)\n" - " LIST\n" - " LITERAL(\"base\")\n"; - DoParserPrintTest(input, expected); -} - -TEST(Parser, FunctionWithConditional) { - const char* input = - "cc_test(\"foo\") {\n" - " sources = [\"foo.cc\"]\n" - " if (OS == \"mac\") {\n" - " sources += \"bar.cc\"\n" - " } else if (OS == \"win\") {\n" - " sources -= [\"asd.cc\", \"foo.cc\"]\n" - " } else {\n" - " dependencies += [\"bar.cc\"]\n" - " }\n" - "}\n"; - const char* expected = - "BLOCK\n" - " FUNCTION(cc_test)\n" - " LIST\n" - " LITERAL(\"foo\")\n" - " BLOCK\n" - " BINARY(=)\n" - " IDENTIFIER(sources)\n" - " LIST\n" - " LITERAL(\"foo.cc\")\n" - " CONDITION\n" - " BINARY(==)\n" - " IDENTIFIER(OS)\n" - " LITERAL(\"mac\")\n" - " BLOCK\n" - " BINARY(+=)\n" - " IDENTIFIER(sources)\n" - " LITERAL(\"bar.cc\")\n" - " CONDITION\n" - " BINARY(==)\n" - " IDENTIFIER(OS)\n" - " LITERAL(\"win\")\n" - " BLOCK\n" - " BINARY(-=)\n" - " IDENTIFIER(sources)\n" - " LIST\n" - " LITERAL(\"asd.cc\")\n" - " LITERAL(\"foo.cc\")\n" - " BLOCK\n" - " BINARY(+=)\n" - " IDENTIFIER(dependencies)\n" - " LIST\n" - " LITERAL(\"bar.cc\")\n"; - DoParserPrintTest(input, expected); -} - -TEST(Parser, NestedBlocks) { - const char* input = "{cc_test(\"foo\") {{foo=1}{}}}"; - const char* expected = - "BLOCK\n" - " BLOCK\n" - " FUNCTION(cc_test)\n" - " LIST\n" - " LITERAL(\"foo\")\n" - " BLOCK\n" - " BLOCK\n" - " BINARY(=)\n" - " IDENTIFIER(foo)\n" - " LITERAL(1)\n" - " BLOCK\n"; - DoParserPrintTest(input, expected); -} - -TEST(Parser, List) { - const char* input = "[] a = [1,asd,] b = [1, 2+3 - foo]"; - const char* expected = - "BLOCK\n" - " LIST\n" - " BINARY(=)\n" - " IDENTIFIER(a)\n" - " LIST\n" - " LITERAL(1)\n" - " IDENTIFIER(asd)\n" - " BINARY(=)\n" - " IDENTIFIER(b)\n" - " LIST\n" - " LITERAL(1)\n" - " BINARY(+)\n" - " LITERAL(2)\n" - " BINARY(-)\n" - " LITERAL(3)\n" - " IDENTIFIER(foo)\n"; - DoParserPrintTest(input, expected); - - DoParserErrorTest("[a, 2+,]", 1, 7); - DoParserErrorTest("[,]", 1, 2); - DoParserErrorTest("[a,,]", 1, 4); -} - -TEST(Parser, UnterminatedBlock) { - DoParserErrorTest("hello {", 1, 7); -} - -TEST(Parser, BadlyTerminatedNumber) { - DoParserErrorTest("1234z", 1, 5); -} diff --git a/tools/gn/path_output.cc b/tools/gn/path_output.cc deleted file mode 100644 index f67b3d4..0000000 --- a/tools/gn/path_output.cc +++ /dev/null @@ -1,116 +0,0 @@ -// 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/path_output.h" - -#include "build/build_config.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/output_file.h" -#include "tools/gn/string_utils.h" - -PathOutput::PathOutput(const SourceDir& current_dir, - EscapingMode escaping, - bool convert_slashes) - : current_dir_(current_dir) { - inverse_current_dir_ = InvertDir(current_dir_); - - options_.mode = escaping; - options_.convert_slashes = convert_slashes; - options_.inhibit_quoting = false; - - if (convert_slashes) - ConvertPathToSystem(&inverse_current_dir_); -} - -PathOutput::~PathOutput() { -} - -void PathOutput::WriteFile(std::ostream& out, const SourceFile& file) const { - WritePathStr(out, file.value()); -} - -void PathOutput::WriteDir(std::ostream& out, - const SourceDir& dir, - DirSlashEnding slash_ending) const { - if (dir.value() == "/") { - // Writing system root is always a slash (this will normally only come up - // on Posix systems). - out << "/"; - } else if (dir.value() == "//") { - // Writing out the source root. - if (slash_ending == DIR_NO_LAST_SLASH) { - // The inverse_current_dir_ will contain a [back]slash at the end, so we - // can't just write it out. - if (inverse_current_dir_.empty()) { - out << "."; - } else { - out.write(inverse_current_dir_.c_str(), - inverse_current_dir_.size() - 1); - } - } else { - if (inverse_current_dir_.empty()) - out << "./"; - else - out << inverse_current_dir_; - } - } else if (slash_ending == DIR_INCLUDE_LAST_SLASH) { - WritePathStr(out, dir.value()); - } else { - // DIR_NO_LAST_SLASH mode, just trim the last char. - WritePathStr(out, base::StringPiece(dir.value().data(), - dir.value().size() - 1)); - } -} - -void PathOutput::WriteFile(std::ostream& out, const OutputFile& file) const { - // Here we assume that the path is already preprocessed. - EscapeStringToStream(out, file.value(), options_); -} - -void PathOutput::WriteSourceRelativeString( - std::ostream& out, - const base::StringPiece& str) const { - // Input begins with two slashes, is relative to source root. Strip off - // the two slashes when cat-ing it. - if (options_.mode == ESCAPE_SHELL) { - // Shell escaping needs an intermediate string since it may end up - // quoting the whole thing. On Windows, the slashes may already be - // converted to backslashes in inverse_current_dir_, but we assume that on - // Windows the escaper won't try to then escape the preconverted - // backslashes and will just pass them, so this is fine. - std::string intermediate; - intermediate.reserve(inverse_current_dir_.size() + str.size()); - intermediate.assign(inverse_current_dir_.c_str(), - inverse_current_dir_.size()); - intermediate.append(str.data(), str.size()); - - EscapeStringToStream(out, - base::StringPiece(intermediate.c_str(), intermediate.size()), - options_); - } else { - // Ninja (and none) escaping can avoid the intermediate string and - // reprocessing of the inverse_current_dir_. - out << inverse_current_dir_; - EscapeStringToStream(out, str, options_); - } -} - -void PathOutput::WritePathStr(std::ostream& out, - const base::StringPiece& str) const { - DCHECK(str.size() > 0 && str[0] == '/'); - - if (str.size() >= 2 && str[1] == '/') { - WriteSourceRelativeString(out, str.substr(2)); - } else { - // Input begins with one slash, don't write the current directory since - // it's system-absolute. -#if defined(OS_WIN) - // On Windows, trim the leading slash, since the input for absolute - // paths will look like "/C:/foo/bar.txt". - EscapeStringToStream(out, str.substr(1), options_); -#else - EscapeStringToStream(out, str, options_); -#endif - } -} diff --git a/tools/gn/path_output.h b/tools/gn/path_output.h deleted file mode 100644 index 00bdbee..0000000 --- a/tools/gn/path_output.h +++ /dev/null @@ -1,80 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_PATH_OUTPUT_H_ -#define TOOLS_GN_PATH_OUTPUT_H_ - -#include <iosfwd> -#include <string> - -#include "base/basictypes.h" -#include "base/strings/string_piece.h" -#include "tools/gn/escape.h" -#include "tools/gn/source_dir.h" - -class OutputFile; -class SourceFile; - -// Writes file names to streams assuming a certain input directory and -// escaping rules. This gives us a central place for managing this state. -class PathOutput { - public: - // Controls whether writing directory names include the trailing slash. - // Often we don't want the trailing slash when writing out to a command line, - // especially on Windows where it's a backslash and might be interpreted as - // escaping the thing following it. - enum DirSlashEnding { - DIR_INCLUDE_LAST_SLASH, - DIR_NO_LAST_SLASH, - }; - - PathOutput(const SourceDir& current_dir, - EscapingMode escaping, - bool convert_slashes); - ~PathOutput(); - - // Read-only since inverse_current_dir_ is computed depending on this. - EscapingMode escaping_mode() const { return options_.mode; } - - // When true, converts slashes to the system-type path separators (on - // Windows, this is a backslash, this is a NOP otherwise). - // - // Read-only since inverse_current_dir_ is computed depending on this. - bool convert_slashes_to_system() const { return options_.convert_slashes; } - - // When the output escaping is ESCAPE_SHELL, the escaper will normally put - // quotes around suspect things. If this value is set to true, we'll disable - // the quoting feature. This means that in ESCAPE_SHELL mode, strings with - // spaces in them qon't be quoted. This mode is for when quoting is done at - // some higher-level. Defaults to false. - bool inhibit_quoting() const { return options_.inhibit_quoting; } - void set_inhibit_quoting(bool iq) { options_.inhibit_quoting = iq; } - - void WriteFile(std::ostream& out, const SourceFile& file) const; - void WriteFile(std::ostream& out, const OutputFile& file) const; - void WriteDir(std::ostream& out, - const SourceDir& dir, - DirSlashEnding slash_ending) const; - - // Backend for WriteFile and WriteDir. This appends the given file or - // directory string to the file. - void WritePathStr(std::ostream& out, const base::StringPiece& str) const; - - private: - // Takes the given string and writes it out, appending to the inverse - // current dir. This assumes leading slashes have been trimmed. - void WriteSourceRelativeString(std::ostream& out, - const base::StringPiece& str) const; - - SourceDir current_dir_; - - // Uses system slashes if convert_slashes_to_system_. - std::string inverse_current_dir_; - - // Since the inverse_current_dir_ depends on some of these, we don't expose - // this directly to modification. - EscapeOptions options_; -}; - -#endif // TOOLS_GN_PATH_OUTPUT_H_ diff --git a/tools/gn/path_output_unittest.cc b/tools/gn/path_output_unittest.cc deleted file mode 100644 index 5133b79..0000000 --- a/tools/gn/path_output_unittest.cc +++ /dev/null @@ -1,193 +0,0 @@ -// 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 <sstream> - -#include "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/path_output.h" -#include "tools/gn/source_dir.h" -#include "tools/gn/source_file.h" - -TEST(PathOutput, Basic) { - SourceDir build_dir("//out/Debug/"); - PathOutput writer(build_dir, ESCAPE_NONE, false); - { - // Normal source-root path. - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo/bar.cc")); - EXPECT_EQ("../../foo/bar.cc", out.str()); - } - { - // File in the root dir. - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo.cc")); - EXPECT_EQ("../../foo.cc", out.str()); - } -#if defined(OS_WIN) - { - // System-absolute path. - std::ostringstream out; - writer.WriteFile(out, SourceFile("/C:/foo/bar.cc")); - EXPECT_EQ("C:/foo/bar.cc", out.str()); - } -#else - { - // System-absolute path. - std::ostringstream out; - writer.WriteFile(out, SourceFile("/foo/bar.cc")); - EXPECT_EQ("/foo/bar.cc", out.str()); - } -#endif -} - -// Same as basic but the output dir is the root. -TEST(PathOutput, BasicInRoot) { - SourceDir build_dir("//"); - PathOutput writer(build_dir, ESCAPE_NONE, false); - { - // Normal source-root path. - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo/bar.cc")); - EXPECT_EQ("foo/bar.cc", out.str()); - } - { - // File in the root dir. - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo.cc")); - EXPECT_EQ("foo.cc", out.str()); - } -} - -TEST(PathOutput, NinjaEscaping) { - SourceDir build_dir("//out/Debug/"); - PathOutput writer(build_dir, ESCAPE_NINJA, false); - { - // Spaces and $ in filenames. - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo/foo bar$.cc")); - EXPECT_EQ("../../foo/foo$ bar$$.cc", out.str()); - } - { - // Not other weird stuff - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo/\"foo\\bar\".cc")); - EXPECT_EQ("../../foo/\"foo\\bar\".cc", out.str()); - } -} - -TEST(PathOutput, ShellEscaping) { - SourceDir build_dir("//out/Debug/"); - PathOutput writer(build_dir, ESCAPE_SHELL, false); - { - // Spaces in filenames should get quoted. - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo/foo bar.cc")); - EXPECT_EQ("\"../../foo/foo bar.cc\"", out.str()); - } - { - // Quotes should get blackslash-escaped. - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo/\"foobar\".cc")); - EXPECT_EQ("../../foo/\\\"foobar\\\".cc", out.str()); - } - { - // Backslashes should get escaped on non-Windows and preserved on Windows. - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo\\bar.cc")); -#if defined(OS_WIN) - EXPECT_EQ("../../foo\\bar.cc", out.str()); -#else - EXPECT_EQ("../../foo\\\\bar.cc", out.str()); -#endif - } -} - -TEST(PathOutput, SlashConversion) { - SourceDir build_dir("//out/Debug/"); - PathOutput writer(build_dir, ESCAPE_NINJA, true); - { - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo/bar.cc")); -#if defined(OS_WIN) - EXPECT_EQ("..\\..\\foo\\bar.cc", out.str()); -#else - EXPECT_EQ("../../foo/bar.cc", out.str()); -#endif - } -} - -TEST(PathOutput, InhibitQuoting) { - SourceDir build_dir("//out/Debug/"); - PathOutput writer(build_dir, ESCAPE_SHELL, false); - writer.set_inhibit_quoting(true); - { - // We should get unescaped spaces in the output with no quotes. - std::ostringstream out; - writer.WriteFile(out, SourceFile("//foo/foo bar.cc")); - EXPECT_EQ("../../foo/foo bar.cc", out.str()); - } -} - -TEST(PathOutput, WriteDir) { - { - SourceDir build_dir("//out/Debug/"); - PathOutput writer(build_dir, ESCAPE_NINJA, false); - { - std::ostringstream out; - writer.WriteDir(out, SourceDir("//foo/bar/"), - PathOutput::DIR_INCLUDE_LAST_SLASH); - EXPECT_EQ("../../foo/bar/", out.str()); - } - { - std::ostringstream out; - writer.WriteDir(out, SourceDir("//foo/bar/"), - PathOutput::DIR_NO_LAST_SLASH); - EXPECT_EQ("../../foo/bar", out.str()); - } - - // Output source root dir. - { - std::ostringstream out; - writer.WriteDir(out, SourceDir("//"), - PathOutput::DIR_INCLUDE_LAST_SLASH); - EXPECT_EQ("../../", out.str()); - } - { - std::ostringstream out; - writer.WriteDir(out, SourceDir("//"), - PathOutput::DIR_NO_LAST_SLASH); - EXPECT_EQ("../..", out.str()); - } - - // Output system root dir. - { - std::ostringstream out; - writer.WriteDir(out, SourceDir("/"), - PathOutput::DIR_INCLUDE_LAST_SLASH); - EXPECT_EQ("/", out.str()); - } - { - std::ostringstream out; - writer.WriteDir(out, SourceDir("/"), - PathOutput::DIR_NO_LAST_SLASH); - EXPECT_EQ("/", out.str()); - } - } - { - // Empty build dir writer. - PathOutput root_writer(SourceDir("//"), ESCAPE_NINJA, false); - { - std::ostringstream out; - root_writer.WriteDir(out, SourceDir("//"), - PathOutput::DIR_INCLUDE_LAST_SLASH); - EXPECT_EQ("./", out.str()); - } - { - std::ostringstream out; - root_writer.WriteDir(out, SourceDir("//"), - PathOutput::DIR_NO_LAST_SLASH); - EXPECT_EQ(".", out.str()); - } - } -} diff --git a/tools/gn/pattern.cc b/tools/gn/pattern.cc deleted file mode 100644 index cc08b2c..0000000 --- a/tools/gn/pattern.cc +++ /dev/null @@ -1,185 +0,0 @@ -// 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/pattern.h" - -#include "tools/gn/value.h" - -namespace { - -void ParsePattern(const std::string& s, std::vector<Pattern::Subrange>* out) { - // Set when the last subrange is a literal so we can just append when we - // find another literal. - Pattern::Subrange* last_literal = NULL; - - for (size_t i = 0; i < s.size(); i++) { - if (s[i] == '*') { - // Don't allow two **. - if (out->size() == 0 || - (*out)[out->size() - 1].type != Pattern::Subrange::ANYTHING) - out->push_back(Pattern::Subrange(Pattern::Subrange::ANYTHING)); - last_literal = NULL; - } else if (s[i] == '\\') { - if (i < s.size() - 1 && s[i + 1] == 'b') { - // "\b" means path boundary. - i++; - out->push_back(Pattern::Subrange(Pattern::Subrange::PATH_BOUNDARY)); - last_literal = NULL; - } else { - // Backslash + anything else means that literal char. - if (!last_literal) { - out->push_back(Pattern::Subrange(Pattern::Subrange::LITERAL)); - last_literal = &(*out)[out->size() - 1]; - } - if (i < s.size() - 1) { - i++; - last_literal->literal.push_back(s[i]); - } else { - // Single backslash at end, use literal backslash. - last_literal->literal.push_back('\\'); - } - } - } else { - if (!last_literal) { - out->push_back(Pattern::Subrange(Pattern::Subrange::LITERAL)); - last_literal = &(*out)[out->size() - 1]; - } - last_literal->literal.push_back(s[i]); - } - } -} - -} // namespace - -Pattern::Pattern(const std::string& s) { - ParsePattern(s, &subranges_); - is_suffix_ = - (subranges_.size() == 2 && - subranges_[0].type == Subrange::ANYTHING && - subranges_[1].type == Subrange::LITERAL); -} - -Pattern::~Pattern() { -} - -bool Pattern::MatchesString(const std::string& s) const { - // Empty pattern matches only empty string. - if (subranges_.empty()) - return s.empty(); - - if (is_suffix_) { - const std::string& suffix = subranges_[1].literal; - if (suffix.size() > s.size()) - return false; // Too short. - return s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0; - } - - return RecursiveMatch(s, 0, 0, true); -} - -// We assume the number of ranges is small so recursive is always reasonable. -// Could be optimized to only be recursive for *. -bool Pattern::RecursiveMatch(const std::string& s, - size_t begin_char, - size_t subrange_index, - bool allow_implicit_path_boundary) const { - if (subrange_index >= subranges_.size()) { - // Hit the end of our subranges, the text should also be at the end for a - // match. - return begin_char == s.size(); - } - - const Subrange& sr = subranges_[subrange_index]; - switch (sr.type) { - case Subrange::LITERAL: { - if (s.size() - begin_char < sr.literal.size()) - return false; // Not enough room. - if (s.compare(begin_char, sr.literal.size(), sr.literal) != 0) - return false; // Literal doesn't match. - - // Recursively check the next one. - return RecursiveMatch(s, begin_char + sr.literal.size(), - subrange_index + 1, true); - } - - case Subrange::PATH_BOUNDARY: { - // When we can accept an implicit path boundary, we have to check both - // a match of the literal and the implicit one. - if (allow_implicit_path_boundary && - (begin_char == 0 || begin_char == s.size())) { - // At implicit path boundary, see if the rest of the pattern matches. - if (RecursiveMatch(s, begin_char, subrange_index + 1, false)) - return true; - } - - // Check for a literal "/". - if (begin_char < s.size() && s[begin_char] == '/') { - // At explicit boundary, see if the rest of the pattern matches. - if (RecursiveMatch(s, begin_char + 1, subrange_index + 1, true)) - return true; - } - return false; - } - - case Subrange::ANYTHING: { - if (subrange_index == subranges_.size() - 1) - return true; // * at the end, consider it matching. - - size_t min_next_size = sr.MinSize(); - - // We don't care about exactly what matched as long as there was a match, - // so we can do this front-to-back. If we needed the match, we would - // normally want "*" to be greedy so would work backwards. - for (size_t i = begin_char; i < s.size() - min_next_size; i++) { - // Note: this could probably be faster by detecting the type of the - // next match in advance and checking for a match in this loop rather - // than doing a full recursive call for each character. - if (RecursiveMatch(s, i, subrange_index + 1, true)) - return true; - } - return false; - } - - default: - NOTREACHED(); - } - - return false; -} - -PatternList::PatternList() { -} - -PatternList::~PatternList() { -} - -void PatternList::SetFromValue(const Value& v, Err* err) { - patterns_.clear(); - - if (v.type() != Value::LIST) { - *err = Err(v.origin(), "This value must be a list."); - return; - } - - const std::vector<Value>& list = v.list_value(); - for (size_t i = 0; i < list.size(); i++) { - if (!list[i].VerifyTypeIs(Value::STRING, err)) - return; - patterns_.push_back(Pattern(list[i].string_value())); - } -} - -bool PatternList::MatchesString(const std::string& s) const { - for (size_t i = 0; i < patterns_.size(); i++) { - if (patterns_[i].MatchesString(s)) - return true; - } - return false; -} - -bool PatternList::MatchesValue(const Value& v) const { - if (v.type() == Value::STRING) - return MatchesString(v.string_value()); - return false; -} diff --git a/tools/gn/pattern.h b/tools/gn/pattern.h deleted file mode 100644 index 582cfea..0000000 --- a/tools/gn/pattern.h +++ /dev/null @@ -1,86 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_PATTERN_H_ -#define TOOLS_GN_PATTERN_H_ - -#include <string> -#include <vector> - -#include "tools/gn/value.h" - -class Pattern { - public: - struct Subrange { - enum Type { - LITERAL, // Matches exactly the contents of the string. - ANYTHING, // * (zero or more chars). - PATH_BOUNDARY // '/' or beginning of string. - }; - - Subrange(Type t, const std::string& l = std::string()) - : type(t), - literal(l) { - } - - // Returns the minimum number of chars that this subrange requires. - size_t MinSize() const { - switch (type) { - case LITERAL: - return literal.size(); - case ANYTHING: - return 0; - case PATH_BOUNDARY: - return 0; // Can match beginning or end of string, which is 0 len. - default: - return 0; - } - } - - Type type; - - // When type == LITERAL this is the text to match. - std::string literal; - }; - - Pattern(const std::string& s); - ~Pattern(); - - // Returns true if the current pattern matches the given string. - bool MatchesString(const std::string& s) const; - - private: - // allow_implicit_path_boundary determines if a path boundary should accept - // matches at the beginning or end of the string. - bool RecursiveMatch(const std::string& s, - size_t begin_char, - size_t subrange_index, - bool allow_implicit_path_boundary) const; - - std::vector<Subrange> subranges_; - - // Set to true when the subranges are "*foo" ("ANYTHING" followed by a - // literal). This covers most patterns so we optimize for this. - bool is_suffix_; -}; - -class PatternList { - public: - PatternList(); - ~PatternList(); - - bool is_empty() const { return patterns_.empty(); } - - // Initializes the pattern list from a give list of pattern strings. Sets - // |*err| on failure. - void SetFromValue(const Value& v, Err* err); - - bool MatchesString(const std::string& s) const; - bool MatchesValue(const Value& v) const; - - private: - std::vector<Pattern> patterns_; -}; - -#endif // TOOLS_GN_PATTERN_H_ diff --git a/tools/gn/pattern_unittest.cc b/tools/gn/pattern_unittest.cc deleted file mode 100644 index e9ffea6..0000000 --- a/tools/gn/pattern_unittest.cc +++ /dev/null @@ -1,61 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/pattern.h" - -namespace { - -struct Case { - const char* pattern; - const char* candidate; - bool expected_match; -}; - -} // namespace - -TEST(Pattern, Matches) { - Case pattern_cases[] = { - // Empty pattern matches only empty string. - { "", "", true }, - { "", "foo", false }, - // Exact matches. - { "foo", "foo", true }, - { "foo", "bar", false }, - // Path boundaries. - { "\\b", "", true }, - { "\\b", "/", true }, - { "\\b\\b", "/", true }, - { "\\b\\b\\b", "", false }, - { "\\b\\b\\b", "/", true }, - { "\\b", "//", false }, - { "\\bfoo\\b", "foo", true }, - { "\\bfoo\\b", "/foo/", true }, - { "\\b\\bfoo", "/foo", true }, - // * - { "*", "", true }, - { "*", "foo", true }, - { "*foo", "foo", true }, - { "*foo", "gagafoo", true }, - { "*foo", "gagafoob", false }, - { "foo*bar", "foobar", true }, - { "foo*bar", "foo-bar", true }, - { "foo*bar", "foolalalalabar", true }, - { "foo*bar", "foolalalalabaz", false }, - { "*a*b*c*d*", "abcd", true }, - { "*a*b*c*d*", "1a2b3c4d5", true }, - { "*a*b*c*d*", "1a2b3c45", false }, - { "*\\bfoo\\b*", "foo", true }, - { "*\\bfoo\\b*", "/foo/", true }, - { "*\\bfoo\\b*", "foob", false }, - { "*\\bfoo\\b*", "lala/foo/bar/baz", true }, - }; - for (size_t i = 0; i < arraysize(pattern_cases); i++) { - const Case& c = pattern_cases[i]; - Pattern pattern(c.pattern); - bool result = pattern.MatchesString(c.candidate); - EXPECT_EQ(c.expected_match, result) << i << ": \"" << c.pattern - << "\", \"" << c.candidate << "\""; - } -} diff --git a/tools/gn/scheduler.cc b/tools/gn/scheduler.cc deleted file mode 100644 index 33c8f1a..0000000 --- a/tools/gn/scheduler.cc +++ /dev/null @@ -1,130 +0,0 @@ -// 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/scheduler.h" - -#include "base/bind.h" -#include "tools/gn/ninja_target_writer.h" -#include "tools/gn/standard_out.h" - -Scheduler* g_scheduler = NULL; - -Scheduler::Scheduler() - : pool_(new base::SequencedWorkerPool(32, "worker_")), - input_file_manager_(new InputFileManager), - verbose_logging_(false), - work_count_(0), - is_failed_(false) { - g_scheduler = this; -} - -Scheduler::~Scheduler() { - g_scheduler = NULL; -} - -bool Scheduler::Run() { - runner_.Run(); - pool_->Shutdown(); - return !is_failed(); -} - -void Scheduler::Log(const std::string& verb, const std::string& msg) { - if (base::MessageLoop::current() == &main_loop_) { - LogOnMainThread(verb, msg); - } else { - // The run loop always joins on the sub threads, so the lifetime of this - // object outlives the invocations of this function, hence "unretained". - main_loop_.PostTask(FROM_HERE, - base::Bind(&Scheduler::LogOnMainThread, - base::Unretained(this), verb, msg)); - } -} - -void Scheduler::FailWithError(const Err& err) { - DCHECK(err.has_error()); - { - base::AutoLock lock(lock_); - - if (is_failed_) - return; // Ignore errors once we see one. - is_failed_ = true; - } - - if (base::MessageLoop::current() == &main_loop_) { - FailWithErrorOnMainThread(err); - } else { - // The run loop always joins on the sub threads, so the lifetime of this - // object outlives the invocations of this function, hence "unretained". - main_loop_.PostTask(FROM_HERE, - base::Bind(&Scheduler::FailWithErrorOnMainThread, - base::Unretained(this), err)); - } -} - -void Scheduler::ScheduleWork(const base::Closure& work) { - IncrementWorkCount(); - pool_->PostWorkerTaskWithShutdownBehavior( - FROM_HERE, base::Bind(&Scheduler::DoWork, - base::Unretained(this), work), - base::SequencedWorkerPool::BLOCK_SHUTDOWN); -} - -void Scheduler::ScheduleTargetFileWrite(const Target* target) { - pool_->PostWorkerTaskWithShutdownBehavior( - FROM_HERE, base::Bind(&Scheduler::DoTargetFileWrite, - base::Unretained(this), target), - base::SequencedWorkerPool::BLOCK_SHUTDOWN); -} - -void Scheduler::AddGenDependency(const SourceFile& source_file) { - base::AutoLock lock(lock_); - gen_dependencies_.push_back(source_file); -} - -std::vector<SourceFile> Scheduler::GetGenDependencies() const { - base::AutoLock lock(lock_); - return gen_dependencies_; -} - -void Scheduler::IncrementWorkCount() { - base::AtomicRefCountInc(&work_count_); -} - -void Scheduler::DecrementWorkCount() { - if (!base::AtomicRefCountDec(&work_count_)) { - if (base::MessageLoop::current() == &main_loop_) { - OnComplete(); - } else { - main_loop_.PostTask(FROM_HERE, - base::Bind(&Scheduler::OnComplete, - base::Unretained(this))); - } - } -} - -void Scheduler::LogOnMainThread(const std::string& verb, - const std::string& msg) { - OutputString(verb, DECORATION_YELLOW); - OutputString(" " + msg + "\n"); -} - -void Scheduler::FailWithErrorOnMainThread(const Err& err) { - err.PrintToStdout(); - runner_.Quit(); -} - -void Scheduler::DoTargetFileWrite(const Target* target) { - NinjaTargetWriter::RunAndWriteFile(target); -} - -void Scheduler::DoWork(const base::Closure& closure) { - closure.Run(); - DecrementWorkCount(); -} - -void Scheduler::OnComplete() { - // Should be called on the main thread. - DCHECK(base::MessageLoop::current() == main_loop()); - runner_.Quit(); -} diff --git a/tools/gn/scheduler.h b/tools/gn/scheduler.h deleted file mode 100644 index eab996d..0000000 --- a/tools/gn/scheduler.h +++ /dev/null @@ -1,90 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_SCHEDULER_H_ -#define TOOLS_GN_SCHEDULER_H_ - -#include "base/atomic_ref_count.h" -#include "base/basictypes.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/synchronization/lock.h" -#include "base/threading/sequenced_worker_pool.h" -#include "tools/gn/input_file_manager.h" - -class Target; - -// Maintains the thread pool and error state. -class Scheduler { - public: - Scheduler(); - ~Scheduler(); - - bool Run(); - - base::MessageLoop* main_loop() { return &main_loop_; } - base::SequencedWorkerPool* pool() { return pool_; } - - InputFileManager* input_file_manager() { return input_file_manager_; } - - bool verbose_logging() const { return verbose_logging_; } - void set_verbose_logging(bool v) { verbose_logging_ = v; } - - // TODO(brettw) data race on this access (benign?). - bool is_failed() const { return is_failed_; } - - void Log(const std::string& verb, const std::string& msg); - void FailWithError(const Err& err); - - void ScheduleWork(const base::Closure& work); - - void ScheduleTargetFileWrite(const Target* target); - - // Declares that the given file was read and affected the build output. - // - // TODO(brettw) this is global rather than per-BuildSettings. If we - // start using >1 build settings, then we probably want this to take a - // BuildSettings object so we know the depdency on a per-build basis. - void AddGenDependency(const SourceFile& source_file); - std::vector<SourceFile> GetGenDependencies() const; - - // We maintain a count of the things we need to do that works like a - // refcount. When this reaches 0, the program exits. - void IncrementWorkCount(); - void DecrementWorkCount(); - - private: - void LogOnMainThread(const std::string& verb, const std::string& msg); - void FailWithErrorOnMainThread(const Err& err); - - void DoTargetFileWrite(const Target* target); - - void DoWork(const base::Closure& closure); - - void OnComplete(); - - base::MessageLoop main_loop_; - scoped_refptr<base::SequencedWorkerPool> pool_; - - scoped_refptr<InputFileManager> input_file_manager_; - - base::RunLoop runner_; - - bool verbose_logging_; - - base::AtomicRefCount work_count_; - - mutable base::Lock lock_; - bool is_failed_; - - // Additional input dependencies. Protected by the lock. - std::vector<SourceFile> gen_dependencies_; - - DISALLOW_COPY_AND_ASSIGN(Scheduler); -}; - -extern Scheduler* g_scheduler; - -#endif // TOOLS_GN_SCHEDULER_H_ - diff --git a/tools/gn/scope.cc b/tools/gn/scope.cc deleted file mode 100644 index 72664d7..0000000 --- a/tools/gn/scope.cc +++ /dev/null @@ -1,372 +0,0 @@ -// 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/scope.h" - -#include "base/logging.h" -#include "base/stl_util.h" -#include "tools/gn/parse_tree.h" - -namespace { - -// FLags set in the mode_flags_ of a scope. If a bit is set, it applies -// recursively to all dependent scopes. -const unsigned kProcessingBuildConfigFlag = 1; -const unsigned kProcessingDefaultBuildConfigFlag = 2; -const unsigned kProcessingImportFlag = 4; - -} // namespace - -Scope::Scope(const Settings* settings) - : const_containing_(NULL), - mutable_containing_(NULL), - settings_(settings), - mode_flags_(0) { -} - -Scope::Scope(Scope* parent) - : const_containing_(NULL), - mutable_containing_(parent), - settings_(parent->settings()), - mode_flags_(0) { -} - -Scope::Scope(const Scope* parent) - : const_containing_(parent), - mutable_containing_(NULL), - settings_(parent->settings()), - mode_flags_(0) { -} - -Scope::~Scope() { - STLDeleteContainerPairSecondPointers(target_defaults_.begin(), - target_defaults_.end()); -} - -const Value* Scope::GetValue(const base::StringPiece& ident, - bool counts_as_used) { - // First check for programatically-provided values. - for (ProviderSet::const_iterator i = programmatic_providers_.begin(); - i != programmatic_providers_.end(); ++i) { - const Value* v = (*i)->GetProgrammaticValue(ident); - if (v) - return v; - } - - RecordMap::iterator found = values_.find(ident); - if (found != values_.end()) { - if (counts_as_used) - found->second.used = true; - return &found->second.value; - } - - // Search in the parent scope. - if (const_containing_) - return const_containing_->GetValue(ident); - if (mutable_containing_) - return mutable_containing_->GetValue(ident, counts_as_used); - return NULL; -} - -Value* Scope::GetValueForcedToCurrentScope(const base::StringPiece& ident, - const ParseNode* set_node) { - RecordMap::iterator found = values_.find(ident); - if (found != values_.end()) - return &found->second.value; // Already have in the current scope. - - // Search in the parent scope. - if (containing()) { - const Value* in_containing = containing()->GetValue(ident); - if (in_containing) { - // Promote to current scope. - return SetValue(ident, *in_containing, set_node); - } - } - return NULL; -} - -const Value* Scope::GetValue(const base::StringPiece& ident) const { - RecordMap::const_iterator found = values_.find(ident); - if (found != values_.end()) - return &found->second.value; - if (containing()) - return containing()->GetValue(ident); - return NULL; -} - -Value* Scope::SetValue(const base::StringPiece& ident, - const Value& v, - const ParseNode* set_node) { - Record& r = values_[ident]; // Clears any existing value. - r.value = v; - r.value.set_origin(set_node); - return &r.value; -} - -bool Scope::AddTemplate(const std::string& name, const FunctionCallNode* decl) { - if (GetTemplate(name)) - return false; - templates_[name] = decl; - return true; -} - -const FunctionCallNode* Scope::GetTemplate(const std::string& name) const { - TemplateMap::const_iterator found = templates_.find(name); - if (found != templates_.end()) - return found->second; - if (containing()) - return containing()->GetTemplate(name); - return NULL; -} - -void Scope::MarkUsed(const base::StringPiece& ident) { - RecordMap::iterator found = values_.find(ident); - if (found == values_.end()) { - NOTREACHED(); - return; - } - found->second.used = true; -} - -void Scope::MarkUnused(const base::StringPiece& ident) { - RecordMap::iterator found = values_.find(ident); - if (found == values_.end()) { - NOTREACHED(); - return; - } - found->second.used = false; -} - -bool Scope::IsSetButUnused(const base::StringPiece& ident) const { - RecordMap::const_iterator found = values_.find(ident); - if (found != values_.end()) { - if (!found->second.used) { - return true; - } - } - return false; -} - -bool Scope::CheckForUnusedVars(Err* err) const { - for (RecordMap::const_iterator i = values_.begin(); - i != values_.end(); ++i) { - if (!i->second.used) { - std::string help = "You set the variable \"" + i->first.as_string() + - "\" here and it was unused before it went\nout of scope."; - - const BinaryOpNode* binary = i->second.value.origin()->AsBinaryOp(); - if (binary) { - // Make a nicer error message for normal var sets. - *err = Err(binary->left()->GetRange(), "Assignment had no effect.", - help); - } else { - // This will happen for internally-generated variables. - *err = Err(i->second.value.origin(), "Assignment had no effect.", help); - } - return false; - } - } - return true; -} - -void Scope::GetCurrentScopeValues(KeyValueVector* output) const { - output->reserve(values_.size()); - for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { - output->push_back(std::make_pair(i->first, i->second.value)); - } -} - -bool Scope::NonRecursiveMergeTo(Scope* dest, - const ParseNode* node_for_err, - const char* desc_for_err, - Err* err) const { - // Values. - for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { - const Value* existing_value = dest->GetValue(i->first); - if (existing_value) { - // Value present in both the source and the dest. - std::string desc_string(desc_for_err); - *err = Err(node_for_err, "Value collision.", - "This " + desc_string + " contains \"" + i->first.as_string() + "\""); - err->AppendSubErr(Err(i->second.value, "defined here.", - "Which would clobber the one in your current scope")); - err->AppendSubErr(Err(*existing_value, "defined here.", - "Executing " + desc_string + " should not conflict with anything " - "in the current\nscope.")); - return false; - } - dest->values_[i->first] = i->second; - } - - // Target defaults are owning pointers. - for (NamedScopeMap::const_iterator i = target_defaults_.begin(); - i != target_defaults_.end(); ++i) { - if (dest->GetTargetDefaults(i->first)) { - // TODO(brettw) it would be nice to know the origin of a - // set_target_defaults so we can give locations for the colliding target - // defaults. - std::string desc_string(desc_for_err); - *err = Err(node_for_err, "Target defaults collision.", - "This " + desc_string + " contains target defaults for\n" - "\"" + i->first + "\" which would clobber one for the\n" - "same target type in your current scope. It's unfortunate that I'm " - "too stupid\nto tell you the location of where the target defaults " - "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); - return false; - } - - Scope* s = new Scope(settings_); - i->second->NonRecursiveMergeTo(s, node_for_err, "<SHOULDN'T HAPPEN>", err); - dest->target_defaults_[i->first] = s; - } - - // Sources assignment filter. - if (sources_assignment_filter_) { - if (dest->GetSourcesAssignmentFilter()) { - // Sources assignment filter present in both the source and the dest. - std::string desc_string(desc_for_err); - *err = Err(node_for_err, "Assignment filter collision.", - "The " + desc_string + " contains a sources_assignment_filter which\n" - "would clobber the one in your current scope."); - return false; - } - dest->sources_assignment_filter_.reset( - new PatternList(*sources_assignment_filter_)); - } - - // Templates. - for (TemplateMap::const_iterator i = templates_.begin(); - i != templates_.end(); ++i) { - const FunctionCallNode* existing_template = dest->GetTemplate(i->first); - if (existing_template) { - // Rule present in both the source and the dest. - std::string desc_string(desc_for_err); - *err = Err(node_for_err, "Template collision.", - "This " + desc_string + " contains a template \"" + i->first + "\""); - err->AppendSubErr(Err(i->second->function(), "defined here.", - "Which would clobber the one in your current scope")); - err->AppendSubErr(Err(existing_template->function(), "defined here.", - "Executing " + desc_string + " should not conflict with anything " - "in the current\nscope.")); - return false; - } - dest->templates_.insert(*i); - } - - return true; -} - -Scope* Scope::MakeTargetDefaults(const std::string& target_type) { - if (GetTargetDefaults(target_type)) - return NULL; - - Scope** dest = &target_defaults_[target_type]; - if (*dest) { - NOTREACHED(); // Already set. - return *dest; - } - *dest = new Scope(settings_); - return *dest; -} - -const Scope* Scope::GetTargetDefaults(const std::string& target_type) const { - NamedScopeMap::const_iterator found = target_defaults_.find(target_type); - if (found != target_defaults_.end()) - return found->second; - if (containing()) - return containing()->GetTargetDefaults(target_type); - return NULL; -} - -const PatternList* Scope::GetSourcesAssignmentFilter() const { - if (sources_assignment_filter_) - return sources_assignment_filter_.get(); - if (containing()) - return containing()->GetSourcesAssignmentFilter(); - return NULL; -} - -void Scope::SetProcessingBuildConfig() { - DCHECK((mode_flags_ & kProcessingBuildConfigFlag) == 0); - mode_flags_ |= kProcessingBuildConfigFlag; -} - -void Scope::ClearProcessingBuildConfig() { - DCHECK(mode_flags_ & kProcessingBuildConfigFlag); - mode_flags_ &= ~(kProcessingBuildConfigFlag); -} - -bool Scope::IsProcessingBuildConfig() const { - if (mode_flags_ & kProcessingBuildConfigFlag) - return true; - if (containing()) - return containing()->IsProcessingBuildConfig(); - return false; -} - -void Scope::SetProcessingDefaultBuildConfig() { - DCHECK((mode_flags_ & kProcessingDefaultBuildConfigFlag) == 0); - mode_flags_ |= kProcessingDefaultBuildConfigFlag; -} - -void Scope::ClearProcessingDefaultBuildConfig() { - DCHECK(mode_flags_ & kProcessingDefaultBuildConfigFlag); - mode_flags_ &= ~(kProcessingDefaultBuildConfigFlag); -} - -bool Scope::IsProcessingDefaultBuildConfig() const { - if (mode_flags_ & kProcessingDefaultBuildConfigFlag) - return true; - if (containing()) - return containing()->IsProcessingDefaultBuildConfig(); - return false; -} - -void Scope::SetProcessingImport() { - DCHECK((mode_flags_ & kProcessingImportFlag) == 0); - mode_flags_ |= kProcessingImportFlag; -} - -void Scope::ClearProcessingImport() { - DCHECK(mode_flags_ & kProcessingImportFlag); - mode_flags_ &= ~(kProcessingImportFlag); -} - -bool Scope::IsProcessingImport() const { - if (mode_flags_ & kProcessingImportFlag) - return true; - if (containing()) - return containing()->IsProcessingImport(); - return false; -} - -void Scope::SetProperty(const void* key, void* value) { - if (!value) { - DCHECK(properties_.find(key) != properties_.end()); - properties_.erase(key); - } else { - properties_[key] = value; - } -} - -void* Scope::GetProperty(const void* key, const Scope** found_on_scope) const { - PropertyMap::const_iterator found = properties_.find(key); - if (found != properties_.end()) { - if (found_on_scope) - *found_on_scope = this; - return found->second; - } - if (containing()) - return containing()->GetProperty(key, found_on_scope); - return NULL; -} - -void Scope::AddProvider(ProgrammaticProvider* p) { - programmatic_providers_.insert(p); -} - -void Scope::RemoveProvider(ProgrammaticProvider* p) { - DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); - programmatic_providers_.erase(p); -} diff --git a/tools/gn/scope.h b/tools/gn/scope.h deleted file mode 100644 index 7d0547e..0000000 --- a/tools/gn/scope.h +++ /dev/null @@ -1,260 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_SCOPE_H_ -#define TOOLS_GN_SCOPE_H_ - -#include <map> -#include <set> - -#include "base/basictypes.h" -#include "base/containers/hash_tables.h" -#include "base/memory/scoped_ptr.h" -#include "tools/gn/err.h" -#include "tools/gn/pattern.h" -#include "tools/gn/value.h" - -class FunctionCallNode; -class ImportManager; -class ParseNode; -class Settings; -class TargetManager; - -// Scope for the script execution. -// -// Scopes are nested. Writing goes into the toplevel scope, reading checks -// values resursively down the stack until a match is found or there are no -// more containing scopes. -// -// A containing scope can be const or non-const. The const containing scope is -// used primarily to refer to the master build config which is shared across -// many invocations. A const containing scope, however, prevents us from -// marking variables "used" which prevents us from issuing errors on unused -// variables. So you should use a non-const containing scope whenever possible. -class Scope { - public: - typedef std::vector<std::pair<base::StringPiece, Value> > KeyValueVector; - - // Allows code to provide values for built-in variables. This class will - // automatically register itself on construction and deregister itself on - // destruction. - class ProgrammaticProvider { - public: - ProgrammaticProvider(Scope* scope) : scope_(scope) { - scope_->AddProvider(this); - } - ~ProgrammaticProvider() { - scope_->RemoveProvider(this); - } - - // Returns a non-null value if the given value can be programmatically - // generated, or NULL if there is none. - virtual const Value* GetProgrammaticValue( - const base::StringPiece& ident) = 0; - - protected: - Scope* scope_; - }; - - // Creates an empty toplevel scope. - Scope(const Settings* settings); - - // Creates a dependent scope. - Scope(Scope* parent); - Scope(const Scope* parent); - - ~Scope(); - - const Settings* settings() const { return settings_; } - - // See the const_/mutable_containing_ var declaraions below. Yes, it's a - // bit weird that we can have a const pointer to the "mutable" one. - Scope* mutable_containing() { return mutable_containing_; } - const Scope* mutable_containing() const { return mutable_containing_; } - const Scope* const_containing() const { return const_containing_; } - const Scope* containing() const { - return mutable_containing_ ? mutable_containing_ : const_containing_; - } - - // Returns NULL if there's no such value. - // - // counts_as_used should be set if the variable is being read in a way that - // should count for unused variable checking. - const Value* GetValue(const base::StringPiece& ident, - bool counts_as_used); - const Value* GetValue(const base::StringPiece& ident) const; - - // Same as GetValue, but if the value exists in a parent scope, we'll copy - // it to the current scope. If the return value is non-null, the value is - // guaranteed to be set in the current scope. Generatlly this will be used - // if the calling code is planning on modifying the value in-place. - // - // Since this is used when doing read-modifies, we never count this access - // as reading the variable, since we assume it will be written to. - Value* GetValueForcedToCurrentScope(const base::StringPiece& ident, - const ParseNode* set_node); - - // The set_node indicates the statement that caused the set, for displaying - // errors later. Returns a pointer to the value in the current scope (a copy - // is made for storage). - Value* SetValue(const base::StringPiece& ident, - const Value& v, - const ParseNode* set_node); - - // Templates associated with this scope. A template can only be set once, so - // AddTemplate will fail and return NULL if a rule with that name already - // exists. GetTemplate returns NULL if the rule doesn't exist, and it will - // check all containing scoped rescursively. - bool AddTemplate(const std::string& name, const FunctionCallNode* decl); - const FunctionCallNode* GetTemplate(const std::string& name) const; - - // Marks the given identifier as (un)used in the current scope. - void MarkUsed(const base::StringPiece& ident); - void MarkUnused(const base::StringPiece& ident); - - // Checks to see if the scope has a var set that hasn't been used. This is - // called before replacing the var with a different one. It does not check - // containing scopes. - // - // If the identifier is present but hasnn't been used, return true. - bool IsSetButUnused(const base::StringPiece& ident) const; - - // Checks the scope to see if any values were set but not used, and fills in - // the error and returns false if they were. - bool CheckForUnusedVars(Err* err) const; - - // Returns all values set in the current scope, without going to the parent - // scopes. - void GetCurrentScopeValues(KeyValueVector* output) const; - - // Copies this scope's values into the destination. Values from the - // containing scope(s) (normally shadowed into the current one) will not be - // copied, neither will the reference to the containing scope (this is why - // it's "non-recursive"). - // - // It is an error to merge a variable into a scope that already has something - // with that name in scope (meaning in that scope or in any of its containing - // scopes). If this happens, the error will be set and the function will - // return false. - // - // This is used in different contexts. When generating the error, the given - // parse node will be blamed, and the given desc will be used to describe - // the operation that doesn't support doing this. For example, desc_for_err - // would be "import" when doing an import, and the error string would say - // something like "The import contains...". - bool NonRecursiveMergeTo(Scope* dest, - const ParseNode* node_for_err, - const char* desc_for_err, - Err* err) const; - - // Makes an empty scope with the given name. Returns NULL if the name is - // already set. - Scope* MakeTargetDefaults(const std::string& target_type); - - // Gets the scope associated with the given target name, or null if it hasn't - // been set. - const Scope* GetTargetDefaults(const std::string& target_type) const; - - // Filter to apply when the sources variable is assigned. May return NULL. - const PatternList* GetSourcesAssignmentFilter() const; - void set_sources_assignment_filter( - scoped_ptr<PatternList> f) { - sources_assignment_filter_ = f.Pass(); - } - - // Indicates if we're currently processing the build configuration file. - // This is true when processing the config file for any toolchain. See also - // *ProcessingDefaultBuildConfig() below. - // - // To set or clear the flag, it must currently be in the opposite state in - // the current scope. Note that querying the state of the flag recursively - // checks all containing scopes until it reaches the top or finds the flag - // set. - void SetProcessingBuildConfig(); - void ClearProcessingBuildConfig(); - bool IsProcessingBuildConfig() const; - - // Indicates we're currently processing the default toolchain's build - // configuration file. - void SetProcessingDefaultBuildConfig(); - void ClearProcessingDefaultBuildConfig(); - bool IsProcessingDefaultBuildConfig() const; - - // Indicates if we're currently processing an import file. - // - // See SetProcessingBaseConfig for how flags work. - void SetProcessingImport(); - void ClearProcessingImport(); - bool IsProcessingImport() const; - - // Properties are opaque pointers that code can use to set state on a Scope - // that it can retrieve later. - // - // The key should be a pointer to some use-case-specific object (to avoid - // collisions, otherwise it doesn't matter). Memory management is up to the - // setter. Setting the value to NULL will delete the property. - // - // Getting a property recursively searches all scopes, and the optional - // |found_on_scope| variable will be filled with the actual scope containing - // the key (if the pointer is non-NULL). - void SetProperty(const void* key, void* value); - void* GetProperty(const void* key, const Scope** found_on_scope) const; - - private: - friend class ProgrammaticProvider; - - struct Record { - Record() : used(false) {} - Record(const Value& v) : used(false), value(v) {} - - bool used; // Set to true when the variable is used. - Value value; - }; - - void AddProvider(ProgrammaticProvider* p); - void RemoveProvider(ProgrammaticProvider* p); - - // Scopes can have no containing scope (both null), a mutable containing - // scope, or a const containing scope. The reason is that when we're doing - // a new target, we want to refer to the base_config scope which will be read - // by multiple threads at the same time, so we REALLY want it to be const. - // When you jsut do a nested {}, however, we sometimes want to be able to - // change things (especially marking unused vars). - const Scope* const_containing_; - Scope* mutable_containing_; - - const Settings* settings_; - - // Bits set for different modes. See the flag definitions in the .cc file - // for more. - unsigned mode_flags_; - - typedef base::hash_map<base::StringPiece, Record> RecordMap; - RecordMap values_; - - // Owning pointers. Note that this can't use string pieces since the names - // are constructed from Values which might be deallocated before this goes - // out of scope. - typedef base::hash_map<std::string, Scope*> NamedScopeMap; - NamedScopeMap target_defaults_; - - // Null indicates not set and that we should fallback to the containing - // scope's filter. - scoped_ptr<PatternList> sources_assignment_filter_; - - // Non-owning pointers, the function calls are owned by the input file which - // should be kept around by the input file manager. - typedef std::map<std::string, const FunctionCallNode*> TemplateMap; - TemplateMap templates_; - - typedef std::map<const void*, void*> PropertyMap; - PropertyMap properties_; - - typedef std::set<ProgrammaticProvider*> ProviderSet; - ProviderSet programmatic_providers_; - - DISALLOW_COPY_AND_ASSIGN(Scope); -}; - -#endif // TOOLS_GN_SCOPE_H_ diff --git a/tools/gn/scope_per_file_provider.cc b/tools/gn/scope_per_file_provider.cc deleted file mode 100644 index 1799d9e..0000000 --- a/tools/gn/scope_per_file_provider.cc +++ /dev/null @@ -1,186 +0,0 @@ -// 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/scope_per_file_provider.h" - -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/settings.h" -#include "tools/gn/source_file.h" -#include "tools/gn/toolchain_manager.h" -#include "tools/gn/value.h" - -const char* ScopePerFileProvider::kDefaultToolchain = - "default_toolchain"; -const char* ScopePerFileProvider::kPythonPath = - "python_path"; -const char* ScopePerFileProvider::kToolchain = - "toolchain"; -const char* ScopePerFileProvider::kRootOutputDirName = - "root_output_dir"; -const char* ScopePerFileProvider::kRootGenDirName = - "root_gen_dir"; -const char* ScopePerFileProvider::kTargetOutputDirName = - "target_output_dir"; -const char* ScopePerFileProvider::kTargetGenDirName = - "target_gen_dir"; -const char* ScopePerFileProvider::kRelativeRootOutputDirName = - "relative_root_output_dir"; -const char* ScopePerFileProvider::kRelativeRootGenDirName = - "relative_root_gen_dir"; -const char* ScopePerFileProvider::kRelativeTargetOutputDirName = - "relative_target_output_dir"; -const char* ScopePerFileProvider::kRelativeTargetGenDirName = - "relative_target_gen_dir"; - -ScopePerFileProvider::ScopePerFileProvider(Scope* scope, - const SourceFile& source_file) - : ProgrammaticProvider(scope), - source_file_(source_file) { -} - -ScopePerFileProvider::~ScopePerFileProvider() { -} - -const Value* ScopePerFileProvider::GetProgrammaticValue( - const base::StringPiece& ident) { - if (ident == kDefaultToolchain) - return GetDefaultToolchain(); - if (ident == kPythonPath) - return GetPythonPath(); - - if (ident == kTargetOutputDirName) - return GetTargetOutputDir(); - if (ident == kTargetGenDirName) - return GetTargetGenDir(); - - if (ident == kRelativeRootOutputDirName) - return GetRelativeRootOutputDir(); - if (ident == kRelativeRootGenDirName) - return GetRelativeRootGenDir(); - if (ident == kRelativeTargetOutputDirName) - return GetRelativeTargetOutputDir(); - if (ident == kRelativeTargetGenDirName) - return GetRelativeTargetGenDir(); - return NULL; -} - -// static -Value ScopePerFileProvider::GetRootOutputDir(const Settings* settings) { - return Value(NULL, GetRootOutputDirWithNoLastSlash(settings)); -} - -// static -Value ScopePerFileProvider::GetRootGenDir(const Settings* settings) { - return Value(NULL, GetRootGenDirWithNoLastSlash(settings)); -} - -const Value* ScopePerFileProvider::GetDefaultToolchain() { - if (!default_toolchain_) { - const ToolchainManager& toolchain_manager = - scope_->settings()->build_settings()->toolchain_manager(); - default_toolchain_.reset(new Value(NULL, - toolchain_manager.GetDefaultToolchainUnlocked().GetUserVisibleName( - false))); - } - return default_toolchain_.get(); -} - -const Value* ScopePerFileProvider::GetPythonPath() { - if (!python_path_) { - python_path_.reset(new Value(NULL, - FilePathToUTF8(scope_->settings()->build_settings()->python_path()))); - } - return python_path_.get(); -} - -const Value* ScopePerFileProvider::GetToolchain() { - if (!toolchain_) { - toolchain_.reset(new Value(NULL, - scope_->settings()->toolchain()->label().GetUserVisibleName(false))); - } - return toolchain_.get(); -} - -const Value* ScopePerFileProvider::GetTargetOutputDir() { - if (!target_output_dir_) { - target_output_dir_.reset(new Value(NULL, - GetRootOutputDirWithNoLastSlash(scope_->settings()) + - GetFileDirWithNoLastSlash())); - } - return target_output_dir_.get(); -} - -const Value* ScopePerFileProvider::GetTargetGenDir() { - if (!target_output_dir_) { - target_gen_dir_.reset(new Value(NULL, - GetRootGenDirWithNoLastSlash(scope_->settings()) + - GetFileDirWithNoLastSlash())); - } - return target_gen_dir_.get(); -} - -const Value* ScopePerFileProvider::GetRelativeRootOutputDir() { - if (!relative_root_output_dir_) { - relative_root_output_dir_.reset(new Value(NULL, - GetRelativeRootWithNoLastSlash() + - GetRootOutputDirWithNoLastSlash(scope_->settings()))); - } - return relative_root_output_dir_.get(); -} - -const Value* ScopePerFileProvider::GetRelativeRootGenDir() { - if (!relative_root_gen_dir_) { - relative_root_gen_dir_.reset(new Value(NULL, - GetRelativeRootWithNoLastSlash() + - GetRootGenDirWithNoLastSlash(scope_->settings()))); - } - return relative_root_gen_dir_.get(); -} - -const Value* ScopePerFileProvider::GetRelativeTargetOutputDir() { - if (!relative_target_output_dir_) { - relative_target_output_dir_.reset(new Value(NULL, - GetRelativeRootWithNoLastSlash() + - GetRootOutputDirWithNoLastSlash(scope_->settings()) + "obj/" + - GetFileDirWithNoLastSlash())); - } - return relative_target_output_dir_.get(); -} - -const Value* ScopePerFileProvider::GetRelativeTargetGenDir() { - if (!relative_target_gen_dir_) { - relative_target_gen_dir_.reset(new Value(NULL, - GetRelativeRootWithNoLastSlash() + - GetRootGenDirWithNoLastSlash(scope_->settings()) + - GetFileDirWithNoLastSlash())); - } - return relative_target_gen_dir_.get(); -} - -// static -std::string ScopePerFileProvider::GetRootOutputDirWithNoLastSlash( - const Settings* settings) { - const std::string& output_dir = - settings->build_settings()->build_dir().value(); - CHECK(!output_dir.empty()); - return output_dir.substr(0, output_dir.size() - 1); -} - -// static -std::string ScopePerFileProvider::GetRootGenDirWithNoLastSlash( - const Settings* settings) { - return GetRootOutputDirWithNoLastSlash(settings) + "/gen"; -} - -std::string ScopePerFileProvider::GetFileDirWithNoLastSlash() const { - std::string dir_value = source_file_.GetDir().value(); - return dir_value.substr(0, dir_value.size() - 1); -} - -std::string ScopePerFileProvider::GetRelativeRootWithNoLastSlash() const { - std::string inverted = InvertDir(source_file_.GetDir()); - if (inverted.empty()) - return "."; - return inverted.substr(0, inverted.size() - 1); -} diff --git a/tools/gn/scope_per_file_provider.h b/tools/gn/scope_per_file_provider.h deleted file mode 100644 index 1edb769..0000000 --- a/tools/gn/scope_per_file_provider.h +++ /dev/null @@ -1,79 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_SCOPE_PER_FILE_PROVIDER_H_ -#define TOOLS_GN_SCOPE_PER_FILE_PROVIDER_H_ - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "tools/gn/scope.h" -#include "tools/gn/source_file.h" - -// ProgrammaticProvider for a scope to provide it with per-file built-in -// variable support. -class ScopePerFileProvider : public Scope::ProgrammaticProvider { - public: - ScopePerFileProvider(Scope* scope, const SourceFile& source_file); - virtual ~ScopePerFileProvider(); - - // ProgrammaticProvider implementation. - virtual const Value* GetProgrammaticValue( - const base::StringPiece& ident) OVERRIDE; - - // Returns the value to expose to script for the given thing. These values - // are acually set globally, but are put here so we can keep all logic - // for converting paths to built-in values in this one file. - static Value GetRootOutputDir(const Settings* settings); - static Value GetRootGenDir(const Settings* settings); - - // Variable names. These two should be set globally independent of the file - // being processed. - static const char* kRootOutputDirName; - static const char* kRootGenDirName; - - // Variable names. These are provided by this class as needed. - static const char* kDefaultToolchain; - static const char* kPythonPath; - static const char* kToolchain; - static const char* kTargetOutputDirName; - static const char* kTargetGenDirName; - static const char* kRelativeRootOutputDirName; - static const char* kRelativeRootGenDirName; - static const char* kRelativeTargetOutputDirName; - static const char* kRelativeTargetGenDirName; - - private: - const Value* GetDefaultToolchain(); - const Value* GetPythonPath(); - const Value* GetToolchain(); - const Value* GetTargetOutputDir(); - const Value* GetTargetGenDir(); - const Value* GetRelativeRootOutputDir(); - const Value* GetRelativeRootGenDir(); - const Value* GetRelativeTargetOutputDir(); - const Value* GetRelativeTargetGenDir(); - - static std::string GetRootOutputDirWithNoLastSlash(const Settings* settings); - static std::string GetRootGenDirWithNoLastSlash(const Settings* settings); - - std::string GetFileDirWithNoLastSlash() const; - std::string GetRelativeRootWithNoLastSlash() const; - - SourceFile source_file_; - - // All values are lazily created. - scoped_ptr<Value> default_toolchain_; - scoped_ptr<Value> python_path_; - scoped_ptr<Value> toolchain_; - scoped_ptr<Value> target_output_dir_; - scoped_ptr<Value> target_gen_dir_; - scoped_ptr<Value> relative_root_output_dir_; - scoped_ptr<Value> relative_root_gen_dir_; - scoped_ptr<Value> relative_target_output_dir_; - scoped_ptr<Value> relative_target_gen_dir_; - - DISALLOW_COPY_AND_ASSIGN(ScopePerFileProvider); -}; - -#endif // TOOLS_GN_SCOPE_PER_FILE_PROVIDER_H_ diff --git a/tools/gn/secondary/base/BUILD.gn b/tools/gn/secondary/base/BUILD.gn deleted file mode 100644 index 2286b19..0000000 --- a/tools/gn/secondary/base/BUILD.gn +++ /dev/null @@ -1,919 +0,0 @@ -# found in the LICENSE file.
-
-component("base") {
- sources = [
- "../build/build_config.h",
- "third_party/dmg_fp/dmg_fp.h",
- "third_party/dmg_fp/g_fmt.cc",
- "third_party/dmg_fp/dtoa_wrapper.cc",
- "third_party/icu/icu_utf.cc",
- "third_party/icu/icu_utf.h",
- "third_party/nspr/prcpucfg.h",
- "third_party/nspr/prcpucfg_freebsd.h",
- "third_party/nspr/prcpucfg_linux.h",
- "third_party/nspr/prcpucfg_mac.h",
- "third_party/nspr/prcpucfg_nacl.h",
- "third_party/nspr/prcpucfg_openbsd.h",
- "third_party/nspr/prcpucfg_solaris.h",
- "third_party/nspr/prcpucfg_win.h",
- "third_party/nspr/prtime.cc",
- "third_party/nspr/prtime.h",
- "third_party/nspr/prtypes.h",
- "third_party/xdg_mime/xdgmime.h",
- "allocator/allocator_extension.cc",
- "allocator/allocator_extension.h",
- "allocator/type_profiler_control.cc",
- "allocator/type_profiler_control.h",
- "android/activity_status.cc",
- "android/activity_status.h",
- "android/base_jni_registrar.cc",
- "android/base_jni_registrar.h",
- "android/build_info.cc",
- "android/build_info.h",
- "android/cpu_features.cc",
- "android/fifo_utils.cc",
- "android/fifo_utils.h",
- "android/important_file_writer_android.cc",
- "android/important_file_writer_android.h",
- "android/scoped_java_ref.cc",
- "android/scoped_java_ref.h",
- "android/jni_android.cc",
- "android/jni_android.h",
- "android/jni_array.cc",
- "android/jni_array.h",
- "android/jni_helper.cc",
- "android/jni_helper.h",
- "android/jni_registrar.cc",
- "android/jni_registrar.h",
- "android/jni_string.cc",
- "android/jni_string.h",
- "android/memory_pressure_listener_android.cc",
- "android/memory_pressure_listener_android.h",
- "android/path_service_android.cc",
- "android/path_service_android.h",
- "android/path_utils.cc",
- "android/path_utils.h",
- "android/sys_utils.cc",
- "android/sys_utils.h",
- "android/thread_utils.h",
- "at_exit.cc",
- "at_exit.h",
- "atomic_ref_count.h",
- "atomic_sequence_num.h",
- "atomicops.h",
- "atomicops_internals_gcc.h",
- "atomicops_internals_mac.h",
- "atomicops_internals_tsan.h",
- "atomicops_internals_x86_gcc.cc",
- "atomicops_internals_x86_gcc.h",
- "atomicops_internals_x86_msvc.h",
- "base_export.h",
- "base_paths.cc",
- "base_paths.h",
- "base_paths_android.cc",
- "base_paths_android.h",
- "base_paths_mac.h",
- "base_paths_mac.mm",
- "base_paths_posix.cc",
- "base_paths_posix.h",
- "base_paths_win.cc",
- "base_paths_win.h",
- "base_switches.h",
- "base64.cc",
- "base64.h",
- "basictypes.h",
- "bind.h",
- "bind_helpers.cc",
- "bind_helpers.h",
- "bind_internal.h",
- "bind_internal_win.h",
- "bits.h",
- "build_time.cc",
- "build_time.h",
- "callback.h",
- "callback_helpers.h",
- "callback_internal.cc",
- "callback_internal.h",
- "cancelable_callback.h",
- "chromeos/chromeos_version.cc",
- "chromeos/chromeos_version.h",
- "command_line.cc",
- "command_line.h",
- "compiler_specific.h",
- "containers/hash_tables.h",
- "containers/linked_list.h",
- "containers/mru_cache.h",
- "containers/small_map.h",
- "containers/stack_container.h",
- "cpu.cc",
- "cpu.h",
- "critical_closure.h",
- "critical_closure_ios.mm",
- "debug/alias.cc",
- "debug/alias.h",
- "debug/crash_logging.cc",
- "debug/crash_logging.h",
- "debug/debug_on_start_win.cc",
- "debug/debug_on_start_win.h",
- "debug/debugger.cc",
- "debug/debugger.h",
- "debug/debugger_posix.cc",
- "debug/debugger_win.cc",
- # This file depends on files from the "allocator" target,
- # but this target does not depend on "allocator" (see
- # allocator.gyp for details).
- "debug/leak_annotations.h",
- "debug/leak_tracker.h",
- "debug/proc_maps_linux.cc",
- "debug/proc_maps_linux.h",
- "debug/profiler.cc",
- "debug/profiler.h",
- "debug/stack_trace.cc",
- "debug/stack_trace.h",
- "debug/stack_trace_android.cc",
- "debug/stack_trace_ios.mm",
- "debug/stack_trace_posix.cc",
- "debug/stack_trace_win.cc",
- "debug/trace_event.h",
- "debug/trace_event_android.cc",
- "debug/trace_event_impl.cc",
- "debug/trace_event_impl.h",
- "debug/trace_event_impl_constants.cc",
- "debug/trace_event_win.cc",
- "deferred_sequenced_task_runner.cc",
- "deferred_sequenced_task_runner.h",
- "environment.cc",
- "environment.h",
- "file_descriptor_posix.h",
- "file_util.cc",
- "file_util.h",
- "file_util_android.cc",
- "file_util_linux.cc",
- "file_util_mac.mm",
- "file_util_posix.cc",
- "file_util_win.cc",
- "file_version_info.h",
- "file_version_info_mac.h",
- "file_version_info_mac.mm",
- "file_version_info_win.cc",
- "file_version_info_win.h",
- "files/dir_reader_fallback.h",
- "files/dir_reader_linux.h",
- "files/dir_reader_posix.h",
- "files/file_enumerator.cc",
- "files/file_enumerator.h",
- "files/file_enumerator_posix.cc",
- "files/file_enumerator_win.cc",
- "files/file_path.cc",
- "files/file_path.h",
- "files/file_path_constants.cc",
- "files/file_path_watcher.cc",
- "files/file_path_watcher.h",
- "files/file_path_watcher_kqueue.cc",
- "files/file_path_watcher_linux.cc",
- "files/file_path_watcher_stub.cc",
- "files/file_path_watcher_win.cc",
- "files/file_util_proxy.cc",
- "files/file_util_proxy.h",
- "files/important_file_writer.h",
- "files/important_file_writer.cc",
- "files/memory_mapped_file.cc",
- "files/memory_mapped_file.h",
- "files/memory_mapped_file_posix.cc",
- "files/memory_mapped_file_win.cc",
- "files/scoped_temp_dir.cc",
- "files/scoped_temp_dir.h",
- "float_util.h",
- "format_macros.h",
- "gtest_prod_util.h",
- "guid.cc",
- "guid.h",
- "guid_posix.cc",
- "guid_win.cc",
- "hash.cc",
- "hash.h",
- "id_map.h",
- "ini_parser.cc",
- "ini_parser.h",
- "ios/device_util.h",
- "ios/device_util.mm",
- "ios/ios_util.h",
- "ios/ios_util.mm",
- "ios/scoped_critical_action.h",
- "ios/scoped_critical_action.mm",
- "json/json_file_value_serializer.cc",
- "json/json_file_value_serializer.h",
- "json/json_parser.cc",
- "json/json_parser.h",
- "json/json_reader.cc",
- "json/json_reader.h",
- "json/json_string_value_serializer.cc",
- "json/json_string_value_serializer.h",
- "json/json_value_converter.h",
- "json/json_writer.cc",
- "json/json_writer.h",
- "json/string_escape.cc",
- "json/string_escape.h",
- "lazy_instance.cc",
- "lazy_instance.h",
- "location.cc",
- "location.h",
- "logging.cc",
- "logging.h",
- "logging_win.cc",
- "logging_win.h",
- "mac/authorization_util.h",
- "mac/authorization_util.mm",
- "mac/bind_objc_block.h",
- "mac/bundle_locations.h",
- "mac/bundle_locations.mm",
- "mac/cocoa_protocols.h",
- "mac/foundation_util.h",
- "mac/foundation_util.mm",
- "mac/launch_services_util.cc",
- "mac/launch_services_util.h",
- "mac/launchd.cc",
- "mac/launchd.h",
- "mac/libdispatch_task_runner.cc",
- "mac/libdispatch_task_runner.h",
- "mac/mac_logging.h",
- "mac/mac_logging.cc",
- "mac/mac_util.h",
- "mac/mac_util.mm",
- "mac/objc_property_releaser.h",
- "mac/objc_property_releaser.mm",
- "mac/os_crash_dumps.cc",
- "mac/os_crash_dumps.h",
- "mac/scoped_aedesc.h",
- "mac/scoped_authorizationref.h",
- "mac/scoped_block.h",
- "mac/scoped_cftyperef.h",
- "mac/scoped_ioobject.h",
- "mac/scoped_ioplugininterface.h",
- "mac/scoped_launch_data.h",
- "mac/scoped_mach_port.cc",
- "mac/scoped_mach_port.h",
- "mac/scoped_nsautorelease_pool.h",
- "mac/scoped_nsautorelease_pool.mm",
- "mac/scoped_nsexception_enabler.h",
- "mac/scoped_nsexception_enabler.mm",
- "mac/scoped_nsobject.h",
- "mac/scoped_sending_event.h",
- "mac/scoped_sending_event.mm",
- "mac/sdk_forward_declarations.h",
- "memory/aligned_memory.cc",
- "memory/aligned_memory.h",
- "memory/discardable_memory.cc",
- "memory/discardable_memory.h",
- "memory/discardable_memory_android.cc",
- "memory/discardable_memory_mac.cc",
- "memory/linked_ptr.h",
- "memory/manual_constructor.h",
- "memory/memory_pressure_listener.cc",
- "memory/memory_pressure_listener.h",
- "memory/raw_scoped_refptr_mismatch_checker.h",
- "memory/ref_counted.cc",
- "memory/ref_counted.h",
- "memory/ref_counted_delete_on_message_loop.h",
- "memory/ref_counted_memory.cc",
- "memory/ref_counted_memory.h",
- "memory/scoped_handle.h",
- "memory/scoped_open_process.h",
- "memory/scoped_policy.h",
- "memory/scoped_ptr.h",
- "memory/scoped_vector.h",
- "memory/shared_memory.h",
- "memory/shared_memory_android.cc",
- "memory/shared_memory_nacl.cc",
- "memory/shared_memory_posix.cc",
- "memory/shared_memory_win.cc",
- "memory/singleton.cc",
- "memory/singleton.h",
- "memory/weak_ptr.cc",
- "memory/weak_ptr.h",
- "message_loop/message_loop.cc",
- "message_loop/message_loop.h",
- "message_loop/message_loop_proxy.cc",
- "message_loop/message_loop_proxy.h",
- "message_loop/message_loop_proxy_impl.cc",
- "message_loop/message_loop_proxy_impl.h",
- "message_loop/message_pump.cc",
- "message_loop/message_pump.h",
- "message_loop/message_pump_android.cc",
- "message_loop/message_pump_android.h",
- "message_loop/message_pump_default.cc",
- "message_loop/message_pump_default.h",
- "message_loop/message_pump_ozone.cc",
- "message_loop/message_pump_ozone.h",
- "message_loop/message_pump_win.cc",
- "message_loop/message_pump_win.h",
- "metrics/sample_map.cc",
- "metrics/sample_map.h",
- "metrics/sample_vector.cc",
- "metrics/sample_vector.h",
- "metrics/bucket_ranges.cc",
- "metrics/bucket_ranges.h",
- "metrics/histogram.cc",
- "metrics/histogram.h",
- "metrics/histogram_base.cc",
- "metrics/histogram_base.h",
- "metrics/histogram_flattener.h",
- "metrics/histogram_samples.cc",
- "metrics/histogram_samples.h",
- "metrics/histogram_snapshot_manager.cc",
- "metrics/histogram_snapshot_manager.h",
- "metrics/sparse_histogram.cc",
- "metrics/sparse_histogram.h",
- "metrics/statistics_recorder.cc",
- "metrics/statistics_recorder.h",
- "metrics/stats_counters.cc",
- "metrics/stats_counters.h",
- "metrics/stats_table.cc",
- "metrics/stats_table.h",
- "move.h",
- "native_library.h",
- "native_library_mac.mm",
- "native_library_posix.cc",
- "native_library_win.cc",
- "nix/mime_util_xdg.cc",
- "nix/mime_util_xdg.h",
- "nix/xdg_util.cc",
- "nix/xdg_util.h",
- "observer_list.h",
- "observer_list_threadsafe.h",
- "os_compat_android.cc",
- "os_compat_android.h",
- "os_compat_nacl.cc",
- "os_compat_nacl.h",
- "path_service.cc",
- "path_service.h",
- "pending_task.cc",
- "pending_task.h",
- "pickle.cc",
- "pickle.h",
- "platform_file.cc",
- "platform_file.h",
- "platform_file_posix.cc",
- "platform_file_win.cc",
- "port.h",
- "posix/eintr_wrapper.h",
- "posix/global_descriptors.cc",
- "posix/global_descriptors.h",
- "posix/unix_domain_socket_linux.cc",
- "posix/unix_domain_socket_linux.h",
- "power_monitor/power_monitor.cc",
- "power_monitor/power_monitor.h",
- "power_monitor/power_monitor_android.cc",
- "power_monitor/power_monitor_android.h",
- "power_monitor/power_monitor_ios.mm",
- "power_monitor/power_monitor_mac.mm",
- "power_monitor/power_monitor_posix.cc",
- "power_monitor/power_monitor_win.cc",
- "power_monitor/power_observer.h",
- "process.h",
- "process_info.h",
- "process_info_mac.cc",
- "process_info_win.cc",
- "process_linux.cc",
- "process_posix.cc",
- "process_util.h",
- "process_win.cc",
- "process/internal_linux.cc",
- "process/internal_linux.h",
- "process/kill.cc",
- "process/kill.h",
- "process/kill_mac.cc",
- "process/kill_posix.cc",
- "process/kill_win.cc",
- "process/launch.h",
- "process/launch_ios.cc",
- "process/launch_mac.cc",
- "process/launch_posix.cc",
- "process/launch_win.cc",
- "process/memory.h",
- "process/memory_linux.cc",
- "process/memory_mac.mm",
- "process/memory_win.cc",
- "process/process_handle_freebsd.cc",
- "process/process_handle_linux.cc",
- "process/process_handle_mac.cc",
- "process/process_handle_openbsd.cc",
- "process/process_handle_posix.cc",
- "process/process_handle_win.cc",
- "process/process_iterator.cc",
- "process/process_iterator.h",
- "process/process_iterator_freebsd.cc",
- "process/process_iterator_linux.cc",
- "process/process_iterator_mac.cc",
- "process/process_iterator_openbsd.cc",
- "process/process_iterator_win.cc",
- "process/process_metrics.h",
- "process/process_metrics_freebsd.cc",
- "process/process_metrics_ios.cc",
- "process/process_metrics_linux.cc",
- "process/process_metrics_mac.cc",
- "process/process_metrics_openbsd.cc",
- "process/process_metrics_posix.cc",
- "process/process_metrics_win.cc",
- "profiler/scoped_profile.cc",
- "profiler/scoped_profile.h",
- "profiler/alternate_timer.cc",
- "profiler/alternate_timer.h",
- "profiler/tracked_time.cc",
- "profiler/tracked_time.h",
- "rand_util.cc",
- "rand_util.h",
- "rand_util_nacl.cc",
- "rand_util_posix.cc",
- "rand_util_win.cc",
- "run_loop.cc",
- "run_loop.h",
- "safe_numerics.h",
- "safe_strerror_posix.cc",
- "safe_strerror_posix.h",
- "scoped_native_library.cc",
- "scoped_native_library.h",
- "sequence_checker.h",
- "sequence_checker_impl.cc",
- "sequence_checker_impl.h",
- "sequenced_task_runner.cc",
- "sequenced_task_runner.h",
- "sequenced_task_runner_helpers.h",
- "sha1.h",
- "sha1_portable.cc",
- "sha1_win.cc",
- "single_thread_task_runner.h",
- "stl_util.h",
- "strings/latin1_string_conversions.cc",
- "strings/latin1_string_conversions.h",
- "strings/nullable_string16.cc",
- "strings/nullable_string16.h",
- "strings/string16.cc",
- "strings/string16.h",
- "strings/string_number_conversions.cc",
- "strings/string_split.cc",
- "strings/string_split.h",
- "strings/string_number_conversions.h",
- "strings/string_piece.cc",
- "strings/string_piece.h",
- "strings/string_tokenizer.h",
- "strings/string_util.cc",
- "strings/string_util.h",
- "strings/string_util_constants.cc",
- "strings/string_util_posix.h",
- "strings/string_util_win.h",
- "strings/stringize_macros.h",
- "strings/stringprintf.cc",
- "strings/stringprintf.h",
- "strings/sys_string_conversions.h",
- "strings/sys_string_conversions_mac.mm",
- "strings/sys_string_conversions_posix.cc",
- "strings/sys_string_conversions_win.cc",
- "strings/utf_offset_string_conversions.cc",
- "strings/utf_offset_string_conversions.h",
- "strings/utf_string_conversion_utils.cc",
- "strings/utf_string_conversion_utils.h",
- "strings/utf_string_conversions.cc",
- "strings/utf_string_conversions.h",
- "supports_user_data.cc",
- "supports_user_data.h",
- "synchronization/cancellation_flag.cc",
- "synchronization/cancellation_flag.h",
- "synchronization/condition_variable.h",
- "synchronization/condition_variable_posix.cc",
- "synchronization/condition_variable_win.cc",
- "synchronization/lock.cc",
- "synchronization/lock.h",
- "synchronization/lock_impl.h",
- "synchronization/lock_impl_posix.cc",
- "synchronization/lock_impl_win.cc",
- "synchronization/spin_wait.h",
- "synchronization/waitable_event.h",
- "synchronization/waitable_event_posix.cc",
- "synchronization/waitable_event_watcher.h",
- "synchronization/waitable_event_watcher_posix.cc",
- "synchronization/waitable_event_watcher_win.cc",
- "synchronization/waitable_event_win.cc",
- "system_monitor/system_monitor.cc",
- "system_monitor/system_monitor.h",
- "sys_byteorder.h",
- "sys_info.cc",
- "sys_info.h",
- "sys_info_android.cc",
- "sys_info_chromeos.cc",
- "sys_info_freebsd.cc",
- "sys_info_ios.mm",
- "sys_info_linux.cc",
- "sys_info_mac.cc",
- "sys_info_openbsd.cc",
- "sys_info_posix.cc",
- "sys_info_win.cc",
- "task_runner.cc",
- "task_runner.h",
- "task_runner_util.h",
- "template_util.h",
- "thread_task_runner_handle.cc",
- "thread_task_runner_handle.h",
- "threading/non_thread_safe.h",
- "threading/non_thread_safe_impl.cc",
- "threading/non_thread_safe_impl.h",
- "threading/platform_thread.h",
- "threading/platform_thread_android.cc",
- "threading/platform_thread_linux.cc",
- "threading/platform_thread_mac.mm",
- "threading/platform_thread_posix.cc",
- "threading/platform_thread_win.cc",
- "threading/post_task_and_reply_impl.cc",
- "threading/post_task_and_reply_impl.h",
- "threading/sequenced_worker_pool.cc",
- "threading/sequenced_worker_pool.h",
- "threading/simple_thread.cc",
- "threading/simple_thread.h",
- "threading/thread.cc",
- "threading/thread.h",
- "threading/thread_checker.h",
- "threading/thread_checker_impl.cc",
- "threading/thread_checker_impl.h",
- "threading/thread_collision_warner.cc",
- "threading/thread_collision_warner.h",
- "threading/thread_id_name_manager.cc",
- "threading/thread_id_name_manager.h",
- "threading/thread_local.h",
- "threading/thread_local_posix.cc",
- "threading/thread_local_storage.h",
- "threading/thread_local_storage_posix.cc",
- "threading/thread_local_storage_win.cc",
- "threading/thread_local_win.cc",
- "threading/thread_restrictions.h",
- "threading/thread_restrictions.cc",
- "threading/watchdog.cc",
- "threading/watchdog.h",
- "threading/worker_pool.h",
- "threading/worker_pool.cc",
- "threading/worker_pool_posix.cc",
- "threading/worker_pool_posix.h",
- "threading/worker_pool_win.cc",
- "time/clock.cc",
- "time/clock.h",
- "time/default_clock.cc",
- "time/default_clock.h",
- "time/default_tick_clock.cc",
- "time/default_tick_clock.h",
- "time/tick_clock.cc",
- "time/tick_clock.h",
- "time/time.cc",
- "time/time.h",
- "time/time_mac.cc",
- "time/time_posix.cc",
- "time/time_win.cc",
- "timer/hi_res_timer_manager_posix.cc",
- "timer/hi_res_timer_manager_win.cc",
- "timer/hi_res_timer_manager.h",
- "timer/timer.cc",
- "timer/timer.h",
- "tracked_objects.cc",
- "tracked_objects.h",
- "tracking_info.cc",
- "tracking_info.h",
- "tuple.h",
- "values.cc",
- "values.h",
- "value_conversions.cc",
- "value_conversions.h",
- "version.cc",
- "version.h",
- "vlog.cc",
- "vlog.h",
- "win/enum_variant.cc",
- "win/enum_variant.h",
- "win/event_trace_consumer.h",
- "win/event_trace_controller.cc",
- "win/event_trace_controller.h",
- "win/event_trace_provider.cc",
- "win/event_trace_provider.h",
- "win/i18n.cc",
- "win/i18n.h",
- "win/iat_patch_function.cc",
- "win/iat_patch_function.h",
- "win/iunknown_impl.cc",
- "win/iunknown_impl.h",
- "win/message_window.cc",
- "win/message_window.h",
- "win/metro.cc",
- "win/metro.h",
- "win/object_watcher.cc",
- "win/object_watcher.h",
- "win/registry.cc",
- "win/registry.h",
- "win/resource_util.cc",
- "win/resource_util.h",
- "win/sampling_profiler.cc",
- "win/sampling_profiler.h",
- "win/scoped_bstr.cc",
- "win/scoped_bstr.h",
- "win/scoped_co_mem.h",
- "win/scoped_com_initializer.h",
- "win/scoped_comptr.h",
- "win/scoped_gdi_object.h",
- "win/scoped_handle.cc",
- "win/scoped_handle.h",
- "win/scoped_hdc.h",
- "win/scoped_hglobal.h",
- "win/scoped_process_information.cc",
- "win/scoped_process_information.h",
- "win/scoped_propvariant.h",
- "win/scoped_select_object.h",
- "win/scoped_variant.cc",
- "win/scoped_variant.h",
- "win/shortcut.cc",
- "win/shortcut.h",
- "win/startup_information.cc",
- "win/startup_information.h",
- "win/text_services_message_filter.cc",
- "win/text_services_message_filter.h",
- "win/win_util.cc",
- "win/win_util.h",
- "win/windows_version.cc",
- "win/windows_version.h",
- "win/wrapped_window_proc.cc",
- "win/wrapped_window_proc.h",
- ]
-
- # TODO(brettw) I don't understand the conditions this file is used.
- sources -= "files/file_path_watcher_stub.cc"
-
- sources -= [
- # TODO(brettw) ozone
- "message_loop/message_pump_ozone.cc",
- "message_loop/message_pump_ozone.h",
-
- "process/process_handle_freebsd.cc",
- "process/process_handle_openbsd.cc",
- "process/process_iterator_freebsd.cc",
- "process/process_iterator_openbsd.cc",
- "process/process_metrics_freebsd.cc",
- "process/process_metrics_openbsd.cc",
- "sys_info_freebsd.cc",
- "sys_info_openbsd.cc",
- ]
-
- if (!is_chromeos) {
- sources -= [
- "sys_info_chromeos.cc",
- ]
- }
- if (!is_mac) {
- sources -= "files/file_path_watcher_kqueue.cc"
- }
-
- # Remove nacl stuff.
- if (!is_nacl) {
- sources -= [
- "os_compat_nacl.cc",
- "os_compat_nacl.h",
- "rand_util_nacl.cc",
- "third_party/nspr/prcpucfg_nacl.h",
- "memory/shared_memory_nacl.cc",
- ]
- }
-
- # Windows stuff.
- if (is_win && !is_nacl) {
- sources -= [
- "strings/string16.cc",
- # Not using sha1_win.cc because it may have caused a
- # regression to page cycler moz.
- "sha1_win.cc",
- ]
-
- if (is_component_build) {
- sources -= "debug/debug_on_start_win.cc"
- }
- }
-
- # Remove non-Mac Unix stuff.
- if (!is_posix || is_mac) {
- sources -= [
- "nix/mime_util_xdg.cc",
- "nix/mime_util_xdg.h",
- "nix/xdg_util.cc",
- "nix/xdg_util.h",
- ]
- }
-
- defines = [
- "BASE_IMPLEMENTATION",
- ]
-
- deps = [
- ":base_static",
- "//base/allocator:allocator_extension_thunks",
- "//third_party/modp_b64",
- "//base/third_party/dynamic_annotations",
- ]
-}
-
-# This is the subset of files from base that should not be used with a dynamic
-# library. Note that this library cannot depend on base because base depends on
-# base_static.
-static_library("base_static") {
- sources = [
- "base_switches.cc",
- "base_switches.h",
- "win/pe_image.cc",
- "win/pe_image.h",
- ]
-}
-
-component("base_i18n") {
- sources = [
- "i18n/base_i18n_export.h",
- "i18n/bidi_line_iterator.cc",
- "i18n/bidi_line_iterator.h",
- "i18n/break_iterator.cc",
- "i18n/break_iterator.h",
- "i18n/char_iterator.cc",
- "i18n/char_iterator.h",
- "i18n/case_conversion.cc",
- "i18n/case_conversion.h",
- "i18n/file_util_icu.cc",
- "i18n/file_util_icu.h",
- "i18n/icu_encoding_detection.cc",
- "i18n/icu_encoding_detection.h",
- "i18n/icu_string_conversions.cc",
- "i18n/icu_string_conversions.h",
- "i18n/icu_util.cc",
- "i18n/icu_util.h",
- "i18n/number_formatting.cc",
- "i18n/number_formatting.h",
- "i18n/rtl.cc",
- "i18n/rtl.h",
- "i18n/string_compare.cc",
- "i18n/string_compare.h",
- "i18n/string_search.cc",
- "i18n/string_search.h",
- "i18n/time_formatting.cc",
- "i18n/time_formatting.h",
- ]
- deps = [
- ":base",
- "//base/third_party/dynamic_annotations",
- "//third_party/icu:icui18n",
- "//third_party/icu:icuuc",
- ]
- defines = [
- "BASE_I18N_IMPLEMENTATION",
- ]
- #'conditions': [
- # ['toolkit_uses_gtk==1', {
- # 'deps': [
- # # i18n/rtl.cc uses gtk
- # '../build/linux/system.gyp:gtk',
- # ],
- # }],
- # ['OS == "win"', {
- # # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- # 'msvs_disabled_warnings': [
- # 4267,
- # ],
- # }],
- #],
- #'export_dependent_settings': [
- # 'base',
- #],
- #'variables': {
- # 'enable_wexit_time_destructors': 1,
- # 'optimize': 'max',
- #},
-}
-
-static_library("test_support_base") {
- sources = [
- "perftimer.cc",
- "test/expectations/expectation.cc",
- "test/expectations/expectation.h",
- "test/expectations/parser.cc",
- "test/expectations/parser.h",
- "test/mock_chrome_application_mac.h",
- "test/mock_chrome_application_mac.mm",
- "test/mock_devices_changed_observer.cc",
- "test/mock_devices_changed_observer.h",
- "test/mock_time_provider.cc",
- "test/mock_time_provider.h",
- "test/multiprocess_test.cc",
- "test/multiprocess_test.h",
- "test/multiprocess_test_android.cc",
- "test/null_task_runner.cc",
- "test/null_task_runner.h",
- "test/perf_test_suite.cc",
- "test/perf_test_suite.h",
- "test/scoped_locale.cc",
- "test/scoped_locale.h",
- "test/scoped_path_override.cc",
- "test/scoped_path_override.h",
- "test/sequenced_task_runner_test_template.cc",
- "test/sequenced_task_runner_test_template.h",
- "test/sequenced_worker_pool_owner.cc",
- "test/sequenced_worker_pool_owner.h",
- "test/simple_test_clock.cc",
- "test/simple_test_clock.h",
- "test/simple_test_tick_clock.cc",
- "test/simple_test_tick_clock.h",
- "test/task_runner_test_template.cc",
- "test/task_runner_test_template.h",
- "test/test_file_util.h",
- "test/test_file_util_linux.cc",
- "test/test_file_util_mac.cc",
- "test/test_file_util_posix.cc",
- "test/test_file_util_win.cc",
- "test/test_listener_ios.h",
- "test/test_listener_ios.mm",
- "test/test_pending_task.cc",
- "test/test_pending_task.h",
- "test/test_process_killer_win.cc",
- "test/test_process_killer_win.h",
- "test/test_reg_util_win.cc",
- "test/test_reg_util_win.h",
- "test/test_shortcut_win.cc",
- "test/test_shortcut_win.h",
- "test/test_simple_task_runner.cc",
- "test/test_simple_task_runner.h",
- "test/test_suite.cc",
- "test/test_suite.h",
- "test/test_support_android.cc",
- "test/test_support_android.h",
- "test/test_support_ios.h",
- "test/test_support_ios.mm",
- "test/test_switches.cc",
- "test/test_switches.h",
- "test/test_timeouts.cc",
- "test/test_timeouts.h",
- "test/thread_test_helper.cc",
- "test/thread_test_helper.h",
- "test/trace_event_analyzer.cc",
- "test/trace_event_analyzer.h",
- "test/values_test_util.cc",
- "test/values_test_util.h",
- ]
- deps = [
- ":base",
- ":base_static",
- ":base_i18n",
- "//testing:gmock",
- "//testing:gtest",
- ]
-
- if (!is_posix) {
- sources -= [
- "test/scoped_locale.cc",
- "test/scoped_locale.h",
- ]
- }
- if (is_ios) {
- # Pull in specific Mac files for iOS (which have been filtered out
- # by file name rules).
- { # Temporarily override the assignment filter in a new scope.
- set_sources_assignment_filter([])
- sources += "test/test_file_util_mac.cc"
- }
- }
- #if (!is_bsd) {
- # sources -= "test/test_file_util_linux.cc"
- #}
- #if (use_gtk) {
- # deps += "/build/linux/system:gtk"
- #}
- #export_dependent_settings [
- # 'base',
- #]
-}
-
-config("perf_test_config") {
- defines = [ "PERF_TEST" ]
-}
-
-static_library("test_support_perf") {
- sources = [
- "perftimer.cc",
- "test/run_all_perftests.cc",
- ]
- deps = [
- ":base",
- "//testing:gtest",
- ]
-
- direct_dependent_configs = [ ":perf_test_config" ]
-
- #if (toolkit_uses_gtk) {
- # deps += "/build/linux/system:gtk",
- #}
-}
-
-static_library("run_all_unittests") {
- sources = [
- "test/run_all_unittests.cc",
- ]
- deps = [
- ":test_support_base",
- ]
-}
diff --git a/tools/gn/secondary/base/allocator/BUILD.gn b/tools/gn/secondary/base/allocator/BUILD.gn deleted file mode 100644 index bbcfe65..0000000 --- a/tools/gn/secondary/base/allocator/BUILD.gn +++ /dev/null @@ -1,6 +0,0 @@ -static_library("allocator_extension_thunks") {
- sources = [
- "allocator_extension_thunks.cc",
- "allocator_extension_thunks.h",
- ]
-}
diff --git a/tools/gn/secondary/base/third_party/dynamic_annotations/BUILD.gn b/tools/gn/secondary/base/third_party/dynamic_annotations/BUILD.gn deleted file mode 100644 index e3939c35..0000000 --- a/tools/gn/secondary/base/third_party/dynamic_annotations/BUILD.gn +++ /dev/null @@ -1,7 +0,0 @@ -static_library("dynamic_annotations") {
- sources = [
- "dynamic_annotations.c",
- "dynamic_annotations.h",
- "../valgrind/valgrind.h",
- ]
-}
diff --git a/tools/gn/secondary/build/config/BUILD.gn b/tools/gn/secondary/build/config/BUILD.gn deleted file mode 100644 index 74c57af..0000000 --- a/tools/gn/secondary/build/config/BUILD.gn +++ /dev/null @@ -1,52 +0,0 @@ -config("my_msvs") {
- includes = [ "../.." ]
- cflags = [
- "/Od", "/WX", "/Zi", "/Gy", "/GS", "/RTC1", "/EHsc",
- ]
- defines = [
- "CHROMIUM_BUILD",
- "TOOLKIT_VIEWS=1",
- "USE_LIBJPEG_TURBO=1",
- "ENABLE_ONE_CLICK_SIGNIN",
- "ENABLE_REMOTING=1",
- "ENABLE_WEBRTC=1",
- "ENABLE_CONFIGURATION_POLICY",
- "ENABLE_INPUT_SPEECH",
- "ENABLE_NOTIFICATIONS",
- "ENABLE_GPU=1",
- "ENABLE_EGLIMAGE=1",
- "ENABLE_TASK_MANAGER=1",
- "ENABLE_EXTENSIONS=1",
- "ENABLE_PLUGIN_INSTALLATION=1",
- "ENABLE_PLUGINS=1",
- "ENABLE_SESSION_SERVICE=1",
- "ENABLE_THEMES=1",
- "ENABLE_AUTOFILL_DIALOG=1",
- "ENABLE_BACKGROUND=1",
- "ENABLE_AUTOMATION=1",
- "ENABLE_GOOGLE_NOW=1",
- "ENABLE_LANGUAGE_DETECTION=1",
- "ENABLE_PRINTING=1",
- "ENABLE_CAPTIVE_PORTAL_DETECTION=1",
- "ENABLE_APP_LIST=1",
- "ENABLE_MESSAGE_CENTER=1",
- "ENABLE_SETTINGS_APP=1",
- "ENABLE_MANAGED_USERS=1",
- ]
-}
-
-config("feature_flags") {
- #defines =
-}
-
-config("debug") {
- defines = [
- "_DEBUG",
- "DYNAMIC_ANNOTATIONS_ENABLED=1",
- "WTF_USE_DYNAMIC_ANNOTATIONS=1",
- ]
-}
-
-config("release") {
-
-}
diff --git a/tools/gn/secondary/build/config/BUILDCONFIG.gn b/tools/gn/secondary/build/config/BUILDCONFIG.gn deleted file mode 100644 index 0245597..0000000 --- a/tools/gn/secondary/build/config/BUILDCONFIG.gn +++ /dev/null @@ -1,187 +0,0 @@ -# =============================================================================
-# BUILD FLAGS
-# =============================================================================
-#
-# This block lists input arguments to the build, along with their default
-# values. GN requires listing them explicitly so it can validate input and have
-# a central place to manage the build flags.
-#
-# If a value is specified on the command line, it will overwrite the defaults
-# given here, otherwise the default will be injected into the root scope.
-#
-# KEEP IN ALPHABETICAL ORDER and write a good description for everything.
-# Use "is_*" names for intrinsic platform descriptions and build modes, and
-# "use_*" names for optional features libraries, and configurations.
-declare_args() {
- is_component_build = 1
- is_chromeos = 0
- is_debug = 1
- use_ash = 0
- use_aura = 0
- use_ozone = 0
-}
-
-# =============================================================================
-# SOURCES FILTERS
-# =============================================================================
-#
-# These patterns filter out platform-specific files when assigning to the
-# sources variable. The magic variable |sources_assignment_filter| is applied
-# to each assignment or appending to the sources variable and matches are
-# automatcally removed.
-#
-# We define lists of filters for each platform for all builds so they can
-# be used by individual targets if necessary (a target can always change
-# sources_assignment_filter on itself if it needs something more specific).
-#
-# Note that the patterns are NOT regular expressions. Only "*" and "\b" (path
-# boundary = end of string or slash) are supported, and the entire string
-# muct match the pattern (so you need "*.cc" to match all .cc files, for
-# example).
-
-windows_sources_filters = [
- "*_win.cc",
- "*_win.h",
- "*_win_unittest.cc",
- "*\bwin/*",
-]
-mac_sources_filters = [
- "*_mac.h",
- "*_mac.cc",
- "*_mac.mm",
- "*_mac_unittest.h",
- "*_mac_unittest.cc",
- "*_mac_unittest.mm",
- "*\bmac/*",
- "*_cocoa.h",
- "*_cocoa.cc",
- "*_cocoa.mm",
- "*_cocoa_unittest.h",
- "*_cocoa_unittest.cc",
- "*_cocoa_unittest.mm",
- "*\bcocoa/*",
-]
-ios_sources_filters = [
- "*_ios.h",
- "*_ios.cc",
- "*_ios.mm",
- "*_ios_unittest.h",
- "*_ios_unittest.cc",
- "*_ios_unittest.mm",
- "*\bios/*",
-]
-objective_c_sources_filters = [
- "*.mm",
-]
-linux_sources_filters = [
- "*_linux.h",
- "*_linux.cc",
- "*_linux_unittest.h",
- "*_linux_unittest.cc",
- "*\blinux/*",
-]
-android_sources_filters = [
- "*_android.h",
- "*_android.cc",
- "*_android_unittest.h",
- "*_android_unittest.cc",
- "*\bandroid/*",
-]
-posix_sources_filters = [
- "*_posix.h",
- "*_posix.cc",
- "*_posix_unittest.h",
- "*_posix_unittest.cc",
- "*\bposix/*",
-]
-
-# Construct the full list of sources we're using for this platform.
-sources_assignment_filter = []
-if (is_win) {
- sources_assignment_filter += posix_sources_filters
-} else {
- sources_assignment_filter += windows_sources_filters
-}
-if (!is_mac) {
- sources_assignment_filter += mac_sources_filters
-}
-if (!is_ios) {
- sources_assignment_filter += ios_sources_filters
-}
-if (!is_mac && !is_ios) {
- sources_assignment_filter += objective_c_sources_filters
-}
-if (!is_linux) {
- sources_assignment_filter += linux_sources_filters
-}
-if (!is_android) {
- sources_assignment_filter += android_sources_filters
-}
-
-# This is the actual set.
-set_sources_assignment_filter(sources_assignment_filter)
-
-# =============================================================================
-# SYSTEM CONFIG
-# =============================================================================
-
-is_nacl = 0
-
-# =============================================================================
-# BUILD OPTIONS
-# =============================================================================
-
-if (is_component_build) {
- component_mode = "shared_library"
-} else {
- component_mode = "static_library"
-}
-
-# =============================================================================
-# TARGET DEFAULTS
-# =============================================================================
-#
-# Set up the default configuration for every build target of the given type.
-# The values configured here will be automatically set on the scope of the
-# corresponding target. Target definitions can add or remove to the settings
-# here as needed.
-
-# Holds all configs used for making native executables and libraries, to avoid
-# duplication in each target below.
-native_compiler_configs = [
- "//build/config:my_msvs", # TODO(brettw) eraseme
-
- "//build/config/compiler:chromium_code",
- "//build/config/compiler:disable_annoying_warnings",
- "//build/config/compiler:no_rtti",
- "//build/config/compiler:runtime_library",
-]
-if (is_win) {
- native_compiler_configs += "//build/config/win:sdk"
-}
-
-if (is_debug) {
- native_compiler_configs += "//build/config:debug"
-} else {
- native_compiler_configs += "//build/config::release"
-}
-
-set_defaults("executable") {
- configs = native_compiler_configs
-}
-
-set_defaults("static_library") {
- configs = native_compiler_configs
-}
-
-set_defaults("shared_library") {
- configs = native_compiler_configs
-}
-
-# ==============================================================================
-# TOOLCHAIN SETUP
-# ==============================================================================
-
-if (is_win) {
- set_default_toolchain("//build/config/win:32")
-}
diff --git a/tools/gn/secondary/build/config/compiler/BUILD.gn b/tools/gn/secondary/build/config/compiler/BUILD.gn deleted file mode 100644 index 0487828..0000000 --- a/tools/gn/secondary/build/config/compiler/BUILD.gn +++ /dev/null @@ -1,134 +0,0 @@ -# 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.
-
-# runtime_library -------------------------------------------------------------
-#
-# Sets the runtime library and associated options.
-#
-# We don't bother making multiple versions that are toggle-able since there
-# is more than one axis of control (which makes it complicated) and there's
-# no practical reason for anybody to change this since the CRT must agree.
-
-config("runtime_library") {
- if (is_component_build) {
- # Component mode: dynamic CRT.
- defines = [ "COMPONENT_BUILD" ]
- if (is_win) {
- # Since the library is shared, it requires exceptions or will give errors
- # about things not matching, so keep exceptions on.
- if (is_debug) {
- cflags = [ "/MDd" ]
- } else {
- cflags = [ "/MD" ]
- }
- }
- } else {
- # Static CRT.
- if (is_win) {
- # We don't use exceptions, and when we link statically we can just get
- # rid of them entirely.
- defines = [ "_HAS_EXCEPTIONS=0" ]
- if (is_debug) {
- cflags = [ "/MTd" ]
- } else {
- cflags = [ "/MT" ]
- }
- }
- }
-
- if (is_win) {
- defines += [
- "__STD_C",
- "__STDC_CONSTANT_MACROS",
- "__STDC_FORMAT_MACROS",
- "_CRT_RAND_S",
- "_CRT_SECURE_NO_DEPRECATE",
- "_SCL_SECURE_NO_DEPRECATE",
- "_UNICODE",
- "UNICODE",
- ]
- }
-}
-
-# chromium_code ---------------------------------------------------------------
-#
-# Toggles between higher and lower warnings for code that is (or isn't)
-# part of Chromium.
-
-config("chromium_code") {
- if (is_win) {
- cflags = [
- "/W4", # Warning level 4.
- ]
- }
-}
-config("no_chromium_code") {
- if (is_win) {
- cflags = [
- "/W3", # Warning level 3.
- "/wd4800", # Disable warning when forcing value to bool.
- ]
- defines = [
- "_CRT_NONSTDC_NO_WARNINGS",
- "_CRT_NONSTDC_NO_DEPRECATE",
- ]
- }
-}
-
-# rtti ------------------------------------------------------------------------
-#
-# Allows turning Run-Time Type Identification on or off.
-
-config("rtti") {
- if (is_win) {
- cflags = [ "/GR" ]
- }
-}
-config("no_rtti") {
- if (is_win) {
- cflags = [ "/GR-" ]
- }
-}
-
-# Warnings ---------------------------------------------------------------------
-
-config("disable_annoying_warnings") {
- if (is_win) {
- # Please keep ordered and add names if you add more.
- cflags = [
- "/wd4018", # Comparing signed and unsigned values.
- "/wd4100", # Unreferenced formal function parameter.
- "/wd4121", # Alignment of a member was sensitive to packing.
- "/wd4125", # Decimal digit terminates octal escape sequence.
- "/wd4127", # Conditional expression is constant.
- "/wd4130", # Logical operation on address of string constant.
- # TODO(brettw) is this necessary? If so, it should probably be on whoever
- # is silly enough to be doing this rather than globally.
- #"/wd4131", # Function uses old-style declarator.
- "/wd4189", # A variable was declared and initialized but never used.
- "/wd4201", # Nonstandard extension used: nameless struct/union.
- "/wd4238", # Nonstandard extension used: class rvalue used as lvalue.
- "/wd4244", # Conversion: possible loss of data.
- "/wd4245", # Conversion: signed/unsigned mismatch,
- "/wd4251", # Class needs to have dll-interface.
- "/wd4310", # Cast truncates constant value.
- "/wd4351", # Elements of array will be default initialized.
- "/wd4355", # 'this' used in base member initializer list.
- "/wd4396", # Inline friend template thing.
- "/wd4428", # Universal character name encountered in source.
- "/wd4481", # Nonstandard extension: override specifier.
- "/wd4503", # Decorated name length exceeded, name was truncated.
- "/wd4505", # Unreferenced local function has been removed.
- "/wd4510", # Default constructor could not be generated.
- "/wd4512", # Assignment operator could not be generated.
- "/wd4530", # Exception handler used, but unwind semantics not enabled.
- "/wd4610", # Class can never be instantiated, constructor required.
- "/wd4611", # C++ object destruction and 'catch'.
- "/wd4701", # Potentially uninitialized local variable name used.
- "/wd4702", # Unreachable code.
- "/wd4706", # Assignment within conditional expression.
- "/wd4819", # Character not in the current code page.
- ]
- }
-}
diff --git a/tools/gn/secondary/build/config/win/BUILD.gn b/tools/gn/secondary/build/config/win/BUILD.gn deleted file mode 100644 index 955504a..0000000 --- a/tools/gn/secondary/build/config/win/BUILD.gn +++ /dev/null @@ -1,184 +0,0 @@ -# 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.
-
-# Should only be running on Windows.
-assert(is_win)
-
-# Setup the Visual Studio state.
-#
-# Its argument is the location to write the environment files.
-# It will write "environment.x86" and "environment.x64" to this directory,
-# and return a list to us.
-#
-# The list contains the include path as its only element. (I'm expecting to
-# add more so it's currently a list inside a list.)
-msvc_config = [["foo"]]
-#exec_script("get_msvc_config.py",
- # [relative_root_output_dir],
- # "value")
-
-# 32-bit toolchain -------------------------------------------------------------
-
-toolchain("32") {
- tool("cc") {
- command = "ninja -t msvc -e \$arch -- cl.exe /nologo /showIncludes /FC @\$out.rsp /c \$in /Fo\$out /Fd\$pdbname"
- description = "CC \$out"
- rspfile = "\$out.rsp"
- rspfile_content = "\$defines \$includes \$cflags \$cflags_c"
- deps = "msvc"
- }
- tool("cxx") {
- command = "ninja -t msvc -e \$arch -- cl.exe /nologo /showIncludes /FC @\$out.rsp /c \$in /Fo\$out /Fd\$pdbname"
- description = "CXX \$out"
- rspfile = "\$out.rsp"
- rspfile_content = "\$defines \$includes \$cflags \$cflags_cc"
- deps = "msvc"
- }
- #tool("idl") {
- # command = $python_path gyp-win-tool midl-wrapper \$arch \$outdir \$tlb \$h \$dlldata \$iid \$
- # \$proxy \$in \$idlflags
- # description = IDL \$in
- #}
- #tool("rc") {
- # command = $python_path gyp-win-tool rc-wrapper \$arch rc.exe \$defines \$includes \$rcflags \$
- # /fo\$out \$in
- # description = RC \$in
- #}
- #tool("asm") {
- # command = $python_path gyp-win-tool asm-wrapper \$arch ml.exe \$defines \$includes /c /Fo \$
- # \$out \$in
- # description = ASM \$in
- #}
- tool("alink") {
- command = "$python_path gyp-win-tool link-wrapper \$arch lib.exe /nologo /ignore:4221 /OUT:\$out @\$out.rsp"
- description = "LIB \$out"
- rspfile = "\$out.rsp"
- rspfile_content = "\$in_newline \$libflags"
- }
- #tool("solink_embed_inc") {
- # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag \$
- # /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool \$
- # manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && \$
- # $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests \$
- # -out:\$dll.manifest && $python_path gyp-win-tool manifest-to-rc \$arch \$dll.manifest \$
- # \$dll.manifest.rc 2 && $python_path gyp-win-tool rc-wrapper \$arch rc.exe \$
- # \$dll.manifest.rc && $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$
- # \$implibflag /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp \$dll.manifest.res
- # description = LINK_EMBED_INC(DLL) \$dll
- # restat = 1
- # rspfile = \$dll.rsp
- # rspfile_content = \$libs \$in_newline \$ldflags
- #}
- #tool("solink_module_embed_inc") {
- # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag \$
- # /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool \$
- # manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && \$
- # $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests \$
- # -out:\$dll.manifest && $python_path gyp-win-tool manifest-to-rc \$arch \$dll.manifest \$
- # \$dll.manifest.rc 2 && $python_path gyp-win-tool rc-wrapper \$arch rc.exe \$
- # \$dll.manifest.rc && $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$
- # \$implibflag /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp \$dll.manifest.res
- # description = LINK_EMBED_INC(DLL) \$dll
- # restat = 1
- # rspfile = \$dll.rsp
- # rspfile_content = \$libs \$in_newline \$ldflags
- #}
- #rule link_embed_inc
- # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo /OUT:\$out \$
- # /PDB:\$out.pdb @\$out.rsp && $python_path gyp-win-tool manifest-wrapper \$arch cmd /c \$
- # if exist \$out.manifest del \$out.manifest && $python_path gyp-win-tool \$
- # manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests -out:\$out.manifest && \$
- # $python_path gyp-win-tool manifest-to-rc \$arch \$out.manifest \$out.manifest.rc 1 && \$
- # $python_path gyp-win-tool rc-wrapper \$arch rc.exe \$out.manifest.rc && \$
- # $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo /OUT:\$out /PDB:\$out.pdb \$
- # @\$out.rsp \$out.manifest.res
- # description = LINK_EMBED_INC \$out
- # rspfile = \$out.rsp
- # rspfile_content = \$in_newline \$libs \$ldflags
- #rule solink_embed
- # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag \$
- # /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool \$
- # manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && \$
- # $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests \$
- # -outputresource:\$dll;2
- # description = LINK_EMBED(DLL) \$dll
- # restat = 1
- # rspfile = \$dll.rsp
- # rspfile_content = \$libs \$in_newline \$ldflags
- #rule solink_module_embed
- # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag \$
- # /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool \$
- # manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && \$
- # $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests \$
- # -outputresource:\$dll;2
- # description = LINK_EMBED(DLL) \$dll
- # restat = 1
- # rspfile = \$dll.rsp
- # rspfile_content = \$libs \$in_newline \$ldflags
- #rule link_embed
- # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo /OUT:\$out \$
- # /PDB:\$out.pdb @\$out.rsp && $python_path gyp-win-tool manifest-wrapper \$arch cmd /c \$
- # if exist \$out.manifest del \$out.manifest && $python_path gyp-win-tool \$
- # manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests -outputresource:\$out;1
- # description = LINK_EMBED \$out
- # rspfile = \$out.rsp
- # rspfile_content = \$in_newline \$libs \$ldflags
- tool("solink") {
- command = "cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests -out:\$dll.manifest"
- description = "LINK(DLL) \$dll"
- restat = "1"
- rspfile = "\$dll.rsp"
- rspfile_content = "\$libs \$in_newline \$ldflags"
- }
- tool("solink_module") {
- command = "cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests -out:\$dll.manifet"
- description = "LINK(DLL) \$dll"
- restat = "1"
- rspfile = "\$dll.rsp"
- rspfile_content = "\$libs \$in_newline \$ldflags"
- }
- tool("link") {
- command = "cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo /OUT:\$out /PDB:\$out.pdb @\$out.rsp && $python_path gyp-win-tool manifest-wrapper \$arch cmd /c if exist \$out.manifest del \$out.manifest && $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests -out:\$out.manifest"
- description = "LINK \$out"
- rspfile = "\$out.rsp"
- rspfile_content = "\$in_newline \$libs \$ldflags"
- }
- tool("stamp") {
- command = "$python_path gyp-win-tool stamp \$out"
- description = "STAMP \$out"
- }
- tool("copy") {
- command = "$python_path gyp-win-tool recursive-mirror \$in \$out"
- description = "COPY \$in \$out"
- }
-}
-
-# 64-bit toolchain -------------------------------------------------------------
-
-toolchain("64") {
-}
-
-# SDK setup --------------------------------------------------------------------
-
-config("sdk") {
- # The include path is the stuff returned by the script plus out own WTL
- # checkout.
- # TODO(brettw) should adding WTL be at this level or should it be more on
- # a per-project basis?
- includes = msvc_config[0] + "../../third_party/wtl/include"
-
- defines = [
- "_ATL_NO_OPENGL",
- "_SECURE_ATL",
- "_WIN32_WINNT=0x0602",
- "_WINDOWS",
- "CERT_CHAIN_PARA_HAS_EXTRA_FIELDS",
- "NOMINMAX",
- "NTDDI_VERSION=0x06020000",
- "PSAPI_VERSION=1",
- "WIN32",
- "WIN32_LEAN_AND_MEAN",
- "WINVER=0x0602",
- ]
-}
diff --git a/tools/gn/secondary/build/config/win/get_msvc_config.py b/tools/gn/secondary/build/config/win/get_msvc_config.py deleted file mode 100644 index 01380cd..0000000 --- a/tools/gn/secondary/build/config/win/get_msvc_config.py +++ /dev/null @@ -1,77 +0,0 @@ -# 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. - -# This file returns the MSVC config used by the Windows build. -# It's a bit hardcoded right now. I suspect we want to build this functionality -# into GN itself in the future. - -import sys - -# This script expects one parameter: the path to the root output directory. - -# TODO(brettw): do escaping. -def FormatStringForGN(x): - return '"' + x + '"' - -def PrintListOfStrings(x): - print '[' - for i in x: - print FormatStringForGN(i) + ', ' - print ']' - -# GN wants system-absolutepaths to begin in slashes. -sdk_root = '/C:\\Program Files (x86)\\Windows Kits\\8.0\\' -vs_root = '/C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\' - -def GetIncludes(): - return [ - sdk_root + 'Include\\shared', - sdk_root + 'Include\\um', - sdk_root + 'Include\\winrt', - vs_root + 'VC\\atlmfc\\include' - ] - -def _FormatAsEnvironmentBlock(envvar_dict): - """Format as an 'environment block' directly suitable for CreateProcess. - Briefly this is a list of key=value\0, terminated by an additional \0. See - CreateProcess documentation for more details.""" - block = '' - nul = '\0' - for key, value in envvar_dict.iteritems(): - block += key + '=' + value + nul - block += nul - return block - -def WriteEnvFile(file_path, values): - f = open(file_path, "w") - f.write(_FormatAsEnvironmentBlock(values)) - -includes = GetIncludes() - -# Write the environment files. -WriteEnvFile(sys.argv[1] + '\\environment.x86', - { 'TMP': 'C:\\Users\\brettw\\AppData\\Local\\Temp', - 'SYSTEMROOT': 'C:\\Windows', - 'TEMP': 'C:\\Users\\brettw\\AppData\\Local\\Temp', - 'LIB': 'c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\lib;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\lib;', - 'LIBPATH': 'C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;', - 'PATH': 'C:\\apps\\depot_tools\\python_bin;c:\\Program Files (x86)\\Microsoft F#\\v4.0\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VSTSDB\\Deploy;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\BIN;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\Tools;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\VCPackages;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin;C:\\apps\\depot_tools\\python_bin;C:\\apps\\depot_tools\\;C:\\apps\\depot_tools\\;C:\\apps\\depot_tools\\;c:\\Program Files (x86)\\Microsoft F#\\v4.0\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VSTSDB\\Deploy;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\BIN;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\Tools;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\VCPackages;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\windows\\corpam;C:\\python_26_amd64\\files;C:\\Windows\\ccmsetup;c:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;c:\\Program Files\\Microsoft SQL Server\\100\\Tools\\Binn\\;c:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;c:\\cygwin\\bin;C:\\apps\\;C:\\apps\\depot_tools;C:\\Program Files (x86)\\Windows Kits\\8.0\\Windows Performance Toolkit\\;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Google\\Cert Installer;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Google\\google_appengine\\', - 'PATHEXT': '=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', - 'INCLUDE': 'c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\INCLUDE;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\INCLUDE;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include;'}) - -WriteEnvFile(sys.argv[1] + '\\environment.x64', - { 'TMP': 'C:\\Users\\brettw\\AppData\\Local\\Temp', - 'SYSTEMROOT': 'C:\\Windows', - 'TEMP': 'C:\\Users\\brettw\\AppData\\Local\\Temp', - 'LIB': 'c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB\\amd64;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB\\amd64;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\lib\\x64;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\lib;', - 'LIBPATH': 'C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework64\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB\\amd64;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB\\amd64;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;', - 'PATH': 'C:\\apps\\depot_tools\\python_bin;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\BIN\\amd64;C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework64\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\VCPackages;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\Tools;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools\\x64;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\x64;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin;C:\\apps\\depot_tools\\python_bin;C:\\apps\\depot_tools\\;C:\\apps\\depot_tools\\;C:\\apps\\depot_tools\\;c:\\Program Files (x86)\\Microsoft F#\\v4.0\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VSTSDB\\Deploy;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\BIN;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\Tools;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\VCPackages;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\windows\\corpam;C:\\python_26_amd64\\files;C:\\Windows\\ccmsetup;c:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;c:\\Program Files\\Microsoft SQL Server\\100\\Tools\\Binn\\;c:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;c:\\cygwin\\bin;C:\\apps\\;C:\\apps\\depot_tools;C:\\Program Files (x86)\\Windows Kits\\8.0\\Windows Performance Toolkit\\;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Google\\Cert Installer;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Google\\google_appengine\\', - 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', - 'INCLUDE': 'c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\INCLUDE;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\INCLUDE;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include;'}) - -# Return the includes and such. -print '[' -PrintListOfStrings(includes) -print ']' - diff --git a/tools/gn/secondary/build/config/win/get_msvc_config_real.py b/tools/gn/secondary/build/config/win/get_msvc_config_real.py deleted file mode 100644 index a209d7f..0000000 --- a/tools/gn/secondary/build/config/win/get_msvc_config_real.py +++ /dev/null @@ -1,575 +0,0 @@ -# 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. - -# This file copies the logic from GYP to find the MSVC configuration. It's not -# currently used because it is too slow. We will probably build this -# functionality into the C++ code in the future. - -"""Handle version information related to Visual Stuio.""" - -import errno -import os -import re -import subprocess -import sys - -class VisualStudioVersion(object): - """Information regarding a version of Visual Studio.""" - - def __init__(self, short_name, description, - solution_version, project_version, flat_sln, uses_vcxproj, - path, sdk_based, default_toolset=None): - self.short_name = short_name - self.description = description - self.solution_version = solution_version - self.project_version = project_version - self.flat_sln = flat_sln - self.uses_vcxproj = uses_vcxproj - self.path = path - self.sdk_based = sdk_based - self.default_toolset = default_toolset - - def ShortName(self): - return self.short_name - - def Description(self): - """Get the full description of the version.""" - return self.description - - def SolutionVersion(self): - """Get the version number of the sln files.""" - return self.solution_version - - def ProjectVersion(self): - """Get the version number of the vcproj or vcxproj files.""" - return self.project_version - - def FlatSolution(self): - return self.flat_sln - - def UsesVcxproj(self): - """Returns true if this version uses a vcxproj file.""" - return self.uses_vcxproj - - def ProjectExtension(self): - """Returns the file extension for the project.""" - return self.uses_vcxproj and '.vcxproj' or '.vcproj' - - def Path(self): - """Returns the path to Visual Studio installation.""" - return self.path - - def ToolPath(self, tool): - """Returns the path to a given compiler tool. """ - return os.path.normpath(os.path.join(self.path, "VC/bin", tool)) - - def DefaultToolset(self): - """Returns the msbuild toolset version that will be used in the absence - of a user override.""" - return self.default_toolset - - def SetupScript(self, target_arch): - """Returns a command (with arguments) to be used to set up the - environment.""" - # Check if we are running in the SDK command line environment and use - # the setup script from the SDK if so. |target_arch| should be either - # 'x86' or 'x64'. - assert target_arch in ('x86', 'x64') - sdk_dir = os.environ.get('WindowsSDKDir') - if self.sdk_based and sdk_dir: - return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')), - '/' + target_arch] - else: - # We don't use VC/vcvarsall.bat for x86 because vcvarsall calls - # vcvars32, which it can only find if VS??COMNTOOLS is set, which it - # isn't always. - if target_arch == 'x86': - return [os.path.normpath( - os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))] - else: - assert target_arch == 'x64' - arg = 'x86_amd64' - if (os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or - os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): - # Use the 64-on-64 compiler if we can. - arg = 'amd64' - return [os.path.normpath( - os.path.join(self.path, 'VC/vcvarsall.bat')), arg] - - -def _RegistryQueryBase(sysdir, key, value): - """Use reg.exe to read a particular key. - - While ideally we might use the win32 module, we would like gyp to be - python neutral, so for instance cygwin python lacks this module. - - Arguments: - sysdir: The system subdirectory to attempt to launch reg.exe from. - key: The registry key to read from. - value: The particular value to read. - Return: - stdout from reg.exe, or None for failure. - """ - # Skip if not on Windows or Python Win32 setup issue - if sys.platform not in ('win32', 'cygwin'): - return None - # Setup params to pass to and attempt to launch reg.exe - cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'), - 'query', key] - if value: - cmd.extend(['/v', value]) - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid - # Note that the error text may be in [1] in some cases - text = p.communicate()[0] - # Check return code from reg.exe; officially 0==success and 1==error - if p.returncode: - return None - return text - - -def _RegistryQuery(key, value=None): - """Use reg.exe to read a particular key through _RegistryQueryBase. - - First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If - that fails, it falls back to System32. Sysnative is available on Vista and - up and available on Windows Server 2003 and XP through KB patch 942589. Note - that Sysnative will always fail if using 64-bit python due to it being a - virtual directory and System32 will work correctly in the first place. - - KB 942589 - http://support.microsoft.com/kb/942589/en-us. - - Arguments: - key: The registry key. - value: The particular registry value to read (optional). - Return: - stdout from reg.exe, or None for failure. - """ - text = None - try: - text = _RegistryQueryBase('Sysnative', key, value) - except OSError, e: - if e.errno == errno.ENOENT: - text = _RegistryQueryBase('System32', key, value) - else: - raise - return text - - -def _RegistryGetValue(key, value): - """Use reg.exe to obtain the value of a registry key. - - Args: - key: The registry key. - value: The particular registry value to read. - Return: - contents of the registry key's value, or None on failure. - """ - text = _RegistryQuery(key, value) - if not text: - return None - # Extract value. - match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text) - if not match: - return None - return match.group(1) - - -def _RegistryKeyExists(key): - """Use reg.exe to see if a key exists. - - Args: - key: The registry key to check. - Return: - True if the key exists - """ - if not _RegistryQuery(key): - return False - return True - - -def _CreateVersion(name, path, sdk_based=False): - """Sets up MSVS project generation. - - Setup is based off the GYP_MSVS_VERSION environment variable or whatever is - autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is - passed in that doesn't match a value in versions python will throw a error. - """ - if path: - path = os.path.normpath(path) - versions = { - '2013': VisualStudioVersion('2013', - 'Visual Studio 2013', - solution_version='13.00', - project_version='4.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v110'), - '2013e': VisualStudioVersion('2013e', - 'Visual Studio 2013', - solution_version='13.00', - project_version='4.0', - flat_sln=True, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v110'), - '2012': VisualStudioVersion('2012', - 'Visual Studio 2012', - solution_version='12.00', - project_version='4.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v110'), - '2012e': VisualStudioVersion('2012e', - 'Visual Studio 2012', - solution_version='12.00', - project_version='4.0', - flat_sln=True, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v110'), - '2010': VisualStudioVersion('2010', - 'Visual Studio 2010', - solution_version='11.00', - project_version='4.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based), - '2010e': VisualStudioVersion('2010e', - 'Visual Studio 2010', - solution_version='11.00', - project_version='4.0', - flat_sln=True, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based), - '2008': VisualStudioVersion('2008', - 'Visual Studio 2008', - solution_version='10.00', - project_version='9.00', - flat_sln=False, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - '2008e': VisualStudioVersion('2008e', - 'Visual Studio 2008', - solution_version='10.00', - project_version='9.00', - flat_sln=True, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - '2005': VisualStudioVersion('2005', - 'Visual Studio 2005', - solution_version='9.00', - project_version='8.00', - flat_sln=False, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - '2005e': VisualStudioVersion('2005e', - 'Visual Studio 2005', - solution_version='9.00', - project_version='8.00', - flat_sln=True, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - } - return versions[str(name)] - - -def _ConvertToCygpath(path): - """Convert to cygwin path if we are using cygwin.""" - if sys.platform == 'cygwin': - p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE) - path = p.communicate()[0].strip() - return path - - -def _DetectVisualStudioVersions(versions_to_check, force_express): - """Collect the list of installed visual studio versions. - - Returns: - A list of visual studio versions installed in descending order of - usage preference. - Base this on the registry and a quick check if devenv.exe exists. - Only versions 8-10 are considered. - Possibilities are: - 2005(e) - Visual Studio 2005 (8) - 2008(e) - Visual Studio 2008 (9) - 2010(e) - Visual Studio 2010 (10) - 2012(e) - Visual Studio 2012 (11) - 2013(e) - Visual Studio 2013 (11) - Where (e) is e for express editions of MSVS and blank otherwise. - """ - version_to_year = { - '8.0': '2005', - '9.0': '2008', - '10.0': '2010', - '11.0': '2012', - '12.0': '2013', - } - versions = [] - for version in versions_to_check: - # Old method of searching for which VS version is installed - # We don't use the 2010-encouraged-way because we also want to get the - # path to the binaries, which it doesn't offer. - keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version, - r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version, - r'HKLM\Software\Microsoft\VCExpress\%s' % version, - r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version] - for index in range(len(keys)): - path = _RegistryGetValue(keys[index], 'InstallDir') - if not path: - continue - path = _ConvertToCygpath(path) - # Check for full. - full_path = os.path.join(path, 'devenv.exe') - express_path = os.path.join(path, 'vcexpress.exe') - if not force_express and os.path.exists(full_path): - # Add this one. - versions.append(_CreateVersion(version_to_year[version], - os.path.join(path, '..', '..'))) - # Check for express. - elif os.path.exists(express_path): - # Add this one. - versions.append(_CreateVersion(version_to_year[version] + 'e', - os.path.join(path, '..', '..'))) - - # The old method above does not work when only SDK is installed. - keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7', - r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'] - for index in range(len(keys)): - path = _RegistryGetValue(keys[index], version) - if not path: - continue - path = _ConvertToCygpath(path) - versions.append(_CreateVersion(version_to_year[version] + 'e', - os.path.join(path, '..'), sdk_based=True)) - - return versions - - -def SelectVisualStudioVersion(version='auto'): - """Select which version of Visual Studio projects to generate. - - Arguments: - version: Hook to allow caller to force a particular version (vs auto). - Returns: - An object representing a visual studio project format version. - """ - # In auto mode, check environment variable for override. - if version == 'auto': - version = os.environ.get('GYP_MSVS_VERSION', 'auto') - version_map = { - 'auto': ('10.0', '9.0', '8.0', '11.0'), - '2005': ('8.0',), - '2005e': ('8.0',), - '2008': ('9.0',), - '2008e': ('9.0',), - '2010': ('10.0',), - '2010e': ('10.0',), - '2012': ('11.0',), - '2012e': ('11.0',), - '2013': ('12.0',), - '2013e': ('12.0',), - } - override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH') - if override_path: - msvs_version = os.environ.get('GYP_MSVS_VERSION') - if not msvs_version or 'e' not in msvs_version: - raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be ' - 'set to an "e" version (e.g. 2010e)') - return _CreateVersion(msvs_version, override_path, sdk_based=True) - version = str(version) - versions = _DetectVisualStudioVersions(version_map[version], 'e' in version) - if not versions: - if version == 'auto': - # Default to 2005 if we couldn't find anything - return _CreateVersion('2005', None) - else: - return _CreateVersion(version, None) - return versions[0] - -def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out): - """It's not sufficient to have the absolute path to the compiler, linker, - etc. on Windows, as those tools rely on .dlls being in the PATH. We also - need to support both x86 and x64 compilers within the same build (to support - msvs_target_platform hackery). Different architectures require a different - compiler binary, and different supporting environment variables (INCLUDE, - LIB, LIBPATH). So, we extract the environment here, wrap all invocations - of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which - sets up the environment, and then we do not prefix the compiler with - an absolute path, instead preferring something like "cl.exe" in the rule - which will then run whichever the environment setup has put in the path. - When the following procedure to generate environment files does not - meet your requirement (e.g. for custom toolchains), you can pass - "-G ninja_use_custom_environment_files" to the gyp to suppress file - generation and use custom environment files prepared by yourself.""" - archs = ('x86', 'x64') - if generator_flags.get('ninja_use_custom_environment_files', 0): - cl_paths = {} - for arch in archs: - cl_paths[arch] = 'cl.exe' - return cl_paths - vs = GetVSVersion(generator_flags) - cl_paths = {} - for arch in archs: - # Extract environment variables for subprocesses. - args = vs.SetupScript(arch) - args.extend(('&&', 'set')) - popen = subprocess.Popen( - args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - variables, _ = popen.communicate() - env = _ExtractImportantEnvironment(variables) - env_block = _FormatAsEnvironmentBlock(env) - f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') - f.write(env_block) - f.close() - - # Find cl.exe location for this architecture. - args = vs.SetupScript(arch) - args.extend(('&&', - 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i')) - popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) - output, _ = popen.communicate() - cl_paths[arch] = _ExtractCLPath(output) - return cl_paths - -def OpenOutput(path, mode='w'): - """Open |path| for writing, creating directories if necessary.""" - try: - os.makedirs(os.path.dirname(path)) - except OSError: - pass - return open(path, mode) - -vs_version = None -def GetVSVersion(generator_flags): - global vs_version - if not vs_version: - vs_version = SelectVisualStudioVersion( - generator_flags.get('msvs_version', 'auto')) - return vs_version - -def _ExtractImportantEnvironment(output_of_set): - """Extracts environment variables required for the toolchain to run from - a textual dump output by the cmd.exe 'set' command.""" - envvars_to_save = ( - 'goma_.*', # TODO(scottmg): This is ugly, but needed for goma. - 'include', - 'lib', - 'libpath', - 'path', - 'pathext', - 'systemroot', - 'temp', - 'tmp', - ) - env = {} - for line in output_of_set.splitlines(): - for envvar in envvars_to_save: - if re.match(envvar + '=', line.lower()): - var, setting = line.split('=', 1) - if envvar == 'path': - # Our own rules (for running gyp-win-tool) and other actions in - # Chromium rely on python being in the path. Add the path to this - # python here so that if it's not in the path when ninja is run - # later, python will still be found. - setting = os.path.dirname(sys.executable) + os.pathsep + setting - env[var.upper()] = setting - break - for required in ('SYSTEMROOT', 'TEMP', 'TMP'): - if required not in env: - raise Exception('Environment variable "%s" ' - 'required to be set to valid path' % required) - return env - -def _FormatAsEnvironmentBlock(envvar_dict): - """Format as an 'environment block' directly suitable for CreateProcess. - Briefly this is a list of key=value\0, terminated by an additional \0. See - CreateProcess documentation for more details.""" - block = '' - nul = '\0' - for key, value in envvar_dict.iteritems(): - block += key + '=' + value + nul - block += nul - return block - - -def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags): - """It's not sufficient to have the absolute path to the compiler, linker, - etc. on Windows, as those tools rely on .dlls being in the PATH. We also - need to support both x86 and x64 compilers within the same build (to support - msvs_target_platform hackery). Different architectures require a different - compiler binary, and different supporting environment variables (INCLUDE, - LIB, LIBPATH). So, we extract the environment here, wrap all invocations - of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which - sets up the environment, and then we do not prefix the compiler with - an absolute path, instead preferring something like "cl.exe" in the rule - which will then run whichever the environment setup has put in the path. - When the following procedure to generate environment files does not - meet your requirement (e.g. for custom toolchains), you can pass - "-G ninja_use_custom_environment_files" to the gyp to suppress file - generation and use custom environment files prepared by yourself.""" - archs = ('x86', 'x64') - if generator_flags.get('ninja_use_custom_environment_files', 0): - cl_paths = {} - for arch in archs: - cl_paths[arch] = 'cl.exe' - return cl_paths - vs = GetVSVersion(generator_flags) - cl_paths = {} - for arch in archs: - # Extract environment variables for subprocesses. - args = vs.SetupScript(arch) - args.extend(('&&', 'set')) - popen = subprocess.Popen( - args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - variables, _ = popen.communicate() - env = _ExtractImportantEnvironment(variables) - env_block = _FormatAsEnvironmentBlock(env) - f = OpenOutput(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') - f.write(env_block) - f.close() - - # Find cl.exe location for this architecture. - args = vs.SetupScript(arch) - args.extend(('&&', - 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i')) - popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) - output, _ = popen.communicate() - cl_paths[arch] = _ExtractCLPath(output) - return cl_paths - -def _ExtractCLPath(output_of_where): - """Gets the path to cl.exe based on the output of calling the environment - setup batch file, followed by the equivalent of `where`.""" - # Take the first line, as that's the first found in the PATH. - for line in output_of_where.strip().splitlines(): - if line.startswith('LOC:'): - return line[len('LOC:'):].strip() - -#print SelectVisualStudioVersion().DefaultToolset() -#GenerateEnvironmentFiles("D:\\src\\src1\\src\\out\\gn\\eraseme", {}) -#print '"', GetVSVersion({}).Path(), '"' -print '"', GetVSVersion({}).sdk_based, '"' - -#------------------------------------------------------------------------------- - -version_info = { - '2010': { - 'includes': [ - 'VC\\atlmfc\\include', - ], - }, -} diff --git a/tools/gn/secondary/ipc/BUILD.gn b/tools/gn/secondary/ipc/BUILD.gn deleted file mode 100644 index 5e55ee9..0000000 --- a/tools/gn/secondary/ipc/BUILD.gn +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright (c) 2012 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.
-
-component("ipc") {
- sources = [
- "file_descriptor_set_posix.cc",
- "file_descriptor_set_posix.h",
- "ipc_channel.cc",
- "ipc_channel.h",
- "ipc_channel_factory.cc",
- "ipc_channel_factory.h",
- "ipc_channel_handle.h",
- "ipc_channel_nacl.cc",
- "ipc_channel_nacl.h",
- "ipc_channel_posix.cc",
- "ipc_channel_posix.h",
- "ipc_channel_proxy.cc",
- "ipc_channel_proxy.h",
- "ipc_channel_reader.cc",
- "ipc_channel_reader.h",
- "ipc_channel_win.cc",
- "ipc_channel_win.h",
- "ipc_descriptors.h",
- "ipc_export.h",
- "ipc_forwarding_message_filter.cc",
- "ipc_forwarding_message_filter.h",
- "ipc_listener.h",
- "ipc_logging.cc",
- "ipc_logging.h",
- "ipc_message.cc",
- "ipc_message.h",
- "ipc_message_macros.h",
- "ipc_message_start.h",
- "ipc_message_utils.cc",
- "ipc_message_utils.h",
- "ipc_param_traits.h",
- "ipc_platform_file.cc",
- "ipc_platform_file.h",
- "ipc_sender.h",
- "ipc_switches.cc",
- "ipc_switches.h",
- "ipc_sync_channel.cc",
- "ipc_sync_channel.h",
- "ipc_sync_message.cc",
- "ipc_sync_message.h",
- "ipc_sync_message_filter.cc",
- "ipc_sync_message_filter.h",
- "param_traits_log_macros.h",
- "param_traits_macros.h",
- "param_traits_read_macros.h",
- "param_traits_write_macros.h",
- "struct_constructor_macros.h",
- "struct_destructor_macros.h",
- "unix_domain_socket_util.cc",
- "unix_domain_socket_util.h",
- ]
-
- #if (!is_untrusted_nacl) {
- sources -= [
- "ipc_channel_nacl.cc",
- "ipc_channel_nacl.h",
- ]
-
- if (is_win || is_ios) {
- sources -= [
- "ipc_channel_factory.cc",
- "unix_domain_socket_util.cc",
- ]
- }
-
- defines = [ "IPC_IMPLEMENTATION" ]
-
- deps = [
- "//base",
- # TODO(viettrungluu): Needed for base/lazy_instance.h, which is suspect.
- "//base/third_party/dynamic_annotations",
- ]
-}
-
-test("ipc_tests") {
- sources = [
- "file_descriptor_set_posix_unittest.cc",
- "ipc_channel_posix_unittest.cc",
- "ipc_channel_unittest.cc",
- "ipc_fuzzing_tests.cc",
- "ipc_message_unittest.cc",
- "ipc_message_utils_unittest.cc",
- "ipc_send_fds_test.cc",
- "ipc_sync_channel_unittest.cc",
- "ipc_sync_message_unittest.cc",
- "ipc_sync_message_unittest.h",
- "ipc_test_base.cc",
- "ipc_test_base.h",
- "sync_socket_unittest.cc",
- "unix_domain_socket_util_unittest.cc",
- ]
-
- #if (toolkit_uses_gtk) {
- # deps += "/build/linux/system:gtk"
- #}
- if (is_win || is_ios) {
- sources -= "unix_domain_socket_util_unittest.cc"
- }
- #if (is_android && gtest_target_type == "shared_library") {
- # deps += "/testing/android/native_test.gyp:native_testNative_code"
- #}
- #if (is_posix && !is_mac && !is_android) {
- # if (linux_use_tcmalloc) {
- # deps += "/base/allocator"
- # }
- #}
-
- deps = [
- ":ipc",
- ":test_support_ipc",
- "//base",
- "//base:base_i18n",
- "//base:run_all_unittests",
- "//base:test_support_base",
- "//testing:gtest",
- ]
-}
-
-test("ipc_perftests") {
- sources = [
- "ipc_perftests.cc",
- "ipc_test_base.cc",
- "ipc_test_base.h",
- ]
-
- #if (toolkit_uses_gtk) {
- # deps += "/build/linux/system:gtk"
- #}
- #if (is_android && gtest_target_type == "shared_library") {
- # deps += "/testing/android/native_test.gyp:native_testNative_code"
- #}
- #if (is_posix && !is_mac && !is_android) {
- # if (linux_use_tcmalloc) {
- # deps += "/base/allocator"
- # }
- #}
-
- deps = [
- ":ipc",
- ":test_support_ipc",
- "//base",
- "//base:base_i18n",
- "//base:test_support_base",
- "//base:test_support_perf",
- "//testing:gtest",
- ]
-}
-
-static_library("test_support_ipc") {
- sources = [
- "ipc_multiprocess_test.cc",
- "ipc_multiprocess_test.h",
- "ipc_test_sink.cc",
- "ipc_test_sink.h",
- ]
- deps = [
- ":ipc",
- "//base",
- "//testing:gtest",
- ]
-}
-
diff --git a/tools/gn/secondary/testing/BUILD.gn b/tools/gn/secondary/testing/BUILD.gn deleted file mode 100644 index b54ceba..0000000 --- a/tools/gn/secondary/testing/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# 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.
-
-static_library("gtest") {
- sources = [
- "gtest/include/gtest/gtest-death-test.h",
- "gtest/include/gtest/gtest-message.h",
- "gtest/include/gtest/gtest-param-test.h",
- "gtest/include/gtest/gtest-printers.h",
- "gtest/include/gtest/gtest-spi.h",
- "gtest/include/gtest/gtest-test-part.h",
- "gtest/include/gtest/gtest-typed-test.h",
- "gtest/include/gtest/gtest.h",
- "gtest/include/gtest/gtest_pred_impl.h",
- "gtest/include/gtest/internal/gtest-death-test-internal.h",
- "gtest/include/gtest/internal/gtest-filepath.h",
- "gtest/include/gtest/internal/gtest-internal.h",
- "gtest/include/gtest/internal/gtest-linked_ptr.h",
- "gtest/include/gtest/internal/gtest-param-util-generated.h",
- "gtest/include/gtest/internal/gtest-param-util.h",
- "gtest/include/gtest/internal/gtest-port.h",
- "gtest/include/gtest/internal/gtest-string.h",
- "gtest/include/gtest/internal/gtest-tuple.h",
- "gtest/include/gtest/internal/gtest-type-util.h",
- #"gtest/src/gtest-all.cc", # Not needed by our build.
- "gtest/src/gtest-death-test.cc",
- "gtest/src/gtest-filepath.cc",
- "gtest/src/gtest-internal-inl.h",
- "gtest/src/gtest-port.cc",
- "gtest/src/gtest-printers.cc",
- "gtest/src/gtest-test-part.cc",
- "gtest/src/gtest-typed-test.cc",
- "gtest/src/gtest.cc",
- "multiprocess_func_list.cc",
- "multiprocess_func_list.h",
- "platform_test.h",
- ]
-
-}
-
-static_library("gmock") {
-
-}
diff --git a/tools/gn/secondary/third_party/modp_b64/BUILD.gn b/tools/gn/secondary/third_party/modp_b64/BUILD.gn deleted file mode 100644 index 5598f12..0000000 --- a/tools/gn/secondary/third_party/modp_b64/BUILD.gn +++ /dev/null @@ -1,11 +0,0 @@ -# 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.
-
-static_library("modp_b64") {
- sources = [
- "modp_b64.cc",
- "modp_b64.h",
- "modp_b64_data.h",
- ]
-}
diff --git a/tools/gn/settings.cc b/tools/gn/settings.cc deleted file mode 100644 index 82014a7..0000000 --- a/tools/gn/settings.cc +++ /dev/null @@ -1,38 +0,0 @@ -// 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/settings.h" - -#include "base/logging.h" -#include "tools/gn/filesystem_utils.h" - -Settings::Settings(const BuildSettings* build_settings, - const Toolchain* toolchain, - const std::string& output_subdir_name) - : build_settings_(build_settings), - toolchain_(toolchain), - target_os_(WIN), // FIXME(brettw) set this properly. - import_manager_(), - base_config_(this) { - DCHECK(output_subdir_name.find('/') == std::string::npos); - if (output_subdir_name.empty()) { - toolchain_output_dir_ = build_settings->build_dir(); - } else { - // We guarantee this ends in a slash. - toolchain_output_subdir_.value().append(output_subdir_name); - toolchain_output_subdir_.value().push_back('/'); - - toolchain_output_dir_ = SourceDir(build_settings->build_dir().value() + - toolchain_output_subdir_.value()); - } - // The output dir will be null in some tests and when invoked to parsed - // one-off data without doing generation. - if (!toolchain_output_dir_.is_null()) - toolchain_gen_dir_ = SourceDir(toolchain_output_dir_.value() + "gen/"); -} - -Settings::~Settings() { -} - - diff --git a/tools/gn/settings.h b/tools/gn/settings.h deleted file mode 100644 index 93a1ae6..0000000 --- a/tools/gn/settings.h +++ /dev/null @@ -1,107 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_SETTINGS_H_ -#define TOOLS_GN_SETTINGS_H_ - -#include "base/files/file_path.h" -#include "tools/gn/build_settings.h" -#include "tools/gn/import_manager.h" -#include "tools/gn/output_file.h" -#include "tools/gn/scope.h" -#include "tools/gn/source_dir.h" -#include "tools/gn/toolchain.h" - -// Holds the settings for one toolchain invocation. There will be one -// Settings object for each toolchain type, each referring to the same -// BuildSettings object for shared stuff. -// -// The Settings object is const once it is constructed, which allows us to -// use it from multiple threads during target generation without locking (which -// is important, because it gets used a lot). -// -// The Toolchain object holds the set of stuff that is set by the toolchain -// declaration, which obviously needs to be set later when we actually parse -// the file with the toolchain declaration in it. -class Settings { - public: - enum TargetOS { - UNKNOWN, - LINUX, - MAC, - WIN - }; - - // Constructs a toolchain settings. The output_subdir_name is the name we - // should use for the subdirectory in the build output directory for this - // toolchain's outputs. It should have no slashes in it. The default - // toolchain should use an empty string. - Settings(const BuildSettings* build_settings, - const Toolchain* toolchain, - const std::string& output_subdir_name); - ~Settings(); - - const BuildSettings* build_settings() const { return build_settings_; } - - // Danger: this must only be used for getting the toolchain label until the - // toolchain has been resolved. Otherwise, it will be modified on an - // arbitrary thread when the toolchain invocation is found. Generally, you - // will only read this from the target generation where we know everything - // has been resolved and won't change. - const Toolchain* toolchain() const { return toolchain_; } - - bool IsMac() const { return target_os_ == MAC; } - bool IsWin() const { return target_os_ == WIN; } - - TargetOS target_os() const { return target_os_; } - void set_target_os(TargetOS t) { target_os_ = t; } - - const OutputFile& toolchain_output_subdir() const { - return toolchain_output_subdir_; - } - const SourceDir& toolchain_output_dir() const { - return toolchain_output_dir_; - } - - // Directory for generated files. - const SourceDir& toolchain_gen_dir() const { - return toolchain_gen_dir_; - } - - // The import manager caches the result of executing imported files in the - // context of a given settings object. - // - // See the ItemTree getter in GlobalSettings for why this doesn't return a - // const pointer. - ImportManager& import_manager() const { return import_manager_; } - - const Scope* base_config() const { return &base_config_; } - Scope* base_config() { return &base_config_; } - - private: - const BuildSettings* build_settings_; - - const Toolchain* toolchain_; - - TargetOS target_os_; - - mutable ImportManager import_manager_; - - // The subdirectory inside the build output for this toolchain. For the - // default toolchain, this will be empty (since the deafult toolchain's - // output directory is the same as the build directory). When nonempty, this - // is guaranteed to end in a slash. - OutputFile toolchain_output_subdir_; - - // Full source file path to the toolchain output directory. - SourceDir toolchain_output_dir_; - - SourceDir toolchain_gen_dir_; - - Scope base_config_; - - DISALLOW_COPY_AND_ASSIGN(Settings); -}; - -#endif // TOOLS_GN_SETTINGS_H_ diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc deleted file mode 100644 index f93cd4d..0000000 --- a/tools/gn/setup.cc +++ /dev/null @@ -1,195 +0,0 @@ -// 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/setup.h" - -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/files/file_path.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/input_file.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/parser.h" -#include "tools/gn/source_dir.h" -#include "tools/gn/source_file.h" -#include "tools/gn/tokenizer.h" -#include "tools/gn/value.h" - -namespace { - -// More logging. -const char kSwitchVerbose[] = "v"; - -const char kSwitchRoot[] = "root"; -const char kSecondarySource[] = "secondary"; - -const base::FilePath::CharType kGnFile[] = FILE_PATH_LITERAL(".gn"); - -base::FilePath FindDotFile(const base::FilePath& current_dir) { - base::FilePath try_this_file = current_dir.Append(kGnFile); - if (base::PathExists(try_this_file)) - return try_this_file; - - base::FilePath with_no_slash = current_dir.StripTrailingSeparators(); - base::FilePath up_one_dir = with_no_slash.DirName(); - if (up_one_dir == current_dir) - return base::FilePath(); // Got to the top. - - return FindDotFile(up_one_dir); -} - -} // namespace - -Setup::Setup() - : dotfile_toolchain_(Label()), - dotfile_settings_(&dotfile_build_settings_, &dotfile_toolchain_, - std::string()), - dotfile_scope_(&dotfile_settings_) { -} - -Setup::~Setup() { -} - -bool Setup::DoSetup() { - CommandLine* cmdline = CommandLine::ForCurrentProcess(); - - scheduler_.set_verbose_logging(cmdline->HasSwitch(kSwitchVerbose)); - - if (!FillSourceDir(*cmdline)) - return false; - if (!RunConfigFile()) - return false; - if (!FillOtherConfig(*cmdline)) - return false; - - // FIXME(brettw) get python path! -/*#if defined(OS_WIN) - build_settings_.set_python_path(base::FilePath( - //L"P:\\depot_tools\\python_bin\\python.exe")); - L"C:\\apps\\depot_tools\\python_bin\\python.exe")); -#else*/ - build_settings_.set_python_path(base::FilePath("python")); -//#endif - - build_settings_.SetBuildDir(SourceDir("//out/gn/")); - - return true; -} - -bool Setup::Run() { - // Load the root build file and start runnung. - build_settings_.toolchain_manager().StartLoadingUnlocked( - SourceFile("//BUILD.gn")); - if (!scheduler_.Run()) - return false; - - Err err = build_settings_.item_tree().CheckForBadItems(); - if (err.has_error()) { - err.PrintToStdout(); - return false; - } - return true; -} - -bool Setup::FillSourceDir(const CommandLine& cmdline) { - // Find the .gn file. - base::FilePath root_path; - - // Prefer the command line args to the config file. - base::FilePath relative_root_path = cmdline.GetSwitchValuePath(kSwitchRoot); - if (!relative_root_path.empty()) { - root_path = base::MakeAbsoluteFilePath(relative_root_path); - dotfile_name_ = root_path.Append(kGnFile); - } else { - base::FilePath cur_dir; - file_util::GetCurrentDirectory(&cur_dir); - dotfile_name_ = FindDotFile(cur_dir); - if (dotfile_name_.empty()) { - Err(Location(), "Can't find source root.", - "I could not find a \".gn\" file in the current directory or any " - "parent,\nand the --root command-line argument was not specified.") - .PrintToStdout(); - return false; - } - root_path = dotfile_name_.DirName(); - } - - if (scheduler_.verbose_logging()) - scheduler_.Log("Using source root", FilePathToUTF8(root_path)); - build_settings_.set_root_path(root_path); - - return true; -} - -bool Setup::RunConfigFile() { - if (scheduler_.verbose_logging()) - scheduler_.Log("Got dotfile", FilePathToUTF8(dotfile_name_)); - - dotfile_input_file_.reset(new InputFile(SourceFile("//.gn"))); - if (!dotfile_input_file_->Load(dotfile_name_)) { - Err(Location(), "Could not load dotfile.", - "The file \"" + FilePathToUTF8(dotfile_name_) + "\" cound't be loaded") - .PrintToStdout(); - return false; - } - - Err err; - dotfile_tokens_ = Tokenizer::Tokenize(dotfile_input_file_.get(), &err); - if (err.has_error()) { - err.PrintToStdout(); - return false; - } - - dotfile_root_ = Parser::Parse(dotfile_tokens_, &err); - if (err.has_error()) { - err.PrintToStdout(); - return false; - } - - dotfile_root_->AsBlock()->ExecuteBlockInScope(&dotfile_scope_, &err); - if (err.has_error()) { - err.PrintToStdout(); - return false; - } - - return true; -} - -bool Setup::FillOtherConfig(const CommandLine& cmdline) { - Err err; - - // Secondary source path. - SourceDir secondary_source; - if (cmdline.HasSwitch(kSecondarySource)) { - // Prefer the command line over the config file. - secondary_source = - SourceDir(cmdline.GetSwitchValueASCII(kSecondarySource)); - } else { - // Read from the config file if present. - const Value* secondary_value = - dotfile_scope_.GetValue("secondary_source", true); - if (secondary_value) { - if (!secondary_value->VerifyTypeIs(Value::STRING, &err)) { - err.PrintToStdout(); - return false; - } - build_settings_.SetSecondarySourcePath( - SourceDir(secondary_value->string_value())); - } - } - - // Build config dir. - const Value* build_config_value = - dotfile_scope_.GetValue("buildconfig", true); - if (!build_config_value) { - Err(Location(), "No build config file.", - "Your .gn file (\"" + FilePathToUTF8(dotfile_name_) + "\")\n" - "didn't specify a \"buildconfig\" value.").PrintToStdout(); - return false; - } - build_settings_.set_build_config_file( - SourceFile("//build/config/BUILDCONFIG.gn")); - - return true; -} diff --git a/tools/gn/setup.h b/tools/gn/setup.h deleted file mode 100644 index e698ac5..0000000 --- a/tools/gn/setup.h +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_SETUP_H_ -#define TOOLS_GN_SETUP_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "tools/gn/build_settings.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/scope.h" -#include "tools/gn/settings.h" -#include "tools/gn/token.h" -#include "tools/gn/toolchain.h" - -class CommandLine; -class InputFile; -class ParseNode; - -// Helper class to setup the build settings and environment for the various -// commands to run. -class Setup { - public: - Setup(); - ~Setup(); - - // Configures the build for the current command line. On success returns - // true. On failure, prints the error and returns false. - bool DoSetup(); - - // Runs the load, returning true on success. On failure, prints the error - // and returns false. - bool Run(); - - BuildSettings& build_settings() { return build_settings_; } - Scheduler& scheduler() { return scheduler_; } - - private: - // Fills the root directory into the settings. Returns true on success. - bool FillSourceDir(const CommandLine& cmdline); - - // Run config file. - bool RunConfigFile(); - - bool FillOtherConfig(const CommandLine& cmdline); - - BuildSettings build_settings_; - Scheduler scheduler_; - - // State for invoking the dotfile. - // TODO(brettw) this seems a bit excessive, maybe we can get this down - // somehow? - base::FilePath dotfile_name_; - scoped_ptr<InputFile> dotfile_input_file_; - std::vector<Token> dotfile_tokens_; - scoped_ptr<ParseNode> dotfile_root_; - BuildSettings dotfile_build_settings_; - Toolchain dotfile_toolchain_; - Settings dotfile_settings_; - Scope dotfile_scope_; - - DISALLOW_COPY_AND_ASSIGN(Setup); -}; - -#endif // TOOLS_GN_SETUP_H_ diff --git a/tools/gn/source_dir.cc b/tools/gn/source_dir.cc deleted file mode 100644 index 5739b52..0000000 --- a/tools/gn/source_dir.cc +++ /dev/null @@ -1,98 +0,0 @@ -// 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/source_dir.h" - -#include "base/logging.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/source_file.h" - -namespace { - -void AssertValueSourceDirString(const std::string& s) { - DCHECK(!s.empty()); - DCHECK(s[0] == '/'); - DCHECK(EndsWithSlash(s)); -} - -} // namespace - -SourceDir::SourceDir() { -} - -SourceDir::SourceDir(const base::StringPiece& p) - : value_(p.data(), p.size()) { - if (!EndsWithSlash(value_)) - value_.push_back('/'); - AssertValueSourceDirString(value_); -} - -SourceDir::~SourceDir() { -} - -SourceFile SourceDir::ResolveRelativeFile(const base::StringPiece& p) const { - SourceFile ret; - - // It's an error to resolve an empty string or one that is a directory - // (indicated by a trailing slash) because this is the function that expects - // to return a file. - if (p.empty() || (p.size() > 0 && p[p.size() - 1] == '/')) - return SourceFile(); - if (p[0] == '/') { - // Absolute path. - ret.value_.assign(p.data(), p.size()); - return ret; - } - - ret.value_.reserve(value_.size() + p.size()); - ret.value_.assign(value_); - ret.value_.append(p.data(), p.size()); - - NormalizePath(&ret.value_); - return ret; -} - -SourceDir SourceDir::ResolveRelativeDir(const base::StringPiece& p) const { - SourceDir ret; - - if (p.empty()) - return ret; - if (p[0] == '/') { - // Absolute path. - return SourceDir(p); - } - - ret.value_.reserve(value_.size() + p.size()); - ret.value_.assign(value_); - ret.value_.append(p.data(), p.size()); - - NormalizePath(&ret.value_); - if (!EndsWithSlash(ret.value_)) - ret.value_.push_back('/'); - AssertValueSourceDirString(ret.value_); - - return ret; -} - -base::FilePath SourceDir::Resolve(const base::FilePath& source_root) const { - if (is_null()) - return base::FilePath(); - - std::string converted; - if (is_system_absolute()) { - converted = value_; - ConvertPathToSystem(&converted); - return base::FilePath(UTF8ToFilePath(converted)); - } - - // String the double-leading slash for source-relative paths. - converted.assign(&value_[2], value_.size() - 2); - ConvertPathToSystem(&converted); - return source_root.Append(UTF8ToFilePath(converted)); -} - -void SourceDir::SwapInValue(std::string* v) { - value_.swap(*v); - AssertValueSourceDirString(value_); -} diff --git a/tools/gn/source_dir.h b/tools/gn/source_dir.h deleted file mode 100644 index 3b6caee..0000000 --- a/tools/gn/source_dir.h +++ /dev/null @@ -1,104 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_SOURCE_DIR_H_ -#define TOOLS_GN_SOURCE_DIR_H_ - -#include <string> - -#include "base/containers/hash_tables.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/strings/string_piece.h" - -class SourceFile; - -// Represents a directory within the source tree. Source dirs begin and end in -// slashes. -// -// If there is one slash at the beginning, it will mean a system-absolute file -// path. On Windows, absolute system paths will be of the form "/C:/foo/bar". -// -// Two slashes at the beginning indicate a path relative to the source root. -class SourceDir { - public: - SourceDir(); - explicit SourceDir(const base::StringPiece& p); - ~SourceDir(); - - // Resolves a file or dir name relative to this source directory. Will return - // an empty SourceDir/File on error. Empty input is always an error (it's - // possible we should say ResolveRelativeDir vs. an empty string should be - // the source dir, but we require "." instead). - SourceFile ResolveRelativeFile(const base::StringPiece& p) const; - SourceDir ResolveRelativeDir(const base::StringPiece& p) const; - - // Resolves this source file relative to some given source root. Returns - // an empty file path on error. - base::FilePath Resolve(const base::FilePath& source_root) const; - - bool is_null() const { return value_.empty(); } - const std::string& value() const { return value_; } - - // Returns true if this path starts with a "//" which indicates a path - // from the source root. - bool is_source_absolute() const { - return value_.size() >= 2 && value_[0] == '/' && value_[1] == '/'; - } - - // Returns true if this path starts with a single slash which indicates a - // system-absolute path. - bool is_system_absolute() const { - return !is_source_absolute(); - } - - // Returns a source-absolute path starting with only one slash at the - // beginning (normally source-absolute paths start with two slashes to mark - // them as such). This is normally used when concatenating directories - // together. - // - // This function asserts that the directory is actually source-absolute. The - // return value points into our buffer. - base::StringPiece SourceAbsoluteWithOneSlash() const { - CHECK(is_source_absolute()); - return base::StringPiece(&value_[1], value_.size() - 1); - } - - void SwapInValue(std::string* v); - - bool operator==(const SourceDir& other) const { - return value_ == other.value_; - } - bool operator!=(const SourceDir& other) const { - return !operator==(other); - } - bool operator<(const SourceDir& other) const { - return value_ < other.value_; - } - - private: - friend class SourceFile; - std::string value_; - - // Copy & assign supported. -}; - -namespace BASE_HASH_NAMESPACE { - -#if defined(COMPILER_GCC) -template<> struct hash<SourceDir> { - std::size_t operator()(const SourceDir& v) const { - hash<std::string> h; - return h(v.value()); - } -}; -#elif defined(COMPILER_MSVC) -inline size_t hash_value(const SourceDir& v) { - return hash_value(v.value()); -} -#endif // COMPILER... - -} // namespace BASE_HASH_NAMESPACE - -#endif // TOOLS_GN_SOURCE_DIR_H_ diff --git a/tools/gn/source_dir_unittest.cc b/tools/gn/source_dir_unittest.cc deleted file mode 100644 index 745513d..0000000 --- a/tools/gn/source_dir_unittest.cc +++ /dev/null @@ -1,45 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/source_dir.h" -#include "tools/gn/source_file.h" - -TEST(SourceDir, ResolveRelativeFile) { - SourceDir base("//base/"); - - // Empty input is an error. - EXPECT_TRUE(base.ResolveRelativeFile("") == SourceFile()); - - // These things are directories, so should be an error. - EXPECT_TRUE(base.ResolveRelativeFile("//foo/bar/") == SourceFile()); - EXPECT_TRUE(base.ResolveRelativeFile("bar/") == SourceFile()); - - // Absolute paths should be passed unchanged. - EXPECT_TRUE(base.ResolveRelativeFile("//foo") == SourceFile("//foo")); - EXPECT_TRUE(base.ResolveRelativeFile("/foo") == SourceFile("/foo")); - - // Basic relative stuff. - EXPECT_TRUE(base.ResolveRelativeFile("foo") == SourceFile("//base/foo")); - EXPECT_TRUE(base.ResolveRelativeFile("./foo") == SourceFile("//base/foo")); - EXPECT_TRUE(base.ResolveRelativeFile("../foo") == SourceFile("//foo")); - EXPECT_TRUE(base.ResolveRelativeFile("../../foo") == SourceFile("//foo")); -} - -TEST(SourceDir, ResolveRelativeDir) { - SourceDir base("//base/"); - - // Empty input is an error. - EXPECT_TRUE(base.ResolveRelativeDir("") == SourceDir()); - - // Absolute paths should be passed unchanged. - EXPECT_TRUE(base.ResolveRelativeDir("//foo") == SourceDir("//foo/")); - EXPECT_TRUE(base.ResolveRelativeDir("/foo") == SourceDir("/foo/")); - - // Basic relative stuff. - EXPECT_TRUE(base.ResolveRelativeDir("foo") == SourceDir("//base/foo/")); - EXPECT_TRUE(base.ResolveRelativeDir("./foo") == SourceDir("//base/foo/")); - EXPECT_TRUE(base.ResolveRelativeDir("../foo") == SourceDir("//foo/")); - EXPECT_TRUE(base.ResolveRelativeDir("../../foo/") == SourceDir("//foo/")); -} diff --git a/tools/gn/source_file.cc b/tools/gn/source_file.cc deleted file mode 100644 index de07de1..0000000 --- a/tools/gn/source_file.cc +++ /dev/null @@ -1,67 +0,0 @@ -// 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/source_file.h" - -#include "base/logging.h" -#include "build/build_config.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/source_dir.h" - -SourceFile::SourceFile() { -} - -SourceFile::SourceFile(const base::StringPiece& p) - : value_(p.data(), p.size()) { - DCHECK(!value_.empty()); - DCHECK(value_[0] == '/'); - DCHECK(!EndsWithSlash(value_)); -} - -SourceFile::~SourceFile() { -} - -std::string SourceFile::GetName() const { - if (is_null()) - return std::string(); - - DCHECK(value_.find('/') != std::string::npos); - size_t last_slash = value_.rfind('/'); - return std::string(&value_[last_slash + 1], - value_.size() - last_slash - 1); -} - -SourceDir SourceFile::GetDir() const { - if (is_null()) - return SourceDir(); - - DCHECK(value_.find('/') != std::string::npos); - size_t last_slash = value_.rfind('/'); - return SourceDir(base::StringPiece(&value_[0], last_slash + 1)); -} - -base::FilePath SourceFile::Resolve(const base::FilePath& source_root) const { - if (is_null()) - return base::FilePath(); - - std::string converted; -#if defined(OS_WIN) - if (is_system_absolute()) { - converted.assign(&value_[1], value_.size() - 1); - DCHECK(converted.size() > 2 && converted[1] == ':') - << "Expecting Windows absolute file path with a drive letter: " - << value_; - return base::FilePath(UTF8ToFilePath(converted)); - } - - converted.assign(&value_[2], value_.size() - 2); - ConvertPathToSystem(&converted); - return root_path_.Append(UTF8ToFilePath(converted)); -#else - if (is_system_absolute()) - return base::FilePath(value_); - converted.assign(&value_[2], value_.size() - 2); - return source_root.Append(converted); -#endif -} diff --git a/tools/gn/source_file.h b/tools/gn/source_file.h deleted file mode 100644 index d883bc0..0000000 --- a/tools/gn/source_file.h +++ /dev/null @@ -1,97 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_SOURCE_FILE_H_ -#define TOOLS_GN_SOURCE_FILE_H_ - -#include <string> - -#include "base/containers/hash_tables.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/strings/string_piece.h" - -class SourceDir; - -// Represents a file within the source tree. Always begins in a slash, never -// ends in one. -class SourceFile { - public: - SourceFile(); - - // Takes a known absolute source file. Always begins in a slash. - explicit SourceFile(const base::StringPiece& p); - - ~SourceFile(); - - bool is_null() const { return value_.empty(); } - const std::string& value() const { return value_; } - - // Returns everythign after the last slash. - std::string GetName() const; - SourceDir GetDir() const; - - // Resolves this source file relative to some given source root. Returns - // an empty file path on error. - base::FilePath Resolve(const base::FilePath& source_root) const; - - // Returns true if this file starts with a "//" which indicates a path - // from the source root. - bool is_source_absolute() const { - return value_.size() >= 2 && value_[0] == '/' && value_[1] == '/'; - } - - // Returns true if this file starts with a single slash which indicates a - // system-absolute path. - bool is_system_absolute() const { - return !is_source_absolute(); - } - - // Returns a source-absolute path starting with only one slash at the - // beginning (normally source-absolute paths start with two slashes to mark - // them as such). This is normally used when concatenating names together. - // - // This function asserts that the file is actually source-absolute. The - // return value points into our buffer. - base::StringPiece SourceAbsoluteWithOneSlash() const { - CHECK(is_source_absolute()); - return base::StringPiece(&value_[1], value_.size() - 1); - } - - bool operator==(const SourceFile& other) const { - return value_ == other.value_; - } - bool operator!=(const SourceFile& other) const { - return !operator==(other); - } - bool operator<(const SourceFile& other) const { - return value_ < other.value_; - } - - private: - friend class SourceDir; - - std::string value_; - - // Copy & assign supported. -}; - -namespace BASE_HASH_NAMESPACE { - -#if defined(COMPILER_GCC) -template<> struct hash<SourceFile> { - std::size_t operator()(const SourceFile& v) const { - hash<std::string> h; - return h(v.value()); - } -}; -#elif defined(COMPILER_MSVC) -inline size_t hash_value(const SourceFile& v) { - return hash_value(v.value()); -} -#endif // COMPILER... - -} // namespace BASE_HASH_NAMESPACE - -#endif // TOOLS_GN_SOURCE_FILE_H_ diff --git a/tools/gn/standard_out.cc b/tools/gn/standard_out.cc deleted file mode 100644 index f6a2031..0000000 --- a/tools/gn/standard_out.cc +++ /dev/null @@ -1,84 +0,0 @@ -// 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/standard_out.h" - -#include "build/build_config.h" - -#if defined(OS_WIN) -#include <windows.h> -#else -#include <stdio.h> -#endif - -namespace { - -bool initialized = false; - -#if defined(OS_WIN) -HANDLE hstdout; -WORD default_attributes; - -bool is_console = false; -#endif - -void EnsureInitialized() { - if (initialized) - return; - initialized = true; - -#if defined(OS_WIN) - hstdout = ::GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_SCREEN_BUFFER_INFO info; - is_console = !!::GetConsoleScreenBufferInfo(hstdout, &info); - default_attributes = info.wAttributes; -#endif -} - -} // namespace - -#if defined(OS_WIN) - -void OutputString(const std::string& output, TextDecoration dec) { - EnsureInitialized(); - if (is_console) { - switch (dec) { - case DECORATION_NONE: - break; - case DECORATION_BOLD: - ::SetConsoleTextAttribute(hstdout, FOREGROUND_INTENSITY); - break; - case DECORATION_RED: - ::SetConsoleTextAttribute(hstdout, - FOREGROUND_RED | FOREGROUND_INTENSITY); - break; - case DECORATION_GREEN: - // Keep green non-bold. - ::SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN); - break; - case DECORATION_BLUE: - ::SetConsoleTextAttribute(hstdout, - FOREGROUND_BLUE | FOREGROUND_INTENSITY); - break; - case DECORATION_YELLOW: - ::SetConsoleTextAttribute(hstdout, - FOREGROUND_RED | FOREGROUND_GREEN); - break; - } - } - - DWORD written = 0; - ::WriteFile(hstdout, output.c_str(), output.size(), &written, NULL); - - if (is_console) - ::SetConsoleTextAttribute(hstdout, default_attributes); -} - -#else - -void OutputString(const std::string& output, TextDecoration dec) { - printf("%s", output.c_str()); -} - -#endif diff --git a/tools/gn/standard_out.h b/tools/gn/standard_out.h deleted file mode 100644 index 2eb525b..0000000 --- a/tools/gn/standard_out.h +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_STANDARD_OUT_H_ -#define TOOLS_GN_STANDARD_OUT_H_ - -#include <string> - -enum TextDecoration { - DECORATION_NONE = 0, - DECORATION_BOLD, - DECORATION_RED, - DECORATION_GREEN, - DECORATION_BLUE, - DECORATION_YELLOW -}; - -void OutputString(const std::string& output, - TextDecoration dec = DECORATION_NONE); - -#endif // TOOLS_GN_STANDARD_OUT_H_ diff --git a/tools/gn/string_utils.cc b/tools/gn/string_utils.cc deleted file mode 100644 index 14d296a..0000000 --- a/tools/gn/string_utils.cc +++ /dev/null @@ -1,168 +0,0 @@ -// 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/string_utils.h" - -#include "tools/gn/err.h" -#include "tools/gn/scope.h" -#include "tools/gn/token.h" -#include "tools/gn/tokenizer.h" -#include "tools/gn/value.h" - -namespace { - -// Constructs an Err indicating a range inside a string. We assume that the -// token has quotes around it that are not counted by the offset. -Err ErrInsideStringToken(const Token& token, size_t offset, size_t size, - const std::string& msg, - const std::string& help = std::string()) { - // The "+1" is skipping over the " at the beginning of the token. - Location begin_loc(token.location().file(), - token.location().line_number(), - token.location().char_offset() + offset + 1); - Location end_loc(token.location().file(), - token.location().line_number(), - token.location().char_offset() + offset + 1 + size); - return Err(LocationRange(begin_loc, end_loc), msg, help); -} - -// Given the character input[i] indicating the $ in a string, locates the -// identifier and places its range in |*identifier|, and updates |*i| to -// point to the last character consumed. -// -// On error returns false and sets the error. -bool LocateInlineIdenfitier(const Token& token, - const char* input, size_t size, - size_t* i, - base::StringPiece* identifier, - Err* err) { - size_t dollars_index = *i; - (*i)++; - if (*i == size) { - *err = ErrInsideStringToken(token, dollars_index, 1, "$ at end of string.", - "I was expecting an identifier after the $."); - return false; - } - - bool has_brackets; - if (input[*i] == '{') { - (*i)++; - if (*i == size) { - *err = ErrInsideStringToken(token, dollars_index, 2, - "${ at end of string.", - "I was expecting an identifier inside the ${...}."); - return false; - } - has_brackets = true; - } else { - has_brackets = false; - } - - // First char is special. - if (!Tokenizer::IsIdentifierFirstChar(input[*i])) { - *err = ErrInsideStringToken( - token, dollars_index, *i - dollars_index + 1, - "$ not followed by an identifier char.", - "It you want a literal $ use \"\\$\"."); - return false; - } - size_t begin_offset = *i; - (*i)++; - - // Find the first non-identifier char following the string. - while (*i < size && Tokenizer::IsIdentifierContinuingChar(input[*i])) - (*i)++; - size_t end_offset = *i; - - // If we started with a bracket, validate that there's an ending one. Leave - // *i pointing to the last char we consumed (backing up one). - if (has_brackets) { - if (*i == size) { - *err = ErrInsideStringToken(token, dollars_index, *i - dollars_index, - "Unterminated ${..."); - return false; - } else if (input[*i] != '}') { - *err = ErrInsideStringToken(token, *i, 1, "Not an identifier in string expansion.", - "The contents of ${...} should be an identifier. " - "This character is out of sorts."); - return false; - } - // We want to consume the bracket but also back up one, so *i is unchanged. - } else { - (*i)--; - } - - *identifier = base::StringPiece(&input[begin_offset], - end_offset - begin_offset); - return true; -} - -bool AppendIdentifierValue(Scope* scope, - const Token& token, - const base::StringPiece& identifier, - std::string* output, - Err* err) { - const Value* value = scope->GetValue(identifier, true); - if (!value) { - // We assume the identifier points inside the token. - *err = ErrInsideStringToken( - token, identifier.data() - token.value().data() - 1, identifier.size(), - "Undefined identifier in string expansion.", - std::string("\"") + identifier + "\" is not currently in scope."); - return false; - } - - output->append(value->ToString()); - return true; -} - -} // namespace - -bool ExpandStringLiteral(Scope* scope, - const Token& literal, - Value* result, - Err* err) { - DCHECK(literal.type() == Token::STRING); - DCHECK(literal.value().size() > 1); // Should include quotes. - DCHECK(result->type() == Value::STRING); // Should be already set. - - // The token includes the surrounding quotes, so strip those off. - const char* input = &literal.value().data()[1]; - size_t size = literal.value().size() - 2; - - std::string& output = result->string_value(); - output.reserve(size); - for (size_t i = 0; i < size; i++) { - if (input[i] == '\\') { - if (i < size - 1) { - switch (input[i + 1]) { - case '\\': - case '"': - case '$': - output.push_back(input[i + 1]); - i++; - continue; - default: // Everything else has no meaning: pass the literal. - break; - } - } - output.push_back(input[i]); - } else if (input[i] == '$') { - base::StringPiece identifier; - if (!LocateInlineIdenfitier(literal, input, size, &i, &identifier, err)) - return false; - if (!AppendIdentifierValue(scope, literal, identifier, &output, err)) - return false; - } else { - output.push_back(input[i]); - } - } - return true; -} - -std::string RemovePrefix(const std::string& str, const std::string& prefix) { - CHECK(str.size() >= prefix.size() && - str.compare(0, prefix.size(), prefix) == 0); - return str.substr(prefix.size()); -} diff --git a/tools/gn/string_utils.h b/tools/gn/string_utils.h deleted file mode 100644 index 7fff1d8..0000000 --- a/tools/gn/string_utils.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_STRING_UTILS_H_ -#define TOOLS_GN_STRING_UTILS_H_ - -#include "base/strings/string_piece.h" - -class Err; -class Scope; -class Token; -class Value; - -inline std::string operator+(const std::string& a, const base::StringPiece& b) { - std::string ret; - ret.reserve(a.size() + b.size()); - ret.assign(a); - ret.append(b.data(), b.size()); - return ret; -} - -inline std::string operator+(const base::StringPiece& a, const std::string& b) { - std::string ret; - ret.reserve(a.size() + b.size()); - ret.assign(a.data(), a.size()); - ret.append(b); - return ret; -} - -// Unescapes and expands variables in the given literal, writing the result -// to the given value. On error, sets |err| and returns false. -bool ExpandStringLiteral(Scope* scope, - const Token& literal, - Value* result, - Err* err); - -// Removes the given prefix from the string. Asserts if the string does -// not have the given prefix. -// -// Note: could potentially return a StringPiece into the str. -std::string RemovePrefix(const std::string& str, const std::string& prefix); - -// Appends the given string piece to the given string. This avoids an -// intermediate copy. -inline void AppendStringPiece(std::string* dest, - const base::StringPiece& piece) { - dest->append(piece.data(), piece.size()); -} - -#endif // TOOLS_GN_STRING_UTILS_H_ diff --git a/tools/gn/string_utils_unittest.cc b/tools/gn/string_utils_unittest.cc deleted file mode 100644 index 81181d2..0000000 --- a/tools/gn/string_utils_unittest.cc +++ /dev/null @@ -1,71 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/err.h" -#include "tools/gn/scope.h" -#include "tools/gn/settings.h" -#include "tools/gn/string_utils.h" -#include "tools/gn/token.h" -#include "tools/gn/value.h" - -namespace { - -bool CheckExpansionCase(const char* input, const char* expected, bool success) { - Scope scope(static_cast<const Settings*>(NULL)); - scope.SetValue("one", Value(NULL, 1), NULL); - scope.SetValue("onestring", Value(NULL, "one"), NULL); - - // Construct the string token, which includes the quotes. - std::string literal_string; - literal_string.push_back('"'); - literal_string.append(input); - literal_string.push_back('"'); - Token literal(Location(), Token::STRING, literal_string); - - Value result(NULL, Value::STRING); - Err err; - bool ret = ExpandStringLiteral(&scope, literal, &result, &err); - - // Err and return value should agree. - EXPECT_NE(ret, err.has_error()); - - if (ret != success) - return false; - - if (!success) - return true; // Don't check result on failure. - return result.string_value() == expected; -} - -} // namespace - -TEST(StringUtils, ExpandStringLiteral) { - EXPECT_TRUE(CheckExpansionCase("", "", true)); - EXPECT_TRUE(CheckExpansionCase("hello", "hello", true)); - EXPECT_TRUE(CheckExpansionCase("hello #$one", "hello #1", true)); - EXPECT_TRUE(CheckExpansionCase("hello #$one/two", "hello #1/two", true)); - EXPECT_TRUE(CheckExpansionCase("hello #${one}", "hello #1", true)); - EXPECT_TRUE(CheckExpansionCase("hello #${one}one", "hello #1one", true)); - EXPECT_TRUE(CheckExpansionCase("hello #${one}$one", "hello #11", true)); - EXPECT_TRUE(CheckExpansionCase("$onestring${one}$one", "one11", true)); - - // Errors - EXPECT_TRUE(CheckExpansionCase("hello #$", NULL, false)); - EXPECT_TRUE(CheckExpansionCase("hello #$%", NULL, false)); - EXPECT_TRUE(CheckExpansionCase("hello #${", NULL, false)); - EXPECT_TRUE(CheckExpansionCase("hello #${}", NULL, false)); - EXPECT_TRUE(CheckExpansionCase("hello #$nonexistant", NULL, false)); - EXPECT_TRUE(CheckExpansionCase("hello #${unterminated", NULL, false)); - - // Unknown backslash values aren't special. - EXPECT_TRUE(CheckExpansionCase("\\", "\\", true)); - EXPECT_TRUE(CheckExpansionCase("\\b", "\\b", true)); - - // Backslashes escape some special things. \"\$\\ -> "$\ Note that gtest - // doesn't like this escape sequence so we have to put it out-of-line. - const char* in = "\\\"\\$\\\\"; - const char* out = "\"$\\"; - EXPECT_TRUE(CheckExpansionCase(in, out, true)); -} diff --git a/tools/gn/target.cc b/tools/gn/target.cc deleted file mode 100644 index 0936f22..0000000 --- a/tools/gn/target.cc +++ /dev/null @@ -1,94 +0,0 @@ -// 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/target.h" - -#include "base/bind.h" -#include "tools/gn/scheduler.h" - -namespace { - -void TargetResolvedThunk(const base::Callback<void(const Target*)>& cb, - const Target* t) { - cb.Run(t); -} - -} // namespace - -Target::Target(const Settings* settings, const Label& label) - : Item(label), - settings_(settings), - output_type_(NONE), - generated_(false), - generator_function_(NULL) { -} - -Target::~Target() { -} - -Target* Target::AsTarget() { - return this; -} - -const Target* Target::AsTarget() const { - return this; -} - -void Target::OnResolved() { - // Gather info from our dependents we need. - for (size_t dep = 0; dep < deps_.size(); dep++) { - // All dependent configs get pulled to us, and to our dependents. - const std::vector<const Config*>& all = - deps_[dep]->all_dependent_configs(); - for (size_t i = 0; i < all.size(); i++) { - configs_.push_back(all[i]); - all_dependent_configs_.push_back(all[i]); - } - - // Direct dependent configs get pulled only to us. - const std::vector<const Config*>& direct = - deps_[dep]->direct_dependent_configs(); - for (size_t i = 0; i < direct.size(); i++) - configs_.push_back(direct[i]); - - // Direct dependent libraries. - if (deps_[dep]->output_type() == STATIC_LIBRARY || - deps_[dep]->output_type() == SHARED_LIBRARY || - deps_[dep]->output_type() == LOADABLE_MODULE) - inherited_libraries_.insert(deps_[dep]); - - // Inherited libraries. DOn't pull transitive libraries from shared - // libraries, since obviously those shouldn't be linked directly into - // later deps unless explicitly specified. - if (deps_[dep]->output_type() != SHARED_LIBRARY && - deps_[dep]->output_type() != LOADABLE_MODULE && - deps_[dep]->output_type() != EXECUTABLE) { - const std::set<const Target*> inherited = - deps_[dep]->inherited_libraries(); - for (std::set<const Target*>::const_iterator i = inherited.begin(); - i != inherited.end(); ++i) - inherited_libraries_.insert(*i); - } - } - - if (!settings_->build_settings()->target_resolved_callback().is_null()) { - g_scheduler->ScheduleWork(base::Bind(&TargetResolvedThunk, - settings_->build_settings()->target_resolved_callback(), - this)); - } -} - -bool Target::HasBeenGenerated() const { - return generated_; -} - -void Target::SetGenerated(const Token* token) { - DCHECK(!generated_); - generated_ = true; - generator_function_ = token; -} - -bool Target::IsLinkable() const { - return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY; -} diff --git a/tools/gn/target.h b/tools/gn/target.h deleted file mode 100644 index 63d62ae..0000000 --- a/tools/gn/target.h +++ /dev/null @@ -1,145 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_TARGET_H_ -#define TOOLS_GN_TARGET_H_ - -#include <set> -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/strings/string_piece.h" -#include "base/synchronization/lock.h" -#include "tools/gn/config_values.h" -#include "tools/gn/item.h" -#include "tools/gn/source_file.h" - -class InputFile; -class Settings; -class Token; - -class Target : public Item { - public: - enum OutputType { - NONE, - EXECUTABLE, - SHARED_LIBRARY, - STATIC_LIBRARY, - LOADABLE_MODULE, - COPY_FILES, - CUSTOM, - }; - typedef std::vector<SourceFile> FileList; - typedef std::vector<std::string> StringVector; - - Target(const Settings* settings, const Label& label); - virtual ~Target(); - - // Item overrides. - virtual Target* AsTarget() OVERRIDE; - virtual const Target* AsTarget() const OVERRIDE; - virtual void OnResolved() OVERRIDE; - - // This flag indicates if we've run the TargetGenerator for this target to - // fill out the rest of the values. Once we've done this, we save the - // location of the function that started the generating so that we can detect - // duplicate declarations. - bool HasBeenGenerated() const; - void SetGenerated(const Token* token); - - const Settings* settings() const { return settings_; } - - OutputType output_type() const { return output_type_; } - void set_output_type(OutputType t) { output_type_ = t; } - - bool IsLinkable() const; - - const FileList& sources() const { return sources_; } - void swap_in_sources(FileList* s) { sources_.swap(*s); } - - const FileList& data() const { return data_; } - void swap_in_data(FileList* d) { data_.swap(*d); } - - const std::vector<const Target*>& deps() const { return deps_; } - void swap_in_deps(std::vector<const Target*>* d) { deps_.swap(*d); } - - // List of configs that this class inherits settings from. - const std::vector<const Config*>& configs() const { return configs_; } - void swap_in_configs(std::vector<const Config*>* c) { configs_.swap(*c); } - - // List of configs that all dependencies (direct and indirect) of this - // target get. These configs are not added to this target. - const std::vector<const Config*>& all_dependent_configs() const { - return all_dependent_configs_; - } - void swap_in_all_dependent_configs(std::vector<const Config*>* c) { - all_dependent_configs_.swap(*c); - } - - // List of configs that targets depending directly on this one get. These - // configs are not added to this target. - const std::vector<const Config*>& direct_dependent_configs() const { - return direct_dependent_configs_; - } - void swap_in_direct_dependent_configs(std::vector<const Config*>* c) { - direct_dependent_configs_.swap(*c); - } - - const std::set<const Target*>& inherited_libraries() const { - return inherited_libraries_; - } - - // This config represents the configuration set directly on this target. - ConfigValues& config_values() { return config_values_; } - const ConfigValues& config_values() const { return config_values_; } - - const SourceDir& destdir() const { return destdir_; } - void set_destdir(const SourceDir& d) { destdir_ = d; } - - const SourceFile& script() const { return script_; } - void set_script(const SourceFile& s) { script_ = s; } - - const std::vector<std::string>& script_args() const { return script_args_; } - void swap_in_script_args(std::vector<std::string>* sa) { - script_args_.swap(*sa); - } - - const FileList& outputs() const { return outputs_; } - void swap_in_outputs(FileList* s) { outputs_.swap(*s); } - - private: - const Settings* settings_; - OutputType output_type_; - - FileList sources_; - FileList data_; - std::vector<const Target*> deps_; - std::vector<const Config*> configs_; - std::vector<const Config*> all_dependent_configs_; - std::vector<const Config*> direct_dependent_configs_; - - // Libraries from transitive deps. Libraries need to be linked only - // with the end target (executable, shared library). These do not get - // pushed beyond shared library boundaries. - std::set<const Target*> inherited_libraries_; - - ConfigValues config_values_; - - SourceDir destdir_; - - // Script target stuff. - SourceFile script_; - std::vector<std::string> script_args_; - FileList outputs_; - - bool generated_; - const Token* generator_function_; // Who generated this: for error messages. - - DISALLOW_COPY_AND_ASSIGN(Target); -}; - -#endif // TOOLS_GN_TARGET_H_ diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc deleted file mode 100644 index 90c8fe6..0000000 --- a/tools/gn/target_generator.cc +++ /dev/null @@ -1,334 +0,0 @@ -// 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/target_generator.h" - -#include "base/files/file_path.h" -#include "base/logging.h" -#include "tools/gn/build_settings.h" -#include "tools/gn/config.h" -#include "tools/gn/config_values_generator.h" -#include "tools/gn/err.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/functions.h" -#include "tools/gn/input_file.h" -#include "tools/gn/item_node.h" -#include "tools/gn/ninja_target_writer.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/scope.h" -#include "tools/gn/target_manager.h" -#include "tools/gn/token.h" -#include "tools/gn/value.h" -#include "tools/gn/value_extractors.h" - -namespace { - -bool TypeHasConfigs(Target::OutputType type) { - return type == Target::EXECUTABLE || - type == Target::SHARED_LIBRARY || - type == Target::STATIC_LIBRARY || - type == Target::LOADABLE_MODULE; -} - -bool TypeHasConfigValues(Target::OutputType type) { - return type == Target::EXECUTABLE || - type == Target::SHARED_LIBRARY || - type == Target::STATIC_LIBRARY || - type == Target::LOADABLE_MODULE; -} - -bool TypeHasSources(Target::OutputType type) { - return type != Target::NONE; -} - -bool TypeHasData(Target::OutputType type) { - return type != Target::NONE; -} - -bool TypeHasDestDir(Target::OutputType type) { - return type == Target::COPY_FILES; -} - -bool TypeHasOutputs(Target::OutputType type) { - return type == Target::CUSTOM; -} - -} // namespace - -TargetGenerator::TargetGenerator(Target* target, - Scope* scope, - const Token& function_token, - const std::vector<Value>& args, - const std::string& output_type, - Err* err) - : target_(target), - scope_(scope), - function_token_(function_token), - args_(args), - output_type_(output_type), - err_(err), - input_directory_(function_token.location().file()->dir()) { -} - -TargetGenerator::~TargetGenerator() { -} - -void TargetGenerator::Run() { - // Output type. - Target::OutputType output_type = GetOutputType(); - target_->set_output_type(output_type); - if (err_->has_error()) - return; - - if (TypeHasConfigs(output_type)) { - FillConfigs(); - FillAllDependentConfigs(); - FillDirectDependentConfigs(); - } - if (TypeHasSources(output_type)) - FillSources(); - if (TypeHasData(output_type)) - FillData(); - if (output_type == Target::CUSTOM) { - FillScript(); - FillScriptArgs(); - } - if (TypeHasOutputs(output_type)) - FillOutputs(); - FillDependencies(); // All types have dependencies. - - if (TypeHasConfigValues(output_type)) { - ConfigValuesGenerator gen(&target_->config_values(), scope_, - function_token_, input_directory_, err_); - gen.Run(); - if (err_->has_error()) - return; - } - - if (TypeHasDestDir(output_type)) - FillDestDir(); - - // Set the toolchain as a dependency of the target. - // TODO(brettw) currently we lock separately for each config, dep, and - // toolchain we add which is bad! Do this in one lock. - { - ItemTree* tree = &GetBuildSettings()->item_tree(); - base::AutoLock lock(tree->lock()); - ItemNode* tc_node = - tree->GetExistingNodeLocked(ToolchainLabelForScope(scope_)); - tree->GetExistingNodeLocked(target_->label())->AddDependency(tc_node); - } - - target_->SetGenerated(&function_token_); - GetBuildSettings()->target_manager().TargetGenerationComplete( - target_->label()); -} - -// static -void TargetGenerator::GenerateTarget(Scope* scope, - const Token& function_token, - const std::vector<Value>& args, - const std::string& output_type, - Err* err) { - // Name is the argument to the function. - if (args.size() != 1u || args[0].type() != Value::STRING) { - *err = Err(function_token, - "Target generator requires one string argument.", - "Otherwise I'm not sure what to call this target."); - return; - } - - // The location of the target is the directory name with no slash at the end. - // FIXME(brettw) validate name. - const Label& toolchain_label = ToolchainLabelForScope(scope); - Label label(function_token.location().file()->dir(), - args[0].string_value(), - toolchain_label.dir(), toolchain_label.name()); - - if (g_scheduler->verbose_logging()) - g_scheduler->Log("Generating target", label.GetUserVisibleName(true)); - - Target* t = scope->settings()->build_settings()->target_manager().GetTarget( - label, function_token.range(), NULL, err); - if (err->has_error()) - return; - - TargetGenerator gen(t, scope, function_token, args, output_type, err); - gen.Run(); -} - -Target::OutputType TargetGenerator::GetOutputType() const { - if (output_type_ == functions::kGroup) - return Target::NONE; - if (output_type_ == functions::kExecutable) - return Target::EXECUTABLE; - if (output_type_ == functions::kSharedLibrary) - return Target::SHARED_LIBRARY; - if (output_type_ == functions::kStaticLibrary) - return Target::STATIC_LIBRARY; - // TODO(brettw) what does loadable module mean? - //if (output_type_ == ???) - // return Target::LOADABLE_MODULE; - if (output_type_ == functions::kCopy) - return Target::COPY_FILES; - if (output_type_ == functions::kCustom) - return Target::CUSTOM; - - *err_ = Err(function_token_, "Not a known output type", - "I am very confused."); - return Target::NONE; -} - -void TargetGenerator::FillGenericConfigs( - const char* var_name, - void (Target::*setter)(std::vector<const Config*>*)) { - const Value* value = scope_->GetValue(var_name, true); - if (!value) - return; - - std::vector<Label> labels; - if (!ExtractListOfLabels(*value, input_directory_, - ToolchainLabelForScope(scope_), &labels, err_)) - return; - - std::vector<const Config*> dest_configs; - dest_configs.resize(labels.size()); - for (size_t i = 0; i < labels.size(); i++) { - dest_configs[i] = Config::GetConfig( - scope_->settings(), - value->list_value()[i].origin()->GetRange(), - labels[i], target_, err_); - if (err_->has_error()) - return; - } - (target_->*setter)(&dest_configs); -} - -void TargetGenerator::FillConfigs() { - FillGenericConfigs("configs", &Target::swap_in_configs); -} - -void TargetGenerator::FillAllDependentConfigs() { - FillGenericConfigs("all_dependent_configs", - &Target::swap_in_all_dependent_configs); -} - -void TargetGenerator::FillDirectDependentConfigs() { - FillGenericConfigs("direct_dependent_configs", - &Target::swap_in_direct_dependent_configs); -} - -void TargetGenerator::FillSources() { - const Value* value = scope_->GetValue("sources", true); - if (!value) - return; - - Target::FileList dest_sources; - if (!ExtractListOfRelativeFiles(*value, input_directory_, &dest_sources, - err_)) - return; - target_->swap_in_sources(&dest_sources); -} - -void TargetGenerator::FillData() { - const Value* value = scope_->GetValue("data", true); - if (!value) - return; - - Target::FileList dest_data; - if (!ExtractListOfRelativeFiles(*value, input_directory_, &dest_data, - err_)) - return; - target_->swap_in_data(&dest_data); -} - -void TargetGenerator::FillDependencies() { - const Value* value = scope_->GetValue("deps", true); - if (!value) - return; - - std::vector<Label> labels; - if (!ExtractListOfLabels(*value, input_directory_, - ToolchainLabelForScope(scope_), &labels, err_)) - return; - - std::vector<const Target*> dest_deps; - dest_deps.resize(labels.size()); - for (size_t i = 0; i < labels.size(); i++) { - dest_deps[i] = GetBuildSettings()->target_manager().GetTarget( - labels[i], value->list_value()[i].origin()->GetRange(), target_, err_); - if (err_->has_error()) - return; - } - - target_->swap_in_deps(&dest_deps); -} - -void TargetGenerator::FillDestDir() { - // Destdir is required for all targets that use it. - const Value* value = scope_->GetValue("destdir", true); - if (!value) { - *err_ = Err(function_token_, "This target type requires a \"destdir\"."); - return; - } - if (!value->VerifyTypeIs(Value::STRING, err_)) - return; - - if (!EnsureStringIsInOutputDir( - GetBuildSettings()->build_dir(), - value->string_value(), *value, err_)) - return; - target_->set_destdir(SourceDir(value->string_value())); -} - -void TargetGenerator::FillScript() { - // If this gets called, the target type requires a script, so error out - // if it doesn't have one. - const Value* value = scope_->GetValue("script", true); - if (!value) { - *err_ = Err(function_token_, "This target type requires a \"script\"."); - return; - } - if (!value->VerifyTypeIs(Value::STRING, err_)) - return; - - target_->set_script( - input_directory_.ResolveRelativeFile(value->string_value())); -} - -void TargetGenerator::FillScriptArgs() { - const Value* value = scope_->GetValue("args", true); - if (!value) - return; - - std::vector<std::string> args; - if (!ExtractListOfStringValues(*value, &args, err_)) - return; - target_->swap_in_script_args(&args); -} - -void TargetGenerator::FillOutputs() { - const Value* value = scope_->GetValue("outputs", true); - if (!value) - return; - - Target::FileList outputs; - if (!ExtractListOfRelativeFiles(*value, input_directory_, &outputs, err_)) - return; - - // Validate that outputs are in the output dir. - CHECK(outputs.size() == value->list_value().size()); - for (size_t i = 0; i < outputs.size(); i++) { - if (!EnsureStringIsInOutputDir( - GetBuildSettings()->build_dir(), - outputs[i].value(), value->list_value()[i], err_)) - return; - } - target_->swap_in_outputs(&outputs); -} - -const BuildSettings* TargetGenerator::GetBuildSettings() const { - return scope_->settings()->build_settings(); -} diff --git a/tools/gn/target_generator.h b/tools/gn/target_generator.h deleted file mode 100644 index 11e920c..0000000 --- a/tools/gn/target_generator.h +++ /dev/null @@ -1,83 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_TARGET_GENERATOR_H_ -#define TOOLS_GN_TARGET_GENERATOR_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "tools/gn/source_dir.h" -#include "tools/gn/target.h" - -class BuildSettings; -class Err; -class Location; -class Scope; -class Token; -class Value; - -// Creates Target objects from a Scope (the result of a script execution). -class TargetGenerator { - public: - TargetGenerator(Target* target, - Scope* scope, - const Token& function_token, - const std::vector<Value>& args, - const std::string& output_type, - Err* err); - ~TargetGenerator(); - - void Run(); - - // The function token is the token of the function name of the generator for - // this target. err() will be set on failure. - static void GenerateTarget(Scope* scope, - const Token& function_token, - const std::vector<Value>& args, - const std::string& output_type, - Err* err); - - private: - // Sets err_ on failure. - Target::OutputType GetOutputType() const; - - // Reads configs from the given var name, and uses the given setting on the - // target to save them - void FillGenericConfigs(const char* var_name, - void (Target::*setter)(std::vector<const Config*>*)); - - void FillConfigs(); - void FillAllDependentConfigs(); - void FillDirectDependentConfigs(); - void FillSources(); - void FillData(); - void FillDependencies(); - void FillDestDir(); - void FillScript(); - void FillScriptArgs(); - void FillOutputs(); - - const BuildSettings* GetBuildSettings() const; - - Target* target_; - Scope* scope_; - const Token& function_token_; - std::vector<Value> args_; - std::string output_type_; - Err* err_; - - // Sources are relative to this. This comes from the input file which doesn't - // get freed so we don't acautlly have to make a copy. - const SourceDir& input_directory_; - - FRIEND_TEST_ALL_PREFIXES(TargetGenerator, ResolveInputPath); - - DISALLOW_COPY_AND_ASSIGN(TargetGenerator); -}; - -#endif // TOOLS_GN_TARGET_GENERATOR_H_ diff --git a/tools/gn/target_generator_unittest.cc b/tools/gn/target_generator_unittest.cc deleted file mode 100644 index feef6a9..0000000 --- a/tools/gn/target_generator_unittest.cc +++ /dev/null @@ -1,8 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/target_generator.h" - diff --git a/tools/gn/target_manager.cc b/tools/gn/target_manager.cc deleted file mode 100644 index ece9f08..0000000 --- a/tools/gn/target_manager.cc +++ /dev/null @@ -1,134 +0,0 @@ -// 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/target_manager.h" - -#include <deque> - -#include "base/bind.h" -#include "base/strings/string_piece.h" -#include "tools/gn/build_settings.h" -#include "tools/gn/err.h" -#include "tools/gn/filesystem_utils.h" -#include "tools/gn/item_node.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/toolchain_manager.h" -#include "tools/gn/value.h" - -TargetManager::TargetManager(const BuildSettings* build_settings) - : build_settings_(build_settings) { -} - -TargetManager::~TargetManager() { -} - -Target* TargetManager::GetTarget(const Label& label, - const LocationRange& specified_from_here, - Target* dep_from, - Err* err) { - DCHECK(!label.is_null()); - DCHECK(!label.toolchain_dir().value().empty()); - DCHECK(!label.toolchain_name().empty()); - - base::AutoLock lock(build_settings_->item_tree().lock()); - - ItemNode* target_node = - build_settings_->item_tree().GetExistingNodeLocked(label); - Target* target = NULL; - if (!target_node) { - // First time we've seen this, may need to load the file. - - // Compute the settings. The common case is that we have a dep_from and - // the toolchains match, so we can use the settings from there rather than - // querying the toolchain manager (which requires locking, etc.). - const Settings* settings; - if (dep_from && dep_from->label().ToolchainsEqual(label)) { - settings = dep_from->settings(); - } else { - settings = - build_settings_->toolchain_manager().GetSettingsForToolchainLocked( - specified_from_here, label.GetToolchainLabel(), err); - if (!settings) - return NULL; - } - - target = new Target(settings, label); - target_node = new ItemNode(target); - target_node->set_originally_referenced_from_here(specified_from_here); - build_settings_->item_tree().AddNodeLocked(target_node); - - // We're generating a node when there is no referencing one. - if (!dep_from) - target_node->set_generated_from_here(specified_from_here); - - // Only schedule loading the given target if somebody is depending on it - // (and we optimize by not re-asking it to run the current file). - // Otherwise, we're probably generating it right now. - if (dep_from && dep_from->label().dir() != label.dir()) { - if (!ScheduleInvocationLocked(specified_from_here, label, err)) - return NULL; - } - } else if ((target = target_node->item()->AsTarget())) { - // Previously saw this item as a target. - - // If we have no dep_from, we're generating it. - if (!dep_from) { - // In this case, it had better not already be generated. - if (target_node->state() != ItemNode::REFERENCED) { - *err = Err(specified_from_here, - "Duplicate target.", - "\"" + label.GetUserVisibleName(true) + - "\" being defined here."); - err->AppendSubErr(Err(target_node->generated_from_here(), - "Originally defined here.")); - return NULL; - } else { - target_node->set_generated_from_here(specified_from_here); - } - } - } else { - // Error, we previously saw this thing as a non-target. - *err = Err(specified_from_here, "Not previously a target.", - "The target being declared here was previously seen referenced as a\n" - "non-target (like a config)"); - err->AppendSubErr(Err(target_node->originally_referenced_from_here(), - "Originally referenced from here.")); - return NULL; - } - - // Keep a record of the guy asking us for this dependency. We know if - // somebody is adding a dependency, that guy it himself not resolved. - if (dep_from && target_node->state() != ItemNode::RESOLVED) { - build_settings_->item_tree().GetExistingNodeLocked( - dep_from->label())->AddDependency(target_node); - } - - return target; -} - -void TargetManager::TargetGenerationComplete(const Label& label) { - base::AutoLock lock(build_settings_->item_tree().lock()); - build_settings_->item_tree().MarkItemGeneratedLocked(label); -} - -void TargetManager::GetAllTargets( - std::vector<const Target*>* all_targets) const { - base::AutoLock lock(build_settings_->item_tree().lock()); - - std::vector<const Item*> all_items; - build_settings_->item_tree().GetAllItemsLocked(&all_items); - for (size_t i = 0; i < all_items.size(); i++) { - const Target* t = all_items[i]->AsTarget(); - if (t) - all_targets->push_back(t); - } -} - -bool TargetManager::ScheduleInvocationLocked( - const LocationRange& specified_from_here, - const Label& label, - Err* err) { - return build_settings_->toolchain_manager().ScheduleInvocationLocked( - specified_from_here, label.GetToolchainLabel(), label.dir(), err); -} diff --git a/tools/gn/target_manager.h b/tools/gn/target_manager.h deleted file mode 100644 index 2dd2aed..0000000 --- a/tools/gn/target_manager.h +++ /dev/null @@ -1,73 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_TARGET_MANAGER_H_ -#define TOOLS_GN_TARGET_MANAGER_H_ - -#include <set> -#include <vector> - -#include "base/basictypes.h" -#include "base/containers/hash_tables.h" -#include "base/synchronization/lock.h" -#include "tools/gn/target.h" - -class BuildSettings; -class Err; -class ItemTree; -class LocationRange; -class ToolchainManager; -class Value; - -// Manages all the targets in the system. This integrates with the ItemTree -// to manage the target-specific rules and creation. -// -// This class is threadsafe. -class TargetManager { - public: - explicit TargetManager(const BuildSettings* settings); - ~TargetManager(); - - // Gets a reference to a named target. The given target name is created if - // it doesn't exist. - // - // The label should be fully specified in that it should include an - // explicit toolchain. - // - // |specified_from_here| should indicate the dependency or the target - // generator causing this access for error message generation. - // - // |dep_from| should be set when a target is getting a dep that it depends - // on. |dep_from| indicates the target that specified the dependency. It - // will be used to track outstanding dependencies so we can know when the - // target and all of its dependencies are complete. It should be null when - // getting a target for other reasons. - // - // On failure, |err| will be set. - // - // The returned pointer must not be dereferenced until it's generated, since - // it could be being generated on another thread. - Target* GetTarget(const Label& label, - const LocationRange& specified_from_here, - Target* dep_from, - Err* err); - - // Called by a target when it has been loaded from the .gin file. Its - // dependencies may or may not be resolved yet. - void TargetGenerationComplete(const Label& label); - - // Returns a list of all targets. - void GetAllTargets(std::vector<const Target*>* all_targets) const; - - private: - bool ScheduleInvocationLocked(const LocationRange& specified_from_here, - const Label& label, - Err* err); - - const BuildSettings* build_settings_; - - DISALLOW_COPY_AND_ASSIGN(TargetManager); -}; - -#endif // TOOLS_GN_TARGET_MANAGER_H diff --git a/tools/gn/target_manager_unittest.cc b/tools/gn/target_manager_unittest.cc deleted file mode 100644 index a1a3ad2..0000000 --- a/tools/gn/target_manager_unittest.cc +++ /dev/null @@ -1,95 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/err.h" -#include "tools/gn/settings.h" -#include "tools/gn/target_manager.h" -#include "tools/gn/value.h" - -/* TODO(brettw) make this compile again -namespace { - -class TestTargetManagerDelegate : public TargetManager::Delegate { - public: - TestTargetManagerDelegate() {} - - virtual bool ScheduleInvocation(ToolchainManager* toolchain_manager, - const LocationRange& origin, - const Label& toolchain_name, - const SourceDir& dir, - Err* err) OVERRIDE { - invokes.push_back(dir.value()); - return true; - } - virtual void ScheduleTargetFileWrite(const Target* target) { - writes.push_back(target); - } - - std::vector<std::string> invokes; - std::vector<const Target*> writes; -}; - -} // namespace - -TEST(TargetManager, ResolveDeps) { - TestTargetManagerDelegate ttmd; - BuildSettings build_settings(&ttmd); - - TargetManager& target_manager = build_settings.target_manager(); - - SourceDir tc_dir("/chrome/"); - std::string tc_name("toolchain"); - - // Get a root target. This should not invoke anything. - Err err; - Label chromelabel(SourceDir("/chrome/"), "chrome", tc_dir, tc_name); - Target* chrome = target_manager.GetTarget( - chromelabel, LocationRange(), NULL, &err); - EXPECT_EQ(0u, ttmd.invokes.size()); - - // Declare it has a dependency on content1 and 2. We should get one - // invocation of the content build file. - Label content1label(SourceDir("/content/"), "content1", tc_dir, tc_name); - Target* content1 = target_manager.GetTarget( - content1label, LocationRange(), chrome, &err); - EXPECT_EQ(1u, ttmd.invokes.size()); - - Label content2label(SourceDir("/content/"), "content2", tc_dir, tc_name); - Target* content2 = target_manager.GetTarget( - content2label, LocationRange(), chrome, &err); - EXPECT_EQ(2u, ttmd.invokes.size()); - - // Declare chrome has a depdency on base, this should load it. - Label baselabel(SourceDir("/base/"), "base", tc_dir, tc_name); - Target* base1 = target_manager.GetTarget( - baselabel, LocationRange(), chrome, &err); - EXPECT_EQ(3u, ttmd.invokes.size()); - - // Declare content1 has a dependency on base. - Target* base2 = target_manager.GetTarget( - baselabel, LocationRange(), content1, &err); - EXPECT_EQ(3u, ttmd.invokes.size()); - EXPECT_EQ(base1, base2); - - // Mark content1 and chrome as done. They have unresolved depdendencies so - // shouldn't be written out yet. - target_manager.TargetGenerationComplete(content1label); - target_manager.TargetGenerationComplete(chromelabel); - EXPECT_EQ(0u, ttmd.writes.size()); - - // Mark content2 as done. It has no dependencies so should be written. - target_manager.TargetGenerationComplete(content2label); - ASSERT_EQ(1u, ttmd.writes.size()); - EXPECT_EQ(content2label, ttmd.writes[0]->label()); - - // Mark base as complete. It should have caused itself, content1 and then - // chrome to be written. - target_manager.TargetGenerationComplete(baselabel); - ASSERT_EQ(4u, ttmd.writes.size()); - EXPECT_EQ(baselabel, ttmd.writes[1]->label()); - EXPECT_EQ(content1label, ttmd.writes[2]->label()); - EXPECT_EQ(chromelabel, ttmd.writes[3]->label()); -} -*/ diff --git a/tools/gn/token.cc b/tools/gn/token.cc deleted file mode 100644 index cbce5e7..0000000 --- a/tools/gn/token.cc +++ /dev/null @@ -1,60 +0,0 @@ -// 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/token.h" - -#include "base/logging.h" - -namespace { - -std::string UnescapeString(const base::StringPiece& input) { - std::string result; - result.reserve(input.size()); - - for (size_t i = 0; i < input.size(); i++) { - if (input[i] == '\\') { - DCHECK(i < input.size() - 1); // Last char shouldn't be a backslash or - // it would have escaped the terminator. - i++; // Skip backslash, next char is a literal. - } - result.push_back(input[i]); - } - return result; -} - -} // namespace - -Token::Token() : type_(INVALID), value_() { -} - -Token::Token(const Location& location, - Type t, - const base::StringPiece& v) - : type_(t), - value_(v), - location_(location) { -} - -bool Token::IsIdentifierEqualTo(const char* v) const { - return type_ == IDENTIFIER && value_ == v; -} - -bool Token::IsOperatorEqualTo(const char* v) const { - return type_ == OPERATOR && value_ == v; -} - -bool Token::IsScoperEqualTo(const char* v) const { - return type_ == SCOPER && value_ == v; -} - -bool Token::IsStringEqualTo(const char* v) const { - return type_ == STRING && value_ == v; -} - -std::string Token::StringValue() const { - DCHECK(type() == STRING); - - // Trim off the string terminators at the end. - return UnescapeString(value_.substr(1, value_.size() - 2)); -} diff --git a/tools/gn/token.h b/tools/gn/token.h deleted file mode 100644 index 64b06ea..0000000 --- a/tools/gn/token.h +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_TOKEN_H_ -#define TOOLS_GN_TOKEN_H_ - -#include "base/strings/string_piece.h" -#include "tools/gn/location.h" - -class Token { - public: - enum Type { - INVALID, - INTEGER, // 123 - STRING, // "blah" - OPERATOR, // =, +=, -=, +, -, ==, !=, <=, >=, <, > - IDENTIFIER, // foo - SCOPER, // (, ), [, ], {, } - SEPARATOR, // , - COMMENT // #...\n - }; - - Token(); - Token(const Location& location, Type t, const base::StringPiece& v); - - Type type() const { return type_; } - const base::StringPiece& value() const { return value_; } - const Location& location() const { return location_; } - LocationRange range() const { - return LocationRange(location_, - Location(location_.file(), location_.line_number(), - location_.char_offset() + value_.size())); - } - - // Helper functions for comparing this token to something. - bool IsIdentifierEqualTo(const char* v) const; - bool IsOperatorEqualTo(const char* v) const; - bool IsScoperEqualTo(const char* v) const; - bool IsStringEqualTo(const char* v) const; - - // For STRING tokens, returns the string value (no quotes at end, does - // unescaping). - std::string StringValue() const; - - private: - Type type_; - base::StringPiece value_; - Location location_; -}; - -#endif // TOOLS_GN_TOKEN_H_ diff --git a/tools/gn/tokenizer.cc b/tools/gn/tokenizer.cc deleted file mode 100644 index 971f56b..0000000 --- a/tools/gn/tokenizer.cc +++ /dev/null @@ -1,309 +0,0 @@ -// 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/tokenizer.h" - -#include "base/logging.h" -#include "tools/gn/input_file.h" - -namespace { - -bool IsNumberChar(char c) { - return c == '-' || (c >= '0' && c <= '9'); -} - -bool CouldBeTwoCharOperatorBegin(char c) { - return c == '<' || c == '>' || c == '!' || c == '=' || c == '-' || - c == '+' || c == '|' || c == '&'; -} - -bool CouldBeTwoCharOperatorEnd(char c) { - return c == '=' || c == '|' || c == '&'; -} - -bool CouldBeOneCharOperator(char c) { - return c == '=' || c == '<' || c == '>' || c == '+' || c == '!' || - c == ':' || c == '|' || c == '&' || c == '-'; -} - -bool CouldBeOperator(char c) { - return CouldBeOneCharOperator(c) || CouldBeTwoCharOperatorBegin(c); -} - -bool IsSeparatorChar(char c) { - return c == ','; -} - -bool IsScoperChar(char c) { - return c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}'; -} - -} // namespace - -Tokenizer::Tokenizer(const InputFile* input_file, Err* err) - : input_file_(input_file), - input_(input_file->contents()), - err_(err), - cur_(0), - line_number_(1), - char_in_line_(1) { -} - -Tokenizer::~Tokenizer() { -} - -// static -std::vector<Token> Tokenizer::Tokenize(const InputFile* input_file, Err* err) { - Tokenizer t(input_file, err); - return t.Run(); -} - -std::vector<Token> Tokenizer::Run() { - std::vector<Token> tokens; - while (!done()) { - AdvanceToNextToken(); - if (done()) - break; - Location location = GetCurrentLocation(); - - Token::Type type = ClassifyCurrent(); - if (type == Token::INVALID) { - *err_ = GetErrorForInvalidToken(location); - break; - } - size_t token_begin = cur_; - AdvanceToEndOfToken(location, type); - if (has_error()) - break; - size_t token_end = cur_; - - // TODO(brettw) This just strips comments from the token stream. This - // is probably wrong, they should be removed at a later stage so we can - // do things like rewrite the file. But this makes the parser simpler and - // is OK for now. - if (type != Token::COMMENT) { - tokens.push_back(Token( - location, - type, - base::StringPiece(&input_.data()[token_begin], - token_end - token_begin))); - } - } - if (err_->has_error()) - tokens.clear(); - return tokens; -} - -// static -size_t Tokenizer::ByteOffsetOfNthLine(const base::StringPiece& buf, int n) { - int cur_line = 1; - size_t cur_byte = 0; - - DCHECK(n > 0); - - if (n == 1) - return 0; - - while (cur_byte < buf.size()) { - if (IsNewline(buf, cur_byte)) { - cur_line++; - if (cur_line == n) - return cur_byte + 1; - } - cur_byte++; - } - return -1; -} - -// static -bool Tokenizer::IsNewline(const base::StringPiece& buffer, size_t offset) { - DCHECK(offset < buffer.size()); - // We may need more logic here to handle different line ending styles. - return buffer[offset] == '\n'; -} - - -void Tokenizer::AdvanceToNextToken() { - while (!at_end() && IsCurrentWhitespace()) - Advance(); -} - -Token::Type Tokenizer::ClassifyCurrent() const { - DCHECK(!at_end()); - char next_char = cur_char(); - if (next_char >= '0' && next_char <= '9') - return Token::INTEGER; - if (next_char == '"') - return Token::STRING; - - // Note: '-' handled specially below. - if (next_char != '-' && CouldBeOperator(next_char)) - return Token::OPERATOR; - - if (IsIdentifierFirstChar(next_char)) - return Token::IDENTIFIER; - - if (IsScoperChar(next_char)) - return Token::SCOPER; - - if (IsSeparatorChar(next_char)) - return Token::SEPARATOR; - - if (next_char == '#') - return Token::COMMENT; - - // For the case of '-' differentiate between a negative number and anything - // else. - if (next_char == '-') { - if (!CanIncrement()) - return Token::OPERATOR; // Just the minus before end of file. - char following_char = input_[cur_ + 1]; - if (following_char >= '0' && following_char <= '9') - return Token::INTEGER; - return Token::OPERATOR; - } - - return Token::INVALID; -} - -void Tokenizer::AdvanceToEndOfToken(const Location& location, - Token::Type type) { - switch (type) { - case Token::INTEGER: - do { - Advance(); - } while (!at_end() && IsNumberChar(cur_char())); - if (!at_end()) { - // Require the char after a number to be some kind of space, scope, - // or operator. - char c = cur_char(); - if (!IsCurrentWhitespace() && !CouldBeOperator(c) && - !IsScoperChar(c) && !IsSeparatorChar(c)) { - *err_ = Err(GetCurrentLocation(), - "This is not a valid number.", - "Learn to count."); - // Highlight the number. - err_->AppendRange(LocationRange(location, GetCurrentLocation())); - } - } - break; - - case Token::STRING: { - char initial = cur_char(); - Advance(); // Advance past initial " - for (;;) { - if (at_end()) { - *err_ = Err(LocationRange(location, - Location(input_file_, line_number_, char_in_line_)), - "Unterminated string literal.", - "Don't leave me hanging like this!"); - break; - } - if (IsCurrentStringTerminator(initial)) { - Advance(); // Skip past last " - break; - } else if (cur_char() == '\n') { - *err_ = Err(LocationRange(location, - GetCurrentLocation()), - "Newline in string constant."); - } - Advance(); - } - break; - } - - case Token::OPERATOR: - // Some operators are two characters, some are one. - if (CouldBeTwoCharOperatorBegin(cur_char())) { - if (CanIncrement() && CouldBeTwoCharOperatorEnd(input_[cur_ + 1])) - Advance(); - } - Advance(); - break; - - case Token::IDENTIFIER: - while (!at_end() && IsIdentifierContinuingChar(cur_char())) - Advance(); - break; - - case Token::SCOPER: - case Token::SEPARATOR: - Advance(); // All are one char. - break; - - case Token::COMMENT: - // Eat to EOL. - while (!at_end() && !IsCurrentNewline()) - Advance(); - break; - - case Token::INVALID: - *err_ = Err(location, "Everything is all messed up", - "Please insert system disk in drive A: and press any key."); - NOTREACHED(); - return; - } -} - -bool Tokenizer::IsCurrentWhitespace() const { - DCHECK(!at_end()); - char c = input_[cur_]; - // Note that tab (0x09) is illegal. - return c == 0x0A || c == 0x0B || c == 0x0C || c == 0x0D || c == 0x20; -} - -bool Tokenizer::IsCurrentStringTerminator(char quote_char) const { - DCHECK(!at_end()); - if (cur_char() != quote_char) - return false; - - // Check for escaping. \" is not a string terminator, but \\" is. Count - // the number of preceeding backslashes. - int num_backslashes = 0; - for (int i = static_cast<int>(cur_) - 1; i >= 0 && input_[i] == '\\'; i--) - num_backslashes++; - - // Even backslashes mean that they were escaping each other and don't count - // as escaping this quote. - return (num_backslashes % 2) == 0; -} - -bool Tokenizer::IsCurrentNewline() const { - return IsNewline(input_, cur_); -} - -void Tokenizer::Advance() { - DCHECK(cur_ < input_.size()); - if (IsCurrentNewline()) { - line_number_++; - char_in_line_ = 1; - } else { - char_in_line_++; - } - cur_++; -} - -Location Tokenizer::GetCurrentLocation() const { - return Location(input_file_, line_number_, char_in_line_); -} - -Err Tokenizer::GetErrorForInvalidToken(const Location& location) const { - std::string help; - if (cur_char() == ';') { - // Semicolon. - help = "Semicolons are not needed, delete this one."; - } else if (cur_char() == '\t') { - // Tab. - help = "You got a tab character in here. Tabs are evil. " - "Convert to spaces."; - } else if (cur_char() == '/' && cur_ + 1 < input_.size() && - (input_[cur_ + 1] == '/' || input_[cur_ + 1] == '*')) { - // Different types of comments. - help = "Comments should start with # instead"; - } else { - help = "I have no idea what this is."; - } - - return Err(location, "Invalid token.", help); -} diff --git a/tools/gn/tokenizer.h b/tools/gn/tokenizer.h deleted file mode 100644 index 5e00169..0000000 --- a/tools/gn/tokenizer.h +++ /dev/null @@ -1,86 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_TOKENIZER_H_ -#define TOOLS_GN_TOKENIZER_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/strings/string_piece.h" -#include "tools/gn/err.h" -#include "tools/gn/token.h" - -class InputFile; - -class Tokenizer { - public: - static std::vector<Token> Tokenize(const InputFile* input_file, Err* err); - - // Counts lines in the given buffer (the first line is "1") and returns - // the byte offset of the beginning of that line, or (size_t)-1 if there - // aren't that many lines in the file. Note that this will return the byte - // one past the end of the input if the last character is a newline. - // - // This is a helper function for error output so that the tokenizer's - // notion of lines can be used elsewhere. - static size_t ByteOffsetOfNthLine(const base::StringPiece& buf, int n); - - // Returns true if the given offset of the string piece counts as a newline. - // The offset must be in the buffer. - static bool IsNewline(const base::StringPiece& buffer, size_t offset); - - static bool IsIdentifierFirstChar(char c) { - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_'; - } - - static bool IsIdentifierContinuingChar(char c) { - // Also allow digits after the first char. - return IsIdentifierFirstChar(c) || (c >= '0' && c <= '9'); - } - - private: - // InputFile must outlive the tokenizer and all generated tokens. - explicit Tokenizer(const InputFile* input_file, Err* err); - ~Tokenizer(); - - std::vector<Token> Run(); - - void AdvanceToNextToken(); - Token::Type ClassifyCurrent() const; - void AdvanceToEndOfToken(const Location& location, Token::Type type); - - bool IsCurrentWhitespace() const; - bool IsCurrentNewline() const; - bool IsCurrentStringTerminator(char quote_char) const; - - bool CanIncrement() const { return cur_ < input_.size(); } - - // Increments the current location by one. - void Advance(); - - // Returns the current character in the file as a location. - Location GetCurrentLocation() const; - - Err GetErrorForInvalidToken(const Location& location) const; - - bool done() const { return at_end() || has_error(); } - - bool at_end() const { return cur_ == input_.size(); } - char cur_char() const { return input_[cur_]; } - - bool has_error() const { return err_->has_error(); } - - const InputFile* input_file_; - const base::StringPiece input_; - Err* err_; - size_t cur_; // Byte offset into input buffer. - - int line_number_; - int char_in_line_; - - DISALLOW_COPY_AND_ASSIGN(Tokenizer); -}; - -#endif // TOOLS_GN_TOKENIZER_H_ diff --git a/tools/gn/tokenizer_unittest.cc b/tools/gn/tokenizer_unittest.cc deleted file mode 100644 index d1a6788..0000000 --- a/tools/gn/tokenizer_unittest.cc +++ /dev/null @@ -1,162 +0,0 @@ -// 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 "testing/gtest/include/gtest/gtest.h" -#include "tools/gn/input_file.h" -#include "tools/gn/token.h" -#include "tools/gn/tokenizer.h" - -namespace { - -struct TokenExpectation { - Token::Type type; - const char* value; -}; - -template<size_t len> -bool CheckTokenizer(const char* input, const TokenExpectation (&expect)[len]) { - InputFile input_file(SourceFile("/test")); - input_file.SetContents(input); - - Err err; - std::vector<Token> results = Tokenizer::Tokenize(&input_file, &err); - - if (results.size() != len) - return false; - for (size_t i = 0; i < len; i++) { - if (expect[i].type != results[i].type()) - return false; - if (expect[i].value != results[i].value()) - return false; - } - return true; -} - -} // namespace - -TEST(Tokenizer, Empty) { - InputFile empty_string_input(SourceFile("/test")); - empty_string_input.SetContents(""); - - Err err; - std::vector<Token> results = Tokenizer::Tokenize(&empty_string_input, &err); - EXPECT_TRUE(results.empty()); - - InputFile whitespace_input(SourceFile("/test")); - whitespace_input.SetContents(" \n\r"); - - results = Tokenizer::Tokenize(&whitespace_input, &err); - EXPECT_TRUE(results.empty()); -} - -TEST(Tokenizer, Identifier) { - TokenExpectation one_ident[] = { - { Token::IDENTIFIER, "foo" } - }; - EXPECT_TRUE(CheckTokenizer(" foo ", one_ident)); -} - -TEST(Tokenizer, Integer) { - TokenExpectation integers[] = { - { Token::INTEGER, "123" }, - { Token::INTEGER, "-123" } - }; - EXPECT_TRUE(CheckTokenizer(" 123 -123 ", integers)); -} - -TEST(Tokenizer, String) { - TokenExpectation strings[] = { - { Token::STRING, "\"foo\"" }, - { Token::STRING, "\"bar\\\"baz\"" }, - { Token::STRING, "\"asdf\\\\\"" } - }; - EXPECT_TRUE(CheckTokenizer(" \"foo\" \"bar\\\"baz\" \"asdf\\\\\" ", - strings)); -} - -TEST(Tokenizer, Operator) { - TokenExpectation operators[] = { - { Token::OPERATOR, "-" }, - { Token::OPERATOR, "+" }, - { Token::OPERATOR, "=" }, - { Token::OPERATOR, "+=" }, - { Token::OPERATOR, "-=" }, - { Token::OPERATOR, "!=" }, - { Token::OPERATOR, "==" }, - { Token::OPERATOR, "<" }, - { Token::OPERATOR, ">" }, - { Token::OPERATOR, "<=" }, - { Token::OPERATOR, ">=" }, - }; - EXPECT_TRUE(CheckTokenizer("- + = += -= != == < > <= >=", - operators)); -} - -TEST(Tokenizer, Scoper) { - TokenExpectation scopers[] = { - { Token::SCOPER, "{" }, - { Token::SCOPER, "[" }, - { Token::SCOPER, "]" }, - { Token::SCOPER, "}" }, - { Token::SCOPER, "(" }, - { Token::SCOPER, ")" }, - }; - EXPECT_TRUE(CheckTokenizer("{[ ]} ()", scopers)); -} - -TEST(Tokenizer, FunctionCall) { - TokenExpectation fn[] = { - { Token::IDENTIFIER, "fun" }, - { Token::SCOPER, "(" }, - { Token::STRING, "\"foo\"" }, - { Token::SCOPER, ")" }, - { Token::SCOPER, "{" }, - { Token::IDENTIFIER, "foo" }, - { Token::OPERATOR, "=" }, - { Token::INTEGER, "12" }, - { Token::SCOPER, "}" }, - }; - EXPECT_TRUE(CheckTokenizer("fun(\"foo\") {\nfoo = 12}", fn)); -} - -TEST(Tokenizer, StringUnescaping) { - InputFile input(SourceFile("/test")); - input.SetContents("\"asd\\\"f\" \"\""); - Err err; - std::vector<Token> results = Tokenizer::Tokenize(&input, &err); - - ASSERT_EQ(2u, results.size()); - EXPECT_EQ("asd\"f", results[0].StringValue()); - EXPECT_EQ("", results[1].StringValue()); -} - -TEST(Tokenizer, Locations) { - InputFile input(SourceFile("/test")); - input.SetContents("1 2 \"three\"\n 4"); - Err err; - std::vector<Token> results = Tokenizer::Tokenize(&input, &err); - - ASSERT_EQ(4u, results.size()); - ASSERT_TRUE(results[0].location() == Location(&input, 1, 1)); - ASSERT_TRUE(results[1].location() == Location(&input, 1, 3)); - ASSERT_TRUE(results[2].location() == Location(&input, 1, 5)); - ASSERT_TRUE(results[3].location() == Location(&input, 2, 3)); -} - -TEST(Tokenizer, ByteOffsetOfNthLine) { - EXPECT_EQ(0u, Tokenizer::ByteOffsetOfNthLine("foo", 1)); - - // Windows and Posix have different line endings, so check the byte at the - // location rather than the offset. - char input1[] = "aaa\nxaa\n\nya"; - EXPECT_EQ('x', input1[Tokenizer::ByteOffsetOfNthLine(input1, 2)]); - EXPECT_EQ('y', input1[Tokenizer::ByteOffsetOfNthLine(input1, 4)]); - - char input2[3]; - input2[0] = 'a'; - input2[1] = '\n'; // Manually set to avoid Windows double-byte endings. - input2[2] = 0; - EXPECT_EQ(0u, Tokenizer::ByteOffsetOfNthLine(input2, 1)); - EXPECT_EQ(2u, Tokenizer::ByteOffsetOfNthLine(input2, 2)); -} diff --git a/tools/gn/toolchain.cc b/tools/gn/toolchain.cc deleted file mode 100644 index 20b81f5..0000000 --- a/tools/gn/toolchain.cc +++ /dev/null @@ -1,79 +0,0 @@ -// 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/toolchain.h" - -#include "base/logging.h" - -const char* Toolchain::kToolCc = "cc"; -const char* Toolchain::kToolCxx = "cxx"; -const char* Toolchain::kToolAsm = "asm"; -const char* Toolchain::kToolAlink = "alink"; -const char* Toolchain::kToolSolink = "solink"; -const char* Toolchain::kToolSolinkModule = "solink_module"; -const char* Toolchain::kToolLink = "link"; -const char* Toolchain::kToolStamp = "stamp"; -const char* Toolchain::kToolCopy = "copy"; - -Toolchain::Tool::Tool() { -} - -Toolchain::Tool::~Tool() { -} - -Toolchain::Toolchain(const Label& label) : Item(label) { -} - -Toolchain::~Toolchain() { -} - -Toolchain* Toolchain::AsToolchain() { - return this; -} - -const Toolchain* Toolchain::AsToolchain() const { - return this; -} - -// static -Toolchain::ToolType Toolchain::ToolNameToType(const base::StringPiece& str) { - if (str == kToolCc) return TYPE_CC; - if (str == kToolCxx) return TYPE_CXX; - if (str == kToolAsm) return TYPE_ASM; - if (str == kToolAlink) return TYPE_ALINK; - if (str == kToolSolink) return TYPE_SOLINK; - if (str == kToolSolinkModule) return TYPE_SOLINK_MODULE; - if (str == kToolLink) return TYPE_LINK; - if (str == kToolStamp) return TYPE_STAMP; - if (str == kToolCopy) return TYPE_COPY; - return TYPE_NONE; -} - -// static -std::string Toolchain::ToolTypeToName(ToolType type) { - switch (type) { - case TYPE_CC: return kToolCc; - case TYPE_CXX: return kToolCxx; - case TYPE_ASM: return kToolAsm; - case TYPE_ALINK: return kToolAlink; - case TYPE_SOLINK: return kToolSolink; - case TYPE_SOLINK_MODULE: return kToolSolinkModule; - case TYPE_LINK: return kToolLink; - case TYPE_STAMP: return kToolStamp; - case TYPE_COPY: return kToolCopy; - default: - NOTREACHED(); - return std::string(); - } -} - -const Toolchain::Tool& Toolchain::GetTool(ToolType type) const { - DCHECK(type != TYPE_NONE); - return tools_[static_cast<size_t>(type)]; -} - -void Toolchain::SetTool(ToolType type, const Tool& t) { - DCHECK(type != TYPE_NONE); - tools_[static_cast<size_t>(type)] = t; -} diff --git a/tools/gn/toolchain.h b/tools/gn/toolchain.h deleted file mode 100644 index 22b8151..0000000 --- a/tools/gn/toolchain.h +++ /dev/null @@ -1,94 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_TOOLCHAIN_H_ -#define TOOLS_GN_TOOLCHAIN_H_ - -#include "base/compiler_specific.h" -#include "base/strings/string_piece.h" -#include "tools/gn/item.h" - -// Holds information on a specific toolchain. This data is filled in when we -// encounter a toolchain definition. -// -// This class is an Item so it can participate in dependency management. In -// particular, when a target uses a toolchain, it should have a dependency on -// that toolchain's object so that we can be sure we loaded the toolchain -// before generating the build for that target. -// -// Note on threadsafety: The label of the toolchain never changes so can -// safetly be accessed from any thread at any time (we do this when asking for -// the toolchain name). But the values in the toolchain do, so these can't -// be accessed until this Item is resolved. -class Toolchain : public Item { - public: - enum ToolType { - TYPE_NONE = 0, - TYPE_CC, - TYPE_CXX, - TYPE_ASM, - TYPE_ALINK, - TYPE_SOLINK, - TYPE_SOLINK_MODULE, - TYPE_LINK, - TYPE_STAMP, - TYPE_COPY, - - TYPE_NUMTYPES // Must be last. - }; - - static const char* kToolCc; - static const char* kToolCxx; - static const char* kToolAsm; - static const char* kToolAlink; - static const char* kToolSolink; - static const char* kToolSolinkModule; - static const char* kToolLink; - static const char* kToolStamp; - static const char* kToolCopy; - - struct Tool { - Tool(); - ~Tool(); - - bool empty() const { - return command.empty() && depfile.empty() && deps.empty() && - description.empty() && pool.empty() && restat.empty() && - rspfile.empty() && rspfile_content.empty(); - } - - std::string command; - std::string depfile; - std::string deps; - std::string description; - std::string pool; - std::string restat; - std::string rspfile; - std::string rspfile_content; - }; - - Toolchain(const Label& label); - virtual ~Toolchain(); - - // Item overrides. - virtual Toolchain* AsToolchain() OVERRIDE; - virtual const Toolchain* AsToolchain() const OVERRIDE; - - // Returns TYPE_NONE on failure. - static ToolType ToolNameToType(const base::StringPiece& str); - static std::string ToolTypeToName(ToolType type); - - const Tool& GetTool(ToolType type) const; - void SetTool(ToolType type, const Tool& t); - - const std::string& environment() const { return environment_; } - void set_environment(const std::string& env) { environment_ = env; } - - private: - Tool tools_[TYPE_NUMTYPES]; - - std::string environment_; -}; - -#endif // TOOLS_GN_TOOLCHAIN_H_ diff --git a/tools/gn/toolchain_manager.cc b/tools/gn/toolchain_manager.cc deleted file mode 100644 index 8a54163..0000000 --- a/tools/gn/toolchain_manager.cc +++ /dev/null @@ -1,480 +0,0 @@ -// 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/toolchain_manager.h" - -#include <set> - -#include "base/bind.h" -#include "tools/gn/err.h" -#include "tools/gn/item.h" -#include "tools/gn/item_node.h" -#include "tools/gn/item_tree.h" -#include "tools/gn/parse_tree.h" -#include "tools/gn/scheduler.h" -#include "tools/gn/scope.h" -#include "tools/gn/scope_per_file_provider.h" - -namespace { - -SourceFile DirToBuildFile(const SourceDir& dir) { - return SourceFile(dir.value() + "BUILD.gn"); -} - -void SetSystemVars(const Settings& settings, Scope* scope) { - // FIXME(brettw) port. - scope->SetValue("is_win", Value(NULL, 1), NULL); - scope->SetValue("is_linux", Value(NULL, 0), NULL); - scope->SetValue("is_posix", Value(NULL, 0), NULL); - scope->SetValue("is_mac", Value(NULL, 0), NULL); - scope->SetValue("is_android", Value(NULL, 0), NULL); - scope->SetValue("is_ios", Value(NULL, 0), NULL); - - // Set this value without the terminating slash because the code expects - // $root_output_dir/foo to work. - scope->SetValue(ScopePerFileProvider::kRootOutputDirName, - ScopePerFileProvider::GetRootOutputDir(&settings), - NULL); - scope->SetValue(ScopePerFileProvider::kRootGenDirName, - ScopePerFileProvider::GetRootGenDir(&settings), - NULL); -} - -} // namespace - -struct ToolchainManager::Info { - Info(const BuildSettings* build_settings, - const Label& toolchain_name, - const std::string& output_subdir_name) - : state(TOOLCHAIN_SETTINGS_NOT_LOADED), - toolchain(toolchain_name), - toolchain_set(false), - settings(build_settings, &toolchain, output_subdir_name), - item_node(NULL) { - } - - // MAkes sure that an ItemNode is created for the toolchain, which lets - // targets depend on the (potentially future) loading of the toolchain. - // - // We can't always do this at the beginning since when doing the default - // build config, we don't know the toolchain name yet. We also need to go - // through some effort to avoid doing this inside the toolchain manager's - // lock (to avoid holding two locks at once). - void EnsureItemNode() { - if (!item_node) { - ItemTree& tree = settings.build_settings()->item_tree(); - item_node = new ItemNode(&toolchain); - tree.AddNodeLocked(item_node); - } - } - - SettingsState state; - - Toolchain toolchain; - bool toolchain_set; - LocationRange toolchain_definition_location; - - // When the state is TOOLCHAIN_SETTINGS_LOADED, the settings should be - // considered read-only and can be read without locking. Otherwise, they - // should not be accessed at all except to load them (which can therefore - // also be done outside of the lock). This works as long as the state flag - // is only ever read or written inside the lock. - Settings settings; - - // While state == TOOLCHAIN_SETTINGS_LOADING, this will collect all - // scheduled invocations using this toolchain. They'll be issued once the - // settings file has been interpreted. - // - // The map maps the source file to "some" location it was invoked from (so - // we can give good error messages. It does NOT map to the root of the - // file to be invoked (the file still needs loading). This will be NULL - // for internally invoked files. - typedef std::map<SourceFile, LocationRange> ScheduledInvocationMap; - ScheduledInvocationMap scheduled_invocations; - - // Tracks all scheduled and executed invocations for this toolchain. This - // is used to avoid invoking a file more than once for a toolchain. - std::set<SourceFile> all_invocations; - - // Filled in by EnsureItemNode, see that for more. - ItemNode* item_node; -}; - -ToolchainManager::ToolchainManager(const BuildSettings* build_settings) - : build_settings_(build_settings) { -} - -ToolchainManager::~ToolchainManager() { - for (ToolchainMap::iterator i = toolchains_.begin(); - i != toolchains_.end(); ++i) - delete i->second; - toolchains_.clear(); -} - -void ToolchainManager::StartLoadingUnlocked(const SourceFile& build_file_name) { - // How the default build config works: Initially we don't have a toolchain - // name to call the settings for the default build config. So we create one - // with an empty toolchain name and execute the default build config file. - // When that's done, we'll go and fix up the name to the default build config - // that the script set. - base::AutoLock lock(GetLock()); - Err err; - Info* info = LoadNewToolchainLocked(LocationRange(), Label(), &err); - if (err.has_error()) - g_scheduler->FailWithError(err); - CHECK(info); - info->scheduled_invocations[build_file_name] = LocationRange(); - info->all_invocations.insert(build_file_name); - - g_scheduler->IncrementWorkCount(); - if (!g_scheduler->input_file_manager()->AsyncLoadFile( - LocationRange(), build_settings_, - build_settings_->build_config_file(), - base::Bind(&ToolchainManager::BackgroundLoadBuildConfig, - base::Unretained(this), info, true), - &err)) { - g_scheduler->FailWithError(err); - g_scheduler->DecrementWorkCount(); - } -} - -const Settings* ToolchainManager::GetSettingsForToolchainLocked( - const LocationRange& from_here, - const Label& toolchain_name, - Err* err) { - GetLock().AssertAcquired(); - ToolchainMap::iterator found = toolchains_.find(toolchain_name); - Info* info = NULL; - if (found == toolchains_.end()) { - info = LoadNewToolchainLocked(from_here, toolchain_name, err); - if (!info) - return NULL; - } else { - info = found->second; - } - info->EnsureItemNode(); - - return &info->settings; -} - -const Toolchain* ToolchainManager::GetToolchainDefinitionUnlocked( - const Label& toolchain_name) { - base::AutoLock lock(GetLock()); - ToolchainMap::iterator found = toolchains_.find(toolchain_name); - if (found == toolchains_.end() || !found->second->toolchain_set) - return NULL; - - // Since we don't allow defining a toolchain more than once, we know that - // once it's set it won't be mutated, so we can safely return this pointer - // for reading outside the lock. - return &found->second->toolchain; -} - -bool ToolchainManager::SetDefaultToolchainUnlocked( - const Label& default_toolchain, - const LocationRange& defined_here, - Err* err) { - base::AutoLock lock(GetLock()); - if (!default_toolchain_.is_null()) { - *err = Err(defined_here, "Default toolchain already set."); - err->AppendSubErr(Err(default_toolchain_defined_here_, - "Previously defined here.", - "You can only set this once.")); - return false; - } - - if (default_toolchain.is_null()) { - *err = Err(defined_here, "Bad default toolchain name.", - "You can't set the default toolchain name to nothing."); - return false; - } - if (!default_toolchain.toolchain_dir().is_null() || - !default_toolchain.toolchain_name().empty()) { - *err = Err(defined_here, "Toolchain name has toolchain.", - "You can't specify a toolchain (inside the parens) for a toolchain " - "name. I got:\n" + default_toolchain.GetUserVisibleName(true)); - return false; - } - - default_toolchain_ = default_toolchain; - default_toolchain_defined_here_ = defined_here; - return true; -} - -Label ToolchainManager::GetDefaultToolchainUnlocked() const { - base::AutoLock lock(GetLock()); - return default_toolchain_; -} - -bool ToolchainManager::SetToolchainDefinitionLocked( - const Toolchain& tc, - const LocationRange& defined_from, - Err* err) { - GetLock().AssertAcquired(); - - ToolchainMap::iterator found = toolchains_.find(tc.label()); - Info* info = NULL; - if (found == toolchains_.end()) { - // New toolchain. - info = LoadNewToolchainLocked(defined_from, tc.label(), err); - if (!info) - return false; - } else { - // It's important to preserve the exact Toolchain object in our tree since - // it will be in the ItemTree and targets may have dependencies on it. - info = found->second; - } - - // The labels should match or else we're setting the wrong one! - CHECK(info->toolchain.label() == tc.label()); - - info->toolchain = tc; - if (info->toolchain_set) { - *err = Err(defined_from, "Duplicate toolchain definition."); - err->AppendSubErr(Err( - info->toolchain_definition_location, - "Previously defined here.", - "A toolchain can only be defined once. One tricky way that this could\n" - "happen is if your definition is itself in a file that's interpreted\n" - "under different toolchains, which would result in multiple\n" - "definitions as the file is loaded multiple times. So be sure your\n" - "toolchain definitions are in files that either don't define any\n" - "targets (probably best) or at least don't contain targets executed\n" - "with more than one toolchain.")); - return false; - } - - info->EnsureItemNode(); - - info->toolchain_set = true; - info->toolchain_definition_location = defined_from; - return true; -} - -bool ToolchainManager::ScheduleInvocationLocked( - const LocationRange& specified_from, - const Label& toolchain_name, - const SourceDir& dir, - Err* err) { - GetLock().AssertAcquired(); - SourceFile build_file(DirToBuildFile(dir)); - - ToolchainMap::iterator found = toolchains_.find(toolchain_name); - Info* info = NULL; - if (found == toolchains_.end()) { - // New toolchain. - info = LoadNewToolchainLocked(specified_from, toolchain_name, err); - if (!info) - return false; - } else { - // Use existing one. - info = found->second; - if (info->all_invocations.find(build_file) != - info->all_invocations.end()) { - // We've already seen this source file for this toolchain, don't need - // to do anything. - return true; - } - } - - info->all_invocations.insert(build_file); - - // True if the settings load needs to be scheduled. - bool info_needs_settings_load = false; - - // True if the settings load has completed. - bool info_settings_loaded = false; - - switch (info->state) { - case TOOLCHAIN_SETTINGS_NOT_LOADED: - info_needs_settings_load = true; - info->scheduled_invocations[build_file] = specified_from; - break; - - case TOOLCHAIN_SETTINGS_LOADING: - info->scheduled_invocations[build_file] = specified_from; - break; - - case TOOLCHAIN_SETTINGS_LOADED: - info_settings_loaded = true; - break; - } - - if (info_needs_settings_load) { - // Load the settings file. - g_scheduler->IncrementWorkCount(); - if (!g_scheduler->input_file_manager()->AsyncLoadFile( - specified_from, build_settings_, - build_settings_->build_config_file(), - base::Bind(&ToolchainManager::BackgroundLoadBuildConfig, - base::Unretained(this), info, false), - err)) { - g_scheduler->DecrementWorkCount(); - return false; - } - } else if (info_settings_loaded) { - // Settings are ready to go, load the target file. - g_scheduler->IncrementWorkCount(); - if (!g_scheduler->input_file_manager()->AsyncLoadFile( - specified_from, build_settings_, build_file, - base::Bind(&ToolchainManager::BackgroundInvoke, - base::Unretained(this), info, build_file), - err)) { - g_scheduler->DecrementWorkCount(); - return false; - } - } - // Else we should have added the infocations to the scheduled_invocations - // from within the lock above. - return true; -} - -// static -std::string ToolchainManager::ToolchainToOutputSubdir( - const Label& toolchain_name) { - // For now just assume the toolchain name is always a valid dir name. We may - // want to clean up the in the future. - return toolchain_name.name(); -} - -ToolchainManager::Info* ToolchainManager::LoadNewToolchainLocked( - const LocationRange& specified_from, - const Label& toolchain_name, - Err* err) { - GetLock().AssertAcquired(); - Info* info = new Info(build_settings_, - toolchain_name, - ToolchainToOutputSubdir(toolchain_name)); - - toolchains_[toolchain_name] = info; - - // Invoke the file containing the toolchain definition so that it gets - // defined. The default one (label is empty) will be done spearately. - if (!toolchain_name.is_null()) { - // The default toolchain should be specified whenever we're requesting - // another one. This is how we know under what context we should execute - // the invoke for the toolchain file. - CHECK(!default_toolchain_.is_null()); - ScheduleInvocationLocked(specified_from, default_toolchain_, - toolchain_name.dir(), err); - } - return info; -} - -void ToolchainManager::FixupDefaultToolchainLocked() { - // Now that we've run the default build config, we should know the - // default toolchain name. Fix up our reference. - // See Start() for more. - GetLock().AssertAcquired(); - if (default_toolchain_.is_null()) { - g_scheduler->FailWithError(Err(Location(), - "Default toolchain not set.", - "Your build config file \"" + - build_settings_->build_config_file().value() + - "\"\ndid not call set_default_toolchain(). This is needed so " - "I know how to actually\ncompile your code.")); - return; - } - - ToolchainMap::iterator old_default = toolchains_.find(Label()); - CHECK(old_default != toolchains_.end()); - Info* info = old_default->second; - toolchains_[default_toolchain_] = info; - toolchains_.erase(old_default); - - // Toolchain should not have been loaded in the build config file. - CHECK(!info->toolchain_set); - - // We need to set the toolchain label now that we know it. There's no way - // to set the label, but we can assign the toolchain to a new one. Loading - // the build config can not change the toolchain, so we won't be overwriting - // anything useful. - info->toolchain = Toolchain(default_toolchain_); - info->EnsureItemNode(); - - // Schedule a load of the toolchain build file. - Err err; - ScheduleInvocationLocked(LocationRange(), default_toolchain_, - default_toolchain_.dir(), &err); - if (err.has_error()) - g_scheduler->FailWithError(err); -} - -void ToolchainManager::BackgroundLoadBuildConfig(Info* info, - bool is_default, - const ParseNode* root) { - // Danger: No early returns without decrementing the work count. - if (root && !g_scheduler->is_failed()) { - // Nobody should be accessing settings at this point other than us since we - // haven't marked it loaded, so we can do it outside the lock. - Scope* base_config = info->settings.base_config(); - SetSystemVars(info->settings, base_config); - base_config->SetProcessingBuildConfig(); - if (is_default) - base_config->SetProcessingDefaultBuildConfig(); - - const BlockNode* root_block = root->AsBlock(); - Err err; - root_block->ExecuteBlockInScope(base_config, &err); - - base_config->ClearProcessingBuildConfig(); - if (is_default) - base_config->ClearProcessingDefaultBuildConfig(); - - if (err.has_error()) { - g_scheduler->FailWithError(err); - } else { - // Base config processing succeeded. - Info::ScheduledInvocationMap schedule_these; - { - base::AutoLock lock(GetLock()); - schedule_these.swap(info->scheduled_invocations); - info->state = TOOLCHAIN_SETTINGS_LOADED; - if (is_default) - FixupDefaultToolchainLocked(); - } - - // Schedule build files waiting on this settings. There can be many so we - // want to load them in parallel on the pool. - for (Info::ScheduledInvocationMap::iterator i = schedule_these.begin(); - i != schedule_these.end() && !g_scheduler->is_failed(); ++i) { - // Note i->second may be NULL, so don't dereference. - g_scheduler->IncrementWorkCount(); - if (!g_scheduler->input_file_manager()->AsyncLoadFile( - i->second, build_settings_, i->first, - base::Bind(&ToolchainManager::BackgroundInvoke, - base::Unretained(this), info, i->first), - &err)) { - g_scheduler->FailWithError(err); - g_scheduler->DecrementWorkCount(); - break; - } - } - } - } - g_scheduler->DecrementWorkCount(); -} - -void ToolchainManager::BackgroundInvoke(const Info* info, - const SourceFile& file_name, - const ParseNode* root) { - if (root && !g_scheduler->is_failed()) { - if (g_scheduler->verbose_logging()) - g_scheduler->Log("Running", file_name.value()); - - Scope our_scope(info->settings.base_config()); - ScopePerFileProvider per_file_provider(&our_scope, file_name); - - Err err; - root->Execute(&our_scope, &err); - if (err.has_error()) - g_scheduler->FailWithError(err); - } - - g_scheduler->DecrementWorkCount(); -} - -base::Lock& ToolchainManager::GetLock() const { - return build_settings_->item_tree().lock(); -} diff --git a/tools/gn/toolchain_manager.h b/tools/gn/toolchain_manager.h deleted file mode 100644 index 4c0be41..0000000 --- a/tools/gn/toolchain_manager.h +++ /dev/null @@ -1,167 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_TOOLCHAIN_MANAGER_H_ -#define TOOLS_GN_TOOLCHAIN_MANAGER_H_ - -#include <map> - -#include "base/basictypes.h" -#include "base/synchronization/lock.h" -#include "tools/gn/label.h" -#include "tools/gn/location.h" -#include "tools/gn/source_file.h" -#include "tools/gn/toolchain.h" - -class Err; -class BuildSettings; -class ParseNode; -class Settings; - -// The toolchain manager manages the mapping of toolchain names to the -// settings and toolchain object. It also loads build files in the context of a -// toolchain context of a toolchain, and manages running the build config -// script when necessary. -// -// This class uses the lock from the item tree to manage threadsafety. The -// functions requiring this lock to be held are named "Locked" to make this -// more clear. The "Unlocked" versions will acquire the lock themselves so will -// break if you call it while locked. (The rationale behind which is which is -// just based on the needs of the callers, so it can be changed.) There are two -// reasons for this: -// -// The first is that when resolving a target, we do a bunch of script -// stuff (slow) and then lookup the target, config, and toolchain dependencies -// based on that. The options are to do a lock around each dependency lookup -// or do a lock around the entire operation. Given that there's not a huge -// amount of work, the "big lock" approach is likely a bit better since it -// avoids lots of locking overhead. -// -// The second reason is that if we had a separate lock here, we would need to -// lock around creating a new toolchain. But creating a new toolchain involves -// adding it to the item tree, and this needs to be done atomically to prevent -// other threads from seeing a partially initialized toolchain. This sets up -// having deadlock do to acquiring multiple locks, or recursive locking -// problems. -class ToolchainManager { - public: - ToolchainManager(const BuildSettings* build_settings); - ~ToolchainManager(); - - // At the very beginning of processing, this begins loading build files. - // This will scheduler loadin the default build config and the given build - // file in that context, going out from there. - // - // This returns immediately, you need to run the Scheduler to actually - // process anything. It's assumed this function is called on the main thread - // before doing anything, so it does not need locking. - void StartLoadingUnlocked(const SourceFile& build_file_name); - - // Returns the settings object for a given toolchain. This does not - // schedule loading the given toolchain if it's not loaded yet: you actually - // need to invoke a target with that toolchain to get that. - // - // On error, returns NULL and sets the error. - const Settings* GetSettingsForToolchainLocked(const LocationRange& from_here, - const Label& toolchain_name, - Err* err); - - // Returns the toolchain definition or NULL if the toolchain hasn't been - // defined yet. - const Toolchain* GetToolchainDefinitionUnlocked(const Label& toolchain_name); - - // Sets the default toolchain. If the default toolchain is already set, - // this function will return false and fill in the given err. - bool SetDefaultToolchainUnlocked(const Label& dt, - const LocationRange& defined_from, - Err* err); - - // Returns the default toolchain name. This will be empty if it hasn't been - // set. - Label GetDefaultToolchainUnlocked() const; - - // Saves the given named toolchain (the name will be taken from the toolchain - // parameter). This will fail and return false if the given toolchain was - // already defined. In this case, the given error will be set. - bool SetToolchainDefinitionLocked(const Toolchain& tc, - const LocationRange& defined_from, - Err* err); - - // Schedules an invocation of the given file under the given toolchain. The - // toolchain file will be loaded if necessary. - // - // The origin should be the node that will be blamed for this invocation if - // an error occurs. If a synchronous error occurs, the given error will be - // set and it will return false. If an async error occurs, the error will be - // sent to the scheduler. - bool ScheduleInvocationLocked(const LocationRange& origin, - const Label& toolchain_name, - const SourceDir& dir, - Err* err); - - private: - enum SettingsState { - // Toolchain settings have not requested to be loaded. This means we - // haven't seen any targets that require this toolchain yet. Not loading - // the settings automatically allows you to define a bunch of toolchains - // and potentially not use them without much overhead. - TOOLCHAIN_SETTINGS_NOT_LOADED, - - // The settings have been scheduled to be loaded but have not completed. - TOOLCHAIN_SETTINGS_LOADING, - - // The settings are done being loaded. - TOOLCHAIN_SETTINGS_LOADED - }; - - struct Info; - - static std::string ToolchainToOutputSubdir(const Label& toolchain_name); - - // Creates a new info struct and saves it in the map. A pointer to the - // struct is returned. No loads are scheduled. - // - // If the label is non-empty, the toolchain will be added to the ItemTree - // so that other nodes can depend on it. THe empty label case is for the - // default build config file (when the toolchain name isn't known yet). It - // will be added later. - // - // On error, will return NULL and the error will be set. - Info* LoadNewToolchainLocked(const LocationRange& specified_from, - const Label& toolchain_name, - Err* err); - - // Fixes up the default toolchain names once they're known when processing - // the default build config, or throw an error if the default toolchain - // hasn't been set. See the StartLoading() implementation for more. - void FixupDefaultToolchainLocked(); - - // Loads the base config for the given toolchain. Run on a background thread - // asynchronously. - void BackgroundLoadBuildConfig(Info* info, - bool is_default, - const ParseNode* root); - - // Invokes the given file for a toolchain with loaded settings. Run on a - // background thread asynchronously. - void BackgroundInvoke(const Info* info, - const SourceFile& file_name, - const ParseNode* root); - - // Returns the lock to use. - base::Lock& GetLock() const; - - const BuildSettings* build_settings_; - - // We own the info pointers. - typedef std::map<Label, Info*> ToolchainMap; - ToolchainMap toolchains_; - - Label default_toolchain_; - LocationRange default_toolchain_defined_here_; - - DISALLOW_COPY_AND_ASSIGN(ToolchainManager); -}; - -#endif // TOOLS_GN_TOOLCHAIN_MANAGER_H_ diff --git a/tools/gn/value.cc b/tools/gn/value.cc deleted file mode 100644 index cb78faa..0000000 --- a/tools/gn/value.cc +++ /dev/null @@ -1,126 +0,0 @@ -// 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/value.h" - -#include "base/strings/string_number_conversions.h" - -Value::Value() - : type_(NONE), - int_value_(0), - origin_(NULL) { -} - -Value::Value(const ParseNode* origin, Type t) - : type_(t), - int_value_(0), - origin_(origin) { -} - -Value::Value(const ParseNode* origin, int64 int_val) - : type_(INTEGER), - int_value_(int_val), - origin_(origin) { -} - -Value::Value(const ParseNode* origin, const base::StringPiece& str_val) - : type_(STRING), - string_value_(str_val.as_string()), - int_value_(0), - origin_(origin) { -} - -Value::~Value() { -} - -// static -const char* Value::DescribeType(Type t) { - switch (t) { - case NONE: - return "none"; - case INTEGER: - return "integer"; - case STRING: - return "string"; - case LIST: - return "list"; - default: - NOTREACHED(); - return "UNKNOWN"; - } -} - -int64 Value::InterpretAsInt() const { - switch (type_) { - case NONE: - return 0; - case INTEGER: - return int_value_; - case STRING: - return string_value_.empty() ? 0 : 1; - case LIST: - return list_value_.empty() ? 0 : 1; - } - return 0; -} - -std::string Value::ToString() const { - switch (type_) { - case NONE: - return "<void>"; - case INTEGER: - return base::Int64ToString(int_value_); - case STRING: - return string_value_; - case LIST: { - std::string result = "["; - for (size_t i = 0; i < list_value_.size(); i++) { - if (i > 0) - result += ", "; - // TODO(brettw) maybe also want to escape quotes in the string. - if (list_value_[i].type() == STRING) - result += std::string("\"") + list_value_[i].ToString() + "\""; - else - result += list_value_[i].ToString(); - } - result.push_back(']'); - return result; - } - } - return std::string(); -} - -bool Value::VerifyTypeIs(Type t, Err* err) const { - if (type_ == t) - return true; - - *err = Err(origin(), std::string("This is not a ") + DescribeType(t) + "."); - return false; -} - -bool Value::operator==(const Value& other) const { - if (type_ != other.type_) - return false; - - switch (type_) { - case Value::INTEGER: - return int_value() == other.int_value(); - case Value::STRING: - return string_value() == other.string_value(); - case Value::LIST: - if (list_value().size() != other.list_value().size()) - return false; - for (size_t i = 0; i < list_value().size(); i++) { - if (list_value()[i] != other.list_value()[i]) - return false; - } - return true; - default: - return false; - } -} - -bool Value::operator!=(const Value& other) const { - return !operator==(other); -} diff --git a/tools/gn/value.h b/tools/gn/value.h deleted file mode 100644 index 8802bff..0000000 --- a/tools/gn/value.h +++ /dev/null @@ -1,91 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_VALUE_H_ -#define TOOLS_GN_VALUE_H_ - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/strings/string_piece.h" -#include "tools/gn/err.h" - -class ParseNode; - -// Represents a variable value in the interpreter. -class Value { - public: - enum Type { - NONE = 0, - INTEGER, - STRING, - LIST - }; - - Value(); - Value(const ParseNode* origin, Type t); - Value(const ParseNode* origin, int64 int_val); - Value(const ParseNode* origin, const base::StringPiece& str_val); - ~Value(); - - Type type() const { return type_; } - - // Returns a string describing the given type. - static const char* DescribeType(Type t); - - // Returns the node that made this. May be NULL. - const ParseNode* origin() const { return origin_; } - void set_origin(const ParseNode* o) { origin_ = o; } - - int64& int_value() { - DCHECK(type_ == INTEGER); - return int_value_; - } - const int64& int_value() const { - DCHECK(type_ == INTEGER); - return int_value_; - } - - std::string& string_value() { - DCHECK(type_ == STRING); - return string_value_; - } - const std::string& string_value() const { - DCHECK(type_ == STRING); - return string_value_; - } - - std::vector<Value>& list_value() { - DCHECK(type_ == LIST); - return list_value_; - } - const std::vector<Value>& list_value() const { - DCHECK(type_ == LIST); - return list_value_; - } - - // Returns the current value converted to an int, normally used for - // boolean operations. Undefined variables, empty lists, and empty strings - // are all interpreted as 0, otherwise 1. - int64 InterpretAsInt() const; - - // Converts the given value to a string. - std::string ToString() const; - - // Verifies that the value is of the given type. If it isn't, returns - // false and sets the error. - bool VerifyTypeIs(Type t, Err* err) const; - - // Compares values. Only the "value" is compared, not the origin. - bool operator==(const Value& other) const; - bool operator!=(const Value& other) const; - - private: - Type type_; - std::string string_value_; - int64 int_value_; - std::vector<Value> list_value_; - const ParseNode* origin_; -}; - -#endif // TOOLS_GN_VALUE_H_ diff --git a/tools/gn/value_extractors.cc b/tools/gn/value_extractors.cc deleted file mode 100644 index 56a2be2..0000000 --- a/tools/gn/value_extractors.cc +++ /dev/null @@ -1,102 +0,0 @@ -// 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/value_extractors.h" - -#include "tools/gn/err.h" -#include "tools/gn/label.h" -#include "tools/gn/source_dir.h" -#include "tools/gn/source_file.h" - -namespace { - -// This extractor rejects files with system-absolute file paths. If we need -// that in the future, we'll have to add some flag to control this. -struct RelativeFileConverter { - RelativeFileConverter(const SourceDir& current_dir_in) - : current_dir(current_dir_in) {} - bool operator()(const Value& v, SourceFile* out, Err* err) const { - if (!v.VerifyTypeIs(Value::STRING, err)) - return false; - *out = current_dir.ResolveRelativeFile(v.string_value()); - if (out->is_system_absolute()) { - *err = Err(v, "System-absolute file path.", - "You can't list a system-absolute file path here. Please include " - "only files in\nthe source tree. Maybe you meant to begin with two " - "slashes to indicate an\nabsolute path in the source tree?"); - return false; - } - return true; - } - const SourceDir& current_dir; -}; - -struct RelativeDirConverter { - RelativeDirConverter(const SourceDir& current_dir_in) - : current_dir(current_dir_in) {} - bool operator()(const Value& v, SourceDir* out, Err* err) const { - if (!v.VerifyTypeIs(Value::STRING, err)) - return false; - *out = current_dir.ResolveRelativeDir(v.string_value()); - return true; - } - const SourceDir& current_dir; -}; - -struct LabelResolver { - LabelResolver(const SourceDir& current_dir_in, - const Label& current_toolchain_in) - : current_dir(current_dir_in), - current_toolchain(current_toolchain_in) {} - bool operator()(const Value& v, Label* out, Err* err) const { - if (!v.VerifyTypeIs(Value::STRING, err)) - return false; - *out = Label::Resolve(current_dir, current_toolchain, v, err); - return !err->has_error(); - } - const SourceDir& current_dir; - const Label& current_toolchain; -}; - -} // namespace - -bool ExtractListOfStringValues(const Value& value, - std::vector<std::string>* dest, - Err* err) { - if (!value.VerifyTypeIs(Value::LIST, err)) - return false; - const std::vector<Value>& input_list = value.list_value(); - dest->reserve(input_list.size()); - for (size_t i = 0; i < input_list.size(); i++) { - if (!input_list[i].VerifyTypeIs(Value::STRING, err)) - return false; - dest->push_back(input_list[i].string_value()); - } - return true; -} - -bool ExtractListOfRelativeFiles(const Value& value, - const SourceDir& current_dir, - std::vector<SourceFile>* files, - Err* err) { - return ListValueExtractor(value, files, err, - RelativeFileConverter(current_dir)); -} - -bool ExtractListOfRelativeDirs(const Value& value, - const SourceDir& current_dir, - std::vector<SourceDir>* dest, - Err* err) { - return ListValueExtractor(value, dest, err, - RelativeDirConverter(current_dir)); -} - -bool ExtractListOfLabels(const Value& value, - const SourceDir& current_dir, - const Label& current_toolchain, - std::vector<Label>* dest, - Err* err) { - return ListValueExtractor(value, dest, err, - LabelResolver(current_dir, current_toolchain)); -} diff --git a/tools/gn/value_extractors.h b/tools/gn/value_extractors.h deleted file mode 100644 index 556f44f..0000000 --- a/tools/gn/value_extractors.h +++ /dev/null @@ -1,57 +0,0 @@ -// 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. - -#ifndef TOOLS_GN_VALUE_EXTRACTORS_H_ -#define TOOLS_GN_VALUE_EXTRACTORS_H_ - -#include <string> -#include <vector> - -#include "tools/gn/value.h" - -class Err; -class Label; -class SourceDir; -class SourceFile; - -// Sets the error and returns false on failure. -template<typename T, class Converter> -bool ListValueExtractor(const Value& value, std::vector<T>* dest, - Err* err, - const Converter& converter) { - if (!value.VerifyTypeIs(Value::LIST, err)) - return false; - const std::vector<Value>& input_list = value.list_value(); - dest->resize(input_list.size()); - for (size_t i = 0; i < input_list.size(); i++) { - if (!converter(input_list[i], &(*dest)[i], err)) - return false; - } - return true; -} - -// On failure, returns false and sets the error. -bool ExtractListOfStringValues(const Value& value, - std::vector<std::string>* dest, - Err* err); - -// Looks for a list of source files relative to a given current dir. -bool ExtractListOfRelativeFiles(const Value& value, - const SourceDir& current_dir, - std::vector<SourceFile>* files, - Err* err); - -// Looks for a list of source directories relative to a given current dir. -bool ExtractListOfRelativeDirs(const Value& value, - const SourceDir& current_dir, - std::vector<SourceDir>* dest, - Err* err); - -bool ExtractListOfLabels(const Value& value, - const SourceDir& current_dir, - const Label& current_toolchain, - std::vector<Label>* dest, - Err* err); - -#endif // TOOLS_GN_VALUE_EXTRACTORS_H_ |