[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; }