pw_presubmit: Add num_jobs member to PresubmitContext

Add a num_jobs member to PresubmitContext objects. This can be set to an
arbitrary value by presubmit steps or helpers they invoke.

Bug: b/246622490
Change-Id: I52d12738b35e3d8bce03490b1abf2e812884733b
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/110390
Pigweed-Auto-Submit: Rob Mohr <mohrr@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Rob Mohr <mohrr@google.com>
diff --git a/pw_presubmit/docs.rst b/pw_presubmit/docs.rst
index 98988ba..f03d57d 100644
--- a/pw_presubmit/docs.rst
+++ b/pw_presubmit/docs.rst
@@ -114,6 +114,7 @@
 * ``package_root``: Root directory for ``pw package`` installations
 * ``override_gn_args``: Additional GN args processed by ``build.gn_gen()``
 * ``luci``: Information about the LUCI build or None if not running in LUCI
+* ``num_jobs``: Number of jobs to run in parallel
 
 The ``luci`` member is of type ``LuciContext`` and has the following members:
 
diff --git a/pw_presubmit/py/pw_presubmit/build.py b/pw_presubmit/py/pw_presubmit/build.py
index 4399b01..de72d92 100644
--- a/pw_presubmit/py/pw_presubmit/build.py
+++ b/pw_presubmit/py/pw_presubmit/build.py
@@ -48,12 +48,18 @@
 
     Intended for use with bazel build and test. May not work with others.
     """
+
+    num_jobs: List[str] = []
+    if ctx.num_jobs is not None:
+        num_jobs.extend(('--jobs', str(ctx.num_jobs)))
+
     call('bazel',
          cmd,
          '--verbose_failures',
          '--verbose_explanations',
          '--worker_verbose',
          f'--symlink_prefix={ctx.output_dir / ".bazel-"}',
+         *num_jobs,
          *args,
          cwd=ctx.root,
          env=env_with_clang_vars())
@@ -149,6 +155,10 @@
           **kwargs) -> None:
     """Runs ninja in the specified directory."""
 
+    num_jobs: List[str] = []
+    if ctx.num_jobs is not None:
+        num_jobs.extend(('-j', str(ctx.num_jobs)))
+
     if save_compdb:
         proc = subprocess.run(
             ['ninja', '-C', ctx.output_dir, '-t', 'compdb', *args],
@@ -163,7 +173,7 @@
             **kwargs)
         (ctx.output_dir / 'ninja.graph').write_bytes(proc.stdout)
 
-    call('ninja', '-C', ctx.output_dir, *args, **kwargs)
+    call('ninja', '-C', ctx.output_dir, *num_jobs, *args, **kwargs)
     (ctx.output_dir / '.ninja_log').rename(ctx.output_dir / 'ninja.log')
 
 
diff --git a/pw_presubmit/py/pw_presubmit/presubmit.py b/pw_presubmit/py/pw_presubmit/presubmit.py
index 75b3433..c9f9a5d 100644
--- a/pw_presubmit/py/pw_presubmit/presubmit.py
+++ b/pw_presubmit/py/pw_presubmit/presubmit.py
@@ -213,6 +213,7 @@
     package_root: Path
     luci: Optional[LuciContext]
     override_gn_args: Dict[str, str]
+    num_jobs: Optional[int] = None
     _failed: bool = False
 
     @property