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;