[otbn] Define a slightly more general way to build code snippets

This Makefile fragment essentially defines a way to do:

    foo.S -> foo.o -> foo.elf

However, you can now add dependencies and define $(otbn-libs) for an
specific ELF to allow one file to depend on another.

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/util/Makefile b/hw/ip/otbn/util/Makefile
index bc24df1..134b605 100644
--- a/hw/ip/otbn/util/Makefile
+++ b/hw/ip/otbn/util/Makefile
@@ -12,7 +12,7 @@
 cs-build-dir := $(build-dir)/code-snippets
 lint-build-dir := $(build-dir)/lint
 
-$(build-dir) $(cs-build-dir) $(lint-build-dir):
+$(build-dir) $(lint-build-dir):
 	mkdir -p $@
 
 pylibs := $(wildcard shared/*.py)
@@ -33,25 +33,17 @@
 $(lint-targets): lint-%:
 	mypy --strict $* $(pylibs)
 
-# Sanity check target that assembles and (trivially) links each of
-# the code snippets.
-asm-snippets := $(notdir $(wildcard $(repo-top)/sw/otbn/code-snippets/*.S))
+# Sanity check target that assembles and links each of the code
+# snippets.
 
-asm-objects := $(addprefix $(cs-build-dir)/,$(asm-snippets:%.S=%.o))
-linked-elfs := $(addprefix $(cs-build-dir)/,$(asm-snippets:%.S=%))
+otbn-code-snippets-obj-dir := $(cs-build-dir)
+otbn-code-snippets-bin-dir := $(cs-build-dir)
+otbn-code-snippets-util-dir  := .
 
-# Firstly, assemble them
-$(asm-objects): $(cs-build-dir)/%.o: \
-  $(repo-top)/sw/otbn/code-snippets/%.S otbn-as $(pylibs) | $(cs-build-dir)
-	./otbn-as -o $@ $<
-
-# Then link them
-$(linked-elfs): $(cs-build-dir)/%: \
-  $(cs-build-dir)/%.o otbn-ld $(pylibs)
-	./otbn-ld -o $@ $<
+include $(repo-top)/sw/otbn/code-snippets/rules.mk
 
 .PHONY: asm-sanity
-asm-sanity: $(linked-elfs)
+asm-sanity: $(otbn-code-snippets-elfs)
 
 .PHONY: clean
 clean:
diff --git a/sw/otbn/code-snippets/Makefile b/sw/otbn/code-snippets/Makefile
new file mode 100644
index 0000000..421cf6d
--- /dev/null
+++ b/sw/otbn/code-snippets/Makefile
@@ -0,0 +1,41 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+#####################################################################
+#
+# THIS IS A TEMPORARY SOLUTION
+#
+# Eventually, the software team is going to have a Meson-based flow
+# for building OTBN software. When that exists, this code will go
+# away.
+#
+#####################################################################
+
+# A Makefile for assembling and linking the code snippets. By default,
+# the rules generate outputs in build-bin/sw/otbn/build-subdir.
+#
+# This is a thin wrapper around ./rules.mk. To customise exactly what
+# gets built where, include rules.mk in your own Makefile (see
+# documentation there) and set the otbn-code-snippets-* variables
+# appropriately.
+#
+
+.PHONY: all
+all: build
+
+repo-top  := ../../..
+
+obj-dir := $(firstword $(OBJ_DIR) $(repo-top)/build-out)
+bin-dir := $(firstword $(BIN_DIR) $(repo-top)/build-bin)
+build-subdir := sw/otbn/code-snippets
+
+otbn-code-snippets-obj-dir := $(obj-dir)/$(build-subdir)
+otbn-code-snippets-bin-dir := $(bin-dir)/$(build-subdir)
+otbn-code-snippets-util-dir  := $(repo-top)/hw/ip/otbn/util
+
+code-snippets-path := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
+include $(code-snippets-path)rules.mk
+
+.PHONY: build
+build: $(otbn-code-snippets-elfs)
diff --git a/sw/otbn/code-snippets/README.md b/sw/otbn/code-snippets/README.md
index eca8198..ef9b23e 100644
--- a/sw/otbn/code-snippets/README.md
+++ b/sw/otbn/code-snippets/README.md
@@ -11,3 +11,7 @@
     instruction.
   - `barrett384.S`: An example of a modular multiplication kernel based on
     Barrett reduction.
+
+Also included in this directory is a Makefile fragment that can be
+used to assemble and link the snippets. This can be used standalone or
+included in another Makefile.
diff --git a/sw/otbn/code-snippets/rules.mk b/sw/otbn/code-snippets/rules.mk
new file mode 100644
index 0000000..a853e83
--- /dev/null
+++ b/sw/otbn/code-snippets/rules.mk
@@ -0,0 +1,84 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+#####################################################################
+#
+# THIS IS A TEMPORARY SOLUTION
+#
+# Eventually, the software team is going to have a Meson-based flow
+# for building OTBN software. When that exists, this code will go
+# away.
+#
+#####################################################################
+
+# A make fragment for assembling and linking the code snippets. This is
+# included by ./Makefile, but can be included in other Makefiles too.
+#
+# The following variables must be set:
+#
+#    variable                      | description
+#  --------------------------------+----------------------------------------
+#    otbn-code-snippets-obj-dir    | Output directory for built objects
+#    otbn-code-snippets-bin-dir    | Output directory for built binaries
+#    otbn-code-snippets-util-dir   | Path to directory containing OTBN tooling
+#
+# The following variables may be set:
+#
+#    variable                      | description
+#  --------------------------------+----------------------------------------
+#    otbn-code-snippets-as         | Path to otbn-as (defaults to util dir)
+#    otbn-code-snippets-ld         | Path to otbn-ld (defaults to util dir)
+#
+# The ugly "otbn-code-snippets-" prefix on variable names is so that this file
+# can be included in other Makefiles without breaking anything.
+
+ifndef otbn-code-snippets-obj-dir
+$(error otbn-code-snippets-obj-dir not set.)
+endif
+ifndef otbn-code-snippets-bin-dir
+$(error otbn-code-snippets-bin-dir not set.)
+endif
+ifndef otbn-code-snippets-util-dir
+$(error otbn-code-snippets-util-dir not set.)
+endif
+
+# Default values for optional variables
+otbn-code-snippets-as ?= $(otbn-code-snippets-util-dir)/otbn-as
+otbn-code-snippets-ld ?= $(otbn-code-snippets-util-dir)/otbn-ld
+
+# Get the list of all assembly files in this directory. Strip away directory
+# and extension to get basenames (used for objects and binaries).
+otbn-code-snippets-path      := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
+otbn-code-snippets-asm-paths := $(wildcard $(otbn-code-snippets-path)*.S)
+otbn-code-snippets-asm-basenames := $(notdir $(otbn-code-snippets-asm-paths))
+otbn-code-snippets-basenames     := $(otbn-code-snippets-asm-basenames:.S=)
+
+$(otbn-code-snippets-obj-dir) $(otbn-code-snippets-bin-dir):
+	mkdir -p $@
+
+# Calculate lists of object and ELF files
+otbn-code-snippets-objects := \
+  $(foreach b,$(otbn-code-snippets-basenames),\
+            $(otbn-code-snippets-obj-dir)/$(b).o)
+otbn-code-snippets-elfs := \
+  $(foreach b,$(otbn-code-snippets-basenames),\
+            $(otbn-code-snippets-bin-dir)/$(b).elf)
+
+# Define rules for assembling the source code to make objects
+$(otbn-code-snippets-objects): \
+  $(otbn-code-snippets-obj-dir)/%.o: \
+  $(otbn-code-snippets-path)%.S $(otbn-code-snippets-as) \
+   | $(otbn-code-snippets-obj-dir)
+	$(otbn-code-snippets-as) -o $@ $<
+
+# Define rules for linking objects to make ELFs
+$(otbn-code-snippets-elfs): \
+  $(otbn-code-snippets-bin-dir)/%.elf: \
+  $(otbn-code-snippets-obj-dir)/%.o $(otbn-code-snippets-ld) \
+   | $(otbn-code-snippets-bin-dir)
+	$(otbn-code-snippets-ld) -o $@ $(otbn-ldflags) $< $(otbn-libs)
+
+#
+# Define any file-specific flags or dependencies
+#