From 36e51b8106467a2bfb0562eeb7fbc5ddd3ee34e1 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Mon, 8 Jan 2024 14:01:22 -0700 Subject: [PATCH 01/12] Add supplemental Makefile for building MPAS dynamical core Variables (e.g., build options) will be read from `${CASEROOT}/Macros.make`. MPAS will be built as a static library located at `${LIBROOT}/libmpas.a`. --- src/dynamics/mpas/Makefile.in.CESM | 110 +++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/dynamics/mpas/Makefile.in.CESM diff --git a/src/dynamics/mpas/Makefile.in.CESM b/src/dynamics/mpas/Makefile.in.CESM new file mode 100644 index 00000000..b7f76abd --- /dev/null +++ b/src/dynamics/mpas/Makefile.in.CESM @@ -0,0 +1,110 @@ +ifeq ($(strip $(CASEROOT)),) + $(warning `CASEROOT` should not be empty. Defaulting to `.`) + + CASEROOT = . +endif + +ifeq ($(strip $(LIBROOT)),) + $(warning `LIBROOT` should not be empty. Defaulting to `..`) + + LIBROOT = .. +endif + +# +# Define and export variables used by MPAS build infrastructure. +# + +export CP = cp -afv +export RM = rm -frv + +# Constants. +export AUTOCLEAN = false +export BUILD_TARGET = N/A +export CORE = atmosphere +export EXE_NAME = atmosphere_model +export GEN_F90 = false +export GIT_VERSION = N/A +export NAMELIST_SUFFIX = atmosphere + +# Read variables (e.g., build options) from `Macros.make`. +include $(CASEROOT)/Macros.make + +# Translate variables (e.g., build options) from `Macros.make` to their equivalent ones used by MPAS build infrastructure. +export AR := ar +export ARFLAGS := -M +export CC := $(strip $(MPICC)) +export CFLAGS := $(strip $(CFLAGS)) +export CPP := cpp -P -traditional +export CPPFLAGS := -D_MPI \ + -DMPAS_BUILD_TARGET="$(BUILD_TARGET)" \ + -DMPAS_CAM_DYCORE \ + -DMPAS_EXE_NAME="$(EXE_NAME)" \ + -DMPAS_EXTERNAL_ESMF_LIB \ + -DMPAS_GIT_VERSION="$(GIT_VERSION)" \ + -DMPAS_NAMELIST_SUFFIX="$(NAMELIST_SUFFIX)" \ + -DMPAS_NATIVE_TIMERS \ + -DMPAS_NO_ESMF_INIT \ + -DMPAS_PIO_SUPPORT \ + -DUSE_PIO2 +export CPPINCLUDES := $(strip $(CPPINCLUDES)) +export CXX := $(strip $(MPICXX)) +export CXXFLAGS := $(strip $(CXXFLAGS)) +export FC := $(strip $(MPIFC)) +export FCINCLUDES := $(strip $(FCINCLUDES)) +export FFLAGS := $(strip $(FC_AUTO_R8) $(FFLAGS) $(FREEFLAGS)) +export LDFLAGS := $(strip $(LDFLAGS)) +export LIBS := $(strip $(LIBS)) +export LINKER := $(strip $(MPIFC)) +export SCC := $(strip $(SCC)) +export SCXX := $(strip $(SCXX)) +export SFC := $(strip $(SFC)) + +# +# Targets. +# + +.PHONY: all +all: + @echo 'Supplemental Makefile for MPAS Dynamical Core in CESM' + @echo '' + @echo 'Variables (e.g., build options) will be read from `$${CASEROOT}/Macros.make`.' + @echo 'MPAS will be built as a static library located at `$${LIBROOT}/libmpas.a`.' + @echo '' + @echo 'Usage hints:' + @echo ' `make libmpas-prepare ESM="CESM" CASEROOT="..." LIBROOT="..."`' + @echo ' `make libmpas-build ESM="CESM" CASEROOT="..." LIBROOT="..."`' + @echo ' `make libmpas-clean ESM="CESM" CASEROOT="..." LIBROOT="..."`' + +.PHONY: libmpas-prepare +libmpas-prepare: libmpas-archiver-script.txt libmpas-no-physics + +# Combine multiple static libraries into `libmpas.a` via archiver/MRI script. This requires GNU or GNU-like archiver (`ar`) program. +libmpas-archiver-script.txt: + @echo "create libmpas.a" > $(@) + @echo "addlib libdycore.a" >> $(@) + @echo "addlib libframework.a" >> $(@) + @echo "addlib libops.a" >> $(@) + @echo "save" >> $(@) + @echo "end" >> $(@) + +# Do not use built-in MPAS/WRF physics. +.PHONY: libmpas-no-physics +libmpas-no-physics: + @sed -E -i -e "s/^ *PHYSICS=.+$$/PHYSICS=/g" core_atmosphere/Makefile + +.PHONY: libmpas-build +libmpas-build: $(LIBROOT)/libmpas.a + +$(LIBROOT)/libmpas.a: libmpas.a + $(CP) $(<) $(@) + +libmpas.a: $(AUTOCLEAN_DEPS) dycore externals frame ops + $(AR) $(ARFLAGS) < libmpas-archiver-script.txt + +.PHONY: libmpas-clean +libmpas-clean: clean + $(RM) $(LIBROOT)/libmpas.a libmpas.a + +.PHONY: externals +externals: $(AUTOCLEAN_DEPS) + ( cd external; $(MAKE) FC="$(FC)" SFC="$(SFC)" CC="$(CC)" SCC="$(SCC)" FFLAGS="$(FFLAGS)" CFLAGS="$(CFLAGS)" CPP="$(CPP)" NETCDF="$(NETCDF)" CORE="$(CORE)" ezxml-lib ) From 174f61478ae9b77be74570ca200c4c72b1c21bdc Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Mon, 8 Jan 2024 14:04:22 -0700 Subject: [PATCH 02/12] Integrate MPAS build infrastructure with CIME Build MPAS by invoking/reusing its own build infrastructure. This way, it would be easier to keep in sync with future upstream changes. --- cime_config/buildlib | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/cime_config/buildlib b/cime_config/buildlib index 7eb30164..5cde79a3 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -156,6 +156,57 @@ def _build_cam(): _LOGGER.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n", cmd, out, err) expect(retcode == 0, f"Command {cmd} failed with rc={retcode}") + # If dynamical core is MPAS, build it after CAM due to dependencies. + if dycore == "mpas": + _build_mpas(case) + +def _build_mpas(case: Case) -> None: + """ + Build MPAS by invoking its build infrastructure. + """ + + case_root = os.path.normpath(case.get_value("CASEROOT")) + atm_src_root = os.path.normpath(case.get_value("COMP_ROOT_DIR_ATM")) + atm_bld_root = os.path.normpath(os.path.join(case.get_value("EXEROOT"), "atm", "obj")) + lib_root = os.path.normpath(os.path.join(case.get_value("EXEROOT"), "lib")) + + gmake = case.get_value("GMAKE") + gmake_j = case.get_value("GMAKE_J") + + mpas_dycore_src_root = os.path.join(atm_src_root, "src", "dynamics", "mpas", "dycore", "src") + mpas_dycore_bld_root = os.path.join(atm_bld_root, "mpas") + + # Make sure `mpas_dycore_src_root` exists. If not, it is likely that `./manage_externals/checkout_externals` did not succeed. + if os.path.isfile(mpas_dycore_src_root): + raise FileExistsError(1, "Unexpected file", mpas_dycore_src_root) + + if not os.path.isdir(mpas_dycore_src_root): + raise FileNotFoundError(1, "No such directory", mpas_dycore_src_root) + + # MPAS supports "in-source" build only. Copy source code to `mpas_dycore_bld_root` to avoid polluting `mpas_dycore_src_root`. + if os.path.isfile(mpas_dycore_bld_root): + raise FileExistsError(1, "Unexpected file", mpas_dycore_bld_root) + + if not os.path.isdir(mpas_dycore_bld_root): + shutil.copytree(mpas_dycore_src_root, mpas_dycore_bld_root) + shutil.copy2(os.path.normpath(os.path.join(mpas_dycore_src_root, "../../Makefile.in.CESM")), os.path.join(mpas_dycore_bld_root, "Makefile.in.CESM")) + + # Invoke makefile target `libmpas-prepare`. + mpas_dycore_make_command = f'{gmake} -C {mpas_dycore_bld_root} libmpas-prepare ESM="CESM" CASEROOT="{case_root}" LIBROOT="{lib_root}" ' + mpas_dycore_make_command += f'FCINCLUDES="-I{atm_bld_root}"' + + (sta, out, err) = run_cmd(mpas_dycore_make_command, from_dir=mpas_dycore_bld_root) + _LOGGER.info("* Command %s:\n\n Output:\n%s\n\n Error:\n%s\n\n", mpas_dycore_make_command, out, err) + expect(sta == 0, f"Command {mpas_dycore_make_command} failed with status {sta}") + + # Invoke makefile target `libmpas-build`. + mpas_dycore_make_command = f'{gmake} -C {mpas_dycore_bld_root} -j {gmake_j} libmpas-build ESM="CESM" CASEROOT="{case_root}" LIBROOT="{lib_root}" ' + mpas_dycore_make_command += f'FCINCLUDES="-I{atm_bld_root}"' + + (sta, out, err) = run_cmd(mpas_dycore_make_command, from_dir=mpas_dycore_bld_root) + _LOGGER.info("* Command %s:\n\n Output:\n%s\n\n Error:\n%s\n\n", mpas_dycore_make_command, out, err) + expect(sta == 0, f"Command {mpas_dycore_make_command} failed with status {sta}") + ############################################################################### if __name__ == "__main__": From 666123f372b59e6ebcca6c12913634dcdb81f738 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Mon, 8 Jan 2024 14:10:51 -0700 Subject: [PATCH 03/12] Add MPAS dynamical core to component configuration --- cime_config/config_component.xml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index d14b3aa9..0decd3f0 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -103,10 +103,11 @@ char - eul,fv,se,none + eul,fv,mpas,se,none fv - eul + eul + mpas se build_component_cam @@ -303,11 +304,12 @@ char - + -lmpas -lmusica -ljsonfortran - - + + + -lmpas build_component_cam env_build.xml From c58c5ecb4ed96135083e0e33c7bbb827456b22f8 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Mon, 8 Jan 2024 15:17:35 -0700 Subject: [PATCH 04/12] Rename to `mpasa` in component configuration `cime/CIME/Tools/Makefile` explicitly queries the value of `CAM_DYCORE`. If the value is `mpas`, it attempts to build MPAS by using old rules and fails. There are some ways to work around this without modifying `cime/CIME/Tools/Makefile` and breaking backward compatibility for CAM. One of them is to rename the value to `mpasa`. --- cime_config/config_component.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 0decd3f0..126de6b8 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -103,11 +103,11 @@ char - eul,fv,mpas,se,none + eul,fv,mpasa,se,none fv eul - mpas + mpasa se build_component_cam From 9c393908741109633cfd018959a2c3aa5d310178 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Tue, 16 Jan 2024 10:36:16 -0700 Subject: [PATCH 05/12] Make sure $LIBROOT exists --- src/dynamics/mpas/Makefile.in.CESM | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dynamics/mpas/Makefile.in.CESM b/src/dynamics/mpas/Makefile.in.CESM index b7f76abd..57ec6dc3 100644 --- a/src/dynamics/mpas/Makefile.in.CESM +++ b/src/dynamics/mpas/Makefile.in.CESM @@ -15,6 +15,7 @@ endif # export CP = cp -afv +export MKDIR = mkdir -pv export RM = rm -frv # Constants. @@ -96,6 +97,7 @@ libmpas-no-physics: libmpas-build: $(LIBROOT)/libmpas.a $(LIBROOT)/libmpas.a: libmpas.a + $(MKDIR) $(LIBROOT) $(CP) $(<) $(@) libmpas.a: $(AUTOCLEAN_DEPS) dycore externals frame ops From 0959d93b2baf5bd8ed98d9b77fd569c7df432059 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Tue, 16 Jan 2024 10:52:00 -0700 Subject: [PATCH 06/12] Add a wrapper function for copying MPAS source code as needed This helps keep MPAS source code in sync between `mpas_dycore_src_root` and `mpas_dycore_bld_root`. --- cime_config/buildlib | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index 5cde79a3..8767cb5b 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -187,9 +187,8 @@ def _build_mpas(case: Case) -> None: if os.path.isfile(mpas_dycore_bld_root): raise FileExistsError(1, "Unexpected file", mpas_dycore_bld_root) - if not os.path.isdir(mpas_dycore_bld_root): - shutil.copytree(mpas_dycore_src_root, mpas_dycore_bld_root) - shutil.copy2(os.path.normpath(os.path.join(mpas_dycore_src_root, "../../Makefile.in.CESM")), os.path.join(mpas_dycore_bld_root, "Makefile.in.CESM")) + shutil.copytree(mpas_dycore_src_root, mpas_dycore_bld_root, copy_function=_copy2_as_needed, dirs_exist_ok=True) + _copy2_as_needed(os.path.normpath(os.path.join(mpas_dycore_src_root, "../../Makefile.in.CESM")), os.path.join(mpas_dycore_bld_root, "Makefile.in.CESM")) # Invoke makefile target `libmpas-prepare`. mpas_dycore_make_command = f'{gmake} -C {mpas_dycore_bld_root} libmpas-prepare ESM="CESM" CASEROOT="{case_root}" LIBROOT="{lib_root}" ' @@ -207,6 +206,27 @@ def _build_mpas(case: Case) -> None: _LOGGER.info("* Command %s:\n\n Output:\n%s\n\n Error:\n%s\n\n", mpas_dycore_make_command, out, err) expect(sta == 0, f"Command {mpas_dycore_make_command} failed with status {sta}") +def _copy2_as_needed(src: str, dst: str) -> None: + """ + Wrapper around `shutil.copy2`. Copy the file `src` to the file or directory `dst` as needed. + """ + + if os.path.isfile(src): + if os.path.isfile(dst): + if int(os.path.getmtime(src)) != int(os.path.getmtime(dst)) or os.path.getsize(src) != os.path.getsize(dst): + # `src` and `dst` are both files but their modification time or size differ. + # Example scenario: User modified some existing source code files. + print("1. Copy from", src, "to", dst) + print(os.path.getmtime(src), os.path.getmtime(dst)) + print(os.path.getsize(src), os.path.getsize(dst)) + shutil.copy2(src, dst) + else: + if os.path.isdir(dst) or os.path.isdir(os.path.dirname(dst)): + # `src` is a new file that does not exist at `dst`. + # Example scenario: User added some new source code files. + print("2. Copy from", src, "to", dst) + shutil.copy2(src, dst) + ############################################################################### if __name__ == "__main__": From 838af980c780491a10b64cd1b0a448542f378d4b Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Tue, 16 Jan 2024 11:14:51 -0700 Subject: [PATCH 07/12] Remove debug print --- cime_config/buildlib | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index 8767cb5b..eec40f86 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -216,15 +216,11 @@ def _copy2_as_needed(src: str, dst: str) -> None: if int(os.path.getmtime(src)) != int(os.path.getmtime(dst)) or os.path.getsize(src) != os.path.getsize(dst): # `src` and `dst` are both files but their modification time or size differ. # Example scenario: User modified some existing source code files. - print("1. Copy from", src, "to", dst) - print(os.path.getmtime(src), os.path.getmtime(dst)) - print(os.path.getsize(src), os.path.getsize(dst)) shutil.copy2(src, dst) else: if os.path.isdir(dst) or os.path.isdir(os.path.dirname(dst)): # `src` is a new file that does not exist at `dst`. # Example scenario: User added some new source code files. - print("2. Copy from", src, "to", dst) shutil.copy2(src, dst) ############################################################################### From 38d0de2f3891a56c4d1a8d00d2f9234fc91f692a Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Tue, 16 Jan 2024 14:21:27 -0700 Subject: [PATCH 08/12] Revert "Rename to `mpasa` in component configuration" This reverts commit c58c5ecb4ed96135083e0e33c7bbb827456b22f8. --- cime_config/config_component.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 126de6b8..0decd3f0 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -103,11 +103,11 @@ char - eul,fv,mpasa,se,none + eul,fv,mpas,se,none fv eul - mpasa + mpas se build_component_cam From 4f47388f5bd1badc05446f9e4163006fe9a0e96c Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Fri, 19 Jan 2024 16:09:27 -0700 Subject: [PATCH 09/12] Switch to use CIME Makefile for building Setup MPAS build infrastructure in a way that MPAS can be built along with CAM. --- cime_config/buildlib | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index eec40f86..54210d74 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -141,6 +141,11 @@ def _build_cam(): #------------------------------------------------------- # build the library #------------------------------------------------------- + + # If dynamical core is MPAS, setup its build infrastructure so it can be built along with CAM below. + if dycore == "mpas": + _setup_mpas(case) + complib = os.path.join(libroot, "libatm.a") makefile = os.path.join(casetools, "Makefile") @@ -156,22 +161,13 @@ def _build_cam(): _LOGGER.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n", cmd, out, err) expect(retcode == 0, f"Command {cmd} failed with rc={retcode}") - # If dynamical core is MPAS, build it after CAM due to dependencies. - if dycore == "mpas": - _build_mpas(case) - -def _build_mpas(case: Case) -> None: +def _setup_mpas(case: Case) -> None: """ - Build MPAS by invoking its build infrastructure. + Setup MPAS build infrastructure. """ - case_root = os.path.normpath(case.get_value("CASEROOT")) atm_src_root = os.path.normpath(case.get_value("COMP_ROOT_DIR_ATM")) atm_bld_root = os.path.normpath(os.path.join(case.get_value("EXEROOT"), "atm", "obj")) - lib_root = os.path.normpath(os.path.join(case.get_value("EXEROOT"), "lib")) - - gmake = case.get_value("GMAKE") - gmake_j = case.get_value("GMAKE_J") mpas_dycore_src_root = os.path.join(atm_src_root, "src", "dynamics", "mpas", "dycore", "src") mpas_dycore_bld_root = os.path.join(atm_bld_root, "mpas") @@ -188,23 +184,9 @@ def _build_mpas(case: Case) -> None: raise FileExistsError(1, "Unexpected file", mpas_dycore_bld_root) shutil.copytree(mpas_dycore_src_root, mpas_dycore_bld_root, copy_function=_copy2_as_needed, dirs_exist_ok=True) - _copy2_as_needed(os.path.normpath(os.path.join(mpas_dycore_src_root, "../../Makefile.in.CESM")), os.path.join(mpas_dycore_bld_root, "Makefile.in.CESM")) - - # Invoke makefile target `libmpas-prepare`. - mpas_dycore_make_command = f'{gmake} -C {mpas_dycore_bld_root} libmpas-prepare ESM="CESM" CASEROOT="{case_root}" LIBROOT="{lib_root}" ' - mpas_dycore_make_command += f'FCINCLUDES="-I{atm_bld_root}"' - - (sta, out, err) = run_cmd(mpas_dycore_make_command, from_dir=mpas_dycore_bld_root) - _LOGGER.info("* Command %s:\n\n Output:\n%s\n\n Error:\n%s\n\n", mpas_dycore_make_command, out, err) - expect(sta == 0, f"Command {mpas_dycore_make_command} failed with status {sta}") - - # Invoke makefile target `libmpas-build`. - mpas_dycore_make_command = f'{gmake} -C {mpas_dycore_bld_root} -j {gmake_j} libmpas-build ESM="CESM" CASEROOT="{case_root}" LIBROOT="{lib_root}" ' - mpas_dycore_make_command += f'FCINCLUDES="-I{atm_bld_root}"' - - (sta, out, err) = run_cmd(mpas_dycore_make_command, from_dir=mpas_dycore_bld_root) - _LOGGER.info("* Command %s:\n\n Output:\n%s\n\n Error:\n%s\n\n", mpas_dycore_make_command, out, err) - expect(sta == 0, f"Command {mpas_dycore_make_command} failed with status {sta}") + shutil.move(os.path.join(mpas_dycore_bld_root, "Makefile"), os.path.join(mpas_dycore_bld_root, "Makefile.CESM")) + _copy2_as_needed(os.path.normpath(os.path.join(mpas_dycore_src_root, os.pardir, os.pardir, "Makefile")), os.path.join(mpas_dycore_bld_root, "Makefile")) + _copy2_as_needed(os.path.normpath(os.path.join(mpas_dycore_src_root, os.pardir, os.pardir, "Makefile.in.CESM")), os.path.join(mpas_dycore_bld_root, "Makefile.in.CESM")) def _copy2_as_needed(src: str, dst: str) -> None: """ From 9842660369bcbead473656860787ec430a28194a Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Fri, 19 Jan 2024 16:11:41 -0700 Subject: [PATCH 10/12] Switch to use CIME Makefile for building Drop dependency to `$(CASEROOT)/Macros.make`. Users are responsible to provide all necessary build options via environment variables or command line arguments. In this case, rely on CIME Makefile to handle this. Print those build options for transparency. --- src/dynamics/mpas/Makefile.in.CESM | 68 ++++++++++++++++-------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/src/dynamics/mpas/Makefile.in.CESM b/src/dynamics/mpas/Makefile.in.CESM index 57ec6dc3..7b15a7e0 100644 --- a/src/dynamics/mpas/Makefile.in.CESM +++ b/src/dynamics/mpas/Makefile.in.CESM @@ -1,9 +1,3 @@ -ifeq ($(strip $(CASEROOT)),) - $(warning `CASEROOT` should not be empty. Defaulting to `.`) - - CASEROOT = . -endif - ifeq ($(strip $(LIBROOT)),) $(warning `LIBROOT` should not be empty. Defaulting to `..`) @@ -27,14 +21,9 @@ export GEN_F90 = false export GIT_VERSION = N/A export NAMELIST_SUFFIX = atmosphere -# Read variables (e.g., build options) from `Macros.make`. -include $(CASEROOT)/Macros.make - -# Translate variables (e.g., build options) from `Macros.make` to their equivalent ones used by MPAS build infrastructure. +# Customize variables (e.g., build options) for use with CESM. export AR := ar export ARFLAGS := -M -export CC := $(strip $(MPICC)) -export CFLAGS := $(strip $(CFLAGS)) export CPP := cpp -P -traditional export CPPFLAGS := -D_MPI \ -DMPAS_BUILD_TARGET="$(BUILD_TARGET)" \ @@ -45,20 +34,15 @@ export CPPFLAGS := -D_MPI \ -DMPAS_NAMELIST_SUFFIX="$(NAMELIST_SUFFIX)" \ -DMPAS_NATIVE_TIMERS \ -DMPAS_NO_ESMF_INIT \ - -DMPAS_PIO_SUPPORT \ - -DUSE_PIO2 -export CPPINCLUDES := $(strip $(CPPINCLUDES)) -export CXX := $(strip $(MPICXX)) -export CXXFLAGS := $(strip $(CXXFLAGS)) -export FC := $(strip $(MPIFC)) -export FCINCLUDES := $(strip $(FCINCLUDES)) -export FFLAGS := $(strip $(FC_AUTO_R8) $(FFLAGS) $(FREEFLAGS)) -export LDFLAGS := $(strip $(LDFLAGS)) -export LIBS := $(strip $(LIBS)) -export LINKER := $(strip $(MPIFC)) -export SCC := $(strip $(SCC)) -export SCXX := $(strip $(SCXX)) -export SFC := $(strip $(SFC)) + -DMPAS_PIO_SUPPORT +# `PIODEF` is defined by CIME Makefile (i.e., `cime/CIME/Tools/Makefile`). Its value can be empty or `-DUSE_PIO2`. +ifneq ($(strip $(PIODEF)),) + export CPPFLAGS += $(strip $(PIODEF)) +endif +export LINKER := $(strip $(FC)) +export SCC := $(strip $(CC)) +export SCXX := $(strip $(CXX)) +export SFC := $(strip $(FC)) # # Targets. @@ -68,16 +52,16 @@ export SFC := $(strip $(SFC)) all: @echo 'Supplemental Makefile for MPAS Dynamical Core in CESM' @echo '' - @echo 'Variables (e.g., build options) will be read from `$${CASEROOT}/Macros.make`.' @echo 'MPAS will be built as a static library located at `$${LIBROOT}/libmpas.a`.' + @echo 'Users are responsible to provide all necessary build options via environment variables or command line arguments.' @echo '' @echo 'Usage hints:' - @echo ' `make libmpas-prepare ESM="CESM" CASEROOT="..." LIBROOT="..."`' - @echo ' `make libmpas-build ESM="CESM" CASEROOT="..." LIBROOT="..."`' - @echo ' `make libmpas-clean ESM="CESM" CASEROOT="..." LIBROOT="..."`' + @echo ' `make libmpas-prepare ESM="CESM" LIBROOT="..."`' + @echo ' `make libmpas-build ESM="CESM" LIBROOT="..."`' + @echo ' `make libmpas-clean ESM="CESM" LIBROOT="..."`' .PHONY: libmpas-prepare -libmpas-prepare: libmpas-archiver-script.txt libmpas-no-physics +libmpas-prepare: libmpas-archiver-script.txt libmpas-no-physics libmpas-preview # Combine multiple static libraries into `libmpas.a` via archiver/MRI script. This requires GNU or GNU-like archiver (`ar`) program. libmpas-archiver-script.txt: @@ -93,6 +77,28 @@ libmpas-archiver-script.txt: libmpas-no-physics: @sed -E -i -e "s/^ *PHYSICS=.+$$/PHYSICS=/g" core_atmosphere/Makefile +.PHONY: libmpas-preview +libmpas-preview: + @echo "Previewing build options for $(LIBROOT)/libmpas.a:" + @echo "AR = $(AR)" + @echo "ARFLAGS = $(ARFLAGS)" + @echo "CC = $(CC)" + @echo "CFLAGS = $(CFLAGS)" + @echo "CPP = $(CPP)" + @echo "CPPFLAGS = $(CPPFLAGS)" + @echo "CPPINCLUDES = $(CPPINCLUDES)" + @echo "CXX = $(CXX)" + @echo "CXXFLAGS = $(CXXFLAGS)" + @echo "FC = $(FC)" + @echo "FCINCLUDES = $(FCINCLUDES)" + @echo "FFLAGS = $(FFLAGS)" + @echo "LDFLAGS = $(LDFLAGS)" + @echo "LIBS = $(LIBS)" + @echo "LINKER = $(LINKER)" + @echo "SCC = $(SCC)" + @echo "SCXX = $(SCXX)" + @echo "SFC = $(SFC)" + .PHONY: libmpas-build libmpas-build: $(LIBROOT)/libmpas.a From e8119b9665b9b91ade1e17563ee2669a6e42c674 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Fri, 19 Jan 2024 16:24:14 -0700 Subject: [PATCH 11/12] Switch to use CIME Makefile for building This Makefile catches the `make` command from CIME Makefile and then executes appropriate targets in order. --- src/dynamics/mpas/Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/dynamics/mpas/Makefile diff --git a/src/dynamics/mpas/Makefile b/src/dynamics/mpas/Makefile new file mode 100644 index 00000000..736ecd2c --- /dev/null +++ b/src/dynamics/mpas/Makefile @@ -0,0 +1,9 @@ +# This Makefile is invoked by CIME Makefile (i.e., `cime/CIME/Tools/Makefile`). + +# Some targets in MPAS build infrastructure are sensitive to this environment variable. Override it to avoid build issues. +override PWD = $(CURDIR) +export PWD + +all: + $(MAKE) -f Makefile.CESM libmpas-prepare ESM="CESM" + $(MAKE) -f Makefile.CESM libmpas-build ESM="CESM" From 3a9b8ad2c0ceecf740a60c40dfade1c78eff1f74 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Fri, 19 Jan 2024 16:43:18 -0700 Subject: [PATCH 12/12] Update component configuration Address reviewer's suggestions. --- cime_config/config_component.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 0decd3f0..f18e1860 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -304,9 +304,9 @@ char - -lmpas + -lmusica -ljsonfortran - + -lmpas