From 92621e1aa07c5412474034fa10aef41344ad591f Mon Sep 17 00:00:00 2001
From: Simon Rose <simon.rose@ess.eu>
Date: Thu, 15 Jun 2023 16:35:30 +0200
Subject: [PATCH] Install metadata as the very last install step

This should take place after every single architecture has been finished. If any of them
fail, then the metadata file will _not_ be installed.
---
 require-ess/tools/driver.makefile | 35 +++++++++++++++----------------
 tests/test_build.py               | 16 ++++++++++++++
 tests/utils.py                    | 14 ++++++++++++-
 3 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/require-ess/tools/driver.makefile b/require-ess/tools/driver.makefile
index 2a73786a..8c5b889c 100644
--- a/require-ess/tools/driver.makefile
+++ b/require-ess/tools/driver.makefile
@@ -98,6 +98,7 @@ VERSIONFILE = ${PRJ}_version_${LIBVERSION}.c
 REGISTRYFILE = ${PRJ}_registerRecordDeviceDriver.cpp
 DEPFILE = ${PRJ}.dep
 METAFILE = ${PRJ}_meta.yaml
+INSTALL_META = ${METAFILE:%=${MODULE_LOCATION}/%}
 
 # Clear potential environment variables.
 TEMPLATES=
@@ -280,6 +281,15 @@ $(COMMON_DIR)/%.db: %.template
 	$(QUIET)$(MSI)    $(USR_DBFLAGS) -o $(COMMON_DIR)/$(notdir $(basename $@).db) $^
 
 
+${COMMON_DIR}/${METAFILE}:
+	@echo "wrapper_url: '$(${PRJ}_E3_GIT_URL)'" > $@
+	@echo "wrapper_git_desc: '$(${PRJ}_E3_GIT_DESC)'" >> $@
+	@echo "module_git_desc: '$(shell git rev-parse HEAD 2> /dev/null)'" >> $@
+
+${INSTALL_META}: ${COMMON_DIR}/${METAFILE}
+	@echo "Installing metadata file $@"
+	$(INSTALL) -d -m444 $< $(@D)
+
 install build debug::
 	@echo "MAKING EPICS VERSION ${EPICSVERSION}"
 
@@ -330,6 +340,11 @@ db_internal: $$(addprefix $(COMMON_DIR)/,$$(notdir $$(patsubst %.substitutions,%
 # and ARCH_FILTER, which are defined _after_ driver.makefile.
 $(foreach target,install build debug,$(eval $(target):: $$$$(foreach arch,$$$${BUILD_ARCHS},$(target)-$$$${arch})))
 
+# Create and install the metadata file as the very last step
+build:: ${COMMON_DIR}/${METAFILE}
+
+install:: ${INSTALL_META}
+
 else # T_A
 
 ifeq ($(filter O.%,$(notdir ${CURDIR})),)
@@ -428,11 +443,6 @@ export BINS
 VLIBS = $(VENDOR_LIBS) $(foreach x,$(VAR_EXTENSIONS),$(VENDOR_LIBS_$x))
 export VLIBS
 
-# This variable is written into a .yaml file in the installed module directory to keep track of
-# metadata for which module was compiled.
-${PRJ}_GIT_DESC := $(shell git rev-parse HEAD 2> /dev/null)
-export ${PRJ}_GIT_DESC
-
 else # in O.*
 ## RUN 3
 # In build directory.
@@ -604,7 +614,7 @@ vpath %.hh $(addprefix ../,$(sort $(dir $(filter-out /%,${HDRS}) ${SRCS}))) $(so
 vpath %.hxx $(addprefix ../,$(sort $(dir $(filter-out /%,${HDRS}) ${SRCS}))) $(sort $(dir $(filter /%,${HDRS})))
 
 
-PRODUCTS = ${MODULELIB} ${MODULEDBD} ${DEPFILE} ${METAFILE}
+PRODUCTS = ${MODULELIB} ${MODULEDBD} ${DEPFILE}
 MODULEINFOS:
 	@echo ${PRJ} > MODULENAME
 	@echo ${PRODUCTS} > PRODUCTS
@@ -621,7 +631,6 @@ ${MODULEDBD}: ${DBDFILES}
 INSTALL_LIBS = ${MODULELIB:%=${INSTALL_LIB}/%}
 INSTALL_VLIBS = $(addprefix ${INSTALL_VLIB}/,$(notdir ${VLIBS}))
 INSTALL_DEPS = ${DEPFILE:%=${INSTALL_LIB}/%}
-INSTALL_META = ${METAFILE:%=${INSTALL_REV}/%}
 INSTALL_DBDS = ${MODULEDBD:%=${INSTALL_DBD}/%}
 INSTALL_DBDS += $(addprefix $(INSTALL_DBD)/,$(notdir ${DBDINSTALLS}))
 ifneq ($(strip $(HDR_SUBDIRS)),)
@@ -639,7 +648,6 @@ debug::
 	@echo "INSTALL_LIBS = $(INSTALL_LIBS)"
 	@echo "INSTALL_VLIBS = $(INSTALL_VLIBS)"
 	@echo "INSTALL_DEPS = $(INSTALL_DEPS)"
-	@echo "INSTALL_META = $(INSTALL_META)"
 	@echo "INSTALL_DBD = $(INSTALL_DBD)"
 	@echo "INSTALL_DBDS = $(INSTALL_DBDS)"
 	@echo "INSTALL_INCLUDE = $(INSTALL_INCLUDE)"
@@ -666,7 +674,7 @@ debug::
 endef
 $(foreach d,$(HDR_SUBDIRS),$(eval $(call install_subdirs,$d)))
 
-INSTALLS += ${INSTALL_CONFIGS} ${INSTALL_SCRS} ${INSTALL_HDRS} ${INSTALL_DBDS} ${INSTALL_DBS} ${INSTALL_LIBS} ${INSTALL_VLIBS} ${INSTALL_BINS} ${INSTALL_DEPS} ${INSTALL_META}
+INSTALLS += ${INSTALL_CONFIGS} ${INSTALL_SCRS} ${INSTALL_HDRS} ${INSTALL_DBDS} ${INSTALL_DBS} ${INSTALL_LIBS} ${INSTALL_VLIBS} ${INSTALL_BINS} ${INSTALL_DEPS}
 
 install: ${INSTALLS}
 
@@ -686,10 +694,6 @@ ${INSTALL_DEPS}: $(notdir ${INSTALL_DEPS})
 	@echo "Installing module dependency file $@"
 	$(INSTALL) -d -m$(INSTALL_PERMISSIONS) $< $(@D)
 
-${INSTALL_META}: $(notdir ${INSTALL_META})
-	@echo "Installing metadata file $@"
-	$(INSTALL) -d -m$(INSTALL_PERMISSIONS) $< $(@D)
-
 ${INSTALL_DBS}: $(notdir ${INSTALL_DBS})
 	@echo "Installing module template files $^ to $(@D)"
 	$(INSTALL) -d -m$(INSTALL_PERMISSIONS) $^ $(@D)
@@ -719,11 +723,6 @@ ${VERSIONFILE}:
 ${REGISTRYFILE}: ${MODULEDBD}
 	$(PERL) $(EPICS_BASE_HOST_BIN)/registerRecordDeviceDriver.pl $< $(basename $@) | grep -v 'iocshRegisterCommon();' > $@
 
-${METAFILE}:
-	@echo "wrapper_url: '$(${PRJ}_E3_GIT_URL)'" > $@
-	@echo "wrapper_git_desc: '$(${PRJ}_E3_GIT_DESC)'" >> $@
-	@echo "module_git_desc: '$(${PRJ}_GIT_DESC)'" >> $@
-
 define DEP_PARSER
 s%$(E3_SITEMODS_PATH)/*\([^/]*\)/\([^/]*\)/.*%\1 \2%p; \
 s%$(EPICS_MODULES)/*\([^/]*\)/\([^/]*\)/.*%\1 \2%p
diff --git a/tests/test_build.py b/tests/test_build.py
index bd1be083..072c20c3 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -664,3 +664,19 @@ def test_target_fails_with_celltarget(wrapper: Wrapper, targets):
         "cell targets cannot be called with non cell targets on the same command line"
         in errs
     )
+
+
+def test_metadata_installed_on_success(wrapper: Wrapper):
+    rc, *_ = wrapper.run_make("install")
+    assert rc == 0
+    assert (wrapper.package_dir / f"{wrapper.name}_meta.yaml").exists()
+
+
+def test_metadata_not_installed_if_arch_fails(wrapper: Wrapper):
+    cross_arch = "foo"
+    wrapper.add_var_to_module_makefile(f"VLIBS_{cross_arch}", "not_a_library")
+    rc, *_ = wrapper.run_make(
+        "install", CROSS_COMPILER_TARGET_ARCHS=cross_arch, OS_CLASS="Linux"
+    )
+    assert rc == 2
+    assert not (wrapper.package_dir / f"{wrapper.name}_meta.yaml").exists()
diff --git a/tests/utils.py b/tests/utils.py
index 7223776e..d22e2459 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -49,6 +49,15 @@ class Wrapper:
         self.makefile = self.path / "Makefile"
         self.module_makefile = self.path / f"{self.name}.Makefile"
 
+        self.install_dir = (
+            self.path
+            / "cellMods"
+            / f"base-{self.base_version}"
+            / f"require-{self.require_version}"
+        )
+
+        self.package_dir = self.install_dir / self.name / self.version
+
         self.url = url
         if self.url:
             Repo.clone_from(self.url, self.path)
@@ -131,7 +140,6 @@ include $(E3_REQUIRE_TOOLS)/driver.makefile
             target = "celluninstall"
 
         env = os.environ.copy()
-        env.update(kwargs)
 
         args = list(args)
         if module_version:
@@ -139,6 +147,10 @@ include $(E3_REQUIRE_TOOLS)/driver.makefile
         if not ("TEST_DEBUG_ARCH" in env and not env["TEST_DEBUG_ARCH"]):
             args.append("EXCLUDE_ARCHS=debug")
 
+        # These are added as arguments to make to ensure that they are prioritised
+        for k, v in kwargs.items():
+            args.append(f"{k}={v}")
+
         if cell_path:
             self.write_dot_local_data("CONFIG_CELL", {"E3_CELL_PATH": cell_path})
         make_cmd = ["make", "-C", self.path, target] + args
-- 
GitLab