#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
# Compile coupler driver and/or data_ocn, data_atm, data_ice
#
# Larry Solheim  ...Mar,2014
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
#
# The following variables may be defined either in the invoking environment
# or on the make command line of the makefile that includes this file.
# These user supplied variables will affect the values of the variables defined above
# All these variables have default values.
#   modver  ...AGCM model version                                (default gcm18)
#   mpi     ...used to define the the update token "MPI"            (default on)
#   coupled ...used to define the the update token "COUPLED"        (default on)
#   cppdefs ...the name of a file containing cpp preprocessor directives
#              (default is CPP_I if that file exists in cwd, undef otherwise)
#   float1  ...used in the determination of the default compiler (default undef)
#              float1=on is the only value that will have any effect
#   openmp  ...used in the determination of the default compiler (default undef)
#              openmp=on is the only value that will have any effect
#   FC      ...the name of the fortran compiler
#              (default depends on other parameters such as float1, openmp, ...)
#   FFLAGS  ...fortran compiler options
#              (default depends on other parameters such as float1, openmp, ...)
#   netcdf  ...used to set compiler options for using netcdf libraries (default on)
#   p5lib   ...used to set compiler options that force the use of a particular set
#              of libraries compatible with an old power5 system       (default off)
#   xlfqinitauto ...used to set compiler options that cause automatic arrays to be
#                   initialzed or not initialized                      (default on)
#                   Other compiler options are also affected by xlfqinitauto
#   xlfimp  ...used to keep or remove the "-qflttrap=imprecise" option from
#              xlf compiler command line options                       (default on)
#   xlflarge...used to add size load options for the xlf compiler      (default off)
#   libdiag ...used to link against the compiled library libLOSUB_diag.a, or variant
#              in addition to other standard compiled libraries        (default off)
#   show_dep_ccrnsrc ...when show_dep_ccrnsrc=on then a list of files from CCRNSRC
#              that are required for the current build will be written to stdout
#              and the program will then stop                          (default off)

# Define an "all" target before including make_defs_cccma.mk
# make_defs_cccma.mk will define targets and if it is included before any targets are defined
# here then the first target the included file defines will become the default target
.PHONY: all
all: cpl_main

# The regrid target cannot use MPI since the regrid executable
# is intended to be run interactively
ifeq ($(findstring regrid,$(MAKECMDGOALS)),regrid)
  export mpi := off
  export coupled := off
endif

# Find all fortran source files in directories specified by SRC_DIRS
# These files will be assigned to the variable FSRC by make_defs_cccma.mk
# and this list will be ordered according to module and include dependenies
# (least dependent first).
# Only the basename of each file will appear in FSRC.
# make_defs_cccma.mk will also write dependency rules into the current makefile
# for any of the files in FSRC that have module or include dependencies
SRC_DIRS := .

# If FSRC is defined here then it is assumed to contain the list of source files
# for which dependencies are to be determined and SRC_DIRS is ignored
# If defined here, file names in FSRC must contain any necessary directory components
# (relative or absolute) to be visible from the directory containing this makefile.
# After being processed by make_defs_cccma.mk FSRC will contain only the
# basename part for each file name in the list.
FSRC := 

ifeq ($(findstring regrid,$(MAKECMDGOALS)),regrid)
  FSRC := regrid.F90
  $(shell sed '/^# *define *use_mpi/d' cpl_cppdefs > tmp_cpl_cppdefs && mv tmp_cpl_cppdefs cpl_cppdefs)
#  $(shell mv tmp_cpl_cppdefs cpl_cppdefs)
endif

# Define commonly used variables and insert dependency rules
# make_defs_cccma.mk will define the following variables
#   MACH_TYPE   ...kernel type on invoking machine
#   MACH_NAME   ...name of invoking machine
#   LOCATION    ...physical location of invoking machine (e.g. cccma, cmc)
#   MODVER      ...the AGCM model version (e.g. gcm16, gcm17, ...)
#   UP2CPP_OPTS ...command line options to be used with up2cpp
#   FC          ...the name of the fortran compiler (e.g. pgf90, mpxlf90, ...)
#   FFLAGS      ...fortran compiler options to use with FC
#   FIXED       ...FC option used to indicate fixed format fortran source
#   FREE        ...FC option used to indicate free format fortran source
#   LISTSRC     ...FC option used to produce a source listing at compile time
#   NETCDF_INCS ...FC options used to locate netcdf includes
#   NETCDF_LIBS ...FC options used to locate netcdf libraries
#   STAMP       ...a date/time string suitable for appending to file names
#   VPATH       ...initialized with CCCma source directories
#   ALL_FSRC    ...a list of all source files and their dependencies
include ../make_defs_cccma.mk

# After being processed in make_defs_cccma.mk
# $(FSRC) will contain the original file list but with any leading pathname component removed

# $(RAW_FSRC) will contain the same list as FSRC but any pathname information
# that is available will be retained

# $(ALL_FSRC) will contain files in FSRC as well as all files containing dependencies
# with any leading pathname component removed. These files will be sorted according to
# dependency with the least dependent files first in the list.

# To link against ESMF libs we need some ESMF specific defs (e.g. ESMF_F90LINKPATHS, ...)
# These are defined in make_defs_cccma.mk if possible

# Identify files containg main programs
MAINS := cpl_main.F90 data_atm.F90 data_ocn.F90 data_ice.F90 regrid.F90

# Redefine ALL_FSRC to eliminate main programs
ALL_FSRC := $(filter-out $(MAINS), $(ALL_FSRC))

$(info In drivers     FSRC = $(FSRC))
$(info In drivers RAW_FSRC = $(RAW_FSRC))
$(info In drivers ALL_FSRC = $(ALL_FSRC))

# Get a list of object files from ALL_FSRC
# Remove all .cdk and .h files except xit2.cdk from the list of object files
INC_SRC := $(filter-out xit2.cdk,$(filter %.cdk %.h,$(ALL_FSRC)))
OBJS := $(filter-out $(ICN_SRC), $(ALL_FSRC))
OBJS := $(patsubst %.f,%.o,   $(patsubst %.F,%.o,   $(OBJS)))
OBJS := $(patsubst %.f90,%.o, $(patsubst %.F90,%.o, $(OBJS)))
OBJS := $(patsubst %.dk,%.o,  $(OBJS)))

# REGRID_LIBS := -L. -lremapper $(LIBS) $(ESMF_F90ESMFLINKLIBS)
REGRID_LIBS := -L. -lregrid $(LIBS) $(ESMF_F90ESMFLINKLIBS)
REGRID_INCS := -I../comm $(INCS) $(ESMF_F90LINKPATHS) $(ESMF_F90LINKRPATHS)

# override is required here because the user may supply a value for LIBS on the command line
override LIBS := -L. -lcplcom $(LIBS)

# Define a location to install main executable programs once compiled
install_dir := ../..

# Define the list of executables that will be installed
EXECS := cpl_main
ifeq ($(findstring regrid,$(MAKECMDGOALS)),regrid)
  # Build the regrid program
  EXECS := regrid
endif
ifeq ($(findstring data,$(MAKECMDGOALS)),data)
  # Include all data executables when "data" appears on the command line
  EXECS := cpl_main data_atm data_ocn data_ice
endif

# Define variables containing compiler command line options required to compile and link
# All ESMF_... variables are defined in the ESMF include file (ESMFMKFILE)
#xxx LINK_OPTS := $(FFLAGS) $(INCS) $(ESMF_F90LINKPATHS) $(ESMF_F90LINKRPATHS) ccc_esmf.o
LINK_OPTS := $(FFLAGS) $(INCS) $(ESMF_F90LINKPATHS) $(ESMF_F90LINKRPATHS)
LINK_LIBS := $(LIBS) $(ESMF_F90ESMFLINKLIBS)

$(info drivers executables $(EXECS))

.PHONY: debug
debug:
	@echo "LIBS     = $(LIBS)"
	@echo "INCS     = $(INCS)"
	@echo "ALL_FSRC = $(ALL_FSRC)"
	@echo "OBJS     = $(OBJS)"

# Invoke SECONDEXPANSION to allow the use of "$@" in the dependency list
# of all targets that appear after this line
.SECONDEXPANSION:

regrid: $$@.F90 regrid_comm
	$(FC) $(FREE) $(FFLAGS) -qtbtable=full -bnoquiet $(REGRID_INCS) $(REGRID_LIBS) -o $@ $@.F90

regrid_comm:
	$(MAKE) -C ../comm regrid install_dir=$(shell pwd)

#xxx cpl_main data_atm data_ocn data_ice: $$@.F90 comlib ccc_esmf
cpl_main: $$@.F90 comlib
ifdef local_cppdefs
	@# Prepend each file with a directive to include cppdefs
	tmpfile=$@_$(STAMP).F90; rm -f $$tmpfile; \
	echo '#include "$(local_cppdefs)"' | cat - $@.F90 > $$tmpfile && \
	$(FC) $(FREE) $(LINK_OPTS) -o $@ $$tmpfile $(LINK_LIBS) && \
	rm -f $$tmpfile
else
	@# Otherwise simply compile the file normally
	$(FC) $(FREE) $(LINK_OPTS) -o $@ $@.F90 $(LINK_LIBS)
endif

# Not sure we want to do this here
#ifdef COUPLER_COMMIT_ID
#	[ -s $@ ] && mv $@ $@_$(shell echo $(COUPLER_COMMIT_ID) | cut -c1-8)
#endif

data_atm data_ocn data_ice: $$@.F90 comlib
ifdef local_cppdefs
	@# Prepend each file with a directive to include cppdefs
	tmpfile=$@_$(STAMP).F90; rm -f $$tmpfile; \
	echo '#include "$(local_cppdefs)"' | cat - $@.F90 > $$tmpfile && \
	$(FC) $(FREE) $(LINK_OPTS) -o $@ $$tmpfile $(LINK_LIBS) && \
	rm -f $$tmpfile
else
	@# Otherwise simply compile the file normally
	$(FC) $(FREE) $(LINK_OPTS) -o $@ $@.F90 $(LINK_LIBS)
endif

data: $(EXECS) chmod_all

comlib:
	@$(MAKE) -C ../comm install install_dir=$(shell pwd)

ccc_esmf: ccc_esmf.o
	@test -s ccc_esmf.mod

install: $(EXECS) chmod_all
	[ -d $(install_dir) ] && cp $(EXECS) $(install_dir)

chmod_all:
	chmod a+rx $(EXECS)

.PHONY: clean veryclean
clean:
	-rm -f *.o *.lst *.mod

veryclean: clean
	-rm -f cpl_main data_atm data_ocn data_ice regrid
