Support pools on binary targets

Currently pools are only supported in tools and actions but not binary
targets which can be useful in some scenarios. This change introduces
support for pools on binary targets.

Fixed: 308
Change-Id: Ifdd0c1e533b6ead22cf16b1114d18d124e8413c9
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/14740
Reviewed-by: Takuto Ikuta <tikuta@google.com>
Reviewed-by: Brett Wilson <brettw@chromium.org>
Commit-Queue: Petr Hosek <phosek@google.com>
diff --git a/docs/reference.md b/docs/reference.md
index 11e217f..09417a5 100644
--- a/docs/reference.md
+++ b/docs/reference.md
@@ -140,7 +140,7 @@
     *   [output_prefix_override: [boolean] Don't use prefix for output name.](#var_output_prefix_override)
     *   [outputs: [file list] Output files for actions and copy targets.](#var_outputs)
     *   [partial_info_plist: [filename] Path plist from asset catalog compiler.](#var_partial_info_plist)
-    *   [pool: [string] Label of the pool used by the action.](#var_pool)
+    *   [pool: [string] Label of the pool used by binary targets and actions.](#var_pool)
     *   [precompiled_header: [string] Header file to precompile.](#var_precompiled_header)
     *   [precompiled_header_type: [string] "gcc" or "msvc".](#var_precompiled_header_type)
     *   [precompiled_source: [file name] Source file to precompile.](#var_precompiled_source)
@@ -6217,16 +6217,21 @@
   The file will be generated regardless of whether the asset compiler has
   been invoked or not. See "gn help create_bundle".
 ```
-### <a name="var_pool"></a>**pool**: Label of the pool used by the action.
+### <a name="var_pool"></a>**pool**: Label of the pool used by binary targets actions.
 
 ```
-  A fully-qualified label representing the pool that will be used for the
-  action. Pools are defined using the pool() {...} declaration.
+  A fully-qualified label representing the pool that will be used for binary
+  targets and actions. Pools are defined using the pool() {...} declaration.
 ```
 
 #### **Example**
 
 ```
+  executable("binary") {
+    pool = "//build:custom_pool"
+    ...
+  }
+
   action("action") {
     pool = "//build:custom_pool"
     ...
@@ -6718,11 +6723,8 @@
     visibility = [ ":mything", "//foo:something_else" ]
 
   Any target in the current directory and any subdirectory thereof, plus
-  any targets in "//bar/" and any subdirectory thereof:
+  any targets in "//bar/" and any subdirectory thereof.
     visibility = [ "./*", "//bar/*" ]
-
-  All targets in the current buildfile that are in the same toolchain:
-    visibility = [ ":*($current_toolchain)" ]
 ```
 ### <a name="var_walk_keys"></a>**walk_keys**: Key(s) for managing the metadata collection walk.
 
diff --git a/src/gn/action_target_generator.cc b/src/gn/action_target_generator.cc
index ff66765..513015b 100644
--- a/src/gn/action_target_generator.cc
+++ b/src/gn/action_target_generator.cc
@@ -183,7 +183,7 @@
   LabelPtrPair<Pool> pair(label);
   pair.origin = target_->defined_from();
 
-  target_->action_values().set_pool(std::move(pair));
+  target_->set_pool(std::move(pair));
   return true;
 }
 
diff --git a/src/gn/action_values.h b/src/gn/action_values.h
index 30436b7..9daf918 100644
--- a/src/gn/action_values.h
+++ b/src/gn/action_values.h
@@ -51,17 +51,12 @@
   }
   bool uses_rsp_file() const { return !rsp_file_contents_.list().empty(); }
 
-  // Pool option
-  const LabelPtrPair<Pool>& pool() const { return pool_; }
-  void set_pool(LabelPtrPair<Pool> pool) { pool_ = std::move(pool); }
-
  private:
   SourceFile script_;
   SubstitutionList args_;
   SubstitutionList outputs_;
   SubstitutionPattern depfile_;
   SubstitutionList rsp_file_contents_;
-  LabelPtrPair<Pool> pool_;
 
   ActionValues(const ActionValues&) = delete;
   ActionValues& operator=(const ActionValues&) = delete;
diff --git a/src/gn/analyzer.cc b/src/gn/analyzer.cc
index b1be618..be646ee 100644
--- a/src/gn/analyzer.cc
+++ b/src/gn/analyzer.cc
@@ -254,10 +254,11 @@
 
       dep_map_.insert(std::make_pair(item->AsTarget()->toolchain(), item));
 
-      if (item->AsTarget()->output_type() == Target::ACTION ||
+      if (item->AsTarget()->IsBinary() ||
+          item->AsTarget()->output_type() == Target::ACTION ||
           item->AsTarget()->output_type() == Target::ACTION_FOREACH) {
         const LabelPtrPair<Pool>& pool =
-            item->AsTarget()->action_values().pool();
+            item->AsTarget()->pool();
         if (pool.ptr)
           dep_map_.insert(std::make_pair(pool.ptr, item));
       }
diff --git a/src/gn/analyzer_unittest.cc b/src/gn/analyzer_unittest.cc
index 98bef67..e3d5696 100644
--- a/src/gn/analyzer_unittest.cc
+++ b/src/gn/analyzer_unittest.cc
@@ -480,7 +480,7 @@
   t->set_output_type(Target::ACTION);
   std::unique_ptr<Pool> p = MakePool("//dir", "pool_name");
   Pool* p_raw = p.get();
-  t->action_values().set_pool(LabelPtrPair<Pool>(p.get()));
+  t->set_pool(LabelPtrPair<Pool>(p.get()));
 
   builder_.ItemDefined(std::move(t));
   builder_.ItemDefined(std::move(p));
diff --git a/src/gn/binary_target_generator.cc b/src/gn/binary_target_generator.cc
index 4cac96f..5796cfe 100644
--- a/src/gn/binary_target_generator.cc
+++ b/src/gn/binary_target_generator.cc
@@ -64,6 +64,9 @@
   if (!FillCompleteStaticLib())
     return;
 
+  if (!FillPool())
+    return;
+
   if (!ValidateSources())
     return;
 
@@ -231,6 +234,25 @@
   return true;
 }
 
+bool BinaryTargetGenerator::FillPool() {
+  const Value* value = scope_->GetValue(variables::kPool, true);
+  if (!value)
+    return true;
+
+  Label label =
+      Label::Resolve(scope_->GetSourceDir(),
+                     scope_->settings()->build_settings()->root_path_utf8(),
+                     ToolchainLabelForScope(scope_), *value, err_);
+  if (err_->has_error())
+    return false;
+
+  LabelPtrPair<Pool> pair(label);
+  pair.origin = target_->defined_from();
+
+  target_->set_pool(std::move(pair));
+  return true;
+}
+
 bool BinaryTargetGenerator::ValidateSources() {
   // For Rust targets, if the only source file is the root `sources` can be
   // omitted/empty.
diff --git a/src/gn/binary_target_generator.h b/src/gn/binary_target_generator.h
index 2c8b769..0bafd68 100644
--- a/src/gn/binary_target_generator.h
+++ b/src/gn/binary_target_generator.h
@@ -30,6 +30,7 @@
   bool FillOutputPrefixOverride();
   bool FillOutputDir();
   bool FillAllowCircularIncludesFrom();
+  bool FillPool();
   bool ValidateSources();
 
   Target::OutputType output_type_;
diff --git a/src/gn/builder.cc b/src/gn/builder.cc
index adb39ab..1522a36 100644
--- a/src/gn/builder.cc
+++ b/src/gn/builder.cc
@@ -254,7 +254,7 @@
       !AddDeps(record, target->all_dependent_configs(), err) ||
       !AddDeps(record, target->public_configs(), err) ||
       !AddGenDeps(record, target->gen_deps(), err) ||
-      !AddActionValuesDep(record, target->action_values(), err) ||
+      !AddPoolDep(record, target, err) ||
       !AddToolchainDep(record, target, err))
     return false;
 
@@ -432,14 +432,14 @@
   return true;
 }
 
-bool Builder::AddActionValuesDep(BuilderRecord* record,
-                                 const ActionValues& action_values,
-                                 Err* err) {
-  if (action_values.pool().label.is_null())
+bool Builder::AddPoolDep(BuilderRecord* record,
+                         const Target* target,
+                         Err* err) {
+  if (target->pool().label.is_null())
     return true;
 
   BuilderRecord* pool_record = GetOrCreateRecordOfType(
-      action_values.pool().label, action_values.pool().origin,
+      target->pool().label, target->pool().origin,
       BuilderRecord::ITEM_POOL, err);
   if (!pool_record)
     return false;
@@ -500,7 +500,7 @@
         !ResolveConfigs(&target->configs(), err) ||
         !ResolveConfigs(&target->all_dependent_configs(), err) ||
         !ResolveConfigs(&target->public_configs(), err) ||
-        !ResolveActionValues(&target->action_values(), err) ||
+        !ResolvePool(target, err) ||
         !ResolveToolchain(target, err))
       return false;
   } else if (record->type() == BuilderRecord::ITEM_CONFIG) {
@@ -579,16 +579,16 @@
   return true;
 }
 
-bool Builder::ResolveActionValues(ActionValues* action_values, Err* err) {
-  if (action_values->pool().label.is_null())
+bool Builder::ResolvePool(Target* target, Err* err) {
+  if (target->pool().label.is_null())
     return true;
 
   BuilderRecord* record = GetResolvedRecordOfType(
-      action_values->pool().label, action_values->pool().origin,
+      target->pool().label, target->pool().origin,
       BuilderRecord::ITEM_POOL, err);
   if (!record)
     return false;
-  action_values->set_pool(LabelPtrPair<Pool>(record->item()->AsPool()));
+  target->set_pool(LabelPtrPair<Pool>(record->item()->AsPool()));
 
   return true;
 }
diff --git a/src/gn/builder.h b/src/gn/builder.h
index bebaa81..e89e2e1 100644
--- a/src/gn/builder.h
+++ b/src/gn/builder.h
@@ -101,9 +101,9 @@
   bool AddGenDeps(BuilderRecord* record,
                   const LabelTargetVector& targets,
                   Err* err);
-  bool AddActionValuesDep(BuilderRecord* record,
-                          const ActionValues& action_values,
-                          Err* err);
+  bool AddPoolDep(BuilderRecord* record,
+                  const Target* target,
+                  Err* err);
   bool AddToolchainDep(BuilderRecord* record, const Target* target, Err* err);
 
   // Given a target, sets the "should generate" bit and pushes it through the
@@ -129,7 +129,7 @@
   // if anything isn't found or if the type doesn't match.
   bool ResolveDeps(LabelTargetVector* deps, Err* err);
   bool ResolveConfigs(UniqueVector<LabelConfigPair>* configs, Err* err);
-  bool ResolveActionValues(ActionValues* action_values, Err* err);
+  bool ResolvePool(Target* target, Err* err);
   bool ResolveToolchain(Target* target, Err* err);
   bool ResolvePools(Toolchain* toolchain, Err* err);
 
diff --git a/src/gn/ninja_action_target_writer.cc b/src/gn/ninja_action_target_writer.cc
index e717d33..60d4204 100644
--- a/src/gn/ninja_action_target_writer.cc
+++ b/src/gn/ninja_action_target_writer.cc
@@ -83,9 +83,9 @@
 
     WriteNinjaVariablesForAction();
 
-    if (target_->action_values().pool().ptr) {
+    if (target_->pool().ptr) {
       out_ << "  pool = ";
-      out_ << target_->action_values().pool().ptr->GetNinjaName(
+      out_ << target_->pool().ptr->GetNinjaName(
           settings_->default_toolchain_label());
       out_ << std::endl;
     }
@@ -213,9 +213,9 @@
     if (target_->action_values().has_depfile()) {
       WriteDepfile(sources[i]);
     }
-    if (target_->action_values().pool().ptr) {
+    if (target_->pool().ptr) {
       out_ << "  pool = ";
-      out_ << target_->action_values().pool().ptr->GetNinjaName(
+      out_ << target_->pool().ptr->GetNinjaName(
           settings_->default_toolchain_label());
       out_ << std::endl;
     }
diff --git a/src/gn/ninja_action_target_writer_unittest.cc b/src/gn/ninja_action_target_writer_unittest.cc
index d363b5e..d57f149 100644
--- a/src/gn/ninja_action_target_writer_unittest.cc
+++ b/src/gn/ninja_action_target_writer_unittest.cc
@@ -91,7 +91,7 @@
             Label(SourceDir("//"), "console", setup.toolchain()->label().dir(),
                   setup.toolchain()->label().name()));
   pool.set_depth(1);
-  target.action_values().set_pool(LabelPtrPair<Pool>(&pool));
+  target.set_pool(LabelPtrPair<Pool>(&pool));
 
   target.SetToolchain(setup.toolchain());
   ASSERT_TRUE(target.OnResolved(&err));
@@ -377,7 +377,7 @@
             Label(SourceDir("//foo/"), "pool", setup.toolchain()->label().dir(),
                   setup.toolchain()->label().name()));
   pool.set_depth(5);
-  target.action_values().set_pool(LabelPtrPair<Pool>(&pool));
+  target.set_pool(LabelPtrPair<Pool>(&pool));
 
   target.SetToolchain(setup.toolchain());
   ASSERT_TRUE(target.OnResolved(&err));
diff --git a/src/gn/ninja_binary_target_writer.cc b/src/gn/ninja_binary_target_writer.cc
index e3e36e5..b960cc0 100644
--- a/src/gn/ninja_binary_target_writer.cc
+++ b/src/gn/ninja_binary_target_writer.cc
@@ -15,6 +15,7 @@
 #include "gn/ninja_rust_binary_target_writer.h"
 #include "gn/ninja_target_command_util.h"
 #include "gn/ninja_utils.h"
+#include "gn/pool.h"
 #include "gn/settings.h"
 #include "gn/string_utils.h"
 #include "gn/substitution_writer.h"
@@ -420,3 +421,12 @@
     swiftmodule_path_output.WriteFile(out, swiftmodule);
   }
 }
+
+void NinjaBinaryTargetWriter::WritePool(std::ostream& out) {
+  if (target_->pool().ptr) {
+    out << "  pool = ";
+    out << target_->pool().ptr->GetNinjaName(
+        settings_->default_toolchain_label());
+    out << std::endl;
+  }
+}
diff --git a/src/gn/ninja_binary_target_writer.h b/src/gn/ninja_binary_target_writer.h
index e87bc9c..c7b6eea 100644
--- a/src/gn/ninja_binary_target_writer.h
+++ b/src/gn/ninja_binary_target_writer.h
@@ -76,6 +76,7 @@
   void WriteSwiftModules(std::ostream& out,
                          const Tool* tool,
                          const std::vector<OutputFile>& swiftmodules);
+  void WritePool(std::ostream& out);
 
   void AddSourceSetFiles(const Target* source_set,
                          UniqueVector<OutputFile>* obj_files) const;
diff --git a/src/gn/ninja_build_writer.cc b/src/gn/ninja_build_writer.cc
index 6a5b91d..eb135ea 100644
--- a/src/gn/ninja_build_writer.cc
+++ b/src/gn/ninja_build_writer.cc
@@ -388,8 +388,10 @@
   }
 
   for (const Target* target : all_targets_) {
-    if (target->output_type() == Target::ACTION) {
-      const LabelPtrPair<Pool>& pool = target->action_values().pool();
+    if (target->IsBinary() ||
+        target->output_type() == Target::ACTION ||
+        target->output_type() == Target::ACTION_FOREACH) {
+      const LabelPtrPair<Pool>& pool = target->pool();
       if (pool.ptr)
         used_pools.insert(pool.ptr);
     }
diff --git a/src/gn/ninja_build_writer_unittest.cc b/src/gn/ninja_build_writer_unittest.cc
index 8ab5e56..ba6af4f 100644
--- a/src/gn/ninja_build_writer_unittest.cc
+++ b/src/gn/ninja_build_writer_unittest.cc
@@ -114,7 +114,7 @@
   target_baz.action_values().outputs() = SubstitutionList::MakeForTest(
       "//out/Debug/out5.out", "//out/Debug/out6.out");
   target_baz.SetToolchain(&other_toolchain);
-  target_baz.action_values().set_pool(
+  target_baz.set_pool(
       LabelPtrPair<Pool>(&another_regular_pool));
   ASSERT_TRUE(target_baz.OnResolved(&err));
 
diff --git a/src/gn/ninja_c_binary_target_writer.cc b/src/gn/ninja_c_binary_target_writer.cc
index 2a13c86..1ef0475 100644
--- a/src/gn/ninja_c_binary_target_writer.cc
+++ b/src/gn/ninja_c_binary_target_writer.cc
@@ -21,6 +21,7 @@
 #include "gn/general_tool.h"
 #include "gn/ninja_target_command_util.h"
 #include "gn/ninja_utils.h"
+#include "gn/pool.h"
 #include "gn/scheduler.h"
 #include "gn/settings.h"
 #include "gn/string_utils.h"
@@ -484,6 +485,7 @@
 
       WriteCompilerBuildLine({source}, deps, order_only_deps, tool_name,
                              tool_outputs);
+      WritePool(out_);
     }
 
     // It's theoretically possible for a compiler to produce more than one
@@ -734,6 +736,7 @@
   WriteOutputSubstitutions();
   WriteLibsList("solibs", solibs);
   WriteLibsList("rlibs", transitive_rustlibs);
+  WritePool(out_);
 }
 
 void NinjaCBinaryTargetWriter::WriteOutputSubstitutions() {
diff --git a/src/gn/ninja_c_binary_target_writer_unittest.cc b/src/gn/ninja_c_binary_target_writer_unittest.cc
index 9476193..38df42b 100644
--- a/src/gn/ninja_c_binary_target_writer_unittest.cc
+++ b/src/gn/ninja_c_binary_target_writer_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "gn/config.h"
 #include "gn/ninja_target_command_util.h"
+#include "gn/pool.h"
 #include "gn/scheduler.h"
 #include "gn/target.h"
 #include "gn/test_with_scheduler.h"
@@ -2720,3 +2721,48 @@
   std::string out_str = out.str();
   EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
 }
+
+TEST_F(NinjaCBinaryTargetWriterTest, Pool) {
+  Err err;
+  TestWithScope setup;
+
+  Pool pool(setup.settings(),
+            Label(SourceDir("//foo/"), "pool", setup.toolchain()->label().dir(),
+                  setup.toolchain()->label().name()));
+  pool.set_depth(42);
+
+  Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+  target.sources().push_back(SourceFile("//foo/source.cc"));
+  target.set_output_type(Target::EXECUTABLE);
+  target.set_pool(LabelPtrPair<Pool>(&pool));
+  target.visibility().SetPublic();
+  target.SetToolchain(setup.toolchain());
+  ASSERT_TRUE(target.OnResolved(&err));
+
+  std::ostringstream out;
+  NinjaBinaryTargetWriter writer(&target, out);
+  writer.Run();
+
+  const char expected[] =
+      "defines =\n"
+      "include_dirs =\n"
+      "root_out_dir = .\n"
+      "target_out_dir = obj/foo\n"
+      "target_output_name = bar\n"
+      "\n"
+      "build obj/foo/bar.source.o: cxx ../../foo/source.cc\n"
+      "  source_file_part = source.cc\n"
+      "  source_name_part = source\n"
+      "  pool = foo_pool\n"
+      "\n"
+      "build ./bar: link obj/foo/bar.source.o\n"
+      "  ldflags =\n"
+      "  libs =\n"
+      "  frameworks =\n"
+      "  swiftmodules =\n"
+      "  output_extension = \n"
+      "  output_dir = \n"
+      "  pool = foo_pool\n";
+  std::string out_str = out.str();
+  EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
+}
diff --git a/src/gn/ninja_rust_binary_target_writer.cc b/src/gn/ninja_rust_binary_target_writer.cc
index 9263a58..6b9c2dc 100644
--- a/src/gn/ninja_rust_binary_target_writer.cc
+++ b/src/gn/ninja_rust_binary_target_writer.cc
@@ -210,6 +210,7 @@
             std::back_inserter(extern_deps));
   WriteExternsAndDeps(extern_deps, transitive_crates, rustdeps, nonrustdeps);
   WriteSourcesAndInputs();
+  WritePool(out_);
 }
 
 void NinjaRustBinaryTargetWriter::WriteCompilerVars() {
diff --git a/src/gn/ninja_rust_binary_target_writer_unittest.cc b/src/gn/ninja_rust_binary_target_writer_unittest.cc
index d224193..41a9fdd 100644
--- a/src/gn/ninja_rust_binary_target_writer_unittest.cc
+++ b/src/gn/ninja_rust_binary_target_writer_unittest.cc
@@ -5,6 +5,7 @@
 #include "gn/ninja_rust_binary_target_writer.h"
 
 #include "gn/config.h"
+#include "gn/pool.h"
 #include "gn/rust_values.h"
 #include "gn/scheduler.h"
 #include "gn/target.h"
@@ -1760,3 +1761,51 @@
     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
   }
 }
+
+TEST_F(NinjaRustBinaryTargetWriterTest, Pool) {
+  Err err;
+  TestWithScope setup;
+
+  Pool pool(setup.settings(),
+            Label(SourceDir("//foo/"), "pool", setup.toolchain()->label().dir(),
+                  setup.toolchain()->label().name()));
+  pool.set_depth(42);
+
+  Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+  SourceFile main("//foo/source.rs");
+  target.sources().push_back(main);
+  target.source_types_used().Set(SourceFile::SOURCE_RS);
+  target.rust_values().set_crate_root(main);
+  target.rust_values().crate_name() = "bar";
+  target.set_output_type(Target::EXECUTABLE);
+  target.set_pool(LabelPtrPair<Pool>(&pool));
+  target.visibility().SetPublic();
+  target.SetToolchain(setup.toolchain());
+  ASSERT_TRUE(target.OnResolved(&err));
+
+  std::ostringstream out;
+  NinjaBinaryTargetWriter writer(&target, out);
+  writer.Run();
+
+  const char expected[] =
+      "crate_name = bar\n"
+      "crate_type = bin\n"
+      "output_extension = \n"
+      "output_dir = \n"
+      "rustflags =\n"
+      "rustenv =\n"
+      "root_out_dir = .\n"
+      "target_out_dir = obj/foo\n"
+      "target_output_name = bar\n"
+      "\n"
+      "build ./bar: rust_bin ../../foo/source.rs | ../../foo/source.rs\n"
+      "  source_file_part = source.rs\n"
+      "  source_name_part = source\n"
+      "  externs =\n"
+      "  rustdeps =\n"
+      "  ldflags =\n"
+      "  sources = ../../foo/source.rs\n"
+      "  pool = foo_pool\n";
+  std::string out_str = out.str();
+  EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
+}
diff --git a/src/gn/target.h b/src/gn/target.h
index 66e5c6c..c965d1b 100644
--- a/src/gn/target.h
+++ b/src/gn/target.h
@@ -294,6 +294,10 @@
     return allow_circular_includes_from_;
   }
 
+  // Pool option
+  const LabelPtrPair<Pool>& pool() const { return pool_; }
+  void set_pool(LabelPtrPair<Pool> pool) { pool_ = std::move(pool); }
+
   const InheritedLibraries& inherited_libraries() const {
     return inherited_libraries_;
   }
@@ -495,6 +499,8 @@
 
   std::set<Label> allow_circular_includes_from_;
 
+  LabelPtrPair<Pool> pool_;
+
   // Static libraries, shared libraries, and source sets from transitive deps
   // that need to be linked.
   InheritedLibraries inherited_libraries_;
diff --git a/src/gn/variables.cc b/src/gn/variables.cc
index ca64776..d61a363 100644
--- a/src/gn/variables.cc
+++ b/src/gn/variables.cc
@@ -1642,15 +1642,20 @@
 
 const char kPool[] = "pool";
 const char kPool_HelpShort[] =
-    "pool: [string] Label of the pool used by the action.";
+    "pool: [string] Label of the pool used by binary targets and actions.";
 const char kPool_Help[] =
-    R"(pool: Label of the pool used by the action.
+    R"(pool: Label of the pool used by binary targets actions.
 
-  A fully-qualified label representing the pool that will be used for the
-  action. Pools are defined using the pool() {...} declaration.
+  A fully-qualified label representing the pool that will be used for binary
+  targets and actions. Pools are defined using the pool() {...} declaration.
 
 Example
 
+  executable("binary") {
+    pool = "//build:custom_pool"
+    ...
+  }
+
   action("action") {
     pool = "//build:custom_pool"
     ...