Jelajahi Sumber

Merge topic 'ninja-pool-custom-command'

9f76961de8 Support job pools in custom commands and targets

Acked-by: Kitware Robot <[email protected]>
Merge-request: !3308
Brad King 6 tahun lalu
induk
melakukan
0064edf417

+ 8 - 0
Help/command/add_custom_command.rst

@@ -23,6 +23,7 @@ The first signature is for adding a custom command to produce an output:
                      [WORKING_DIRECTORY dir]
                      [WORKING_DIRECTORY dir]
                      [COMMENT comment]
                      [COMMENT comment]
                      [DEPFILE depfile]
                      [DEPFILE depfile]
+                     [JOB_POOL job_pool]
                      [VERBATIM] [APPEND] [USES_TERMINAL]
                      [VERBATIM] [APPEND] [USES_TERMINAL]
                      [COMMAND_EXPAND_LISTS])
                      [COMMAND_EXPAND_LISTS])
 
 
@@ -144,6 +145,13 @@ The options are:
   Note that the ``IMPLICIT_DEPENDS`` option is currently supported
   Note that the ``IMPLICIT_DEPENDS`` option is currently supported
   only for Makefile generators and will be ignored by other generators.
   only for Makefile generators and will be ignored by other generators.
 
 
+``JOB_POOL``
+  Specify a :prop_gbl:`pool <JOB_POOLS>` for the :generator:`Ninja`
+  generator. Incompatible with ``USES_TERMINAL``, which implies
+  the ``console`` pool.
+  Using a pool that is not defined by :prop_gbl:`JOB_POOLS` causes
+  an error by ninja at build time.
+
 ``MAIN_DEPENDENCY``
 ``MAIN_DEPENDENCY``
   Specify the primary input source file to the command.  This is
   Specify the primary input source file to the command.  This is
   treated just like any value given to the ``DEPENDS`` option
   treated just like any value given to the ``DEPENDS`` option

+ 8 - 0
Help/command/add_custom_target.rst

@@ -11,6 +11,7 @@ Add a target with no output so it will always be built.
                     [BYPRODUCTS [files...]]
                     [BYPRODUCTS [files...]]
                     [WORKING_DIRECTORY dir]
                     [WORKING_DIRECTORY dir]
                     [COMMENT comment]
                     [COMMENT comment]
+                    [JOB_POOL job_pool]
                     [VERBATIM] [USES_TERMINAL]
                     [VERBATIM] [USES_TERMINAL]
                     [COMMAND_EXPAND_LISTS]
                     [COMMAND_EXPAND_LISTS]
                     [SOURCES src1 [src2...]])
                     [SOURCES src1 [src2...]])
@@ -97,6 +98,13 @@ The options are:
   ``${CC} "-I$<JOIN:$<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>,;-I>" foo.cc``
   ``${CC} "-I$<JOIN:$<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>,;-I>" foo.cc``
   to be properly expanded.
   to be properly expanded.
 
 
+``JOB_POOL``
+  Specify a :prop_gbl:`pool <JOB_POOLS>` for the :generator:`Ninja`
+  generator. Incompatible with ``USES_TERMINAL``, which implies
+  the ``console`` pool.
+  Using a pool that is not defined by :prop_gbl:`JOB_POOLS` causes
+  an error by ninja at build time.
+
 ``SOURCES``
 ``SOURCES``
   Specify additional source files to be included in the custom target.
   Specify additional source files to be included in the custom target.
   Specified source files will be added to IDE project files for
   Specified source files will be added to IDE project files for

+ 5 - 0
Help/prop_gbl/JOB_POOLS.rst

@@ -18,6 +18,11 @@ Defined pools could be used globally by setting
 :variable:`CMAKE_JOB_POOL_COMPILE` and :variable:`CMAKE_JOB_POOL_LINK`
 :variable:`CMAKE_JOB_POOL_COMPILE` and :variable:`CMAKE_JOB_POOL_LINK`
 or per target by setting the target properties
 or per target by setting the target properties
 :prop_tgt:`JOB_POOL_COMPILE` and :prop_tgt:`JOB_POOL_LINK`.
 :prop_tgt:`JOB_POOL_COMPILE` and :prop_tgt:`JOB_POOL_LINK`.
+:command:`Custom commands <add_custom_command>` and
+:command:`custom targets <add_custom_target>` can specify pools using the
+option ``JOB_POOL``.
+Using a pool that is not defined by :prop_gbl:`JOB_POOLS` causes
+an error by ninja at build time.
 
 
 If not set, this property uses the value of the :variable:`CMAKE_JOB_POOLS`
 If not set, this property uses the value of the :variable:`CMAKE_JOB_POOLS`
 variable.
 variable.

+ 6 - 0
Help/release/dev/ninja-add_custom_command-pool.rst

@@ -0,0 +1,6 @@
+ninja-add_custom_command-pool
+--------------------------------
+
+* The commands :command:`add_custom_command` and :command:`add_custom_target`
+  gained a new ``JOB_POOL`` option that works with the :generator:`Ninja`
+  generator to set the pool variable on the build statement.

+ 16 - 3
Source/cmAddCustomCommandCommand.cxx

@@ -31,7 +31,7 @@ bool cmAddCustomCommandCommand::InitialPass(
     return false;
     return false;
   }
   }
 
 
-  std::string source, target, main_dependency, working, depfile;
+  std::string source, target, main_dependency, working, depfile, job_pool;
   std::string comment_buffer;
   std::string comment_buffer;
   const char* comment = nullptr;
   const char* comment = nullptr;
   std::vector<std::string> depends, outputs, output, byproducts;
   std::vector<std::string> depends, outputs, output, byproducts;
@@ -65,6 +65,7 @@ bool cmAddCustomCommandCommand::InitialPass(
     doing_comment,
     doing_comment,
     doing_working_directory,
     doing_working_directory,
     doing_depfile,
     doing_depfile,
+    doing_job_pool,
     doing_nothing
     doing_nothing
   };
   };
 
 
@@ -81,6 +82,7 @@ bool cmAddCustomCommandCommand::InitialPass(
   MAKE_STATIC_KEYWORD(DEPENDS);
   MAKE_STATIC_KEYWORD(DEPENDS);
   MAKE_STATIC_KEYWORD(DEPFILE);
   MAKE_STATIC_KEYWORD(DEPFILE);
   MAKE_STATIC_KEYWORD(IMPLICIT_DEPENDS);
   MAKE_STATIC_KEYWORD(IMPLICIT_DEPENDS);
+  MAKE_STATIC_KEYWORD(JOB_POOL);
   MAKE_STATIC_KEYWORD(MAIN_DEPENDENCY);
   MAKE_STATIC_KEYWORD(MAIN_DEPENDENCY);
   MAKE_STATIC_KEYWORD(OUTPUT);
   MAKE_STATIC_KEYWORD(OUTPUT);
   MAKE_STATIC_KEYWORD(OUTPUTS);
   MAKE_STATIC_KEYWORD(OUTPUTS);
@@ -104,6 +106,7 @@ bool cmAddCustomCommandCommand::InitialPass(
     keywords.insert(keyDEPENDS);
     keywords.insert(keyDEPENDS);
     keywords.insert(keyDEPFILE);
     keywords.insert(keyDEPFILE);
     keywords.insert(keyIMPLICIT_DEPENDS);
     keywords.insert(keyIMPLICIT_DEPENDS);
+    keywords.insert(keyJOB_POOL);
     keywords.insert(keyMAIN_DEPENDENCY);
     keywords.insert(keyMAIN_DEPENDENCY);
     keywords.insert(keyOUTPUT);
     keywords.insert(keyOUTPUT);
     keywords.insert(keyOUTPUTS);
     keywords.insert(keyOUTPUTS);
@@ -170,6 +173,8 @@ bool cmAddCustomCommandCommand::InitialPass(
                          this->Makefile->GetGlobalGenerator()->GetName());
                          this->Makefile->GetGlobalGenerator()->GetName());
           return false;
           return false;
         }
         }
+      } else if (copy == keyJOB_POOL) {
+        doing = doing_job_pool;
       }
       }
     } else {
     } else {
       std::string filename;
       std::string filename;
@@ -211,6 +216,9 @@ bool cmAddCustomCommandCommand::InitialPass(
         case doing_depfile:
         case doing_depfile:
           depfile = copy;
           depfile = copy;
           break;
           break;
+        case doing_job_pool:
+          job_pool = copy;
+          break;
         case doing_working_directory:
         case doing_working_directory:
           working = copy;
           working = copy;
           break;
           break;
@@ -318,6 +326,11 @@ bool cmAddCustomCommandCommand::InitialPass(
     return false;
     return false;
   }
   }
 
 
+  if (uses_terminal && !job_pool.empty()) {
+    this->SetError("JOB_POOL is shadowed by USES_TERMINAL.");
+    return false;
+  }
+
   // Choose which mode of the command to use.
   // Choose which mode of the command to use.
   bool escapeOldStyle = !verbatim;
   bool escapeOldStyle = !verbatim;
   if (source.empty() && output.empty()) {
   if (source.empty() && output.empty()) {
@@ -325,14 +338,14 @@ bool cmAddCustomCommandCommand::InitialPass(
     std::vector<std::string> no_depends;
     std::vector<std::string> no_depends;
     this->Makefile->AddCustomCommandToTarget(
     this->Makefile->AddCustomCommandToTarget(
       target, byproducts, no_depends, commandLines, cctype, comment,
       target, byproducts, no_depends, commandLines, cctype, comment,
-      working.c_str(), escapeOldStyle, uses_terminal, depfile,
+      working.c_str(), escapeOldStyle, uses_terminal, depfile, job_pool,
       command_expand_lists);
       command_expand_lists);
   } else if (target.empty()) {
   } else if (target.empty()) {
     // Target is empty, use the output.
     // Target is empty, use the output.
     this->Makefile->AddCustomCommandToOutput(
     this->Makefile->AddCustomCommandToOutput(
       output, byproducts, depends, main_dependency, commandLines, comment,
       output, byproducts, depends, main_dependency, commandLines, comment,
       working.c_str(), false, escapeOldStyle, uses_terminal,
       working.c_str(), false, escapeOldStyle, uses_terminal,
-      command_expand_lists, depfile);
+      command_expand_lists, depfile, job_pool);
 
 
     // Add implicit dependency scanning requests if any were given.
     // Add implicit dependency scanning requests if any were given.
     if (!implicit_depends.empty()) {
     if (!implicit_depends.empty()) {

+ 13 - 1
Source/cmAddCustomTargetCommand.cxx

@@ -52,6 +52,7 @@ bool cmAddCustomTargetCommand::InitialPass(
   std::string comment_buffer;
   std::string comment_buffer;
   const char* comment = nullptr;
   const char* comment = nullptr;
   std::vector<std::string> sources;
   std::vector<std::string> sources;
+  std::string job_pool;
 
 
   // Keep track of parser state.
   // Keep track of parser state.
   enum tdoing
   enum tdoing
@@ -62,6 +63,7 @@ bool cmAddCustomTargetCommand::InitialPass(
     doing_working_directory,
     doing_working_directory,
     doing_comment,
     doing_comment,
     doing_source,
     doing_source,
+    doing_job_pool,
     doing_nothing
     doing_nothing
   };
   };
   tdoing doing = doing_command;
   tdoing doing = doing_command;
@@ -97,6 +99,8 @@ bool cmAddCustomTargetCommand::InitialPass(
       command_expand_lists = true;
       command_expand_lists = true;
     } else if (copy == "COMMENT") {
     } else if (copy == "COMMENT") {
       doing = doing_comment;
       doing = doing_comment;
+    } else if (copy == "JOB_POOL") {
+      doing = doing_job_pool;
     } else if (copy == "COMMAND") {
     } else if (copy == "COMMAND") {
       doing = doing_command;
       doing = doing_command;
 
 
@@ -137,6 +141,9 @@ bool cmAddCustomTargetCommand::InitialPass(
         case doing_source:
         case doing_source:
           sources.push_back(copy);
           sources.push_back(copy);
           break;
           break;
+        case doing_job_pool:
+          job_pool = copy;
+          break;
         default:
         default:
           this->SetError("Wrong syntax. Unknown type of argument.");
           this->SetError("Wrong syntax. Unknown type of argument.");
           return false;
           return false;
@@ -200,12 +207,17 @@ bool cmAddCustomTargetCommand::InitialPass(
     return true;
     return true;
   }
   }
 
 
+  if (uses_terminal && !job_pool.empty()) {
+    this->SetError("JOB_POOL is shadowed by USES_TERMINAL.");
+    return false;
+  }
+
   // Add the utility target to the makefile.
   // Add the utility target to the makefile.
   bool escapeOldStyle = !verbatim;
   bool escapeOldStyle = !verbatim;
   cmTarget* target = this->Makefile->AddUtilityCommand(
   cmTarget* target = this->Makefile->AddUtilityCommand(
     targetName, cmMakefile::TargetOrigin::Project, excludeFromAll,
     targetName, cmMakefile::TargetOrigin::Project, excludeFromAll,
     working_directory.c_str(), byproducts, depends, commandLines,
     working_directory.c_str(), byproducts, depends, commandLines,
-    escapeOldStyle, comment, uses_terminal, command_expand_lists);
+    escapeOldStyle, comment, uses_terminal, command_expand_lists, job_pool);
 
 
   // Add additional user-specified source files to the target.
   // Add additional user-specified source files to the target.
   target->AddSources(sources);
   target->AddSources(sources);

+ 10 - 0
Source/cmCustomCommand.cxx

@@ -134,3 +134,13 @@ void cmCustomCommand::SetDepfile(const std::string& depfile)
 {
 {
   this->Depfile = depfile;
   this->Depfile = depfile;
 }
 }
+
+const std::string& cmCustomCommand::GetJobPool() const
+{
+  return this->JobPool;
+}
+
+void cmCustomCommand::SetJobPool(const std::string& job_pool)
+{
+  this->JobPool = job_pool;
+}

+ 5 - 0
Source/cmCustomCommand.h

@@ -89,6 +89,10 @@ public:
   const std::string& GetDepfile() const;
   const std::string& GetDepfile() const;
   void SetDepfile(const std::string& depfile);
   void SetDepfile(const std::string& depfile);
 
 
+  /** Set/Get the job_pool (used by the Ninja generator) */
+  const std::string& GetJobPool() const;
+  void SetJobPool(const std::string& job_pool);
+
 private:
 private:
   std::vector<std::string> Outputs;
   std::vector<std::string> Outputs;
   std::vector<std::string> Byproducts;
   std::vector<std::string> Byproducts;
@@ -99,6 +103,7 @@ private:
   std::string Comment;
   std::string Comment;
   std::string WorkingDirectory;
   std::string WorkingDirectory;
   std::string Depfile;
   std::string Depfile;
+  std::string JobPool;
   bool HaveComment = false;
   bool HaveComment = false;
   bool EscapeAllowMakeVars = false;
   bool EscapeAllowMakeVars = false;
   bool EscapeOldStyle = true;
   bool EscapeOldStyle = true;

+ 7 - 3
Source/cmGlobalNinjaGenerator.cxx

@@ -250,8 +250,9 @@ void cmGlobalNinjaGenerator::AddCustomCommandRule()
 
 
 void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
 void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
   const std::string& command, const std::string& description,
   const std::string& command, const std::string& description,
-  const std::string& comment, const std::string& depfile, bool uses_terminal,
-  bool restat, const cmNinjaDeps& outputs, const cmNinjaDeps& deps,
+  const std::string& comment, const std::string& depfile,
+  const std::string& job_pool, bool uses_terminal, bool restat,
+  const cmNinjaDeps& outputs, const cmNinjaDeps& deps,
   const cmNinjaDeps& orderOnly)
   const cmNinjaDeps& orderOnly)
 {
 {
   std::string cmd = command; // NOLINT(*)
   std::string cmd = command; // NOLINT(*)
@@ -271,6 +272,8 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
   }
   }
   if (uses_terminal && SupportsConsolePool()) {
   if (uses_terminal && SupportsConsolePool()) {
     vars["pool"] = "console";
     vars["pool"] = "console";
+  } else if (!job_pool.empty()) {
+    vars["pool"] = job_pool;
   }
   }
   if (!depfile.empty()) {
   if (!depfile.empty()) {
     vars["depfile"] = depfile;
     vars["depfile"] = depfile;
@@ -925,7 +928,8 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
               std::back_inserter(orderOnlyDeps));
               std::back_inserter(orderOnlyDeps));
     WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
     WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
                             "Assume dependencies for generated source file.",
                             "Assume dependencies for generated source file.",
-                            /*depfile*/ "", /*uses_terminal*/ false,
+                            /*depfile*/ "", /*job_pool*/ "",
+                            /*uses_terminal*/ false,
                             /*restat*/ true, cmNinjaDeps(1, asd.first),
                             /*restat*/ true, cmNinjaDeps(1, asd.first),
                             cmNinjaDeps(), orderOnlyDeps);
                             cmNinjaDeps(), orderOnlyDeps);
   }
   }

+ 2 - 1
Source/cmGlobalNinjaGenerator.h

@@ -129,7 +129,8 @@ public:
   void WriteCustomCommandBuild(const std::string& command,
   void WriteCustomCommandBuild(const std::string& command,
                                const std::string& description,
                                const std::string& description,
                                const std::string& comment,
                                const std::string& comment,
-                               const std::string& depfile, bool uses_terminal,
+                               const std::string& depfile,
+                               const std::string& pool, bool uses_terminal,
                                bool restat, const cmNinjaDeps& outputs,
                                bool restat, const cmNinjaDeps& outputs,
                                const cmNinjaDeps& deps = cmNinjaDeps(),
                                const cmNinjaDeps& deps = cmNinjaDeps(),
                                const cmNinjaDeps& orderOnly = cmNinjaDeps());
                                const cmNinjaDeps& orderOnly = cmNinjaDeps());

+ 1 - 1
Source/cmGlobalXCodeGenerator.cxx

@@ -568,7 +568,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
         gen->GetMakefile()->AddCustomCommandToTarget(
         gen->GetMakefile()->AddCustomCommandToTarget(
           target->GetName(), no_byproducts, no_depends, commandLines,
           target->GetName(), no_byproducts, no_depends, commandLines,
           cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true,
           cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true,
-          false, "", false, cmMakefile::AcceptObjectLibraryCommands);
+          false, "", "", false, cmMakefile::AcceptObjectLibraryCommands);
       }
       }
 
 
       if (!this->IsExcluded(target)) {
       if (!this->IsExcluded(target)) {

+ 1 - 1
Source/cmLocalNinjaGenerator.cxx

@@ -506,7 +506,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
     this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
     this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
       this->BuildCommandLine(cmdLines, customStep),
       this->BuildCommandLine(cmdLines, customStep),
       this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
       this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
-      cc->GetDepfile(), cc->GetUsesTerminal(),
+      cc->GetDepfile(), cc->GetJobPool(), cc->GetUsesTerminal(),
       /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps,
       /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps,
       orderOnlyDeps);
       orderOnlyDeps);
   }
   }

+ 17 - 12
Source/cmMakefile.cxx

@@ -814,8 +814,8 @@ void cmMakefile::AddCustomCommandToTarget(
   const std::vector<std::string>& depends,
   const std::vector<std::string>& depends,
   const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
   const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
   const char* comment, const char* workingDir, bool escapeOldStyle,
   const char* comment, const char* workingDir, bool escapeOldStyle,
-  bool uses_terminal, const std::string& depfile, bool command_expand_lists,
-  ObjectLibraryCommands objLibraryCommands)
+  bool uses_terminal, const std::string& depfile, const std::string& job_pool,
+  bool command_expand_lists, ObjectLibraryCommands objLibraryCommands)
 {
 {
   // Find the target to which to add the custom command.
   // Find the target to which to add the custom command.
   cmTargets::iterator ti = this->Targets.find(target);
   cmTargets::iterator ti = this->Targets.find(target);
@@ -890,6 +890,7 @@ void cmMakefile::AddCustomCommandToTarget(
   cc.SetUsesTerminal(uses_terminal);
   cc.SetUsesTerminal(uses_terminal);
   cc.SetCommandExpandLists(command_expand_lists);
   cc.SetCommandExpandLists(command_expand_lists);
   cc.SetDepfile(depfile);
   cc.SetDepfile(depfile);
+  cc.SetJobPool(job_pool);
   switch (type) {
   switch (type) {
     case cmTarget::PRE_BUILD:
     case cmTarget::PRE_BUILD:
       t.AddPreBuildCommand(cc);
       t.AddPreBuildCommand(cc);
@@ -909,7 +910,8 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
   const std::vector<std::string>& depends, const std::string& main_dependency,
   const std::vector<std::string>& depends, const std::string& main_dependency,
   const cmCustomCommandLines& commandLines, const char* comment,
   const cmCustomCommandLines& commandLines, const char* comment,
   const char* workingDir, bool replace, bool escapeOldStyle,
   const char* workingDir, bool replace, bool escapeOldStyle,
-  bool uses_terminal, bool command_expand_lists, const std::string& depfile)
+  bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+  const std::string& job_pool)
 {
 {
   // Make sure there is at least one output.
   // Make sure there is at least one output.
   if (outputs.empty()) {
   if (outputs.empty()) {
@@ -1003,6 +1005,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
     cc->SetUsesTerminal(uses_terminal);
     cc->SetUsesTerminal(uses_terminal);
     cc->SetCommandExpandLists(command_expand_lists);
     cc->SetCommandExpandLists(command_expand_lists);
     cc->SetDepfile(depfile);
     cc->SetDepfile(depfile);
+    cc->SetJobPool(job_pool);
     file->SetCustomCommand(cc);
     file->SetCustomCommand(cc);
     this->UpdateOutputToSourceMap(outputs, file);
     this->UpdateOutputToSourceMap(outputs, file);
   }
   }
@@ -1040,7 +1043,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
   const std::string& main_dependency, const cmCustomCommandLines& commandLines,
   const std::string& main_dependency, const cmCustomCommandLines& commandLines,
   const char* comment, const char* workingDir, bool replace,
   const char* comment, const char* workingDir, bool replace,
   bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
   bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
-  const std::string& depfile)
+  const std::string& depfile, const std::string& job_pool)
 {
 {
   std::vector<std::string> outputs;
   std::vector<std::string> outputs;
   outputs.push_back(output);
   outputs.push_back(output);
@@ -1048,7 +1051,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
   return this->AddCustomCommandToOutput(
   return this->AddCustomCommandToOutput(
     outputs, no_byproducts, depends, main_dependency, commandLines, comment,
     outputs, no_byproducts, depends, main_dependency, commandLines, comment,
     workingDir, replace, escapeOldStyle, uses_terminal, command_expand_lists,
     workingDir, replace, escapeOldStyle, uses_terminal, command_expand_lists,
-    depfile);
+    depfile, job_pool);
 }
 }
 
 
 void cmMakefile::AddCustomCommandOldStyle(
 void cmMakefile::AddCustomCommandOldStyle(
@@ -1142,13 +1145,14 @@ cmTarget* cmMakefile::AddUtilityCommand(
   const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
   const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
   const char* workingDirectory, const std::vector<std::string>& depends,
   const char* workingDirectory, const std::vector<std::string>& depends,
   const cmCustomCommandLines& commandLines, bool escapeOldStyle,
   const cmCustomCommandLines& commandLines, bool escapeOldStyle,
-  const char* comment, bool uses_terminal, bool command_expand_lists)
+  const char* comment, bool uses_terminal, bool command_expand_lists,
+  const std::string& job_pool)
 {
 {
   std::vector<std::string> no_byproducts;
   std::vector<std::string> no_byproducts;
-  return this->AddUtilityCommand(utilityName, origin, excludeFromAll,
-                                 workingDirectory, no_byproducts, depends,
-                                 commandLines, escapeOldStyle, comment,
-                                 uses_terminal, command_expand_lists);
+  return this->AddUtilityCommand(
+    utilityName, origin, excludeFromAll, workingDirectory, no_byproducts,
+    depends, commandLines, escapeOldStyle, comment, uses_terminal,
+    command_expand_lists, job_pool);
 }
 }
 
 
 cmTarget* cmMakefile::AddUtilityCommand(
 cmTarget* cmMakefile::AddUtilityCommand(
@@ -1156,7 +1160,8 @@ cmTarget* cmMakefile::AddUtilityCommand(
   const char* workingDirectory, const std::vector<std::string>& byproducts,
   const char* workingDirectory, const std::vector<std::string>& byproducts,
   const std::vector<std::string>& depends,
   const std::vector<std::string>& depends,
   const cmCustomCommandLines& commandLines, bool escapeOldStyle,
   const cmCustomCommandLines& commandLines, bool escapeOldStyle,
-  const char* comment, bool uses_terminal, bool command_expand_lists)
+  const char* comment, bool uses_terminal, bool command_expand_lists,
+  const std::string& job_pool)
 {
 {
   // Create a target instance for this utility.
   // Create a target instance for this utility.
   cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
   cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
@@ -1182,7 +1187,7 @@ cmTarget* cmMakefile::AddUtilityCommand(
     this->AddCustomCommandToOutput(
     this->AddCustomCommandToOutput(
       forced, byproducts, depends, no_main_dependency, commandLines, comment,
       forced, byproducts, depends, no_main_dependency, commandLines, comment,
       workingDirectory, no_replace, escapeOldStyle, uses_terminal,
       workingDirectory, no_replace, escapeOldStyle, uses_terminal,
-      command_expand_lists);
+      command_expand_lists, /*depfile=*/"", job_pool);
     cmSourceFile* sf = target->AddSourceCMP0049(force);
     cmSourceFile* sf = target->AddSourceCMP0049(force);
 
 
     // The output is not actually created so mark it symbolic.
     // The output is not actually created so mark it symbolic.

+ 5 - 5
Source/cmMakefile.h

@@ -150,7 +150,7 @@ public:
     const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
     const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
     const char* comment, const char* workingDir, bool escapeOldStyle = true,
     const char* comment, const char* workingDir, bool escapeOldStyle = true,
     bool uses_terminal = false, const std::string& depfile = "",
     bool uses_terminal = false, const std::string& depfile = "",
-    bool command_expand_lists = false,
+    const std::string& job_pool = "", bool command_expand_lists = false,
     ObjectLibraryCommands objLibraryCommands = RejectObjectLibraryCommands);
     ObjectLibraryCommands objLibraryCommands = RejectObjectLibraryCommands);
   cmSourceFile* AddCustomCommandToOutput(
   cmSourceFile* AddCustomCommandToOutput(
     const std::vector<std::string>& outputs,
     const std::vector<std::string>& outputs,
@@ -160,14 +160,14 @@ public:
     const cmCustomCommandLines& commandLines, const char* comment,
     const cmCustomCommandLines& commandLines, const char* comment,
     const char* workingDir, bool replace = false, bool escapeOldStyle = true,
     const char* workingDir, bool replace = false, bool escapeOldStyle = true,
     bool uses_terminal = false, bool command_expand_lists = false,
     bool uses_terminal = false, bool command_expand_lists = false,
-    const std::string& depfile = "");
+    const std::string& depfile = "", const std::string& job_pool = "");
   cmSourceFile* AddCustomCommandToOutput(
   cmSourceFile* AddCustomCommandToOutput(
     const std::string& output, const std::vector<std::string>& depends,
     const std::string& output, const std::vector<std::string>& depends,
     const std::string& main_dependency,
     const std::string& main_dependency,
     const cmCustomCommandLines& commandLines, const char* comment,
     const cmCustomCommandLines& commandLines, const char* comment,
     const char* workingDir, bool replace = false, bool escapeOldStyle = true,
     const char* workingDir, bool replace = false, bool escapeOldStyle = true,
     bool uses_terminal = false, bool command_expand_lists = false,
     bool uses_terminal = false, bool command_expand_lists = false,
-    const std::string& depfile = "");
+    const std::string& depfile = "", const std::string& job_pool = "");
   void AddCustomCommandOldStyle(const std::string& target,
   void AddCustomCommandOldStyle(const std::string& target,
                                 const std::vector<std::string>& outputs,
                                 const std::vector<std::string>& outputs,
                                 const std::vector<std::string>& depends,
                                 const std::vector<std::string>& depends,
@@ -223,14 +223,14 @@ public:
     const char* workingDirectory, const std::vector<std::string>& depends,
     const char* workingDirectory, const std::vector<std::string>& depends,
     const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
     const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
     const char* comment = nullptr, bool uses_terminal = false,
     const char* comment = nullptr, bool uses_terminal = false,
-    bool command_expand_lists = false);
+    bool command_expand_lists = false, const std::string& job_pool = "");
   cmTarget* AddUtilityCommand(
   cmTarget* AddUtilityCommand(
     const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
     const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
     const char* workingDirectory, const std::vector<std::string>& byproducts,
     const char* workingDirectory, const std::vector<std::string>& byproducts,
     const std::vector<std::string>& depends,
     const std::vector<std::string>& depends,
     const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
     const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
     const char* comment = nullptr, bool uses_terminal = false,
     const char* comment = nullptr, bool uses_terminal = false,
-    bool command_expand_lists = false);
+    bool command_expand_lists = false, const std::string& job_pool = "");
 
 
   /**
   /**
    * Add a subdirectory to the build.
    * Add a subdirectory to the build.

+ 1 - 1
Source/cmNinjaUtilityTargetGenerator.cxx

@@ -132,7 +132,7 @@ void cmNinjaUtilityTargetGenerator::Generate()
 
 
     this->GetGlobalGenerator()->WriteCustomCommandBuild(
     this->GetGlobalGenerator()->WriteCustomCommandBuild(
       command, desc, "Utility command for " + this->GetTargetName(),
       command, desc, "Utility command for " + this->GetTargetName(),
-      /*depfile*/ "", uses_terminal,
+      /*depfile*/ "", /*job_pool*/ "", uses_terminal,
       /*restat*/ true, util_outputs, deps);
       /*restat*/ true, util_outputs, deps);
 
 
     this->GetGlobalGenerator()->WritePhonyBuild(
     this->GetGlobalGenerator()->WritePhonyBuild(

+ 8 - 0
Tests/RunCMake/Ninja/CustomCommandJobPool-check.cmake

@@ -0,0 +1,8 @@
+set(log "${RunCMake_BINARY_DIR}/CustomCommandJobPool-build/build.ninja")
+file(READ "${log}" build_file)
+if(NOT "${build_file}" MATCHES "pool = custom_command_pool")
+  set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: pool = custom_command_pool")
+endif()
+if(NOT "${build_file}" MATCHES "pool = custom_target_pool")
+  set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: pool = custom_target_pool")
+endif()

+ 17 - 0
Tests/RunCMake/Ninja/CustomCommandJobPool.cmake

@@ -0,0 +1,17 @@
+add_custom_command(
+  OUTPUT hello.copy.c
+  COMMAND "${CMAKE_COMMAND}" -E copy
+          "${CMAKE_CURRENT_SOURCE_DIR}/hello.c"
+          hello.copy.c
+  WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+  JOB_POOL "custom_command_pool"
+  )
+add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/hello.copy.c")
+
+add_custom_target(
+  hello.echo
+  COMMAND echo
+  JOB_POOL "custom_target_pool"
+)
+
+include(CheckNoPrefixSubDir.cmake)

+ 1 - 0
Tests/RunCMake/Ninja/JobPoolUsesTerminal-result.txt

@@ -0,0 +1 @@
+1

+ 9 - 0
Tests/RunCMake/Ninja/JobPoolUsesTerminal-stderr.txt

@@ -0,0 +1,9 @@
+^CMake Error at JobPoolUsesTerminal.cmake:1 \(add_custom_command\):
+  add_custom_command JOB_POOL is shadowed by USES_TERMINAL.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Error at JobPoolUsesTerminal.cmake:2 \(add_custom_target\):
+  add_custom_target JOB_POOL is shadowed by USES_TERMINAL.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$

+ 2 - 0
Tests/RunCMake/Ninja/JobPoolUsesTerminal.cmake

@@ -0,0 +1,2 @@
+add_custom_command(OUTPUT x COMMAND y USES_TERMINAL JOB_POOL z)
+add_custom_target(CustomTarget COMMAND y USES_TERMINAL JOB_POOL z)

+ 2 - 0
Tests/RunCMake/Ninja/RunCMakeTest.cmake

@@ -57,6 +57,8 @@ run_CMP0058(NEW-no)
 run_CMP0058(NEW-by)
 run_CMP0058(NEW-by)
 
 
 run_cmake(CustomCommandDepfile)
 run_cmake(CustomCommandDepfile)
+run_cmake(CustomCommandJobPool)
+run_cmake(JobPoolUsesTerminal)
 
 
 run_cmake(RspFileC)
 run_cmake(RspFileC)
 run_cmake(RspFileCXX)
 run_cmake(RspFileCXX)