Refactor SubstitutionType for increased flexibility This removes the SubstitutionType enum and the associated arrays of GN and Ninja substitution names, replacing them with a more dynamic collection of data. This is part of a larger refactoring that will allow for additional types of Tools (e.g. non-C/C++ langauge compilation) to be added more simply and cleanly. Change-Id: I2267a87b16d69790e584e729e426dab594784f71 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/4760 Commit-Queue: Julie Hockett <juliehockett@google.com> Reviewed-by: Brett Wilson <brettw@google.com>
diff --git a/base/containers/flat_set.h b/base/containers/flat_set.h new file mode 100644 index 0000000..700617f --- /dev/null +++ b/base/containers/flat_set.h
@@ -0,0 +1,141 @@ +// Copyright 2017 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 BASE_CONTAINERS_FLAT_SET_H_ +#define BASE_CONTAINERS_FLAT_SET_H_ + +#include <functional> + +#include "base/containers/flat_tree.h" +#include "base/template_util.h" + +namespace base { + +// flat_set is a container with a std::set-like interface that stores its +// contents in a sorted vector. +// +// Please see //base/containers/README.md for an overview of which container +// to select. +// +// PROS +// +// - Good memory locality. +// - Low overhead, especially for smaller sets. +// - Performance is good for more workloads than you might expect (see +// overview link above). +// - Supports C++14 set interface. +// +// CONS +// +// - Inserts and removals are O(n). +// +// IMPORTANT NOTES +// +// - Iterators are invalidated across mutations. +// - If possible, construct a flat_set in one operation by inserting into +// a std::vector and moving that vector into the flat_set constructor. +// - For multiple removals use base::EraseIf() which is O(n) rather than +// O(n * removed_items). +// +// QUICK REFERENCE +// +// Most of the core functionality is inherited from flat_tree. Please see +// flat_tree.h for more details for most of these functions. As a quick +// reference, the functions available are: +// +// Constructors (inputs need not be sorted): +// flat_set(InputIterator first, InputIterator last, +// FlatContainerDupes = KEEP_FIRST_OF_DUPES, +// const Compare& compare = Compare()); +// flat_set(const flat_set&); +// flat_set(flat_set&&); +// flat_set(std::vector<Key>, +// FlatContainerDupes = KEEP_FIRST_OF_DUPES, +// const Compare& compare = Compare()); // Re-use storage. +// flat_set(std::initializer_list<value_type> ilist, +// FlatContainerDupes = KEEP_FIRST_OF_DUPES, +// const Compare& comp = Compare()); +// +// Assignment functions: +// flat_set& operator=(const flat_set&); +// flat_set& operator=(flat_set&&); +// flat_set& operator=(initializer_list<Key>); +// +// Memory management functions: +// void reserve(size_t); +// size_t capacity() const; +// void shrink_to_fit(); +// +// Size management functions: +// void clear(); +// size_t size() const; +// size_t max_size() const; +// bool empty() const; +// +// Iterator functions: +// iterator begin(); +// const_iterator begin() const; +// const_iterator cbegin() const; +// iterator end(); +// const_iterator end() const; +// const_iterator cend() const; +// reverse_iterator rbegin(); +// const reverse_iterator rbegin() const; +// const_reverse_iterator crbegin() const; +// reverse_iterator rend(); +// const_reverse_iterator rend() const; +// const_reverse_iterator crend() const; +// +// Insert and accessor functions: +// pair<iterator, bool> insert(const key_type&); +// pair<iterator, bool> insert(key_type&&); +// void insert(InputIterator first, InputIterator last, +// FlatContainerDupes = KEEP_FIRST_OF_DUPES); +// iterator insert(const_iterator hint, const key_type&); +// iterator insert(const_iterator hint, key_type&&); +// pair<iterator, bool> emplace(Args&&...); +// iterator emplace_hint(const_iterator, Args&&...); +// +// Erase functions: +// iterator erase(iterator); +// iterator erase(const_iterator); +// iterator erase(const_iterator first, const_iterator& last); +// template <typename K> size_t erase(const K& key); +// +// Comparators (see std::set documentation). +// key_compare key_comp() const; +// value_compare value_comp() const; +// +// Search functions: +// template <typename K> size_t count(const K&) const; +// template <typename K> iterator find(const K&); +// template <typename K> const_iterator find(const K&) const; +// template <typename K> bool contains(const K&) const; +// template <typename K> pair<iterator, iterator> equal_range(K&); +// template <typename K> iterator lower_bound(const K&); +// template <typename K> const_iterator lower_bound(const K&) const; +// template <typename K> iterator upper_bound(const K&); +// template <typename K> const_iterator upper_bound(const K&) const; +// +// General functions: +// void swap(flat_set&&); +// +// Non-member operators: +// bool operator==(const flat_set&, const flat_set); +// bool operator!=(const flat_set&, const flat_set); +// bool operator<(const flat_set&, const flat_set); +// bool operator>(const flat_set&, const flat_set); +// bool operator>=(const flat_set&, const flat_set); +// bool operator<=(const flat_set&, const flat_set); +// +template <class Key, class Compare = std::less<>> +using flat_set = typename ::base::internal::flat_tree< + Key, + Key, + ::base::internal::GetKeyFromValueIdentity<Key>, + Compare>; + +} // namespace base + +#endif // BASE_CONTAINERS_FLAT_SET_H_ \ No newline at end of file
diff --git a/build/gen.py b/build/gen.py index eeb7cb5..874ecba 100755 --- a/build/gen.py +++ b/build/gen.py
@@ -425,6 +425,7 @@ 'tools/gn/bundle_data_target_generator.cc', 'tools/gn/bundle_file_rule.cc', 'tools/gn/c_include_iterator.cc', + 'tools/gn/c_substitution_type.cc', 'tools/gn/c_tool.cc', 'tools/gn/command_analyze.cc', 'tools/gn/command_args.cc',
diff --git a/tools/gn/action_target_generator.cc b/tools/gn/action_target_generator.cc index c0ba6c8..61e9d09 100644 --- a/tools/gn/action_target_generator.cc +++ b/tools/gn/action_target_generator.cc
@@ -74,7 +74,7 @@ const auto& required_args_substitutions = target_->action_values().args().required_types(); bool has_rsp_file_name = base::ContainsValue(required_args_substitutions, - SUBSTITUTION_RSP_FILE_NAME); + &SubstitutionRspFileName); if (target_->action_values().uses_rsp_file() && !has_rsp_file_name) { *err_ = Err( function_call_, "Missing {{response_file_name}} in args.",
diff --git a/tools/gn/bundle_data_target_generator.cc b/tools/gn/bundle_data_target_generator.cc index 23f26fd..cfd2903 100644 --- a/tools/gn/bundle_data_target_generator.cc +++ b/tools/gn/bundle_data_target_generator.cc
@@ -55,10 +55,10 @@ return false; // Check the substitutions used are valid for this purpose. - for (SubstitutionType type : outputs.required_types()) { + for (const Substitution* type : outputs.required_types()) { if (!IsValidBundleDataSubstitution(type)) { *err_ = Err(value->origin(), "Invalid substitution type.", - "The substitution " + std::string(kSubstitutionNames[type]) + + "The substitution " + std::string(type->name) + " isn't valid for something\n" "operating on a bundle_data file such as this."); return false;
diff --git a/tools/gn/bundle_file_rule.cc b/tools/gn/bundle_file_rule.cc index 5dffb07..2b9881c 100644 --- a/tools/gn/bundle_file_rule.cc +++ b/tools/gn/bundle_file_rule.cc
@@ -51,47 +51,40 @@ Err* err) const { std::string output_path; for (const auto& subrange : pattern_.ranges()) { - switch (subrange.type) { - case SUBSTITUTION_LITERAL: - output_path.append(subrange.literal); - break; - case SUBSTITUTION_BUNDLE_ROOT_DIR: - if (bundle_data.contents_dir().is_null()) { - *err = ErrMissingPropertyForExpansion(settings, target, this, - variables::kBundleRootDir); - return false; - } - output_path.append(bundle_data.root_dir().value()); - break; - case SUBSTITUTION_BUNDLE_CONTENTS_DIR: - if (bundle_data.contents_dir().is_null()) { - *err = ErrMissingPropertyForExpansion(settings, target, this, - variables::kBundleContentsDir); - return false; - } - output_path.append(bundle_data.contents_dir().value()); - break; - case SUBSTITUTION_BUNDLE_RESOURCES_DIR: - if (bundle_data.resources_dir().is_null()) { - *err = ErrMissingPropertyForExpansion(settings, target, this, - variables::kBundleResourcesDir); - return false; - } - output_path.append(bundle_data.resources_dir().value()); - break; - case SUBSTITUTION_BUNDLE_EXECUTABLE_DIR: - if (bundle_data.executable_dir().is_null()) { - *err = ErrMissingPropertyForExpansion( - settings, target, this, variables::kBundleExecutableDir); - return false; - } - output_path.append(bundle_data.executable_dir().value()); - break; - default: - output_path.append(SubstitutionWriter::GetSourceSubstitution( - target_, target_->settings(), source_file, subrange.type, - SubstitutionWriter::OUTPUT_ABSOLUTE, SourceDir())); - break; + if (subrange.type == &SubstitutionLiteral) { + output_path.append(subrange.literal); + } else if (subrange.type == &SubstitutionBundleRootDir) { + if (bundle_data.contents_dir().is_null()) { + *err = ErrMissingPropertyForExpansion(settings, target, this, + variables::kBundleRootDir); + return false; + } + output_path.append(bundle_data.root_dir().value()); + } else if (subrange.type == &SubstitutionBundleContentsDir) { + if (bundle_data.contents_dir().is_null()) { + *err = ErrMissingPropertyForExpansion(settings, target, this, + variables::kBundleContentsDir); + return false; + } + output_path.append(bundle_data.contents_dir().value()); + } else if (subrange.type == &SubstitutionBundleResourcesDir) { + if (bundle_data.resources_dir().is_null()) { + *err = ErrMissingPropertyForExpansion(settings, target, this, + variables::kBundleResourcesDir); + return false; + } + output_path.append(bundle_data.resources_dir().value()); + } else if (subrange.type == &SubstitutionBundleExecutableDir) { + if (bundle_data.executable_dir().is_null()) { + *err = ErrMissingPropertyForExpansion(settings, target, this, + variables::kBundleExecutableDir); + return false; + } + output_path.append(bundle_data.executable_dir().value()); + } else { + output_path.append(SubstitutionWriter::GetSourceSubstitution( + target_, target_->settings(), source_file, subrange.type, + SubstitutionWriter::OUTPUT_ABSOLUTE, SourceDir())); } } *expanded_source_file = SourceFile(SourceFile::SWAP_IN, &output_path);
diff --git a/tools/gn/c_substitution_type.cc b/tools/gn/c_substitution_type.cc new file mode 100644 index 0000000..3054124 --- /dev/null +++ b/tools/gn/c_substitution_type.cc
@@ -0,0 +1,86 @@ +// Copyright 2019 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/c_substitution_type.h" + +#include <stddef.h> +#include <stdlib.h> + +#include "tools/gn/err.h" + +const SubstitutionTypes CSubstitutions = { + &CSubstitutionAsmFlags, &CSubstitutionCFlags, + &CSubstitutionCFlagsC, &CSubstitutionCFlagsCc, + &CSubstitutionCFlagsObjC, &CSubstitutionCFlagsObjCc, + &CSubstitutionDefines, &CSubstitutionIncludeDirs, + + &CSubstitutionLinkerInputs, &CSubstitutionLinkerInputsNewline, + &CSubstitutionLdFlags, &CSubstitutionLibs, + &CSubstitutionOutputDir, &CSubstitutionOutputExtension, + &CSubstitutionSoLibs, + + &CSubstitutionArFlags, +}; + +// Valid for compiler tools. +const Substitution CSubstitutionAsmFlags = {"{{asmflags}}", "asmflags"}; +const Substitution CSubstitutionCFlags = {"{{cflags}}", "cflags"}; +const Substitution CSubstitutionCFlagsC = {"{{cflags_c}}", "cflags_c"}; +const Substitution CSubstitutionCFlagsCc = {"{{cflags_cc}}", "cflags_cc"}; +const Substitution CSubstitutionCFlagsObjC = {"{{cflags_objc}}", "cflags_objc"}; +const Substitution CSubstitutionCFlagsObjCc = {"{{cflags_objcc}}", + "cflags_objcc"}; +const Substitution CSubstitutionDefines = {"{{defines}}", "defines"}; +const Substitution CSubstitutionIncludeDirs = {"{{include_dirs}}", + "include_dirs"}; + +// Valid for linker tools. +const Substitution CSubstitutionLinkerInputs = {"{{inputs}}", "in"}; +const Substitution CSubstitutionLinkerInputsNewline = {"{{inputs_newline}}", + "in_newline"}; +const Substitution CSubstitutionLdFlags = {"{{ldflags}}", "ldflags"}; +const Substitution CSubstitutionLibs = {"{{libs}}", "libs"}; +const Substitution CSubstitutionOutputDir = {"{{output_dir}}", "output_dir"}; +const Substitution CSubstitutionOutputExtension = {"{{output_extension}}", + "output_extension"}; +const Substitution CSubstitutionSoLibs = {"{{solibs}}", "solibs"}; + +// Valid for alink only. +const Substitution CSubstitutionArFlags = {"{{arflags}}", "arflags"}; + +bool IsValidCompilerSubstitution(const Substitution* type) { + return IsValidToolSubstitution(type) || IsValidSourceSubstitution(type) || + type == &SubstitutionSource || type == &CSubstitutionAsmFlags || + type == &CSubstitutionCFlags || type == &CSubstitutionCFlagsC || + type == &CSubstitutionCFlagsCc || type == &CSubstitutionCFlagsObjC || + type == &CSubstitutionCFlagsObjCc || type == &CSubstitutionDefines || + type == &CSubstitutionIncludeDirs; +} + +bool IsValidCompilerOutputsSubstitution(const Substitution* type) { + // All tool types except "output" (which would be infinitely recursive). + return (IsValidToolSubstitution(type) && type != &SubstitutionOutput) || + IsValidSourceSubstitution(type); +} + +bool IsValidLinkerSubstitution(const Substitution* type) { + return IsValidToolSubstitution(type) || type == &CSubstitutionLinkerInputs || + type == &CSubstitutionLinkerInputsNewline || + type == &CSubstitutionLdFlags || type == &CSubstitutionLibs || + type == &CSubstitutionOutputDir || + type == &CSubstitutionOutputExtension || type == &CSubstitutionSoLibs; +} + +bool IsValidLinkerOutputsSubstitution(const Substitution* type) { + // All valid compiler outputs plus the output extension. + return IsValidCompilerOutputsSubstitution(type) || + type == &CSubstitutionOutputDir || type == &CSubstitutionOutputExtension; +} + +bool IsValidALinkSubstitution(const Substitution* type) { + return IsValidToolSubstitution(type) || type == &CSubstitutionLinkerInputs || + type == &CSubstitutionLinkerInputsNewline || + type == &CSubstitutionArFlags || type == &CSubstitutionOutputDir || + type == &CSubstitutionOutputExtension; +}
diff --git a/tools/gn/c_substitution_type.h b/tools/gn/c_substitution_type.h new file mode 100644 index 0000000..eee5304 --- /dev/null +++ b/tools/gn/c_substitution_type.h
@@ -0,0 +1,45 @@ +// Copyright 2019 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_C_SUBSTITUTION_TYPE_H_ +#define TOOLS_GN_C_SUBSTITUTION_TYPE_H_ + +#include <set> +#include <vector> + +#include "tools/gn/substitution_type.h" + +// The set of substitutions available to all tools. +extern const SubstitutionTypes CSubstitutions; + +// Valid for compiler tools. +extern const Substitution CSubstitutionAsmFlags; +extern const Substitution CSubstitutionCFlags; +extern const Substitution CSubstitutionCFlagsC; +extern const Substitution CSubstitutionCFlagsCc; +extern const Substitution CSubstitutionCFlagsObjC; +extern const Substitution CSubstitutionCFlagsObjCc; +extern const Substitution CSubstitutionDefines; +extern const Substitution CSubstitutionIncludeDirs; + +// Valid for linker tools. +extern const Substitution CSubstitutionLinkerInputs; +extern const Substitution CSubstitutionLinkerInputsNewline; +extern const Substitution CSubstitutionLdFlags; +extern const Substitution CSubstitutionLibs; +extern const Substitution CSubstitutionOutputDir; +extern const Substitution CSubstitutionOutputExtension; +extern const Substitution CSubstitutionSoLibs; + +// Valid for alink only. +extern const Substitution CSubstitutionArFlags; + +// Both compiler and linker tools. +bool IsValidCompilerSubstitution(const Substitution* type); +bool IsValidCompilerOutputsSubstitution(const Substitution* type); +bool IsValidLinkerSubstitution(const Substitution* type); +bool IsValidLinkerOutputsSubstitution(const Substitution* type); +bool IsValidALinkSubstitution(const Substitution* type); + +#endif // TOOLS_GN_C_SUBSTITUTION_TYPE_H_
diff --git a/tools/gn/c_tool.cc b/tools/gn/c_tool.cc index 6167286..59452fb 100644 --- a/tools/gn/c_tool.cc +++ b/tools/gn/c_tool.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "tools/gn/c_tool.h" +#include "tools/gn/c_substitution_type.h" #include "tools/gn/target.h" const char* CTool::kCToolCc = "cc"; @@ -155,8 +156,7 @@ for (const auto& cur_type : list.required_types()) { if (!ValidateOutputSubstitution(cur_type)) { *err = Err(*value, "Pattern not valid here.", - "You used the pattern " + - std::string(kSubstitutionNames[cur_type]) + + "You used the pattern " + std::string(cur_type->name) + " which is not valid\nfor this variable."); return false; } @@ -206,7 +206,7 @@ return true; } -bool CTool::ValidateSubstitution(SubstitutionType sub_type) const { +bool CTool::ValidateSubstitution(const Substitution* sub_type) const { if (name_ == kCToolCc || name_ == kCToolCxx || name_ == kCToolObjC || name_ == kCToolObjCxx || name_ == kCToolRc || name_ == kCToolAsm) return IsValidCompilerSubstitution(sub_type); @@ -219,7 +219,7 @@ return false; } -bool CTool::ValidateOutputSubstitution(SubstitutionType sub_type) const { +bool CTool::ValidateOutputSubstitution(const Substitution* sub_type) const { if (name_ == kCToolCc || name_ == kCToolCxx || name_ == kCToolObjC || name_ == kCToolObjCxx || name_ == kCToolRc || name_ == kCToolAsm) return IsValidCompilerOutputsSubstitution(sub_type);
diff --git a/tools/gn/c_tool.h b/tools/gn/c_tool.h index 045024c..129a733 100644 --- a/tools/gn/c_tool.h +++ b/tools/gn/c_tool.h
@@ -46,7 +46,7 @@ bool InitTool(Scope* block_scope, Toolchain* toolchain, Err* err); bool ValidateName(const char* name) const override; void SetComplete() override; - bool ValidateSubstitution(SubstitutionType sub_type) const override; + bool ValidateSubstitution(const Substitution* sub_type) const override; CTool* AsC() override; const CTool* AsC() const override; @@ -109,7 +109,7 @@ // Initialization methods used by InitTool(). If successful, will set the // field and return true, otherwise will return false. Must be called before // SetComplete(). - bool ValidateOutputSubstitution(SubstitutionType sub_type) const; + bool ValidateOutputSubstitution(const Substitution* sub_type) const; bool ValidateRuntimeOutputs(Err* err); // Validates either link_output or depend_output. To generalize to either, // pass
diff --git a/tools/gn/compile_commands_writer.cc b/tools/gn/compile_commands_writer.cc index e0af121..e4a1a19 100644 --- a/tools/gn/compile_commands_writer.cc +++ b/tools/gn/compile_commands_writer.cc
@@ -7,9 +7,10 @@ #include <sstream> #include "base/json/string_escape.h" -#include "base/strings/stringprintf.h" #include "base/strings/string_split.h" +#include "base/strings/stringprintf.h" #include "tools/gn/builder.h" +#include "tools/gn/c_substitution_type.h" #include "tools/gn/c_tool.h" #include "tools/gn/config_values_extractors.h" #include "tools/gn/deps_iterator.h" @@ -68,32 +69,32 @@ base::EscapeJSONString(includes_out.str(), false, &flags.includes); std::ostringstream cflags_out; - WriteOneFlag(target, SUBSTITUTION_CFLAGS, false, Tool::kToolNone, + WriteOneFlag(target, &CSubstitutionCFlags, false, Tool::kToolNone, &ConfigValues::cflags, opts, path_output, cflags_out, /*write_substitution=*/false); base::EscapeJSONString(cflags_out.str(), false, &flags.cflags); std::ostringstream cflags_c_out; - WriteOneFlag(target, SUBSTITUTION_CFLAGS_C, has_precompiled_headers, + WriteOneFlag(target, &CSubstitutionCFlagsC, has_precompiled_headers, CTool::kCToolCc, &ConfigValues::cflags_c, opts, path_output, cflags_c_out, /*write_substitution=*/false); base::EscapeJSONString(cflags_c_out.str(), false, &flags.cflags_c); std::ostringstream cflags_cc_out; - WriteOneFlag(target, SUBSTITUTION_CFLAGS_CC, has_precompiled_headers, + WriteOneFlag(target, &CSubstitutionCFlagsCc, has_precompiled_headers, CTool::kCToolCxx, &ConfigValues::cflags_cc, opts, path_output, cflags_cc_out, /*write_substitution=*/false); base::EscapeJSONString(cflags_cc_out.str(), false, &flags.cflags_cc); std::ostringstream cflags_objc_out; - WriteOneFlag(target, SUBSTITUTION_CFLAGS_OBJC, has_precompiled_headers, + WriteOneFlag(target, &CSubstitutionCFlagsObjC, has_precompiled_headers, CTool::kCToolObjC, &ConfigValues::cflags_objc, opts, path_output, cflags_objc_out, /*write_substitution=*/false); base::EscapeJSONString(cflags_objc_out.str(), false, &flags.cflags_objc); std::ostringstream cflags_objcc_out; - WriteOneFlag(target, SUBSTITUTION_CFLAGS_OBJCC, has_precompiled_headers, + WriteOneFlag(target, &CSubstitutionCFlagsObjCc, has_precompiled_headers, CTool::kCToolObjCxx, &ConfigValues::cflags_objcc, opts, path_output, cflags_objcc_out, /*write_substitution=*/false); base::EscapeJSONString(cflags_objcc_out.str(), false, &flags.cflags_objcc); @@ -132,65 +133,53 @@ for (const auto& range : tool->command().ranges()) { // TODO: this is emitting a bonus space prior to each substitution. - switch (range.type) { - case SUBSTITUTION_LITERAL: - EscapeStringToStream(command_out, range.literal, no_quoting); - break; - case SUBSTITUTION_OUTPUT: - path_output.WriteFiles(command_out, tool_outputs); - break; - case SUBSTITUTION_DEFINES: - command_out << flags.defines; - break; - case SUBSTITUTION_INCLUDE_DIRS: - command_out << flags.includes; - break; - case SUBSTITUTION_CFLAGS: - command_out << flags.cflags; - break; - case SUBSTITUTION_CFLAGS_C: - if (source_type == SOURCE_C) - command_out << flags.cflags_c; - break; - case SUBSTITUTION_CFLAGS_CC: - if (source_type == SOURCE_CPP) - command_out << flags.cflags_cc; - break; - case SUBSTITUTION_CFLAGS_OBJC: - if (source_type == SOURCE_M) - command_out << flags.cflags_objc; - break; - case SUBSTITUTION_CFLAGS_OBJCC: - if (source_type == SOURCE_MM) - command_out << flags.cflags_objcc; - break; - case SUBSTITUTION_LABEL: - case SUBSTITUTION_LABEL_NAME: - case SUBSTITUTION_ROOT_GEN_DIR: - case SUBSTITUTION_ROOT_OUT_DIR: - case SUBSTITUTION_TARGET_GEN_DIR: - case SUBSTITUTION_TARGET_OUT_DIR: - case SUBSTITUTION_TARGET_OUTPUT_NAME: - case SUBSTITUTION_SOURCE: - case SUBSTITUTION_SOURCE_NAME_PART: - case SUBSTITUTION_SOURCE_FILE_PART: - case SUBSTITUTION_SOURCE_DIR: - case SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR: - case SUBSTITUTION_SOURCE_GEN_DIR: - case SUBSTITUTION_SOURCE_OUT_DIR: - case SUBSTITUTION_SOURCE_TARGET_RELATIVE: - EscapeStringToStream(command_out, - SubstitutionWriter::GetCompilerSubstitution( - target, source, range.type), - opts); - break; - + if (range.type == &SubstitutionLiteral) { + EscapeStringToStream(command_out, range.literal, no_quoting); + } else if (range.type == &SubstitutionOutput) { + path_output.WriteFiles(command_out, tool_outputs); + } else if (range.type == &CSubstitutionDefines) { + command_out << flags.defines; + } else if (range.type == &CSubstitutionIncludeDirs) { + command_out << flags.includes; + } else if (range.type == &CSubstitutionCFlags) { + command_out << flags.cflags; + } else if (range.type == &CSubstitutionCFlagsC) { + if (source_type == SOURCE_C) + command_out << flags.cflags_c; + } else if (range.type == &CSubstitutionCFlagsCc) { + if (source_type == SOURCE_CPP) + command_out << flags.cflags_cc; + } else if (range.type == &CSubstitutionCFlagsObjC) { + if (source_type == SOURCE_M) + command_out << flags.cflags_objc; + } else if (range.type == &CSubstitutionCFlagsObjCc) { + if (source_type == SOURCE_MM) + command_out << flags.cflags_objcc; + } else if (range.type == &SubstitutionLabel || + range.type == &SubstitutionLabelName || + range.type == &SubstitutionRootGenDir || + range.type == &SubstitutionRootOutDir || + range.type == &SubstitutionTargetGenDir || + range.type == &SubstitutionTargetOutDir || + range.type == &SubstitutionTargetOutputName || + range.type == &SubstitutionSource || + range.type == &SubstitutionSourceNamePart || + range.type == &SubstitutionSourceFilePart || + range.type == &SubstitutionSourceDir || + range.type == &SubstitutionSourceRootRelativeDir || + range.type == &SubstitutionSourceGenDir || + range.type == &SubstitutionSourceOutDir || + range.type == &SubstitutionSourceTargetRelative) { + EscapeStringToStream(command_out, + SubstitutionWriter::GetCompilerSubstitution( + target, source, range.type), + opts); + } else { // Other flags shouldn't be relevant to compiling C/C++/ObjC/ObjC++ // source files. - default: - NOTREACHED() << "Unsupported substitution for this type of target : " - << kSubstitutionNames[range.type]; - continue; + NOTREACHED() << "Unsupported substitution for this type of target : " + << range.type->name; + continue; } } compile_commands->append(kPrettyPrintLineEnding); @@ -300,7 +289,6 @@ if (!WriteFileIfChanged(output_path, json, err)) return false; return true; - } std::vector<const Target*> CompileCommandsWriter::FilterTargets(
diff --git a/tools/gn/function_process_file_template.cc b/tools/gn/function_process_file_template.cc index 47de640..7035503 100644 --- a/tools/gn/function_process_file_template.cc +++ b/tools/gn/function_process_file_template.cc
@@ -95,7 +95,7 @@ } auto& types = subst.required_types(); - if (base::ContainsValue(types, SUBSTITUTION_SOURCE_TARGET_RELATIVE)) { + if (base::ContainsValue(types, &SubstitutionSourceTargetRelative)) { *err = Err(template_arg, "Not a valid substitution type for the function."); return Value(); }
diff --git a/tools/gn/general_tool.cc b/tools/gn/general_tool.cc index d89dd30..a0f285d 100644 --- a/tools/gn/general_tool.cc +++ b/tools/gn/general_tool.cc
@@ -39,7 +39,7 @@ return Tool::InitTool(scope, toolchain, err); } -bool GeneralTool::ValidateSubstitution(SubstitutionType sub_type) const { +bool GeneralTool::ValidateSubstitution(const Substitution* sub_type) const { if (name_ == kGeneralToolStamp || name_ == kGeneralToolAction) return IsValidToolSubstitution(sub_type); else if (name_ == kGeneralToolCopy || name_ == kGeneralToolCopyBundleData)
diff --git a/tools/gn/general_tool.h b/tools/gn/general_tool.h index df9caf2..b6e1af0 100644 --- a/tools/gn/general_tool.h +++ b/tools/gn/general_tool.h
@@ -35,7 +35,7 @@ bool InitTool(Scope* block_scope, Toolchain* toolchain, Err* err); bool ValidateName(const char* name) const override; void SetComplete() override; - bool ValidateSubstitution(SubstitutionType sub_type) const override; + bool ValidateSubstitution(const Substitution* sub_type) const override; GeneralTool* AsGeneral() override; const GeneralTool* AsGeneral() const override;
diff --git a/tools/gn/ninja_c_binary_target_writer.cc b/tools/gn/ninja_c_binary_target_writer.cc index b96e724..f6ffd15 100644 --- a/tools/gn/ninja_c_binary_target_writer.cc +++ b/tools/gn/ninja_c_binary_target_writer.cc
@@ -13,12 +13,13 @@ #include <unordered_set> #include "base/strings/string_util.h" +#include "tools/gn/c_substitution_type.h" #include "tools/gn/config_values_extractors.h" #include "tools/gn/deps_iterator.h" #include "tools/gn/err.h" #include "tools/gn/escape.h" -#include "tools/gn/general_tool.h" #include "tools/gn/filesystem_utils.h" +#include "tools/gn/general_tool.h" #include "tools/gn/ninja_target_command_util.h" #include "tools/gn/ninja_utils.h" #include "tools/gn/scheduler.h" @@ -41,15 +42,15 @@ // precompiled header files. const char* GetPCHLangForToolType(const char* name) { if (name == CTool::kCToolCc) - return "c-header"; + return "c-header"; if (name == CTool::kCToolCxx) - return "c++-header"; + return "c++-header"; if (name == CTool::kCToolObjC) - return "objective-c-header"; + return "objective-c-header"; if (name == CTool::kCToolObjCxx) - return "objective-c++-header"; - NOTREACHED() << "Not a valid PCH tool type: " << name; - return ""; + return "objective-c++-header"; + NOTREACHED() << "Not a valid PCH tool type: " << name; + return ""; } // Appends the object files generated by the given source set to the given @@ -87,7 +88,8 @@ } } if (used_types.Get(SOURCE_M)) { - const CTool* tool = source_set->toolchain()->GetToolAsC(CTool::kCToolObjC); + const CTool* tool = + source_set->toolchain()->GetToolAsC(CTool::kCToolObjC); if (tool && tool->precompiled_header_type() == CTool::PCH_MSVC) { GetPCHOutputFiles(source_set, CTool::kCToolObjC, &tool_outputs); obj_files->Append(tool_outputs.begin(), tool_outputs.end()); @@ -210,16 +212,16 @@ const SubstitutionBits& subst = target_->toolchain()->substitution_bits(); // Defines. - if (subst.used[SUBSTITUTION_DEFINES]) { - out_ << kSubstitutionNinjaNames[SUBSTITUTION_DEFINES] << " ="; + if (subst.used.count(&CSubstitutionDefines)) { + out_ << CSubstitutionDefines.ninja_name << " ="; RecursiveTargetConfigToStream<std::string>(target_, &ConfigValues::defines, DefineWriter(), out_); out_ << std::endl; } // Include directories. - if (subst.used[SUBSTITUTION_INCLUDE_DIRS]) { - out_ << kSubstitutionNinjaNames[SUBSTITUTION_INCLUDE_DIRS] << " ="; + if (subst.used.count(&CSubstitutionIncludeDirs)) { + out_ << CSubstitutionIncludeDirs.ninja_name << " ="; PathOutput include_path_output( path_output_.current_dir(), settings_->build_settings()->root_path_utf8(), ESCAPE_NINJA_COMMAND); @@ -234,31 +236,31 @@ EscapeOptions opts = GetFlagOptions(); if (used_types.Get(SOURCE_S) || used_types.Get(SOURCE_ASM)) { - WriteOneFlag(target_, SUBSTITUTION_ASMFLAGS, false, Tool::kToolNone, + WriteOneFlag(target_, &CSubstitutionAsmFlags, false, Tool::kToolNone, &ConfigValues::asmflags, opts, path_output_, out_); } if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_CPP) || used_types.Get(SOURCE_M) || used_types.Get(SOURCE_MM)) { - WriteOneFlag(target_, SUBSTITUTION_CFLAGS, false, Tool::kToolNone, + WriteOneFlag(target_, &CSubstitutionCFlags, false, Tool::kToolNone, &ConfigValues::cflags, opts, path_output_, out_); } if (used_types.Get(SOURCE_C)) { - WriteOneFlag(target_, SUBSTITUTION_CFLAGS_C, has_precompiled_headers, + WriteOneFlag(target_, &CSubstitutionCFlagsC, has_precompiled_headers, CTool::kCToolCc, &ConfigValues::cflags_c, opts, path_output_, out_); } if (used_types.Get(SOURCE_CPP)) { - WriteOneFlag(target_, SUBSTITUTION_CFLAGS_CC, has_precompiled_headers, + WriteOneFlag(target_, &CSubstitutionCFlagsCc, has_precompiled_headers, CTool::kCToolCxx, &ConfigValues::cflags_cc, opts, path_output_, out_); } if (used_types.Get(SOURCE_M)) { - WriteOneFlag(target_, SUBSTITUTION_CFLAGS_OBJC, has_precompiled_headers, + WriteOneFlag(target_, &CSubstitutionCFlagsObjC, has_precompiled_headers, CTool::kCToolObjC, &ConfigValues::cflags_objc, opts, path_output_, out_); } if (used_types.Get(SOURCE_MM)) { - WriteOneFlag(target_, SUBSTITUTION_CFLAGS_OBJCC, has_precompiled_headers, + WriteOneFlag(target_, &CSubstitutionCFlagsObjCc, has_precompiled_headers, CTool::kCToolObjCxx, &ConfigValues::cflags_objcc, opts, path_output_, out_); } @@ -318,14 +320,14 @@ const CTool* tool_c = target_->toolchain()->GetToolAsC(CTool::kCToolCc); if (tool_c && tool_c->precompiled_header_type() != CTool::PCH_NONE && used_types.Get(SOURCE_C)) { - WritePCHCommand(SUBSTITUTION_CFLAGS_C, CTool::kCToolCc, + WritePCHCommand(&CSubstitutionCFlagsC, CTool::kCToolCc, tool_c->precompiled_header_type(), input_dep, order_only_deps, object_files, other_files); } const CTool* tool_cxx = target_->toolchain()->GetToolAsC(CTool::kCToolCxx); if (tool_cxx && tool_cxx->precompiled_header_type() != CTool::PCH_NONE && used_types.Get(SOURCE_CPP)) { - WritePCHCommand(SUBSTITUTION_CFLAGS_CC, CTool::kCToolCxx, + WritePCHCommand(&CSubstitutionCFlagsCc, CTool::kCToolCxx, tool_cxx->precompiled_header_type(), input_dep, order_only_deps, object_files, other_files); } @@ -333,7 +335,7 @@ const CTool* tool_objc = target_->toolchain()->GetToolAsC(CTool::kCToolObjC); if (tool_objc && tool_objc->precompiled_header_type() == CTool::PCH_GCC && used_types.Get(SOURCE_M)) { - WritePCHCommand(SUBSTITUTION_CFLAGS_OBJC, CTool::kCToolObjC, + WritePCHCommand(&CSubstitutionCFlagsObjC, CTool::kCToolObjC, tool_objc->precompiled_header_type(), input_dep, order_only_deps, object_files, other_files); } @@ -342,14 +344,14 @@ target_->toolchain()->GetToolAsC(CTool::kCToolObjCxx); if (tool_objcxx && tool_objcxx->precompiled_header_type() == CTool::PCH_GCC && used_types.Get(SOURCE_MM)) { - WritePCHCommand(SUBSTITUTION_CFLAGS_OBJCC, CTool::kCToolObjCxx, + WritePCHCommand(&CSubstitutionCFlagsObjCc, CTool::kCToolObjCxx, tool_objcxx->precompiled_header_type(), input_dep, order_only_deps, object_files, other_files); } } void NinjaCBinaryTargetWriter::WritePCHCommand( - SubstitutionType flag_type, + const Substitution* flag_type, const char* tool_name, CTool::PrecompiledHeaderType header_type, const OutputFile& input_dep, @@ -372,7 +374,7 @@ } void NinjaCBinaryTargetWriter::WriteGCCPCHCommand( - SubstitutionType flag_type, + const Substitution* flag_type, const char* tool_name, const OutputFile& input_dep, const std::vector<OutputFile>& order_only_deps, @@ -395,7 +397,7 @@ // This build line needs a custom language-specific flags value. Rule-specific // variables are just indented underneath the rule line. - out_ << " " << kSubstitutionNinjaNames[flag_type] << " ="; + out_ << " " << flag_type->ninja_name << " ="; // Each substitution flag is overwritten in the target rule to replace the // implicitly generated -include flag with the -x <header lang> flag required @@ -424,7 +426,7 @@ } void NinjaCBinaryTargetWriter::WriteWindowsPCHCommand( - SubstitutionType flag_type, + const Substitution* flag_type, const char* tool_name, const OutputFile& input_dep, const std::vector<OutputFile>& order_only_deps, @@ -447,11 +449,11 @@ // This build line needs a custom language-specific flags value. Rule-specific // variables are just indented underneath the rule line. - out_ << " " << kSubstitutionNinjaNames[flag_type] << " ="; + out_ << " " << flag_type->ninja_name << " ="; // Append the command to generate the .pch file. // This adds the value to the existing flag instead of overwriting it. - out_ << " ${" << kSubstitutionNinjaNames[flag_type] << "}"; + out_ << " ${" << flag_type->ninja_name << "}"; out_ << " /Yc" << target_->config_values().precompiled_header(); // Write two blank lines to help separate the PCH build lines from the @@ -723,11 +725,11 @@ void NinjaCBinaryTargetWriter::WriteOutputSubstitutions() { out_ << " output_extension = " << SubstitutionWriter::GetLinkerSubstitution( - target_, tool_, SUBSTITUTION_OUTPUT_EXTENSION); + target_, tool_, &CSubstitutionOutputExtension); out_ << std::endl; out_ << " output_dir = " << SubstitutionWriter::GetLinkerSubstitution(target_, tool_, - SUBSTITUTION_OUTPUT_DIR); + &CSubstitutionOutputDir); out_ << std::endl; }
diff --git a/tools/gn/ninja_c_binary_target_writer.h b/tools/gn/ninja_c_binary_target_writer.h index 4fb89d9..4d1bdfa 100644 --- a/tools/gn/ninja_c_binary_target_writer.h +++ b/tools/gn/ninja_c_binary_target_writer.h
@@ -48,7 +48,7 @@ std::vector<OutputFile>* other_files); // Writes a .pch compile build line for a language type. - void WritePCHCommand(SubstitutionType flag_type, + void WritePCHCommand(const Substitution* flag_type, const char* tool_name, CTool::PrecompiledHeaderType header_type, const OutputFile& input_dep, @@ -56,13 +56,13 @@ std::vector<OutputFile>* object_files, std::vector<OutputFile>* other_files); - void WriteGCCPCHCommand(SubstitutionType flag_type, + void WriteGCCPCHCommand(const Substitution* flag_type, const char* tool_name, const OutputFile& input_dep, const std::vector<OutputFile>& order_only_deps, std::vector<OutputFile>* gch_files); - void WriteWindowsPCHCommand(SubstitutionType flag_type, + void WriteWindowsPCHCommand(const Substitution* flag_type, const char* tool_name, const OutputFile& input_dep, const std::vector<OutputFile>& order_only_deps,
diff --git a/tools/gn/ninja_target_command_util.cc b/tools/gn/ninja_target_command_util.cc index 2aa3e4b..ef9957e 100644 --- a/tools/gn/ninja_target_command_util.cc +++ b/tools/gn/ninja_target_command_util.cc
@@ -42,7 +42,7 @@ } void WriteOneFlag(const Target* target, - SubstitutionType subst_enum, + const Substitution* subst_enum, bool has_precompiled_headers, const char* tool_name, const std::vector<std::string>& (ConfigValues::*getter)() @@ -51,11 +51,11 @@ PathOutput& path_output, std::ostream& out, bool write_substitution) { - if (!target->toolchain()->substitution_bits().used[subst_enum]) + if (!target->toolchain()->substitution_bits().used.count(subst_enum)) return; if (write_substitution) - out << kSubstitutionNinjaNames[subst_enum] << " ="; + out << subst_enum->ninja_name << " ="; if (has_precompiled_headers) { const CTool* tool = target->toolchain()->GetToolAsC(tool_name);
diff --git a/tools/gn/ninja_target_command_util.h b/tools/gn/ninja_target_command_util.h index 686fada..327e120 100644 --- a/tools/gn/ninja_target_command_util.h +++ b/tools/gn/ninja_target_command_util.h
@@ -61,7 +61,7 @@ // tool-specific (e.g. "cflags_c"). For non-tool-specific flags (e.g. // "defines") tool_type should be TYPE_NONE. void WriteOneFlag(const Target* target, - SubstitutionType subst_enum, + const Substitution* subst_enum, bool has_precompiled_headers, const char* tool_name, const std::vector<std::string>& (ConfigValues::*getter)()
diff --git a/tools/gn/ninja_target_writer.cc b/tools/gn/ninja_target_writer.cc index 8287ec0..239e50f 100644 --- a/tools/gn/ninja_target_writer.cc +++ b/tools/gn/ninja_target_writer.cc
@@ -120,11 +120,11 @@ return rules.str(); } -void NinjaTargetWriter::WriteEscapedSubstitution(SubstitutionType type) { +void NinjaTargetWriter::WriteEscapedSubstitution(const Substitution* type) { EscapeOptions opts; opts.mode = ESCAPE_NINJA; - out_ << kSubstitutionNinjaNames[type] << " = "; + out_ << type->ninja_name << " = "; EscapeStringToStream( out_, SubstitutionWriter::GetTargetSubstitution(target_, type), opts); out_ << std::endl; @@ -134,44 +134,44 @@ bool written_anything = false; // Target label. - if (bits.used[SUBSTITUTION_LABEL]) { - WriteEscapedSubstitution(SUBSTITUTION_LABEL); + if (bits.used.count(&SubstitutionLabel)) { + WriteEscapedSubstitution(&SubstitutionLabel); written_anything = true; } // Target label name - if (bits.used[SUBSTITUTION_LABEL_NAME]) { - WriteEscapedSubstitution(SUBSTITUTION_LABEL_NAME); + if (bits.used.count(&SubstitutionLabelName)) { + WriteEscapedSubstitution(&SubstitutionLabelName); written_anything = true; } // Root gen dir. - if (bits.used[SUBSTITUTION_ROOT_GEN_DIR]) { - WriteEscapedSubstitution(SUBSTITUTION_ROOT_GEN_DIR); + if (bits.used.count(&SubstitutionRootGenDir)) { + WriteEscapedSubstitution(&SubstitutionRootGenDir); written_anything = true; } // Root out dir. - if (bits.used[SUBSTITUTION_ROOT_OUT_DIR]) { - WriteEscapedSubstitution(SUBSTITUTION_ROOT_OUT_DIR); + if (bits.used.count(&SubstitutionRootOutDir)) { + WriteEscapedSubstitution(&SubstitutionRootOutDir); written_anything = true; } // Target gen dir. - if (bits.used[SUBSTITUTION_TARGET_GEN_DIR]) { - WriteEscapedSubstitution(SUBSTITUTION_TARGET_GEN_DIR); + if (bits.used.count(&SubstitutionTargetGenDir)) { + WriteEscapedSubstitution(&SubstitutionTargetGenDir); written_anything = true; } // Target out dir. - if (bits.used[SUBSTITUTION_TARGET_OUT_DIR]) { - WriteEscapedSubstitution(SUBSTITUTION_TARGET_OUT_DIR); + if (bits.used.count(&SubstitutionTargetOutDir)) { + WriteEscapedSubstitution(&SubstitutionTargetOutDir); written_anything = true; } // Target output name. - if (bits.used[SUBSTITUTION_TARGET_OUTPUT_NAME]) { - WriteEscapedSubstitution(SUBSTITUTION_TARGET_OUTPUT_NAME); + if (bits.used.count(&SubstitutionTargetOutputName)) { + WriteEscapedSubstitution(&SubstitutionTargetOutputName); written_anything = true; }
diff --git a/tools/gn/ninja_target_writer.h b/tools/gn/ninja_target_writer.h index a6db060..b49f33e 100644 --- a/tools/gn/ninja_target_writer.h +++ b/tools/gn/ninja_target_writer.h
@@ -64,7 +64,7 @@ private: void WriteCopyRules(); - void WriteEscapedSubstitution(SubstitutionType type); + void WriteEscapedSubstitution(const Substitution* type); DISALLOW_COPY_AND_ASSIGN(NinjaTargetWriter); };
diff --git a/tools/gn/substitution_list.h b/tools/gn/substitution_list.h index 45123cb..e8614eb 100644 --- a/tools/gn/substitution_list.h +++ b/tools/gn/substitution_list.h
@@ -31,7 +31,7 @@ // Returns a list of all substitution types used by the patterns in this // list, with the exception of LITERAL. - const std::vector<SubstitutionType>& required_types() const { + const std::vector<const Substitution*>& required_types() const { return required_types_; } @@ -40,7 +40,7 @@ private: std::vector<SubstitutionPattern> list_; - std::vector<SubstitutionType> required_types_; + std::vector<const Substitution*> required_types_; }; #endif // TOOLS_GN_SUBSTITUTION_LIST_H_
diff --git a/tools/gn/substitution_pattern.cc b/tools/gn/substitution_pattern.cc index 9b5e815..b02532d 100644 --- a/tools/gn/substitution_pattern.cc +++ b/tools/gn/substitution_pattern.cc
@@ -12,9 +12,9 @@ #include "tools/gn/filesystem_utils.h" #include "tools/gn/value.h" -SubstitutionPattern::Subrange::Subrange() : type(SUBSTITUTION_LITERAL) {} +SubstitutionPattern::Subrange::Subrange() : type(&SubstitutionLiteral) {} -SubstitutionPattern::Subrange::Subrange(SubstitutionType t, +SubstitutionPattern::Subrange::Subrange(const Substitution* t, const std::string& l) : type(t), literal(l) {} @@ -45,24 +45,25 @@ // Pick up everything from the previous spot to here as a literal. if (next == std::string::npos) { if (cur != str.size()) - ranges_.push_back(Subrange(SUBSTITUTION_LITERAL, str.substr(cur))); + ranges_.push_back(Subrange(&SubstitutionLiteral, str.substr(cur))); break; } else if (next > cur) { ranges_.push_back( - Subrange(SUBSTITUTION_LITERAL, str.substr(cur, next - cur))); + Subrange(&SubstitutionLiteral, str.substr(cur, next - cur))); } // Find which specific pattern this corresponds to. bool found_match = false; - for (size_t i = SUBSTITUTION_FIRST_PATTERN; i < SUBSTITUTION_NUM_TYPES; - i++) { - const char* cur_pattern = kSubstitutionNames[i]; - size_t cur_len = strlen(cur_pattern); - if (str.compare(next, cur_len, cur_pattern) == 0) { - ranges_.push_back(Subrange(static_cast<SubstitutionType>(i))); - cur = next + cur_len; - found_match = true; - break; + for (const SubstitutionTypes* types : AllSubstitutions) { + for (const Substitution* sub : *types) { + const char* cur_pattern = sub->name; + size_t cur_len = strlen(cur_pattern); + if (str.compare(next, cur_len, cur_pattern) == 0) { + ranges_.push_back(Subrange(sub)); + cur = next + cur_len; + found_match = true; + break; + } } } @@ -99,18 +100,18 @@ std::string SubstitutionPattern::AsString() const { std::string result; for (const auto& elem : ranges_) { - if (elem.type == SUBSTITUTION_LITERAL) + if (elem.type == &SubstitutionLiteral) result.append(elem.literal); else - result.append(kSubstitutionNames[elem.type]); + result.append(elem.type->name); } return result; } void SubstitutionPattern::FillRequiredTypes(SubstitutionBits* bits) const { for (const auto& elem : ranges_) { - if (elem.type != SUBSTITUTION_LITERAL) - bits->used[static_cast<size_t>(elem.type)] = true; + if (elem.type != &SubstitutionLiteral) + bits->used.insert(elem.type); } } @@ -121,7 +122,7 @@ return false; } - if (ranges_[0].type == SUBSTITUTION_LITERAL) { + if (ranges_[0].type == &SubstitutionLiteral) { // If the first thing is a literal, it must start with the output dir. if (!EnsureStringIsInOutputDir(build_settings->build_dir(), ranges_[0].literal, origin_, err))
diff --git a/tools/gn/substitution_pattern.h b/tools/gn/substitution_pattern.h index 850d736..81bd897 100644 --- a/tools/gn/substitution_pattern.h +++ b/tools/gn/substitution_pattern.h
@@ -20,14 +20,14 @@ public: struct Subrange { Subrange(); - explicit Subrange(SubstitutionType t, const std::string& l = std::string()); + explicit Subrange(const Substitution* t, const std::string& l = std::string()); ~Subrange(); inline bool operator==(const Subrange& other) const { return type == other.type && literal == other.literal; } - SubstitutionType type; + const Substitution* type; // When type_ == LITERAL, this specifies the literal. std::string literal; @@ -50,7 +50,7 @@ std::string AsString() const; // Sets the bits in the given vector corresponding to the substitutions used - // by this pattern. SUBSTITUTION_LITERAL is ignored. + // by this pattern. SubstitutionLiteral is ignored. void FillRequiredTypes(SubstitutionBits* bits) const; // Checks whether this pattern resolves to something in the output directory @@ -59,8 +59,8 @@ bool IsInOutputDir(const BuildSettings* build_settings, Err* err) const; // Returns a vector listing the substitutions used by this pattern, not - // counting SUBSTITUTION_LITERAL. - const std::vector<SubstitutionType>& required_types() const { + // counting SubstitutionLiteral. + const std::vector<const Substitution*>& required_types() const { return required_types_; } @@ -73,7 +73,7 @@ std::vector<Subrange> ranges_; const ParseNode* origin_; - std::vector<SubstitutionType> required_types_; + std::vector<const Substitution*> required_types_; }; #endif // TOOLS_GN_SUBSTITUTION_PATTERN_H_
diff --git a/tools/gn/substitution_pattern_unittest.cc b/tools/gn/substitution_pattern_unittest.cc index c8c7396..59c057f 100644 --- a/tools/gn/substitution_pattern_unittest.cc +++ b/tools/gn/substitution_pattern_unittest.cc
@@ -12,7 +12,7 @@ EXPECT_TRUE(pattern.Parse("This is a literal", nullptr, &err)); EXPECT_FALSE(err.has_error()); ASSERT_EQ(1u, pattern.ranges().size()); - EXPECT_EQ(SUBSTITUTION_LITERAL, pattern.ranges()[0].type); + EXPECT_EQ(&SubstitutionLiteral, pattern.ranges()[0].type); EXPECT_EQ("This is a literal", pattern.ranges()[0].literal); } @@ -24,13 +24,13 @@ EXPECT_FALSE(err.has_error()); ASSERT_EQ(5u, pattern.ranges().size()); - EXPECT_EQ(SUBSTITUTION_LITERAL, pattern.ranges()[0].type); + EXPECT_EQ(&SubstitutionLiteral, pattern.ranges()[0].type); EXPECT_EQ("AA", pattern.ranges()[0].literal); - EXPECT_EQ(SUBSTITUTION_SOURCE, pattern.ranges()[1].type); - EXPECT_EQ(SUBSTITUTION_SOURCE_NAME_PART, pattern.ranges()[2].type); - EXPECT_EQ(SUBSTITUTION_LITERAL, pattern.ranges()[3].type); + EXPECT_EQ(&SubstitutionSource, pattern.ranges()[1].type); + EXPECT_EQ(&SubstitutionSourceNamePart, pattern.ranges()[2].type); + EXPECT_EQ(&SubstitutionLiteral, pattern.ranges()[3].type); EXPECT_EQ("BB", pattern.ranges()[3].literal); - EXPECT_EQ(SUBSTITUTION_SOURCE_FILE_PART, pattern.ranges()[4].type); + EXPECT_EQ(&SubstitutionSourceFilePart, pattern.ranges()[4].type); } TEST(SubstitutionPattern, ParseErrors) {
diff --git a/tools/gn/substitution_type.cc b/tools/gn/substitution_type.cc index d47a8d0..f38013e 100644 --- a/tools/gn/substitution_type.cc +++ b/tools/gn/substitution_type.cc
@@ -7,234 +7,178 @@ #include <stddef.h> #include <stdlib.h> +#include "tools/gn/c_substitution_type.h" #include "tools/gn/err.h" -const char* kSubstitutionNames[SUBSTITUTION_NUM_TYPES] = { - "<<literal>>", // SUBSTITUTION_LITERAL +const std::vector<SubstitutionTypes*> AllSubstitutions = {&GeneralSubstitutions, + &CSubstitutions}; - "{{source}}", // SUBSTITUTION_SOURCE - "{{output}}", // SUBSTITUTION_OUTPUT +const SubstitutionTypes GeneralSubstitutions = { + &SubstitutionLiteral, - "{{source_name_part}}", // SUBSTITUTION_NAME_PART - "{{source_file_part}}", // SUBSTITUTION_FILE_PART - "{{source_dir}}", // SUBSTITUTION_SOURCE_DIR - "{{source_root_relative_dir}}", // SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR - "{{source_gen_dir}}", // SUBSTITUTION_SOURCE_GEN_DIR - "{{source_out_dir}}", // SUBSTITUTION_SOURCE_OUT_DIR - "{{source_target_relative}}", // SUBSTITUTION_SOURCE_TARGET_RELATIVE + &SubstitutionOutput, + &SubstitutionLabel, + &SubstitutionLabelName, + &SubstitutionRootGenDir, + &SubstitutionRootOutDir, + &SubstitutionTargetGenDir, + &SubstitutionTargetOutDir, + &SubstitutionTargetOutputName, - "{{label}}", // SUBSTITUTION_LABEL - "{{label_name}}", // SUBSTITUTION_LABEL_NAME - "{{root_gen_dir}}", // SUBSTITUTION_ROOT_GEN_DIR - "{{root_out_dir}}", // SUBSTITUTION_ROOT_OUT_DIR - "{{target_gen_dir}}", // SUBSTITUTION_TARGET_GEN_DIR - "{{target_out_dir}}", // SUBSTITUTION_TARGET_OUT_DIR - "{{target_output_name}}", // SUBSTITUTION_TARGET_OUTPUT_NAME + &SubstitutionSource, + &SubstitutionSourceNamePart, + &SubstitutionSourceFilePart, + &SubstitutionSourceDir, + &SubstitutionSourceRootRelativeDir, + &SubstitutionSourceGenDir, + &SubstitutionSourceOutDir, + &SubstitutionSourceTargetRelative, - "{{asmflags}}", // SUBSTITUTION_ASMFLAGS - "{{cflags}}", // SUBSTITUTION_CFLAGS - "{{cflags_c}}", // SUBSTITUTION_CFLAGS_C - "{{cflags_cc}}", // SUBSTITUTION_CFLAGS_CC - "{{cflags_objc}}", // SUBSTITUTION_CFLAGS_OBJC - "{{cflags_objcc}}", // SUBSTITUTION_CFLAGS_OBJCC - "{{defines}}", // SUBSTITUTION_DEFINES - "{{include_dirs}}", // SUBSTITUTION_INCLUDE_DIRS + &SubstitutionBundleRootDir, + &SubstitutionBundleContentsDir, + &SubstitutionBundleResourcesDir, + &SubstitutionBundleExecutableDir, - "{{inputs}}", // SUBSTITUTION_LINKER_INPUTS - "{{inputs_newline}}", // SUBSTITUTION_LINKER_INPUTS_NEWLINE - "{{ldflags}}", // SUBSTITUTION_LDFLAGS - "{{libs}}", // SUBSTITUTION_LIBS - "{{output_dir}}", // SUBSTITUTION_OUTPUT_DIR - "{{output_extension}}", // SUBSTITUTION_OUTPUT_EXTENSION - "{{solibs}}", // SUBSTITUTION_SOLIBS + &SubstitutionBundleProductType, + &SubstitutionBundlePartialInfoPlist, - "{{arflags}}", // SUBSTITUTION_ARFLAGS - - "{{bundle_root_dir}}", // SUBSTITUTION_BUNDLE_ROOT_DIR - "{{bundle_contents_dir}}", // SUBSTITUTION_BUNDLE_CONTENTS_DIR - "{{bundle_resources_dir}}", // SUBSTITUTION_BUNDLE_RESOURCES_DIR - "{{bundle_executable_dir}}", // SUBSTITUTION_BUNDLE_EXECUTABLE_DIR - "{{bundle_product_type}}", // SUBSTITUTION_BUNDLE_PRODUCT_TYPE - "{{bundle_partial_info_plist}}", // SUBSTITUTION_BUNDLE_PARTIAL_INFO_PLIST, - - "{{response_file_name}}", // SUBSTITUTION_RSP_FILE_NAME + &SubstitutionRspFileName, }; -const char* kSubstitutionNinjaNames[SUBSTITUTION_NUM_TYPES] = { - nullptr, // SUBSTITUTION_LITERAL +const Substitution SubstitutionLiteral = {"<<literal>>", nullptr}; - "in", // SUBSTITUTION_SOURCE - "out", // SUBSTITUTION_OUTPUT +const Substitution SubstitutionSource = {"{{source}}", "in"}; +const Substitution SubstitutionOutput = {"{{output}}", "out"}; - "source_name_part", // SUBSTITUTION_NAME_PART - "source_file_part", // SUBSTITUTION_FILE_PART - "source_dir", // SUBSTITUTION_SOURCE_DIR - "source_root_relative_dir", // SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR - "source_gen_dir", // SUBSTITUTION_SOURCE_GEN_DIR - "source_out_dir", // SUBSTITUTION_SOURCE_OUT_DIR - "source_target_relative", // SUBSTITUTION_SOURCE_TARGET_RELATIVE +const Substitution SubstitutionSourceNamePart = {"{{source_name_part}}", + "source_name_part"}; +const Substitution SubstitutionSourceFilePart = {"{{source_file_part}}", + "source_file_part"}; +const Substitution SubstitutionSourceDir = {"{{source_dir}}", "source_dir"}; +const Substitution SubstitutionSourceRootRelativeDir = { + "{{source_root_relative_dir}}", "source_root_relative_dir"}; +const Substitution SubstitutionSourceGenDir = {"{{source_gen_dir}}", + "source_gen_dir"}; +const Substitution SubstitutionSourceOutDir = {"{{source_out_dir}}", + "source_out_dir"}; +const Substitution SubstitutionSourceTargetRelative = { + "{{source_target_relative}}", "source_target_relative"}; - "label", // SUBSTITUTION_LABEL - "label_name", // SUBSTITUTION_LABEL_NAME - "root_gen_dir", // SUBSTITUTION_ROOT_GEN_DIR - "root_out_dir", // SUBSTITUTION_ROOT_OUT_DIR - "target_gen_dir", // SUBSTITUTION_TARGET_GEN_DIR - "target_out_dir", // SUBSTITUTION_TARGET_OUT_DIR - "target_output_name", // SUBSTITUTION_TARGET_OUTPUT_NAME +// Valid for all compiler and linker tools. These depend on the target and +// do not vary on a per-file basis. +const Substitution SubstitutionLabel = {"{{label}}", "label"}; +const Substitution SubstitutionLabelName = {"{{label_name}}", "label_name"}; +const Substitution SubstitutionRootGenDir = {"{{root_gen_dir}}", + "root_gen_dir"}; +const Substitution SubstitutionRootOutDir = {"{{root_out_dir}}", + "root_out_dir"}; +const Substitution SubstitutionTargetGenDir = {"{{target_gen_dir}}", + "target_gen_dir"}; +const Substitution SubstitutionTargetOutDir = {"{{target_out_dir}}", + "target_out_dir"}; +const Substitution SubstitutionTargetOutputName = {"{{target_output_name}}", + "target_output_name"}; - "asmflags", // SUBSTITUTION_ASMFLAGS - "cflags", // SUBSTITUTION_CFLAGS - "cflags_c", // SUBSTITUTION_CFLAGS_C - "cflags_cc", // SUBSTITUTION_CFLAGS_CC - "cflags_objc", // SUBSTITUTION_CFLAGS_OBJC - "cflags_objcc", // SUBSTITUTION_CFLAGS_OBJCC - "defines", // SUBSTITUTION_DEFINES - "include_dirs", // SUBSTITUTION_INCLUDE_DIRS +// Valid for bundle_data targets. +const Substitution SubstitutionBundleRootDir = {"{{bundle_root_dir}}", + "bundle_root_dir"}; +const Substitution SubstitutionBundleContentsDir = {"{{bundle_contents_dir}}", + "bundle_contents_dir"}; +const Substitution SubstitutionBundleResourcesDir = {"{{bundle_resources_dir}}", + "bundle_resources_dir"}; +const Substitution SubstitutionBundleExecutableDir = { + "{{bundle_executable_dir}}", "bundle_executable_dir"}; - // LINKER_INPUTS expands to the same Ninja var as SUBSTITUTION_SOURCE. These - // are used in different contexts and are named differently to keep things - // clear, but they both expand to the "set of input files" for a build rule. - "in", // SUBSTITUTION_LINKER_INPUTS - "in_newline", // SUBSTITUTION_LINKER_INPUTS_NEWLINE - "ldflags", // SUBSTITUTION_LDFLAGS - "libs", // SUBSTITUTION_LIBS - "output_dir", // SUBSTITUTION_OUTPUT_DIR - "output_extension", // SUBSTITUTION_OUTPUT_EXTENSION - "solibs", // SUBSTITUTION_SOLIBS +// Valid for compile_xcassets tool. +const Substitution SubstitutionBundleProductType = {"{{bundle_product_type}}", + "product_type"}; +const Substitution SubstitutionBundlePartialInfoPlist = { + "{{bundle_partial_info_plist}}", "partial_info_plist"}; - "arflags", // SUBSTITUTION_ARFLAGS +// Used only for the args of actions. +const Substitution SubstitutionRspFileName = {"{{response_file_name}}", + "rspfile"}; - "bundle_root_dir", // SUBSTITUTION_BUNDLE_ROOT_DIR - "bundle_contents_dir", // SUBSTITUTION_BUNDLE_CONTENTS_DIR - "bundle_resources_dir", // SUBSTITUTION_BUNDLE_RESOURCES_DIR - "bundle_executable_dir", // SUBSTITUTION_BUNDLE_EXECUTABLE_DIR - "product_type", // SUBSTITUTION_BUNDLE_PRODUCT_TYPE - "partial_info_plist", // SUBSTITUTION_BUNDLE_PARTIAL_INFO_PLIST - - "rspfile", // SUBSTITUTION_RSP_FILE_NAME -}; - -SubstitutionBits::SubstitutionBits() : used() {} +SubstitutionBits::SubstitutionBits() = default; void SubstitutionBits::MergeFrom(const SubstitutionBits& other) { - for (size_t i = 0; i < SUBSTITUTION_NUM_TYPES; i++) - used[i] |= other.used[i]; + for (const Substitution* s : other.used) + used.insert(s); } -void SubstitutionBits::FillVector(std::vector<SubstitutionType>* vect) const { - for (size_t i = SUBSTITUTION_FIRST_PATTERN; i < SUBSTITUTION_NUM_TYPES; i++) { - if (used[i]) - vect->push_back(static_cast<SubstitutionType>(i)); +void SubstitutionBits::FillVector( + std::vector<const Substitution*>* vect) const { + for (const Substitution* s : used) { + vect->push_back(s); } } -bool SubstitutionIsInOutputDir(SubstitutionType type) { - return type == SUBSTITUTION_SOURCE_GEN_DIR || - type == SUBSTITUTION_SOURCE_OUT_DIR || - type == SUBSTITUTION_ROOT_GEN_DIR || - type == SUBSTITUTION_ROOT_OUT_DIR || - type == SUBSTITUTION_TARGET_GEN_DIR || - type == SUBSTITUTION_TARGET_OUT_DIR; +bool SubstitutionIsInOutputDir(const Substitution* type) { + return type == &SubstitutionSourceGenDir || + type == &SubstitutionSourceOutDir || type == &SubstitutionRootGenDir || + type == &SubstitutionRootOutDir || type == &SubstitutionTargetGenDir || + type == &SubstitutionTargetOutDir; } -bool SubstitutionIsInBundleDir(SubstitutionType type) { - return type == SUBSTITUTION_BUNDLE_ROOT_DIR || - type == SUBSTITUTION_BUNDLE_CONTENTS_DIR || - type == SUBSTITUTION_BUNDLE_RESOURCES_DIR || - type == SUBSTITUTION_BUNDLE_EXECUTABLE_DIR; +bool SubstitutionIsInBundleDir(const Substitution* type) { + return type == &SubstitutionBundleRootDir || + type == &SubstitutionBundleContentsDir || + type == &SubstitutionBundleResourcesDir || + type == &SubstitutionBundleExecutableDir; } -bool IsValidBundleDataSubstitution(SubstitutionType type) { - return type == SUBSTITUTION_LITERAL || - type == SUBSTITUTION_SOURCE_NAME_PART || - type == SUBSTITUTION_SOURCE_FILE_PART || - type == SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR || - type == SUBSTITUTION_BUNDLE_ROOT_DIR || - type == SUBSTITUTION_BUNDLE_CONTENTS_DIR || - type == SUBSTITUTION_BUNDLE_RESOURCES_DIR || - type == SUBSTITUTION_BUNDLE_EXECUTABLE_DIR; +bool IsValidBundleDataSubstitution(const Substitution* type) { + return type == &SubstitutionLiteral || type == &SubstitutionSourceNamePart || + type == &SubstitutionSourceFilePart || + type == &SubstitutionSourceRootRelativeDir || + type == &SubstitutionBundleRootDir || + type == &SubstitutionBundleContentsDir || + type == &SubstitutionBundleResourcesDir || + type == &SubstitutionBundleExecutableDir; } -bool IsValidSourceSubstitution(SubstitutionType type) { - return type == SUBSTITUTION_LITERAL || type == SUBSTITUTION_SOURCE || - type == SUBSTITUTION_SOURCE_NAME_PART || - type == SUBSTITUTION_SOURCE_FILE_PART || - type == SUBSTITUTION_SOURCE_DIR || - type == SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR || - type == SUBSTITUTION_SOURCE_GEN_DIR || - type == SUBSTITUTION_SOURCE_OUT_DIR || - type == SUBSTITUTION_SOURCE_TARGET_RELATIVE; +bool IsValidSourceSubstitution(const Substitution* type) { + return type == &SubstitutionLiteral || type == &SubstitutionSource || + type == &SubstitutionSourceNamePart || + type == &SubstitutionSourceFilePart || + type == &SubstitutionSourceDir || + type == &SubstitutionSourceRootRelativeDir || + type == &SubstitutionSourceGenDir || + type == &SubstitutionSourceOutDir || + type == &SubstitutionSourceTargetRelative; } -bool IsValidScriptArgsSubstitution(SubstitutionType type) { - return IsValidSourceSubstitution(type) || type == SUBSTITUTION_RSP_FILE_NAME; +bool IsValidScriptArgsSubstitution(const Substitution* type) { + return IsValidSourceSubstitution(type) || type == &SubstitutionRspFileName; } -bool IsValidToolSubstitution(SubstitutionType type) { - return type == SUBSTITUTION_LITERAL || type == SUBSTITUTION_OUTPUT || - type == SUBSTITUTION_LABEL || type == SUBSTITUTION_LABEL_NAME || - type == SUBSTITUTION_ROOT_GEN_DIR || - type == SUBSTITUTION_ROOT_OUT_DIR || - type == SUBSTITUTION_TARGET_GEN_DIR || - type == SUBSTITUTION_TARGET_OUT_DIR || - type == SUBSTITUTION_TARGET_OUTPUT_NAME; +bool IsValidToolSubstitution(const Substitution* type) { + return type == &SubstitutionLiteral || type == &SubstitutionOutput || + type == &SubstitutionLabel || type == &SubstitutionLabelName || + type == &SubstitutionRootGenDir || type == &SubstitutionRootOutDir || + type == &SubstitutionTargetGenDir || + type == &SubstitutionTargetOutDir || + type == &SubstitutionTargetOutputName; } -bool IsValidCompilerSubstitution(SubstitutionType type) { - return IsValidToolSubstitution(type) || IsValidSourceSubstitution(type) || - type == SUBSTITUTION_SOURCE || type == SUBSTITUTION_ASMFLAGS || - type == SUBSTITUTION_CFLAGS || type == SUBSTITUTION_CFLAGS_C || - type == SUBSTITUTION_CFLAGS_CC || type == SUBSTITUTION_CFLAGS_OBJC || - type == SUBSTITUTION_CFLAGS_OBJCC || type == SUBSTITUTION_DEFINES || - type == SUBSTITUTION_INCLUDE_DIRS; +bool IsValidCopySubstitution(const Substitution* type) { + return IsValidToolSubstitution(type) || type == &SubstitutionSource; } -bool IsValidCompilerOutputsSubstitution(SubstitutionType type) { - // All tool types except "output" (which would be infinitely recursive). - return (IsValidToolSubstitution(type) && type != SUBSTITUTION_OUTPUT) || - IsValidSourceSubstitution(type); +bool IsValidCompileXCassetsSubstitution(const Substitution* type) { + return IsValidToolSubstitution(type) || type == &CSubstitutionLinkerInputs || + type == &SubstitutionBundleProductType || + type == &SubstitutionBundlePartialInfoPlist; } -bool IsValidLinkerSubstitution(SubstitutionType type) { - return IsValidToolSubstitution(type) || type == SUBSTITUTION_LINKER_INPUTS || - type == SUBSTITUTION_LINKER_INPUTS_NEWLINE || - type == SUBSTITUTION_LDFLAGS || type == SUBSTITUTION_LIBS || - type == SUBSTITUTION_OUTPUT_DIR || - type == SUBSTITUTION_OUTPUT_EXTENSION || type == SUBSTITUTION_SOLIBS; -} - -bool IsValidLinkerOutputsSubstitution(SubstitutionType type) { - // All valid compiler outputs plus the output extension. - return IsValidCompilerOutputsSubstitution(type) || - type == SUBSTITUTION_OUTPUT_DIR || - type == SUBSTITUTION_OUTPUT_EXTENSION; -} - -bool IsValidALinkSubstitution(SubstitutionType type) { - return IsValidToolSubstitution(type) || type == SUBSTITUTION_LINKER_INPUTS || - type == SUBSTITUTION_LINKER_INPUTS_NEWLINE || - type == SUBSTITUTION_ARFLAGS || type == SUBSTITUTION_OUTPUT_DIR || - type == SUBSTITUTION_OUTPUT_EXTENSION; -} - -bool IsValidCopySubstitution(SubstitutionType type) { - return IsValidToolSubstitution(type) || type == SUBSTITUTION_SOURCE; -} - -bool IsValidCompileXCassetsSubstitution(SubstitutionType type) { - return IsValidToolSubstitution(type) || type == SUBSTITUTION_LINKER_INPUTS || - type == SUBSTITUTION_BUNDLE_PRODUCT_TYPE || - type == SUBSTITUTION_BUNDLE_PARTIAL_INFO_PLIST; -} - -bool EnsureValidSubstitutions(const std::vector<SubstitutionType>& types, - bool (*is_valid_subst)(SubstitutionType), +bool EnsureValidSubstitutions(const std::vector<const Substitution*>& types, + bool (*is_valid_subst)(const Substitution*), const ParseNode* origin, Err* err) { - for (SubstitutionType type : types) { + for (const Substitution* type : types) { if (!is_valid_subst(type)) { *err = Err(origin, "Invalid substitution type.", - "The substitution " + std::string(kSubstitutionNames[type]) + + "The substitution " + std::string(type->name) + " isn't valid for something\n" "operating on a source file such as this."); return false;
diff --git a/tools/gn/substitution_type.h b/tools/gn/substitution_type.h index 9e2bdb7..5bdbf90 100644 --- a/tools/gn/substitution_type.h +++ b/tools/gn/substitution_type.h
@@ -7,87 +7,64 @@ #include <vector> +#include "base/containers/flat_set.h" +#include "base/macros.h" + class Err; class ParseNode; -// Keep kSubstitutionNames, kSubstitutionNinjaNames and the -// IsValid*Substitution functions in sync if you change anything here. -enum SubstitutionType { - SUBSTITUTION_LITERAL = 0, - - // The index of the first pattern. To loop overal all patterns, go from here - // until NUM_TYPES. - SUBSTITUTION_FIRST_PATTERN, - - // These map to Ninja's {in} and {out} variables. - SUBSTITUTION_SOURCE = SUBSTITUTION_FIRST_PATTERN, // {{source}} - SUBSTITUTION_OUTPUT, // {{output}} - - // Valid for all compiler tools. - SUBSTITUTION_SOURCE_NAME_PART, // {{source_name_part}} - SUBSTITUTION_SOURCE_FILE_PART, // {{source_file_part}} - SUBSTITUTION_SOURCE_DIR, // {{source_dir}} - SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR, // {{root_relative_dir}} - SUBSTITUTION_SOURCE_GEN_DIR, // {{source_gen_dir}} - SUBSTITUTION_SOURCE_OUT_DIR, // {{source_out_dir}} - SUBSTITUTION_SOURCE_TARGET_RELATIVE, // {{source_target_relative}} - - // Valid for all compiler and linker tools. These depend on the target and - // do not vary on a per-file basis. - SUBSTITUTION_LABEL, // {{label}} - SUBSTITUTION_LABEL_NAME, // {{label_name}} - SUBSTITUTION_ROOT_GEN_DIR, // {{root_gen_dir}} - SUBSTITUTION_ROOT_OUT_DIR, // {{root_out_dir}} - SUBSTITUTION_TARGET_GEN_DIR, // {{target_gen_dir}} - SUBSTITUTION_TARGET_OUT_DIR, // {{target_out_dir}} - SUBSTITUTION_TARGET_OUTPUT_NAME, // {{target_output_name}} - - // Valid for compiler tools. - SUBSTITUTION_ASMFLAGS, // {{asmflags}} - SUBSTITUTION_CFLAGS, // {{cflags}} - SUBSTITUTION_CFLAGS_C, // {{cflags_c}} - SUBSTITUTION_CFLAGS_CC, // {{cflags_cc}} - SUBSTITUTION_CFLAGS_OBJC, // {{cflags_objc}} - SUBSTITUTION_CFLAGS_OBJCC, // {{cflags_objcc}} - SUBSTITUTION_DEFINES, // {{defines}} - SUBSTITUTION_INCLUDE_DIRS, // {{include_dirs}} - - // Valid for linker tools. - SUBSTITUTION_LINKER_INPUTS, // {{inputs}} - SUBSTITUTION_LINKER_INPUTS_NEWLINE, // {{inputs_newline}} - SUBSTITUTION_LDFLAGS, // {{ldflags}} - SUBSTITUTION_LIBS, // {{libs}} - SUBSTITUTION_OUTPUT_DIR, // {{output_dir}} - SUBSTITUTION_OUTPUT_EXTENSION, // {{output_extension}} - SUBSTITUTION_SOLIBS, // {{solibs}} - - // Valid for alink only. - SUBSTITUTION_ARFLAGS, // {{arflags}} - - // Valid for bundle_data targets. - SUBSTITUTION_BUNDLE_ROOT_DIR, // {{bundle_root_dir}} - SUBSTITUTION_BUNDLE_CONTENTS_DIR, // {{bundle_contents_dir}} - SUBSTITUTION_BUNDLE_RESOURCES_DIR, // {{bundle_resources_dir}} - SUBSTITUTION_BUNDLE_EXECUTABLE_DIR, // {{bundle_executable_dir}} - - // Valid for compile_xcassets tool. - SUBSTITUTION_BUNDLE_PRODUCT_TYPE, // {{bundle_product_type}} - SUBSTITUTION_BUNDLE_PARTIAL_INFO_PLIST, // {{bundle_partial_info_plist}} - - // Used only for the args of actions. - SUBSTITUTION_RSP_FILE_NAME, // {{response_file_name}} - - SUBSTITUTION_NUM_TYPES // Must be last. +// Each pair here represents the string representation of the substitution in GN +// and in Ninja. +struct Substitution { + const char* name; + const char* ninja_name; + DISALLOW_COPY_AND_ASSIGN(Substitution); }; -// An array of size SUBSTITUTION_NUM_TYPES that lists the names of the -// substitution patterns, including the curly braces. So, for example, -// kSubstitutionNames[SUBSTITUTION_SOURCE] == "{{source}}". -extern const char* kSubstitutionNames[SUBSTITUTION_NUM_TYPES]; +using SubstitutionTypes = const std::vector<const Substitution*>; -// Ninja variables corresponding to each substitution. These do not include -// the dollar sign. -extern const char* kSubstitutionNinjaNames[SUBSTITUTION_NUM_TYPES]; +// All possible substitutions, organized into logical sets. +extern const std::vector<SubstitutionTypes*> AllSubstitutions; + +// The set of substitutions available to all tools. +extern const SubstitutionTypes GeneralSubstitutions; + +// Types of substitutions. +extern const Substitution SubstitutionLiteral; + +// Valid for all tools. These depend on the target and +// do not vary on a per-file basis. +extern const Substitution SubstitutionOutput; +extern const Substitution SubstitutionLabel; +extern const Substitution SubstitutionLabelName; +extern const Substitution SubstitutionRootGenDir; +extern const Substitution SubstitutionRootOutDir; +extern const Substitution SubstitutionTargetGenDir; +extern const Substitution SubstitutionTargetOutDir; +extern const Substitution SubstitutionTargetOutputName; + +// Valid for all compiler tools. +extern const Substitution SubstitutionSource; +extern const Substitution SubstitutionSourceNamePart; +extern const Substitution SubstitutionSourceFilePart; +extern const Substitution SubstitutionSourceDir; +extern const Substitution SubstitutionSourceRootRelativeDir; +extern const Substitution SubstitutionSourceGenDir; +extern const Substitution SubstitutionSourceOutDir; +extern const Substitution SubstitutionSourceTargetRelative; + +// Valid for bundle_data targets. +extern const Substitution SubstitutionBundleRootDir; +extern const Substitution SubstitutionBundleContentsDir; +extern const Substitution SubstitutionBundleResourcesDir; +extern const Substitution SubstitutionBundleExecutableDir; + +// Valid for compile_xcassets tool. +extern const Substitution SubstitutionBundleProductType; +extern const Substitution SubstitutionBundlePartialInfoPlist; + +// Used only for the args of actions. +extern const Substitution SubstitutionRspFileName; // A wrapper around an array if flags indicating whether a given substitution // type is required in some context. By convention, the LITERAL type bit is @@ -99,43 +76,40 @@ // then be the union of all bits in the two lists. void MergeFrom(const SubstitutionBits& other); - // Converts the substitution type bitfield (with a true set for each required - // item) to a vector of the types listed. Does not include LITERAL. - void FillVector(std::vector<SubstitutionType>* vect) const; + // Converts the substitution type set to a vector of the types listed. Does + // not include SubstitutionLiteral. + void FillVector(std::vector<const Substitution*>* vect) const; - bool used[SUBSTITUTION_NUM_TYPES]; + // This set depends on global uniqueness of pointers, and so all points in + // this set should be the Substitution* constants. + base::flat_set<const Substitution*> used; }; // Returns true if the given substitution pattern references the output // directory. This is used to check strings that begin with a substitution to // verify that they produce a file in the output directory. -bool SubstitutionIsInOutputDir(SubstitutionType type); +bool SubstitutionIsInOutputDir(const Substitution* type); // Returns true if the given substitution pattern references the bundle // directory. This is used to check strings that begin with a substitution to // verify that they produce a file in the bundle directory. -bool SubstitutionIsInBundleDir(SubstitutionType type); +bool SubstitutionIsInBundleDir(const Substitution* type); // Returns true if the given substitution is valid for the named purpose. -bool IsValidBundleDataSubstitution(SubstitutionType type); -bool IsValidSourceSubstitution(SubstitutionType type); -bool IsValidScriptArgsSubstitution(SubstitutionType type); +bool IsValidBundleDataSubstitution(const Substitution* type); +bool IsValidSourceSubstitution(const Substitution* type); +bool IsValidScriptArgsSubstitution(const Substitution* type); // Both compiler and linker tools. -bool IsValidToolSubstitution(SubstitutionType type); -bool IsValidCompilerSubstitution(SubstitutionType type); -bool IsValidCompilerOutputsSubstitution(SubstitutionType type); -bool IsValidLinkerSubstitution(SubstitutionType type); -bool IsValidLinkerOutputsSubstitution(SubstitutionType type); -bool IsValidALinkSubstitution(SubstitutionType type); -bool IsValidCopySubstitution(SubstitutionType type); -bool IsValidCompileXCassetsSubstitution(SubstitutionType type); +bool IsValidToolSubstitution(const Substitution* type); +bool IsValidCopySubstitution(const Substitution* type); +bool IsValidCompileXCassetsSubstitution(const Substitution* type); // Validates that each substitution type in the vector passes the given // is_valid_subst predicate. Returns true on success. On failure, fills in the // error object with an appropriate message and returns false. -bool EnsureValidSubstitutions(const std::vector<SubstitutionType>& types, - bool (*is_valid_subst)(SubstitutionType), +bool EnsureValidSubstitutions(const std::vector<const Substitution*>& types, + bool (*is_valid_subst)(const Substitution*), const ParseNode* origin, Err* err);
diff --git a/tools/gn/substitution_writer.cc b/tools/gn/substitution_writer.cc index 96a12b1..c8bc70f 100644 --- a/tools/gn/substitution_writer.cc +++ b/tools/gn/substitution_writer.cc
@@ -5,6 +5,7 @@ #include "tools/gn/substitution_writer.h" #include "tools/gn/build_settings.h" +#include "tools/gn/c_substitution_type.h" #include "tools/gn/escape.h" #include "tools/gn/filesystem_utils.h" #include "tools/gn/output_file.h" @@ -156,11 +157,11 @@ bool needs_quotes = false; std::string result; for (const auto& range : pattern.ranges()) { - if (range.type == SUBSTITUTION_LITERAL) { + if (range.type == &SubstitutionLiteral) { result.append(EscapeString(range.literal, no_quoting, &needs_quotes)); } else { result.append("${"); - result.append(kSubstitutionNinjaNames[range.type]); + result.append(range.type->ninja_name); result.append("}"); } } @@ -176,7 +177,7 @@ std::vector<SourceFile>* output) { for (const auto& pattern : list.list()) { CHECK(pattern.ranges().size() == 1 && - pattern.ranges()[0].type == SUBSTITUTION_LITERAL) + pattern.ranges()[0].type == &SubstitutionLiteral) << "The substitution pattern \"" << pattern.AsString() << "\" was expected to be a literal with no {{substitutions}}."; const std::string& literal = pattern.ranges()[0].literal; @@ -219,7 +220,7 @@ const SourceFile& source) { std::string result_value; for (const auto& subrange : pattern.ranges()) { - if (subrange.type == SUBSTITUTION_LITERAL) { + if (subrange.type == &SubstitutionLiteral) { result_value.append(subrange.literal); } else { result_value.append(GetSourceSubstitution(target, settings, source, @@ -316,7 +317,7 @@ const Target* target, const Settings* settings, const SourceFile& source, - const std::vector<SubstitutionType>& types, + const std::vector<const Substitution*>& types, const EscapeOptions& escape_options, std::ostream& out) { for (const auto& type : types) { @@ -324,8 +325,8 @@ // is implicit in the rule. RESPONSE_FILE_NAME is written separately // only when writing target rules since it can never be used in any // other context (like process_file_template). - if (type != SUBSTITUTION_SOURCE && type != SUBSTITUTION_RSP_FILE_NAME) { - out << " " << kSubstitutionNinjaNames[type] << " = "; + if (type != &SubstitutionSource && type != &SubstitutionRspFileName) { + out << " " << type->ninja_name << " = "; EscapeStringToStream( out, GetSourceSubstitution(target, settings, source, type, OUTPUT_RELATIVE, @@ -341,59 +342,46 @@ const Target* target, const Settings* settings, const SourceFile& source, - SubstitutionType type, + const Substitution* type, OutputStyle output_style, const SourceDir& relative_to) { std::string to_rebase; - switch (type) { - case SUBSTITUTION_SOURCE: - if (source.is_system_absolute()) - return source.value(); - to_rebase = source.value(); - break; - - case SUBSTITUTION_SOURCE_NAME_PART: - return FindFilenameNoExtension(&source.value()).as_string(); - - case SUBSTITUTION_SOURCE_FILE_PART: - return source.GetName(); - - case SUBSTITUTION_SOURCE_DIR: - if (source.is_system_absolute()) - return DirectoryWithNoLastSlash(source.GetDir()); - to_rebase = DirectoryWithNoLastSlash(source.GetDir()); - break; - - case SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR: - if (source.is_system_absolute()) - return DirectoryWithNoLastSlash(source.GetDir()); - return RebasePath(DirectoryWithNoLastSlash(source.GetDir()), - SourceDir("//"), + if (type == &SubstitutionSource) { + if (source.is_system_absolute()) + return source.value(); + to_rebase = source.value(); + } else if (type == &SubstitutionSourceNamePart) { + return FindFilenameNoExtension(&source.value()).as_string(); + } else if (type == &SubstitutionSourceFilePart) { + return source.GetName(); + } else if (type == &SubstitutionSourceDir) { + if (source.is_system_absolute()) + return DirectoryWithNoLastSlash(source.GetDir()); + to_rebase = DirectoryWithNoLastSlash(source.GetDir()); + } else if (type == &SubstitutionSourceRootRelativeDir) { + if (source.is_system_absolute()) + return DirectoryWithNoLastSlash(source.GetDir()); + return RebasePath(DirectoryWithNoLastSlash(source.GetDir()), + SourceDir("//"), + settings->build_settings()->root_path_utf8()); + } else if (type == &SubstitutionSourceGenDir) { + to_rebase = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir( + BuildDirContext(settings), source.GetDir(), BuildDirType::GEN)); + } else if (type == &SubstitutionSourceOutDir) { + to_rebase = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir( + BuildDirContext(settings), source.GetDir(), BuildDirType::OBJ)); + } else if (type == &SubstitutionSourceTargetRelative) { + if (target) { + return RebasePath(source.value(), target->label().dir(), settings->build_settings()->root_path_utf8()); - - case SUBSTITUTION_SOURCE_GEN_DIR: - to_rebase = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir( - BuildDirContext(settings), source.GetDir(), BuildDirType::GEN)); - break; - - case SUBSTITUTION_SOURCE_OUT_DIR: - to_rebase = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir( - BuildDirContext(settings), source.GetDir(), BuildDirType::OBJ)); - break; - - case SUBSTITUTION_SOURCE_TARGET_RELATIVE: - if (target) { - return RebasePath(source.value(), target->label().dir(), - settings->build_settings()->root_path_utf8()); - } - NOTREACHED() << "Cannot use substitution " << kSubstitutionNames[type] - << " without target"; - return std::string(); - - default: - NOTREACHED() << "Unsupported substitution for this function: " - << kSubstitutionNames[type]; - return std::string(); + } + NOTREACHED() << "Cannot use substitution " << type->name + << " without target"; + return std::string(); + } else { + NOTREACHED() << "Unsupported substitution for this function: " + << type->name; + return std::string(); } // If we get here, the result is a path that should be made relative or @@ -412,7 +400,7 @@ const SubstitutionPattern& pattern) { std::string result_value; for (const auto& subrange : pattern.ranges()) { - if (subrange.type == SUBSTITUTION_LITERAL) { + if (subrange.type == &SubstitutionLiteral) { result_value.append(subrange.literal); } else { std::string subst; @@ -435,49 +423,42 @@ // static bool SubstitutionWriter::GetTargetSubstitution(const Target* target, - SubstitutionType type, + const Substitution* type, std::string* result) { - switch (type) { - case SUBSTITUTION_LABEL: - // Only include the toolchain for non-default toolchains. - *result = - target->label().GetUserVisibleName(!target->settings()->is_default()); - break; - case SUBSTITUTION_LABEL_NAME: - *result = target->label().name(); - break; - case SUBSTITUTION_ROOT_GEN_DIR: - SetDirOrDotWithNoSlash( - GetBuildDirAsOutputFile(BuildDirContext(target), BuildDirType::GEN) - .value(), - result); - break; - case SUBSTITUTION_ROOT_OUT_DIR: - SetDirOrDotWithNoSlash( - target->settings()->toolchain_output_subdir().value(), result); - break; - case SUBSTITUTION_TARGET_GEN_DIR: - SetDirOrDotWithNoSlash( - GetBuildDirForTargetAsOutputFile(target, BuildDirType::GEN).value(), - result); - break; - case SUBSTITUTION_TARGET_OUT_DIR: - SetDirOrDotWithNoSlash( - GetBuildDirForTargetAsOutputFile(target, BuildDirType::OBJ).value(), - result); - break; - case SUBSTITUTION_TARGET_OUTPUT_NAME: - *result = target->GetComputedOutputName(); - break; - default: - return false; + if (type == &SubstitutionLabel) { + // Only include the toolchain for non-default toolchains. + *result = + target->label().GetUserVisibleName(!target->settings()->is_default()); + } else if (type == &SubstitutionLabelName) { + *result = target->label().name(); + } else if (type == &SubstitutionRootGenDir) { + SetDirOrDotWithNoSlash( + GetBuildDirAsOutputFile(BuildDirContext(target), BuildDirType::GEN) + .value(), + result); + } else if (type == &SubstitutionRootOutDir) { + SetDirOrDotWithNoSlash( + target->settings()->toolchain_output_subdir().value(), result); + } else if (type == &SubstitutionTargetGenDir) { + SetDirOrDotWithNoSlash( + GetBuildDirForTargetAsOutputFile(target, BuildDirType::GEN).value(), + result); + } else if (type == &SubstitutionTargetOutDir) { + SetDirOrDotWithNoSlash( + GetBuildDirForTargetAsOutputFile(target, BuildDirType::OBJ).value(), + result); + } else if (type == &SubstitutionTargetOutputName) { + *result = target->GetComputedOutputName(); + } else { + return false; } return true; } // static -std::string SubstitutionWriter::GetTargetSubstitution(const Target* target, - SubstitutionType type) { +std::string SubstitutionWriter::GetTargetSubstitution( + const Target* target, + const Substitution* type) { std::string result; GetTargetSubstitution(target, type, &result); return result; @@ -490,7 +471,7 @@ const SubstitutionPattern& pattern) { OutputFile result; for (const auto& subrange : pattern.ranges()) { - if (subrange.type == SUBSTITUTION_LITERAL) { + if (subrange.type == &SubstitutionLiteral) { result.value().append(subrange.literal); } else { result.value().append( @@ -514,7 +495,7 @@ std::string SubstitutionWriter::GetCompilerSubstitution( const Target* target, const SourceFile& source, - SubstitutionType type) { + const Substitution* type) { // First try the common tool ones. std::string result; if (GetTargetSubstitution(target, type, &result)) @@ -533,7 +514,7 @@ const SubstitutionPattern& pattern) { OutputFile result; for (const auto& subrange : pattern.ranges()) { - if (subrange.type == SUBSTITUTION_LITERAL) { + if (subrange.type == &SubstitutionLiteral) { result.value().append(subrange.literal); } else { result.value().append(GetLinkerSubstitution(target, tool, subrange.type)); @@ -553,44 +534,43 @@ } // static -std::string SubstitutionWriter::GetLinkerSubstitution(const Target* target, - const Tool* tool, - SubstitutionType type) { +std::string SubstitutionWriter::GetLinkerSubstitution( + const Target* target, + const Tool* tool, + const Substitution* type) { // First try the common tool ones. std::string result; if (GetTargetSubstitution(target, type, &result)) return result; // Fall-through to the linker-specific ones. - switch (type) { - case SUBSTITUTION_OUTPUT_DIR: - // Use the target's value if there is one (it will have no expansion - // patterns since it can directly use GN variables to compute whatever - // path it wants), or the tool's default (which will contain further - // expansions). - if (target->output_dir().is_null()) { - return ApplyPatternToLinkerAsOutputFile(target, tool, - tool->default_output_dir()) - .value(); - } - SetDirOrDotWithNoSlash( - RebasePath(target->output_dir().value(), - target->settings()->build_settings()->build_dir()), - &result); - return result; + if (type == &CSubstitutionOutputDir) { + // Use the target's value if there is one (it will have no expansion + // patterns since it can directly use GN variables to compute whatever + // path it wants), or the tool's default (which will contain further + // expansions). + if (target->output_dir().is_null()) { + return ApplyPatternToLinkerAsOutputFile(target, tool, + tool->default_output_dir()) + .value(); + } + SetDirOrDotWithNoSlash( + RebasePath(target->output_dir().value(), + target->settings()->build_settings()->build_dir()), + &result); + return result; + } else if (type == &CSubstitutionOutputExtension) { + // Use the extension provided on the target if specified, otherwise + // fall back on the default. Note that the target's output extension + // does not include the dot but the tool's does. + if (!target->output_extension_set()) + return tool->default_output_extension(); + if (target->output_extension().empty()) + return std::string(); // Explicitly set to no extension. + return std::string(".") + target->output_extension(); - case SUBSTITUTION_OUTPUT_EXTENSION: - // Use the extension provided on the target if specified, otherwise - // fall back on the default. Note that the target's output extension - // does not include the dot but the tool's does. - if (!target->output_extension_set()) - return tool->default_output_extension(); - if (target->output_extension().empty()) - return std::string(); // Explicitly set to no extension. - return std::string(".") + target->output_extension(); - - default: - NOTREACHED(); - return std::string(); + } else { + NOTREACHED(); + return std::string(); } }
diff --git a/tools/gn/substitution_writer.h b/tools/gn/substitution_writer.h index 530f064..24cc283 100644 --- a/tools/gn/substitution_writer.h +++ b/tools/gn/substitution_writer.h
@@ -155,7 +155,7 @@ const Target* target, const Settings* settings, const SourceFile& source, - const std::vector<SubstitutionType>& types, + const std::vector<const Substitution*>& types, const EscapeOptions& escape_options, std::ostream& out); @@ -168,7 +168,7 @@ static std::string GetSourceSubstitution(const Target* target, const Settings* settings, const SourceFile& source, - SubstitutionType type, + const Substitution* type, OutputStyle output_style, const SourceDir& relative_to); @@ -190,10 +190,10 @@ // compiler and linker ones which will fall through if it's not a common tool // one). static bool GetTargetSubstitution(const Target* target, - SubstitutionType type, + const Substitution* type, std::string* result); static std::string GetTargetSubstitution(const Target* target, - SubstitutionType type); + const Substitution* type); // Compiler substitutions ---------------------------------------------------- // @@ -214,7 +214,7 @@ // directory. static std::string GetCompilerSubstitution(const Target* target, const SourceFile& source, - SubstitutionType type); + const Substitution* type); // Linker substitutions ------------------------------------------------------ @@ -232,7 +232,7 @@ // directory. static std::string GetLinkerSubstitution(const Target* target, const Tool* tool, - SubstitutionType type); + const Substitution* type); }; #endif // TOOLS_GN_SUBSTITUTION_WRITER_H_
diff --git a/tools/gn/substitution_writer_unittest.cc b/tools/gn/substitution_writer_unittest.cc index cc476e4..bea8fec 100644 --- a/tools/gn/substitution_writer_unittest.cc +++ b/tools/gn/substitution_writer_unittest.cc
@@ -4,6 +4,7 @@ #include <sstream> +#include "tools/gn/c_substitution_type.h" #include "tools/gn/err.h" #include "tools/gn/escape.h" #include "tools/gn/substitution_list.h" @@ -62,10 +63,10 @@ TEST(SubstitutionWriter, WriteNinjaVariablesForSource) { TestWithScope setup; - std::vector<SubstitutionType> types; - types.push_back(SUBSTITUTION_SOURCE); - types.push_back(SUBSTITUTION_SOURCE_NAME_PART); - types.push_back(SUBSTITUTION_SOURCE_DIR); + std::vector<const Substitution*> types; + types.push_back(&SubstitutionSource); + types.push_back(&SubstitutionSourceNamePart); + types.push_back(&SubstitutionSourceDir); EscapeOptions options; options.mode = ESCAPE_NONE; @@ -123,61 +124,58 @@ // Try all possible templates with a normal looking string. EXPECT_EQ("../../foo/bar/baz.txt", - GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE)); + GetRelSubst("//foo/bar/baz.txt", &SubstitutionSource)); EXPECT_EQ("//foo/bar/baz.txt", - GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE)); + GetAbsSubst("//foo/bar/baz.txt", &SubstitutionSource)); EXPECT_EQ("baz", - GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_NAME_PART)); + GetRelSubst("//foo/bar/baz.txt", &SubstitutionSourceNamePart)); EXPECT_EQ("baz", - GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_NAME_PART)); + GetAbsSubst("//foo/bar/baz.txt", &SubstitutionSourceNamePart)); EXPECT_EQ("baz.txt", - GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_FILE_PART)); + GetRelSubst("//foo/bar/baz.txt", &SubstitutionSourceFilePart)); EXPECT_EQ("baz.txt", - GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_FILE_PART)); + GetAbsSubst("//foo/bar/baz.txt", &SubstitutionSourceFilePart)); EXPECT_EQ("../../foo/bar", - GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_DIR)); + GetRelSubst("//foo/bar/baz.txt", &SubstitutionSourceDir)); EXPECT_EQ("//foo/bar", - GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_DIR)); + GetAbsSubst("//foo/bar/baz.txt", &SubstitutionSourceDir)); EXPECT_EQ("foo/bar", GetRelSubst("//foo/bar/baz.txt", - SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR)); + &SubstitutionSourceRootRelativeDir)); EXPECT_EQ("foo/bar", GetAbsSubst("//foo/bar/baz.txt", - SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR)); + &SubstitutionSourceRootRelativeDir)); EXPECT_EQ("gen/foo/bar", - GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_GEN_DIR)); + GetRelSubst("//foo/bar/baz.txt", &SubstitutionSourceGenDir)); EXPECT_EQ("//out/Debug/gen/foo/bar", - GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_GEN_DIR)); + GetAbsSubst("//foo/bar/baz.txt", &SubstitutionSourceGenDir)); EXPECT_EQ("obj/foo/bar", - GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_OUT_DIR)); + GetRelSubst("//foo/bar/baz.txt", &SubstitutionSourceOutDir)); EXPECT_EQ("//out/Debug/obj/foo/bar", - GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_OUT_DIR)); + GetAbsSubst("//foo/bar/baz.txt", &SubstitutionSourceOutDir)); // Operations on an absolute path. - EXPECT_EQ("/baz.txt", GetRelSubst("/baz.txt", SUBSTITUTION_SOURCE)); - EXPECT_EQ("/.", GetRelSubst("/baz.txt", SUBSTITUTION_SOURCE_DIR)); - EXPECT_EQ("gen/ABS_PATH", - GetRelSubst("/baz.txt", SUBSTITUTION_SOURCE_GEN_DIR)); - EXPECT_EQ("obj/ABS_PATH", - GetRelSubst("/baz.txt", SUBSTITUTION_SOURCE_OUT_DIR)); + EXPECT_EQ("/baz.txt", GetRelSubst("/baz.txt", &SubstitutionSource)); + EXPECT_EQ("/.", GetRelSubst("/baz.txt", &SubstitutionSourceDir)); + EXPECT_EQ("gen/ABS_PATH", GetRelSubst("/baz.txt", &SubstitutionSourceGenDir)); + EXPECT_EQ("obj/ABS_PATH", GetRelSubst("/baz.txt", &SubstitutionSourceOutDir)); #if defined(OS_WIN) EXPECT_EQ("gen/ABS_PATH/C", - GetRelSubst("/C:/baz.txt", SUBSTITUTION_SOURCE_GEN_DIR)); + GetRelSubst("/C:/baz.txt", &SubstitutionSourceGenDir)); EXPECT_EQ("obj/ABS_PATH/C", - GetRelSubst("/C:/baz.txt", SUBSTITUTION_SOURCE_OUT_DIR)); + GetRelSubst("/C:/baz.txt", &SubstitutionSourceOutDir)); #endif - EXPECT_EQ(".", - GetRelSubst("//baz.txt", SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR)); + EXPECT_EQ(".", GetRelSubst("//baz.txt", &SubstitutionSourceRootRelativeDir)); EXPECT_EQ("baz.txt", GetRelSubst("//foo/bar/baz.txt", - SUBSTITUTION_SOURCE_TARGET_RELATIVE)); + &SubstitutionSourceTargetRelative)); EXPECT_EQ("baz.txt", GetAbsSubst("//foo/bar/baz.txt", - SUBSTITUTION_SOURCE_TARGET_RELATIVE)); + &SubstitutionSourceTargetRelative)); #undef GetAbsSubst #undef GetRelSubst @@ -194,31 +192,31 @@ std::string result; EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution( - &target, SUBSTITUTION_LABEL, &result)); + &target, &SubstitutionLabel, &result)); EXPECT_EQ("//foo/bar:baz", result); EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution( - &target, SUBSTITUTION_LABEL_NAME, &result)); + &target, &SubstitutionLabelName, &result)); EXPECT_EQ("baz", result); EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution( - &target, SUBSTITUTION_ROOT_GEN_DIR, &result)); + &target, &SubstitutionRootGenDir, &result)); EXPECT_EQ("gen", result); EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution( - &target, SUBSTITUTION_ROOT_OUT_DIR, &result)); + &target, &SubstitutionRootOutDir, &result)); EXPECT_EQ(".", result); EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution( - &target, SUBSTITUTION_TARGET_GEN_DIR, &result)); + &target, &SubstitutionTargetGenDir, &result)); EXPECT_EQ("gen/foo/bar", result); EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution( - &target, SUBSTITUTION_TARGET_OUT_DIR, &result)); + &target, &SubstitutionTargetOutDir, &result)); EXPECT_EQ("obj/foo/bar", result); EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution( - &target, SUBSTITUTION_TARGET_OUTPUT_NAME, &result)); + &target, &SubstitutionTargetOutputName, &result)); EXPECT_EQ("libbaz", result); } @@ -235,10 +233,10 @@ // of each of those classes of things to make sure this is hooked up. EXPECT_EQ("file", SubstitutionWriter::GetCompilerSubstitution( &target, SourceFile("//foo/bar/file.txt"), - SUBSTITUTION_SOURCE_NAME_PART)); + &SubstitutionSourceNamePart)); EXPECT_EQ("gen/foo/bar", SubstitutionWriter::GetCompilerSubstitution( &target, SourceFile("//foo/bar/file.txt"), - SUBSTITUTION_TARGET_GEN_DIR)); + &SubstitutionTargetGenDir)); } TEST(SubstitutionWriter, LinkerSubstitutions) { @@ -255,9 +253,9 @@ // The compiler substitution is just target + OUTPUT_EXTENSION combined. So // test one target one plus the output extension. EXPECT_EQ(".so", SubstitutionWriter::GetLinkerSubstitution( - &target, tool, SUBSTITUTION_OUTPUT_EXTENSION)); + &target, tool, &CSubstitutionOutputExtension)); EXPECT_EQ("gen/foo/bar", SubstitutionWriter::GetLinkerSubstitution( - &target, tool, SUBSTITUTION_TARGET_GEN_DIR)); + &target, tool, &SubstitutionTargetGenDir)); // Test that we handle paths that end up in the root build dir properly // (no leading "./" or "/"). @@ -272,10 +270,10 @@ // Output extensions can be overridden. target.set_output_extension("extension"); EXPECT_EQ(".extension", SubstitutionWriter::GetLinkerSubstitution( - &target, tool, SUBSTITUTION_OUTPUT_EXTENSION)); + &target, tool, &CSubstitutionOutputExtension)); target.set_output_extension(""); EXPECT_EQ("", SubstitutionWriter::GetLinkerSubstitution( - &target, tool, SUBSTITUTION_OUTPUT_EXTENSION)); + &target, tool, &CSubstitutionOutputExtension)); // Output directory is tested in a separate test below. } @@ -304,8 +302,8 @@ ASSERT_TRUE(output_name.Parse("{{output_dir}}/{{target_output_name}}.exe", nullptr, &err)); EXPECT_EQ("./baz/baz.exe", - SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(&target, tool.get(), - output_name) + SubstitutionWriter::ApplyPatternToLinkerAsOutputFile( + &target, tool.get(), output_name) .value()); // Override the output name to the root build dir. @@ -317,7 +315,7 @@ // Override the output name to a new subdirectory. target.set_output_dir(SourceDir("//out/Debug/foo/bar")); EXPECT_EQ("foo/bar/baz.exe", - SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(&target, tool.get(), - output_name) + SubstitutionWriter::ApplyPatternToLinkerAsOutputFile( + &target, tool.get(), output_name) .value()); }
diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc index 9ad8969..a468426 100644 --- a/tools/gn/target_generator.cc +++ b/tools/gn/target_generator.cc
@@ -368,7 +368,7 @@ return false; } - if (pattern.ranges()[0].type == SUBSTITUTION_LITERAL) { + if (pattern.ranges()[0].type == &SubstitutionLiteral) { // If the first thing is a literal, it must start with the output dir. if (!EnsureStringIsInOutputDir(GetBuildSettings()->build_dir(), pattern.ranges()[0].literal,
diff --git a/tools/gn/tool.cc b/tools/gn/tool.cc index 51e0bc2..f60e3d4 100644 --- a/tools/gn/tool.cc +++ b/tools/gn/tool.cc
@@ -53,14 +53,14 @@ return false; } -bool Tool::ValidateSubstitutionList(const std::vector<SubstitutionType>& list, +bool Tool::ValidateSubstitutionList(const std::vector<const Substitution*>& list, const Value* origin, Err* err) const { for (const auto& cur_type : list) { if (!ValidateSubstitution(cur_type)) { *err = Err(*origin, "Pattern not valid here.", "You used the pattern " + - std::string(kSubstitutionNames[cur_type]) + + std::string(cur_type->name) + " which is not valid\nfor this variable."); return false; }
diff --git a/tools/gn/tool.h b/tools/gn/tool.h index 4060527..d800886 100644 --- a/tools/gn/tool.h +++ b/tools/gn/tool.h
@@ -53,7 +53,7 @@ virtual void SetComplete() = 0; // Validate substitutions in this tool. - virtual bool ValidateSubstitution(SubstitutionType sub_type) const = 0; + virtual bool ValidateSubstitution(const Substitution* sub_type) const = 0; // Manual RTTI virtual CTool* AsC(); @@ -183,7 +183,7 @@ // SetComplete(). bool IsPatternInOutputList(const SubstitutionList& output_list, const SubstitutionPattern& pattern) const; - bool ValidateSubstitutionList(const std::vector<SubstitutionType>& list, + bool ValidateSubstitutionList(const std::vector<const Substitution*>& list, const Value* origin, Err* err) const; bool ValidateOutputs(Err* err) const;