build: Switch to non-module properties

Bug: 600
Change-Id: Id5aef0248a8f7c93e9683b229ca888d360de7384
Reviewed-on: https://pigweed-review.googlesource.com/c/infra/recipes/+/79360
Reviewed-by: Ted Pudlik <tpudlik@google.com>
Reviewed-by: Oliver Newman <olivernewman@google.com>
Commit-Queue: Rob Mohr <mohrr@google.com>
diff --git a/recipe_modules/build/api.py b/recipe_modules/build/api.py
index f67042c..7c00c93 100644
--- a/recipe_modules/build/api.py
+++ b/recipe_modules/build/api.py
@@ -31,10 +31,14 @@
     def initialize(self):
         self.dir = self.m.path['start_dir'].join('build')
 
-    def gn_gen(self, checkout_dir):
+    def gn_gen(self, checkout_dir, options=None):
+        # TODO(pwbug/600) Make options required.
         cmd = ['gn', 'gen']
 
-        for gn_arg in self.gn_args:
+        # TODO(pwbug/600) Always use options.
+        gn_args = options.gn_args if options else self.gn_args
+
+        for gn_arg in gn_args:
             cmd.append('--args={}'.format(gn_arg))
 
         # Infrequently needed but harmless to always add this.
@@ -59,15 +63,17 @@
             ).stdout
             return {x['name']: x for x in args or ()}
 
-    def ninja(self):
+    def ninja(self, options=None):
+        # TODO(pwbug/600) Make options required.
         cmd = ['ninja', '-C', self.dir]
-        cmd.extend(self.ninja_targets)
-
+        # TODO(pwbug/600) Always use options.
+        cmd.extend(options.ninja_targets if options else self.ninja_targets)
         self.m.step('ninja', cmd)
 
-    def __call__(self, checkout_dir):
-        self.gn_gen(checkout_dir)
-        self.ninja()
+    def __call__(self, checkout_dir, options=None):
+        # TODO(pwbug/600) Make options required.
+        self.gn_gen(checkout_dir, options)
+        self.ninja(options)
 
     def archive_to_cas(self):
         # TODO(pwbug/389) Only archive necessary files.
diff --git a/recipe_modules/build/options.proto b/recipe_modules/build/options.proto
new file mode 100644
index 0000000..b122ad8
--- /dev/null
+++ b/recipe_modules/build/options.proto
@@ -0,0 +1,24 @@
+// Copyright 2020 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+syntax = "proto3";
+
+package recipe_modules.pigweed.build;
+
+message Options {
+  // List of gn args ("var=value", ...). Default: empty.
+  repeated string gn_args = 1;
+
+  // List of targets to build. Default: empty (build default target).
+  repeated string ninja_targets = 2;
+}
diff --git a/recipe_modules/build/properties.proto b/recipe_modules/build/properties.proto
index 1b3d763..ed13b9e 100644
--- a/recipe_modules/build/properties.proto
+++ b/recipe_modules/build/properties.proto
@@ -15,6 +15,7 @@
 
 package recipe_modules.pigweed.build;
 
+// TODO(pwbug/600) Remove this file.
 message InputProperties {
   // List of gn args ("var=value", ...). Default: empty.
   repeated string gn_args = 1;
diff --git a/recipe_modules/build/test_api.py b/recipe_modules/build/test_api.py
index e79f168..5ffd705 100644
--- a/recipe_modules/build/test_api.py
+++ b/recipe_modules/build/test_api.py
@@ -13,18 +13,18 @@
 # the License.
 """Test API for build."""
 
-from PB.recipe_modules.pigweed.build import properties as build_properties
+from PB.recipe_modules.pigweed.build import options
 from recipe_engine import recipe_test_api
 
 
 class BuildTestApi(recipe_test_api.RecipeTestApi):
     """Test API for build."""
 
-    def properties(self, gn_args, ninja_targets):
+    def options(self, gn_args=(), ninja_targets=()):
         assert isinstance(gn_args, (list, tuple))
         assert isinstance(ninja_targets, (list, tuple))
 
-        props = build_properties.InputProperties()
-        props.gn_args.extend(gn_args)
-        props.ninja_targets.extend(ninja_targets)
-        return {'$pigweed/build': props}
+        opts = options.Options()
+        opts.gn_args.extend(gn_args)
+        opts.ninja_targets.extend(ninja_targets)
+        return opts
diff --git a/recipe_modules/build/tests/full.proto b/recipe_modules/build/tests/full.proto
new file mode 100644
index 0000000..7770792
--- /dev/null
+++ b/recipe_modules/build/tests/full.proto
@@ -0,0 +1,23 @@
+// Copyright 2022 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+syntax = "proto3";
+
+package recipe_modules.pigweed.build.tests;
+
+import "recipe_modules/pigweed/build/options.proto";
+
+message InputProperties {
+  recipe_modules.pigweed.build.Options build_options = 1;
+}
diff --git a/recipe_modules/build/tests/full.py b/recipe_modules/build/tests/full.py
index 1e4edfe..5e000cb 100644
--- a/recipe_modules/build/tests/full.py
+++ b/recipe_modules/build/tests/full.py
@@ -13,7 +13,7 @@
 # the License.
 """Full test of build module."""
 
-from recipe_engine.recipe_api import Property
+from PB.recipe_modules.pigweed.build.tests.full import InputProperties
 
 DEPS = [
     'fuchsia/status_check',
@@ -22,11 +22,13 @@
     'recipe_engine/properties',
 ]
 
+PROPERTIES = InputProperties
+
 PYTHON_VERSION_COMPATIBILITY = "PY3"
 
 
-def RunSteps(api):
-    api.build(api.path['start_dir'].join('checkout'))
+def RunSteps(api, props):
+    api.build(api.path['start_dir'].join('checkout'), props.build_options)
     api.build.save_logs(export_dir=api.build.dir.join('export'))
     api.build.get_gn_args()
     api.build.archive_to_cas()
@@ -37,7 +39,7 @@
     yield (
         api.status_check.test('full')
         + api.properties(
-            **api.build.properties(
+            build_options=api.build.options(
                 gn_args=['foo=true'], ninja_targets=['target'],
             )
         )
diff --git a/recipes/build.expected/basic.json b/recipes/build.expected/basic.json
index c577eac..1b11e52 100644
--- a/recipes/build.expected/basic.json
+++ b/recipes/build.expected/basic.json
@@ -1126,6 +1126,7 @@
     "cmd": [
       "gn",
       "gen",
+      "--args=gnarg",
       "--export-compile-commands",
       "[START_DIR]/build"
     ],
diff --git a/recipes/build.proto b/recipes/build.proto
new file mode 100644
index 0000000..8fc2f24
--- /dev/null
+++ b/recipes/build.proto
@@ -0,0 +1,23 @@
+// Copyright 2022 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+syntax = "proto3";
+
+package recipes.pigweed.build;
+
+import "recipe_modules/pigweed/build/options.proto";
+
+message InputProperties {
+  recipe_modules.pigweed.build.Options build_options = 1;
+}
diff --git a/recipes/build.py b/recipes/build.py
index b56d988..1554ab4 100644
--- a/recipes/build.py
+++ b/recipes/build.py
@@ -13,23 +13,28 @@
 # the License.
 """Recipe for testing Pigweed with multiple swarming tasks."""
 
+from PB.recipes.pigweed.build import InputProperties
+
 DEPS = [
     'fuchsia/status_check',
     'pigweed/build',
     'pigweed/checkout',
     'pigweed/environment',
+    'recipe_engine/properties',
     'recipe_engine/step',
 ]
 
+PROPERTIES = InputProperties
+
 PYTHON_VERSION_COMPATIBILITY = "PY3"
 
 
-def RunSteps(api):
+def RunSteps(api, props):
     api.checkout()
     api.environment.init(api.checkout.root)
 
     with api.environment():
-        api.build(api.checkout.root)
+        api.build(api.checkout.root, props.build_options)
         digest = api.build.archive_to_cas()
 
     with api.step.nest('result') as pres:
@@ -37,4 +42,8 @@
 
 
 def GenTests(api):
-    yield api.status_check.test('basic') + api.checkout.ci_test_data()
+    yield (
+        api.status_check.test('basic')
+        + api.checkout.ci_test_data()
+        + api.properties(build_options=api.build.options(gn_args=['gnarg']))
+    )