[tvos] Search for `kTargetXcodePlatform` from all arguments
This introduces GetArgFromAllArguments() and uses it to
search for `kTargetXcodePlatform` from all arguments.
Bug: chromium:391914246
Change-Id: I990a9609d05e3f154e65116f24e0591229569b2d
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/18920
Commit-Queue: David Turner <digit@google.com>
Reviewed-by: Sylvain Defresne <sdefresne@chromium.org>
Reviewed-by: David Turner <digit@google.com>
diff --git a/src/gn/args.cc b/src/gn/args.cc
index c67f8bc..28c9304 100644
--- a/src/gn/args.cc
+++ b/src/gn/args.cc
@@ -139,6 +139,46 @@
return &found->second;
}
+std::vector<const Settings*> Args::GetSortedToolchainsLocked() const {
+ std::vector<const Settings*> toolchains;
+ toolchains.reserve(declared_arguments_per_toolchain_.size());
+ for (const auto& map_pair : declared_arguments_per_toolchain_) {
+ toolchains.push_back(map_pair.first);
+ }
+ std::sort(toolchains.begin(), toolchains.end(),
+ [](const Settings* a, const Settings* b) -> bool {
+ // NOTE: There can be multiple default toolchains in the map!
+ // which happens when declare_args() blocks are found in args.gn
+ // or some of its imports. This uses a Settings instance with
+ // an empty label, where `is_default()` returns true.
+ if (a->is_default() != b->is_default())
+ return a->is_default();
+ return a->toolchain_label() < b->toolchain_label();
+ });
+ return toolchains;
+}
+
+std::optional<Value> Args::GetArgFromAllArguments(const char* name) const {
+ // First, look into overrides defined in .gn
+ const Value* override = GetArgOverride(name);
+ if (override)
+ return std::make_optional(*override);
+
+ // Second, look into each toolchain definition, the default one
+ // always appear first here.
+ std::lock_guard<std::mutex> lock(lock_);
+
+ for (const Settings* toolchain : GetSortedToolchainsLocked()) {
+ const auto& value_map = declared_arguments_per_toolchain_[toolchain];
+ auto it = value_map.find(name);
+ if (it != value_map.end())
+ return std::make_optional(it->second);
+ }
+
+ // No match
+ return std::nullopt;
+}
+
void Args::SetupRootScope(Scope* dest,
const Scope::KeyValueMap& toolchain_overrides) const {
std::lock_guard<std::mutex> lock(lock_);
@@ -273,21 +313,7 @@
// Sort the toolchains from declared_arguments_per_toolchain_ so
// the return value will be deterministic. Always prioritize
// the default toolchain.
- std::vector<const Settings*> toolchains;
- toolchains.reserve(declared_arguments_per_toolchain_.size());
- for (const auto& map_pair : declared_arguments_per_toolchain_) {
- toolchains.push_back(map_pair.first);
- }
- std::sort(toolchains.begin(), toolchains.end(),
- [](const Settings* a, const Settings* b) -> bool {
- // NOTE: There can be multiple default toolchains in the map!
- // which happens when declare_args() blocks are found in args.gn
- // or some of its imports. This uses a Settings instance with
- // an empty label, where `is_default()` returns true.
- if (a->is_default() != b->is_default())
- return a->is_default();
- return a->toolchain_label() < b->toolchain_label();
- });
+ std::vector<const Settings*> toolchains = GetSortedToolchainsLocked();
// Default values.
for (const auto& toolchain : toolchains) {
diff --git a/src/gn/args.h b/src/gn/args.h
index 2914c59..0bc1821 100644
--- a/src/gn/args.h
+++ b/src/gn/args.h
@@ -7,6 +7,7 @@
#include <map>
#include <mutex>
+#include <optional>
#include <set>
#include <string_view>
#include <unordered_map>
@@ -56,6 +57,10 @@
// argument is set.
const Value* GetArgOverride(const char* name) const;
+ // Similar to above, except it searches for `name` from all arguments. If it
+ // has an override, it returns `override_value`.
+ std::optional<Value> GetArgFromAllArguments(const char* name) const;
+
// Sets up the root scope for a toolchain. This applies the default system
// flags and saves the toolchain overrides so they can be applied to
// declare_args blocks that appear when loading files in that toolchain.
@@ -116,6 +121,10 @@
// toolchain.
Scope::KeyValueMap& OverridesForToolchainLocked(Scope* scope) const;
+ // Returns toolchains in a deterministic way. Always prioritize
+ // the default toolchain. Requires the lock being acquired.
+ std::vector<const Settings*> GetSortedToolchainsLocked() const;
+
// Since this is called during setup which we assume is single-threaded,
// this is not protected by the lock. It should be set only during init.
Scope::KeyValueMap overrides_;
diff --git a/src/gn/args_unittest.cc b/src/gn/args_unittest.cc
index 650db6d..d2ae970 100644
--- a/src/gn/args_unittest.cc
+++ b/src/gn/args_unittest.cc
@@ -79,3 +79,36 @@
ASSERT_NE(nullptr, setup.scope()->GetValue("c"));
EXPECT_EQ(Value(nullptr, "cvalue2"), *setup.scope()->GetValue("c"));
}
+
+// Ensure that GetArgFromAllArguments() searches for an arg from all arguments.
+TEST(ArgsTest, VerifyGetArgFromAllArguments) {
+ TestWithScope setup;
+ Args args1;
+ Err err;
+
+ Scope::KeyValueMap key_value_map;
+ Value a_value = Value(nullptr, "avalue");
+ key_value_map["a"] = a_value;
+ EXPECT_TRUE(args1.DeclareArgs(key_value_map, setup.scope(), &err));
+
+ // Should not find "a" from overrides.
+ ASSERT_EQ(nullptr, args1.GetArgOverride("a"));
+
+ // Should find "a" from all args as it's declared.
+ EXPECT_EQ(a_value, *args1.GetArgFromAllArguments("a"));
+
+ // Should not find "b" from all args as it's not declared.
+ EXPECT_FALSE(args1.GetArgFromAllArguments("b"));
+
+ Args args2;
+ args2.AddArgOverrides(key_value_map);
+
+ // Should find "a" from overrides.
+ const Value* a_value_from_ovderrides = args2.GetArgOverride("a");
+ ASSERT_NE(nullptr, a_value_from_ovderrides);
+ EXPECT_EQ(a_value, *a_value_from_ovderrides);
+
+ // Should find "a" from all args since GetArgFromAllArguments() includes
+ // overrides.
+ EXPECT_EQ(a_value, *args2.GetArgFromAllArguments("a"));
+}
diff --git a/src/gn/xcode_writer.cc b/src/gn/xcode_writer.cc
index ed4b33e..4f4911a 100644
--- a/src/gn/xcode_writer.cc
+++ b/src/gn/xcode_writer.cc
@@ -90,8 +90,9 @@
const Args& args,
const ParseNode* node,
Err* err) {
- const Value* target_xcode_platform_value =
- args.GetArgOverride(variables::kTargetXcodePlatform);
+ std::optional<Value> target_xcode_platform_value =
+ args.GetArgFromAllArguments(variables::kTargetXcodePlatform);
+
if (!target_xcode_platform_value) {
return WRITER_TARGET_XCODE_PLATFORM_IPHONEOS;
}