clm5/cime_config/buildlib
2024-05-09 15:14:01 +08:00

198 lines
7.8 KiB
Python

#!/usr/bin/env python3
"""
build ctsm library
"""
import sys, os
_CIMEROOT = os.environ.get("CIMEROOT")
if _CIMEROOT is None:
raise SystemExit("ERROR: must set CIMEROOT environment variable")
_LIBDIR = os.path.join(_CIMEROOT, "CIME", "Tools")
sys.path.append(_LIBDIR)
from standard_script_setup import *
from CIME.buildlib import parse_input
from CIME.build import get_standard_makefile_args
from CIME.case import Case
from CIME.utils import run_cmd, expect
logger = logging.getLogger(__name__)
###############################################################################
def _write_ctsm_mk(gmake, gmake_opts, makefile, exeroot, libroot):
"""Writes a ctsm.mk file in exeroot.
This file can be included by atmosphere model builds outside of cime.
"""
cime_output_file = os.path.join(exeroot, "cime_variables.mk")
# Set COMP_NAME=driver because some link flags are set differently when COMP_NAME=driver, and
# those are the ones we want here.
cmd = (
"{gmake} write_include_and_link_flags OUTPUT_FILE={cime_output_file} "
"COMP_NAME=driver {gmake_opts} -f {makefile} "
).format(
gmake=gmake,
cime_output_file=cime_output_file,
gmake_opts=gmake_opts,
makefile=makefile,
)
rc, out, err = run_cmd(cmd)
logger.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n" % (cmd, out, err))
expect(rc == 0, "Command %s failed with rc=%s" % (cmd, rc))
ctsm_mk_path = os.path.join(exeroot, "ctsm.mk")
with open(ctsm_mk_path, "w") as ctsm_mk:
ctsm_mk.write(
"""
# ======================================================================
# Include this file to get makefile variables needed to include / link
# LILAC/CTSM in an atmosphere model's build
#
# Variables of interest are:
# - CTSM_INCLUDES: add this to the compilation line
# - CTSM_LIBS: add this to the link line
# ======================================================================
# ======================================================================
# The following CIME variables are meant for internal use, and generally
# should not be included directly in an atmosphere model's build.
# ======================================================================
"""
)
with open(cime_output_file) as infile:
ctsm_mk.write(infile.read())
ctsm_bld_dir = os.path.abspath(os.path.join(libroot, os.pardir))
with open(ctsm_mk_path, "a") as ctsm_mk:
ctsm_mk.write(
"""
# ======================================================================
# The following settings are meant for internal use, and generally
# should not be included directly in an atmosphere model's build.
# NOTE: clm library name and subdirectory will eventually need to
# be updated to ctsm.
# ======================================================================
CTSM_BLD_DIR = {ctsm_bld_dir}
CTSM_INC = $(CTSM_BLD_DIR)/clm/obj
# ======================================================================
# The following settings should be included in an atmosphere model's build.
# ======================================================================
CTSM_INCLUDES = $(CIME_ESMF_F90COMPILEPATHS) -I$(CIME_CSM_SHR_INCLUDE) -I$(CTSM_INC)
CTSM_LIBS = -L$(CTSM_BLD_DIR)/lib -lclm $(CIME_ULIBS) $(CIME_SLIBS) $(CIME_MLIBS) $(CIME_F90_LDFLAGS)
""".format(
ctsm_bld_dir=ctsm_bld_dir
)
)
###############################################################################
def _main_func():
###############################################################################
caseroot, libroot, bldroot = parse_input(sys.argv)
with Case(caseroot) as case:
casetools = case.get_value("CASETOOLS")
makefile = os.path.join(casetools, "Makefile")
lnd_root = case.get_value("COMP_ROOT_DIR_LND")
gmake_j = case.get_value("GMAKE_J")
gmake = case.get_value("GMAKE")
gmake_opts = get_standard_makefile_args(case)
driver = case.get_value("COMP_INTERFACE").lower()
lilac_mode = case.get_value("LILAC_MODE")
if lilac_mode == "on":
driver = "lilac"
# -------------------------------------------------------
# create Filepath file
# -------------------------------------------------------
compname = case.get_value("COMP_LND")
filepath_file = os.path.join(bldroot, "Filepath")
if not os.path.isfile(filepath_file):
caseroot = case.get_value("CASEROOT")
expect(
((compname == "clm") or (compname == "ctsm")),
"Unexpected COMP_LND name: %s" % (compname),
)
paths = [
os.path.join(caseroot, "SourceMods", "src." + compname),
os.path.join(lnd_root, "src", "cpl", driver),
os.path.join(lnd_root, "src", "main"),
os.path.join(lnd_root, "src", "biogeophys"),
os.path.join(lnd_root, "src", "biogeochem"),
os.path.join(lnd_root, "src", "soilbiogeochem"),
os.path.join(lnd_root, "src", "dyn_subgrid"),
os.path.join(lnd_root, "src", "init_interp"),
os.path.join(lnd_root, "src", "self_tests"),
os.path.join(lnd_root, "src", "fates"),
os.path.join(lnd_root, "src", "fates", "main"),
os.path.join(lnd_root, "src", "fates", "biogeophys"),
os.path.join(lnd_root, "src", "fates", "biogeochem"),
os.path.join(lnd_root, "src", "fates", "fire"),
os.path.join(lnd_root, "src", "fates", "parteh"),
os.path.join(lnd_root, "src", "fates", "radiation"),
os.path.join(lnd_root, "src", "utils"),
os.path.join(lnd_root, "src", "cpl"),
os.path.join(lnd_root, "src", "cpl", "utils"),
]
if lilac_mode == "on":
paths.append(os.path.join(lnd_root, "lilac", "src"))
# If we want to build with a real river model (e.g., MOSART), we'll need
# to use its directories in place of stub_rof
paths.append(os.path.join(lnd_root, "lilac", "stub_rof"))
if driver == "lilac" or driver == "nuopc":
paths.append(os.path.join(lnd_root, "src", "cpl", "share_esmf"))
with open(filepath_file, "w") as filepath:
filepath.write("\n".join(paths))
filepath.write("\n")
# -------------------------------------------------------
# create the library in libroot
# -------------------------------------------------------
complib = os.path.join(libroot, "lib%s.a" % (compname))
cmd = "{} complib -j {} COMP_NAME={} COMPLIB={} -f {} {}".format(
gmake, gmake_j, compname, complib, makefile, gmake_opts
)
rc, out, err = run_cmd(cmd)
logger.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n" % (cmd, out, err))
expect(rc == 0, "Command %s failed with rc=%s" % (cmd, rc))
# ------------------------------------------------------------------------
# for lilac usage, we need a file containing some Makefile variables (for the atmosphere model's build)
# ------------------------------------------------------------------------
if lilac_mode == "on":
_write_ctsm_mk(
gmake=gmake,
gmake_opts=gmake_opts,
makefile=makefile,
exeroot=case.get_value("EXEROOT"),
libroot=libroot,
)
###############################################################################
if __name__ == "__main__":
logger.warning(
"WARNING: buildlib is being called as a program rather than a subroutine as "
+ "it is expected to be in the CESM context"
)
_main_func()