diff --git a/cice.setup b/cice.setup index d8c67f4ca..08a512651 100755 --- a/cice.setup +++ b/cice.setup @@ -847,7 +847,7 @@ echo "${testname_base}" cd ${testname_base} source ./cice.settings set ciceexe = "../ciceexe.\${ICE_COMPILER}.\${ICE_COMMDIR}.\${ICE_BLDDEBUG}.\${ICE_THREADED}.\${ICE_IOTYPE}" -./cice.build \${ciceexe} +./cice.build --exe \${ciceexe} if !(-e \${ciceexe}) cp -p \${ICE_RUNDIR}/cice \${ciceexe} EOF end diff --git a/configuration/scripts/Makefile b/configuration/scripts/Makefile index 362397b1d..3c7857c21 100644 --- a/configuration/scripts/Makefile +++ b/configuration/scripts/Makefile @@ -8,7 +8,6 @@ # SRCS= ~ list of src files, default is all .c .F .F90 files in VPATH # VPFILE= ~ file with list of dirs, used to create VPATH # SRCFILE= ~ file with list of src files, used to create SRCS -# DEPGEN= ~ dependency generator utility, default is makdep # # ~ any macro definitions found in this file or the included # MACFILE will be over-riden by cmd-line macro definitions @@ -31,7 +30,9 @@ VPFILE := NONE VPATH := . SRCFILE := NONE SRCS := NONE -DEPGEN := ./makdep # an externally provided dependency generator + +# dependency generator +DEPGEN := ./makdep ifneq ($(VPATH),.) # this variable was specified on cmd line or in an env var @@ -58,26 +59,33 @@ endif OBJS := $(addsuffix .o, $(sort $(basename $(notdir $(SRCS))))) DEPS := $(addsuffix .d, $(sort $(basename $(notdir $(SRCS))))) INCS := $(patsubst %,-I%, $(VPATH) ) +OBJS_DEPGEN := $(addprefix $(ICE_CASEDIR)/,$(addsuffix .c, $(notdir $(DEPGEN)))) +MODDIR:= -I. RM := rm .SUFFIXES: .SUFFIXES: .F90 .F .c .o +.PHONY: all cice targets target db_files db_flags clean realclean all: $(EXEC) +cice: $(EXEC) + #------------------------------------------------------------------------------- # include the file that provides macro definitions required by build rules -# note: the MACFILE may not be needed for certain goals #------------------------------------------------------------------------------- -ifneq ($(MAKECMDGOALS), db_files) - -include $(MACFILE) -endif +-include $(MACFILE) #------------------------------------------------------------------------------- -# echo file names, paths, compile flags, etc. used during build +# echo supported targets, file names, paths, compile flags, etc. used during build #------------------------------------------------------------------------------- +targets: + @echo " " + @echo "Supported Makefile Targets are: cice, makdep, depends, clean, realclean, targets, db_files, db_flags" +target: targets + db_files: @echo " " @echo "* EXEC := $(EXEC)" @@ -89,12 +97,22 @@ db_files: @echo "* SRCS := $(SRCS)" @echo "* OBJS := $(OBJS)" @echo "* DEPS := $(DEPS)" + @echo "* ULIBS := $(ULIBS)" + @echo "* SLIBS := $(SLIBS)" + @echo "* INCLDIR := $(INCLDIR)" + @echo "* OBJS_DEPGEN := $(OBJS_DEPGEN)" db_flags: @echo " " - @echo "* cpp := $(CPP) $(CPPFLAGS) $(CPPDEFS) $(INCS) $(INCLDIR)" - @echo "* cc := $(CC) -c $(CFLAGS) $(INCS) $(INCLDIR)" - @echo "* .F.o := $(FC) -c $(FFLAGS) $(FIXEDFLAGS) $(INCS) $(INCLDIR)" - @echo "* .F90.o := $(FC) -c $(FFLAGS) $(FREEFLAGS) $(INCS) $(INCLDIR)" + @echo "* $(DEPGEN) := $(SCC) $(CFLAGS_HOST)" + @echo "* %.d : %.c := $(DEPGEN) $(INCS)" + @echo "* %.d : %.F := $(DEPGEN) $(INCS)" + @echo "* %.d : %.F90 := $(DEPGEN) $(INCS)" + @echo "* %.d : %.H := $(DEPGEN) $(INCS)" + @echo "* cpp := $(CPP) $(CPPFLAGS) $(CPPDEFS) $(INCLDIR)" + @echo "* .c.o := $(CC) $(CFLAGS) $(CPPDEFS) $(INCLDIR)" + @echo "* .F.o := $(FC) -c $(FFLAGS) $(FIXEDFLAGS) $(CPPDEFS) $(INCLDIR)" + @echo "* .F90.o := $(FC) -c $(FFLAGS) $(FREEFLAGS) $(CPPDEFS) $(MODDIR) $(INCLDIR)" + @echo "* $(notdir $(EXEC)) := $(LD) $(LDFLAGS) $(ULIBS) $(SLIBS)" #------------------------------------------------------------------------------- # build rule for makdep: MACFILE, cmd-line, or env vars must provide @@ -105,7 +123,8 @@ ifndef $(CFLAGS_HOST) CFLAGS_HOST := endif -$(DEPGEN): $(ICE_CASEDIR)/makdep.c +$(DEPGEN): $(OBJS_DEPGEN) + @ echo "Building makdep" $(SCC) -o $@ $(CFLAGS_HOST) $< #------------------------------------------------------------------------------- @@ -116,29 +135,25 @@ $(EXEC): $(OBJS) $(LD) -o $(EXEC) $(LDFLAGS) $(OBJS) $(ULIBS) $(SLIBS) .c.o: - $(CC) $(CFLAGS) $(CPPDEFS) $(INCS) $(INCLDIR) $< + $(CC) $(CFLAGS) $(CPPDEFS) $(INCLDIR) $< .F.o: - $(FC) -c $(FFLAGS) $(FIXEDFLAGS) $(CPPDEFS) $(INCS) $(INCLDIR) $< + $(FC) -c $(FFLAGS) $(FIXEDFLAGS) $(CPPDEFS) $(INCLDIR) $< .F90.o: - $(FC) -c $(FFLAGS) $(FREEFLAGS) $(CPPDEFS) $(INCS) $(INCLDIR) $< - -mostlyclean: - $(RM) -f *.f *.f90 + $(FC) -c $(FFLAGS) $(FREEFLAGS) $(CPPDEFS) $(MODDIR) $(INCLDIR) $< clean: - $(RM) -f *.f *.f90 *.d *.mod *.o $(EXEC) -# $(RM) -f *.f *.f90 *.d *.$(MOD_SUFFIX) $(OBJS) + $(RM) -f *.o *.d *.mod $(EXEC) -realclean: - $(RM) -f *.f *.f90 *.d *.$(MOD_SUFFIX) $(OBJS) $(EXEC) +realclean: clean + $(RM) -f $(DEPGEN) #------------------------------------------------------------------------------- # Build & include dependency files #------------------------------------------------------------------------------- # ASSUMPTIONS: -# o an externally provided dependency generator, $(DEPGEN), is available, +# o the dependency generator, $(DEPGEN), can be built, # its cmd line syntax is compatible with the build rules below. Eg, for # each .o file, there is a corresponding .d (dependency) file, and both # will be dependent on the same src file, eg. foo.o foo.d : foo.F90 @@ -146,28 +161,36 @@ realclean: # are understood & accepted. #------------------------------------------------------------------------------- -%.d : %.c +depends: $(DEPS) + +%.d : %.c $(DEPGEN) @ echo "Building dependency for $@" @ $(DEPGEN) -f $(INCS) $< | head -3 > $@ -%.d : %.F +%.d : %.F $(DEPGEN) @ echo "Building dependency for $@" @ $(DEPGEN) -f $(INCS) $< > $@ -%.d : %.F90 +%.d : %.F90 $(DEPGEN) @ echo "Building dependency for $@" @ $(DEPGEN) -f $(INCS) $< > $@ -%.d : %.H +%.d : %.H $(DEPGEN) @ echo "Building dependency for $@" @ $(DEPGEN) -f $(INCS) $< > $@ # the if-tests prevent DEPS files from being created when they're not needed ifneq ($(MAKECMDGOALS), db_files) ifneq ($(MAKECMDGOALS), db_flags) -ifneq ($(MAKECMDGOALS), mostlyclean) ifneq ($(MAKECMDGOALS), clean) ifneq ($(MAKECMDGOALS), realclean) +ifneq ($(MAKECMDGOALS), targets) +ifneq ($(MAKECMDGOALS), target) +ifneq ($(MAKECMDGOALS), makdep) +ifneq ($(MAKECMDGOALS), depends) -include $(DEPS) endif endif endif endif endif +endif +endif +endif diff --git a/configuration/scripts/cice.build b/configuration/scripts/cice.build index 62ea6c447..61d639e09 100755 --- a/configuration/scripts/cice.build +++ b/configuration/scripts/cice.build @@ -4,29 +4,93 @@ # If the cice binary is passed as an argument and the file exists, # copy it into the run directory and don't build the model. +set dohelp = 0 +set directmake = 0 +set target = "UnDEFineD" set ciceexe = "UnDEFineD" -if ($#argv == 1) then - set ciceexe = $1 - echo "${0}: ciceexe = ${ciceexe}" - if (-e ${ciceexe}) then - - source ./cice.settings - source ${ICE_CASEDIR}/env.${ICE_MACHCOMP} -nomodules || exit 2 - if !(-d ${ICE_RUNDIR}) mkdir -p ${ICE_RUNDIR} - cp -p ${ciceexe} ${ICE_RUNDIR}/cice - - echo "`date` ${0}:${ICE_CASENAME} build copied ${ciceexe}" >> ${ICE_CASEDIR}/README.case - if ( ${ICE_TEST} != ${ICE_SPVAL} ) then - echo "#---" >! ${ICE_CASEDIR}/test_output - echo "COPY ${ICE_TESTNAME} build" >> ${ICE_CASEDIR}/test_output - echo "PEND ${ICE_TESTNAME} run" >> ${ICE_CASEDIR}/test_output +if ($#argv == 0) then + # continue, standard way to build +else + # -h, --help + if ("$1" == "-h" || "$1" == "--help") then + set dohelp = 1 + + # --exe + else if ("$1" == "--exe") then + if ($#argv > 2) then + echo "${0}: ERROR: --exe ciceexe without other arguments is required" + exit -99 + endif + set ciceexe = $2 + echo "${0}: ciceexe = ${ciceexe}" + if (-e ${ciceexe}) then + + source ./cice.settings + source ${ICE_CASEDIR}/env.${ICE_MACHCOMP} -nomodules || exit 2 + if !(-d ${ICE_RUNDIR}) mkdir -p ${ICE_RUNDIR} + cp -p ${ciceexe} ${ICE_RUNDIR}/cice + + echo "`date` ${0}:${ICE_CASENAME} build copied ${ciceexe}" >> ${ICE_CASEDIR}/README.case + if ( ${ICE_TEST} != ${ICE_SPVAL} ) then + echo "#---" >! ${ICE_CASEDIR}/test_output + echo "COPY ${ICE_TESTNAME} build" >> ${ICE_CASEDIR}/test_output + echo "PEND ${ICE_TESTNAME} run" >> ${ICE_CASEDIR}/test_output + endif + + exit 0 endif - exit 0 - + # direct make with target + else + set directmake = 1 + set target = "$*" endif endif +if (${dohelp} == 1) then + cat << EOF1 + +NAME + cice.build [-h,--help] [make arguments] [target] + +SYNOPSIS + -h || --help + [make arguments] [target] + +DESCRIPTION + --help, -h : help + [make arguments] [target] : specify make arguments and target + +EXAMPLES + cice.build + will build the model using the standard approach with all the bells and whistles. + This is recommended. + cice.build --help + will show cice.build help + cice.build [target] + will call gmake directly and make the target + cice.build clean + is an example of a targeted build + cice.build targets + is an example of a targeted build that shows the valid Makefile targets + cice.build --version + will call make directly and pass --version as an argument to make + cice.build [make arguments] [target] + will call make directly and pass arguments and/or a target to make + +ADDITIONAL INFORMATION + The argument implementation supports -h or --help as a first argument. Otherwise, + it passes all other arguments directly to make and calls it directly. In this + mode, most of the cice.build script features are by-passed. The recommended + way to run the script is without arguments. + +SEE ALSO + User Documentation at https://github.com/cice-consortium/cice/ + +EOF1 +exit -99 +endif + #==================================== source ./cice.settings @@ -47,10 +111,7 @@ set stamp = `date '+%y%m%d-%H%M%S'` set ICE_BLDLOG_FILE = "cice.bldlog.${stamp}" set quiet = ${ICE_QUIETMODE} -if (${ICE_CLEANBUILD} == 'true') then - echo "cleaning objdir" - rm -r -f ${ICE_OBJDIR} -endif +if !(-d ${ICE_RUNDIR}) mkdir -p ${ICE_RUNDIR} if !(-d ${ICE_OBJDIR}) mkdir -p ${ICE_OBJDIR} cd ${ICE_OBJDIR} @@ -79,6 +140,22 @@ ${ICE_SANDBOX}/cicecore/shared ${ICE_SANDBOX}/icepack/columnphysics EOF +if !($?ICE_MACHINE_BLDTHRDS) then + set ICE_MACHINE_BLDTHRDS = 1 +endif + +if (${directmake} == 1) then + echo "make ${target}" + ${ICE_MACHINE_MAKE} -j ${ICE_MACHINE_BLDTHRDS} VPFILE=Filepath EXEC=${ICE_RUNDIR}/cice \ + -f ${ICE_CASEDIR}/Makefile MACFILE=${ICE_CASEDIR}/Macros.${ICE_MACHCOMP} ${target} + set bldstat = ${status} + if (${bldstat} != 0) then + echo "${0}: targeted make FAILED" + exit -99 + endif + exit 0 +endif + echo " " echo ICE_GRID = ${ICE_GRID} echo ICE_NTASK = ${ICE_NTASKS} @@ -88,16 +165,7 @@ echo "Filepath = " cat ${ICE_OBJDIR}/Filepath echo " " -echo "building makdep" -${ICE_MACHINE_MAKE} \ - -f ${ICE_CASEDIR}/Makefile MACFILE=${ICE_CASEDIR}/Macros.${ICE_MACHCOMP} makdep || exit 2 - echo "building cice > ${ICE_OBJDIR}/${ICE_BLDLOG_FILE}" - -if !(-d ${ICE_RUNDIR}) mkdir -p ${ICE_RUNDIR} -if !($?ICE_MACHINE_BLDTHRDS) then - set ICE_MACHINE_BLDTHRDS = 1 -endif if (-e ${ICE_BLDLOG_FILE}) rm ${ICE_BLDLOG_FILE} if (${ICE_CLEANBUILD} == 'true') then diff --git a/doc/source/developer_guide/dg_scripts.rst b/doc/source/developer_guide/dg_scripts.rst index 525f2f1ab..cf06db64e 100755 --- a/doc/source/developer_guide/dg_scripts.rst +++ b/doc/source/developer_guide/dg_scripts.rst @@ -90,6 +90,13 @@ The machine is built by the cice.build script which invokes Make. There is a special trap for circular dependencies in the cice.build script to highlight this error when it occurs. +The **cice.build** script has some additional features including the ability to +pass a Makefile target. This is documented in :ref:`cicebuild`. In addition, there +is a hidden feature in the **cice.build** script that allows for reuse of +executables. This is used by the test suites to significantly reduce cost of +building the model. It is invoked with the ``--exe`` argument to **cice.build** +and should not be invoked by users interactively. + .. _dev_machines: Machines diff --git a/doc/source/user_guide/ug_running.rst b/doc/source/user_guide/ug_running.rst index 923e3c90c..d4df62144 100644 --- a/doc/source/user_guide/ug_running.rst +++ b/doc/source/user_guide/ug_running.rst @@ -121,7 +121,7 @@ Once a case/test is created, several files are placed in the case directory - **makdep.c** is a tool that will automatically generate the make dependencies - **Macros.[machine]** defines the Makefile macros - **Makefile** is the makefile used to build the model -- **cice.build** is a script that builds and compiles the model +- **cice.build** is a script that calls the Makefile and compiles the model - **ice\_in** is the namelist input file - **setup\_run\_dirs.csh** is a script that will create the run directories. This will be called automatically from the **cice.run** script if the user does not invoke it. - **cice.run** is a batch run script @@ -161,7 +161,7 @@ case directory, NOT the run directory. .. _case_options: -Command Line Options +**cice.setup** Command Line Options ~~~~~~~~~~~~~~~~~~~~ ``cice.setup -h`` provides a summary of the command line options. There are three different modes, ``--case``, ``--test``, and ``--suite``. This section provides details about the relevant options for setting up cases with examples. @@ -267,6 +267,84 @@ To add some optional settings, one might do:: Once the cases are created, users are free to modify the cice.settings and ice_in namelist to further modify their setup. +.. _cicebuild: + +More about **cice.build** +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**cice.build** is copied into the case directory and should be run interactively from the +case directory to build the model. CICE is built with make and there is a generic +Makefile and a machine specific Macros file in the case directory. **cice.build** +is a wrapper for a call to make that includes several other features. + +CICE is built as follows. First, the makdep binary is created by compiling a small +C program. The makdep binary is then run and dependency files are created. The dependency +files are included into the Makefile automatically. As a result, make dependencies do not +need to be explicitly defined by the user. In the next step, make compiles the CICE +code and generates the cice binary. + +The standard and recommended way to run is with +no arguments +:: + + cice.build + +However, **cice.build** does support a couple other use modes. +:: + + cice.build [-h|--help] + +provides a summary of the usage. +:: + + cice.build [make arguments] [target] + +turns off most of the features of the cice.build script and turns it into a wrapper +for the make call. The arguments and/or target are passed to make and invoked more +or less like make [make arguments] [target]. This will be the case if either or +both the arguments or target are passed to cice.build. Some examples of that are +:: + + cice.build --version + +which will pass --version to make. +:: + + cice.build targets + +is a valid target of the CICE Makefile and simply echos all the valid +targets of the Makefile. +:: + + cice.build cice + +or :: + + cice.build all + +are largely equivalent to running **cice.build** without an argument, +although as noted earlier, many of the extra features of the cice.build script +are turned off when calling cice.build with a target or an argument. Any of the +full builds will compile makdep, generate the source code dependencies, and +compile the source code. +:: + + cice.build [clean|realclean] + cice.build [db_files|db_flags] + cice.build [makdep|depends] + +are other valid options for cleaning the build, writing out information about +the Makefile setup, and building just the makdep tool or the dependency file. +It is also possible to target a particular CICE object file. + +Finally, there is one important parameter in **cice.settings**. The ``ICE_CLEANBUILD`` +variable defines whether the model is cleaned before a build is carried out. By +default, this variable is true which means each invokation of **cice.build** will +automatically clean the prior build. If incremental builds are desired to save +time during development, the ``ICE_CLEANBUILD`` setting in **cice.settings** should +be modified. + + .. _porting: Porting