From 3c4c2865c54fb8f87fb86d6f1211a4c34d085e1f Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Fri, 13 Feb 2026 14:02:59 +1100 Subject: [PATCH 1/5] tidyup and testing with api-v2 --- .../cice5/access-esm1.6-intel.spack.yaml.j2 | 1 + ...cess-om2+deterministic-intel.spack.yaml.j2 | 2 +- ...cess-om2~deterministic-intel.spack.yaml.j2 | 1 + .../access/nri/packages/cice5/package.py | 74 ++++++++++++++++--- 4 files changed, 65 insertions(+), 13 deletions(-) diff --git a/.github/build-ci/manifests/cice5/access-esm1.6-intel.spack.yaml.j2 b/.github/build-ci/manifests/cice5/access-esm1.6-intel.spack.yaml.j2 index 745d0816..098fb2cd 100644 --- a/.github/build-ci/manifests/cice5/access-esm1.6-intel.spack.yaml.j2 +++ b/.github/build-ci/manifests/cice5/access-esm1.6-intel.spack.yaml.j2 @@ -2,6 +2,7 @@ spack: specs: - 'access-esm1p6 ^cice5 nxglob=360 nyglob=300 blckx=15 blcky=300 mxblcks=1' - 'access-esm1p6 ^cice5 build_system=makefile' + - 'access-esm1p6 ^cice5 build_system=cmake' packages: python: require: diff --git a/.github/build-ci/manifests/cice5/access-om2+deterministic-intel.spack.yaml.j2 b/.github/build-ci/manifests/cice5/access-om2+deterministic-intel.spack.yaml.j2 index 1bbd51e9..962c7b5b 100644 --- a/.github/build-ci/manifests/cice5/access-om2+deterministic-intel.spack.yaml.j2 +++ b/.github/build-ci/manifests/cice5/access-om2+deterministic-intel.spack.yaml.j2 @@ -1,6 +1,6 @@ spack: specs: - - 'access-om2 +deterministic ^cice5 build_system=cmake nxglob=360 nyglob=300 blckx=15 blcky=300 mxblcks=1' + - 'access-om2 +deterministic ^cice5 build_system=cmake nxglob=360 nyglob=300 blckx=15 blcky=150 mxblcks=2' - 'access-om2 +deterministic ^cice5 build_system=makefile' packages: python: diff --git a/.github/build-ci/manifests/cice5/access-om2~deterministic-intel.spack.yaml.j2 b/.github/build-ci/manifests/cice5/access-om2~deterministic-intel.spack.yaml.j2 index d6ca11d3..51ceeae7 100644 --- a/.github/build-ci/manifests/cice5/access-om2~deterministic-intel.spack.yaml.j2 +++ b/.github/build-ci/manifests/cice5/access-om2~deterministic-intel.spack.yaml.j2 @@ -2,6 +2,7 @@ spack: specs: - 'access-om2 ~deterministic ^cice5 build_system=cmake nxglob=360 nyglob=300 blckx=15 blcky=300 mxblcks=1' - 'access-om2 ~deterministic ^cice5 build_system=makefile' + - 'access-om2 ~deterministic ^cice5 build_system=cmake' packages: python: require: diff --git a/spack_repo/access/nri/packages/cice5/package.py b/spack_repo/access/nri/packages/cice5/package.py index b155fc1c..4ebdf74f 100644 --- a/spack_repo/access/nri/packages/cice5/package.py +++ b/spack_repo/access/nri/packages/cice5/package.py @@ -7,13 +7,27 @@ from spack_repo.builtin.build_systems.makefile import MakefilePackage from spack.package import * +# These are the default layouts, inc 3 executables for OM2 +# alternatively, supply the 5 layouts variant to produce 1 executable +OM2_LAYOUTS = [ + {"nxglob": "360", "nyglob": "300", "blckx": "15", "blcky": "300", "mxblcks": "1"}, + {"nxglob": "1440", "nyglob": "1080", "blckx": "30", "blcky": "27", "mxblcks": "4"}, + {"nxglob": "3600", "nyglob": "2700", "blckx": "40", "blcky": "30", "mxblcks": "12"}, + ] +ESM1P6_LAYOUTS = [ + {"nxglob": "360", "nyglob": "300", "blckx": "30", "blcky": "300", "mxblcks": "1"}, +] + + def _int_validator(s): """Test a string variant is a valid integer """ - if (s.isdigit() and int(s) > 0): - return True - else: - print(f"ERROR: {s} not a valid integer") - return False + if (s != "none"): + if (s.isdigit() and int(s) > 0): + return True + else: + print(f"ERROR: {s} not a valid integer") + return False + class Cice5(CMakePackage, MakefilePackage): """The Los Alamos sea ice model (CICE) is the result of an effort to develop @@ -32,7 +46,7 @@ class Cice5(CMakePackage, MakefilePackage): version("access-om2", branch="master") version("access-esm1.6", branch="access-esm1.6") - # by default, keep existing processor layout defined in makefile + # by default, keep existing processor layout # if nxglob, nyglob, blckx, blcky, mxblcks are supplied, then spack will switch to cmake build_system("makefile", "cmake", default="makefile") @@ -113,26 +127,63 @@ class Cice5(CMakePackage, MakefilePackage): depends_on("libaccessom2+deterministic", when="+deterministic") depends_on("libaccessom2~deterministic", when="~deterministic") + class CMakeBuilder(cmake.CMakeBuilder): + phases = ["set_layouts", "cmake_build_install"] + + def set_layouts(self, pkg, spec, prefix): + layout_variants = OM2_LAYOUTS[0].keys() + + # if all 5 layouts variants are available, set the layouts dict + if all([ + self.spec.variants[variant].value != 'none' + for variant in layout_variants + ]): + layouts = [{variant: self.spec.variants[variant].value + for variant in layout_variants}] + # else if no layout variants are available, use the defaults + elif all([ + self.spec.variants[variant].value == 'none' + for variant in layout_variants + ]): + if self.spec.variants["model"].value == "access-esm1.6": + layouts = ESM1P6_LAYOUTS + else: + layouts = OM2_LAYOUTS + else: + raise Error(f"All of {layout_variants} " + "variants must be set if any are set") + + self._all_layouts = layouts + def cmake_args(self): + # combine the normal cmake build phases, so its easier to produce multiple builds + # cmake_args is called during super().cmake() if self.spec.variants["model"].value == "access-esm1.6": args = [self.define("CICE_DRIVER", "access")] else: # access-om2 args = [self.define("CICE_DRIVER", "auscom")] args.extend([ + self.define("CICE_NXGLOB", self._layout['nxglob']), + self.define("CICE_NYGLOB", self._layout['nyglob']), + self.define("CICE_BLCKX", self._layout['blckx']), + self.define("CICE_BLCKY", self._layout['blcky']), + self.define("CICE_MXBLCKS", self._layout['mxblcks']), self.define_from_variant("CICE_IO", "io_type"), - self.define_from_variant("CICE_NXGLOB", "nxglob"), - self.define_from_variant("CICE_NYGLOB", "nyglob"), - self.define_from_variant("CICE_BLCKX", "blckx"), - self.define_from_variant("CICE_BLCKY", "blcky"), - self.define_from_variant("CICE_MXBLCKS", "mxblcks"), self.define_from_variant("CICE_DETERMINISTIC", "deterministic"), ]) return args + def cmake_build_install(self, pkg, spec, prefix): + for layout in self._all_layouts: + self._layout = layout + super().cmake(pkg, spec, prefix) + super().build(pkg, spec, prefix) + super().install(pkg, spec, prefix) + class MakefileBuilder(makefile.MakefileBuilder): @@ -217,7 +268,6 @@ def set_deps_targets(self, pkg, spec, prefix): self.__deps["ldflags"] = " ".join([lstr] + [self.get_linker_args(spec, d) for d in ldeps]) - def edit(self, pkg, spec, prefix): srcdir = self.stage.source_path From 8c74a8801f09621d07eb01a47c05080c1d8e3f71 Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Fri, 13 Feb 2026 14:15:15 +1100 Subject: [PATCH 2/5] empty From 1cc3b883e8825d1fd3794d34b653f22bbbdd9c0d Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Mon, 16 Feb 2026 15:35:57 +1100 Subject: [PATCH 3/5] Move cmake_args higher in class definition Split into seperate cmake, build and install steps --- .../access/nri/packages/cice5/package.py | 63 ++++++++++++------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/spack_repo/access/nri/packages/cice5/package.py b/spack_repo/access/nri/packages/cice5/package.py index 4ebdf74f..cb2d6f8e 100644 --- a/spack_repo/access/nri/packages/cice5/package.py +++ b/spack_repo/access/nri/packages/cice5/package.py @@ -130,9 +130,31 @@ class Cice5(CMakePackage, MakefilePackage): class CMakeBuilder(cmake.CMakeBuilder): - phases = ["set_layouts", "cmake_build_install"] + phases = ["set_layouts", "cmake", "build", "install"] + + def cmake_args(self): + """List of the arguments that must be passed to cmake""" + # set cmake args based on the values in _layout, cmake_args is called during super().cmake() + if self.spec.variants["model"].value == "access-esm1.6": + args = [self.define("CICE_DRIVER", "access")] + else: # access-om2 + args = [self.define("CICE_DRIVER", "auscom")] + + args.extend([ + self.define("CICE_NXGLOB", self._layout['nxglob']), + self.define("CICE_NYGLOB", self._layout['nyglob']), + self.define("CICE_BLCKX", self._layout['blckx']), + self.define("CICE_BLCKY", self._layout['blcky']), + self.define("CICE_MXBLCKS", self._layout['mxblcks']), + self.define_from_variant("CICE_IO", "io_type"), + self.define_from_variant("CICE_DETERMINISTIC", "deterministic"), + ]) + + return args def set_layouts(self, pkg, spec, prefix): + """Layout of cice processors to use. If variants are set, use those. + Otherwise, use defaults.""" layout_variants = OM2_LAYOUTS[0].keys() # if all 5 layouts variants are available, set the layouts dict @@ -157,31 +179,30 @@ def set_layouts(self, pkg, spec, prefix): self._all_layouts = layouts - def cmake_args(self): - # combine the normal cmake build phases, so its easier to produce multiple builds - # cmake_args is called during super().cmake() - if self.spec.variants["model"].value == "access-esm1.6": - args = [self.define("CICE_DRIVER", "access")] - else: # access-om2 - args = [self.define("CICE_DRIVER", "auscom")] - - args.extend([ - self.define("CICE_NXGLOB", self._layout['nxglob']), - self.define("CICE_NYGLOB", self._layout['nyglob']), - self.define("CICE_BLCKX", self._layout['blckx']), - self.define("CICE_BLCKY", self._layout['blcky']), - self.define("CICE_MXBLCKS", self._layout['mxblcks']), - self.define_from_variant("CICE_IO", "io_type"), - self.define_from_variant("CICE_DETERMINISTIC", "deterministic"), - ]) - - return args + @property + def build_dirname(self) -> str: + """Directory name to use when building the package. """ + # We modify this to ensure uniqueness with multiple builds + build = ( + f"{self._layout['nxglob']}x{self._layout['nyglob']}_" + f"{self._layout['blckx']}x{self._layout['blcky']}_" + f"{self._layout['mxblcks']}" + ) + return f"{super().build_dirname}/{build}" - def cmake_build_install(self, pkg, spec, prefix): + def cmake(self, pkg, spec, prefix): for layout in self._all_layouts: self._layout = layout super().cmake(pkg, spec, prefix) + + def build(self, pkg, spec, prefix): + for layout in self._all_layouts: + self._layout = layout super().build(pkg, spec, prefix) + + def install(self, pkg, spec, prefix): + for layout in self._all_layouts: + self._layout = layout super().install(pkg, spec, prefix) From 1195201e5c1632285fc4077b51965cb19f5d8aaf Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Wed, 18 Feb 2026 11:27:17 +1100 Subject: [PATCH 4/5] review comments and formating --- .../access/nri/packages/cice5/package.py | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/spack_repo/access/nri/packages/cice5/package.py b/spack_repo/access/nri/packages/cice5/package.py index cb2d6f8e..ce102c93 100644 --- a/spack_repo/access/nri/packages/cice5/package.py +++ b/spack_repo/access/nri/packages/cice5/package.py @@ -8,7 +8,7 @@ from spack.package import * # These are the default layouts, inc 3 executables for OM2 -# alternatively, supply the 5 layouts variant to produce 1 executable +# alternatively, supply the 5 layout variant to produce 1 executable OM2_LAYOUTS = [ {"nxglob": "360", "nyglob": "300", "blckx": "15", "blcky": "300", "mxblcks": "1"}, {"nxglob": "1440", "nyglob": "1080", "blckx": "30", "blcky": "27", "mxblcks": "4"}, @@ -132,9 +132,15 @@ class CMakeBuilder(cmake.CMakeBuilder): phases = ["set_layouts", "cmake", "build", "install"] + _all_layouts = [{}] # all layouts to build, + # see OM2_LAYOUTS and ESM1P6_LAYOUTS for examples + _layout = {} # current layout being setup/built/installed + def cmake_args(self): - """List of the arguments that must be passed to cmake""" - # set cmake args based on the values in _layout, cmake_args is called during super().cmake() + """List of the arguments that must be passed to cmake. + These are set based on the values in _layout. + cmake_args is called during super().cmake() + """ if self.spec.variants["model"].value == "access-esm1.6": args = [self.define("CICE_DRIVER", "access")] else: # access-om2 @@ -152,6 +158,18 @@ def cmake_args(self): return args + @property + def build_dirname(self) -> str: + """Directory name to use when building the package. + We modify this using _layout to ensure uniqueness with multiple builds + """ + build = ( + f"{self._layout['nxglob']}x{self._layout['nyglob']}_" + f"{self._layout['blckx']}x{self._layout['blcky']}_" + f"{self._layout['mxblcks']}" + ) + return f"{super().build_dirname}/{build}" + def set_layouts(self, pkg, spec, prefix): """Layout of cice processors to use. If variants are set, use those. Otherwise, use defaults.""" @@ -179,17 +197,6 @@ def set_layouts(self, pkg, spec, prefix): self._all_layouts = layouts - @property - def build_dirname(self) -> str: - """Directory name to use when building the package. """ - # We modify this to ensure uniqueness with multiple builds - build = ( - f"{self._layout['nxglob']}x{self._layout['nyglob']}_" - f"{self._layout['blckx']}x{self._layout['blcky']}_" - f"{self._layout['mxblcks']}" - ) - return f"{super().build_dirname}/{build}" - def cmake(self, pkg, spec, prefix): for layout in self._all_layouts: self._layout = layout From 68ebf7ea77478abcb6d773abfc95ffcdf386c25a Mon Sep 17 00:00:00 2001 From: Anton Steketee <79179784+anton-seaice@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:49:53 +1100 Subject: [PATCH 5/5] Update spack_repo/access/nri/packages/cice5/package.py Co-authored-by: Dougie Squire <42455466+dougiesquire@users.noreply.github.com> --- spack_repo/access/nri/packages/cice5/package.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spack_repo/access/nri/packages/cice5/package.py b/spack_repo/access/nri/packages/cice5/package.py index ce102c93..8bab1b34 100644 --- a/spack_repo/access/nri/packages/cice5/package.py +++ b/spack_repo/access/nri/packages/cice5/package.py @@ -8,7 +8,7 @@ from spack.package import * # These are the default layouts, inc 3 executables for OM2 -# alternatively, supply the 5 layout variant to produce 1 executable +# alternatively, supply the 5 layout variants to produce 1 executable OM2_LAYOUTS = [ {"nxglob": "360", "nyglob": "300", "blckx": "15", "blcky": "300", "mxblcks": "1"}, {"nxglob": "1440", "nyglob": "1080", "blckx": "30", "blcky": "27", "mxblcks": "4"},