diff --git a/Makefile.am b/Makefile.am index 9254d916e5..42cd7edbd1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -115,5 +115,16 @@ include $(top_srcdir)/mkmods.mk # -rm -f FMSConfig.cmake FMSConfigVersion.cmake EXTRA_DIST = README.md #_package_init_cmake + +if COV +check-code-coverage: check + -cd ${top_builddir}/test_fms && chmod +x intel_coverage.sh && ./intel_coverage.sh + +.PHONY: check-code-coverage + +clean-local: + -rm -rf .mods coverage-data coverage-report +else clean-local: -rm -rf .mods +endif diff --git a/configure.ac b/configure.ac index cc1367ccb8..a552ae33bc 100644 --- a/configure.ac +++ b/configure.ac @@ -79,6 +79,12 @@ AC_ARG_ENABLE([setting-flags], AS_IF([test ${enable_setting_flags:-yes} = yes], [enable_setting_flags=yes], [enable_setting_flags=no]) +AC_ARG_ENABLE([code-coverage], + [AS_HELP_STRING([--enable-code-coverage], + [Allow configure to set flags and add check-code-coverage target for code coverage analysis (Default no)])]) +AS_IF([test ${enable_code_coverage:-no} = no], + [enable_code_coverage=no], + [enable_code_coverage=yes]) # Does the user want to build documentation? AC_MSG_CHECKING([whether documentation should be build (requires doxygen)]) @@ -174,6 +180,16 @@ if test $with_mpi = yes; then GX_FC_CHECK_MOD([mpi], [], [], [AC_MSG_ERROR([Can't find the MPI Fortran module. Set FC/CPPFLAGS/FCFLAGS])]) AC_CHECK_FUNC([MPI_init], [], [AC_MSG_ERROR([Can't find the MPI Fortran library. Set FC/LDFLAGS/LIBS])]) fi +# check intel compiler and coverage tools are avaiable if code coverage is enabled +if test "$enable_code_coverage" = yes; then + if test ! -z "`$FC --version | grep ifort`"; then + AC_CHECK_PROGS([PROFMERGE],[profmerge]) + AC_CHECK_PROGS([CODECOV], [codecov]) + else + AC_MSG_ERROR([Intel compiler and coverage tools required for coverage report]) + fi +fi +AM_CONDITIONAL(COV, [test "$enable_code_coverage" = yes]) # Require netCDF GX_FC_CHECK_MOD([netcdf], [], [], [AC_MSG_ERROR([Can't find the netCDF Fortran module. Set CPPFLAGS/FCFLAGS])]) @@ -238,6 +254,12 @@ if test $enable_setting_flags = yes; then if test ! -z "$OPENMP_FCFLAGS"; then FCFLAGS="$FCFLAGS $OPENMP_FCFLAGS" fi + + # Add code coverage flags + if test $enable_code_coverage = yes; then + FCFLAGS="$FCFLAGS -prof-gen=srcpos" + CFLAGS="$CFLAGS -prof-gen=srcpos" + fi fi # Define an AM_CONDITIONAL to determine if you are on a CRAY @@ -358,6 +380,7 @@ AC_CONFIG_FILES([ docs/Makefile parser/Makefile test_fms/test_common.sh + test_fms/intel_coverage.sh test_fms/Makefile test_fms/diag_manager/Makefile test_fms/data_override/Makefile diff --git a/mkmods.mk b/mkmods.mk index e433f4a23b..1508528763 100644 --- a/mkmods.mk +++ b/mkmods.mk @@ -6,4 +6,4 @@ SUFFIXES = .$(FC_MODEXT) _mod.$(FC_MODEXT) $(PPFCCOMPILE) -c $< @cp $(MODDIR)/$@ . -CLEANFILES = *.$(FC_MODEXT) $(BUILT_SOURCES:%=$(MODDIR)/%) *__genmod.$(FC_MODEXT) *__genmod.f90 +CLEANFILES = *.$(FC_MODEXT) $(BUILT_SOURCES:%=$(MODDIR)/%) *__genmod.$(FC_MODEXT) *__genmod.f90 *.dyn *.spi *.dpi *.spl diff --git a/test_fms/Makefile.am b/test_fms/Makefile.am index 639a69c5b0..b691ce9096 100644 --- a/test_fms/Makefile.am +++ b/test_fms/Makefile.am @@ -30,4 +30,4 @@ horiz_interp field_manager axis_utils affinity fms2_io parser # This input file must be distributed, it is turned into # test_common.sh by configure. -EXTRA_DIST = test_common.sh.in +EXTRA_DIST = test_common.sh.in intel_coverage.sh.in diff --git a/test_fms/affinity/Makefile.am b/test_fms/affinity/Makefile.am index 6d94e593f4..e5f4996a67 100644 --- a/test_fms/affinity/Makefile.am +++ b/test_fms/affinity/Makefile.am @@ -41,4 +41,4 @@ TESTS = test_affinity2.sh EXTRA_DIST = input_base.nml test_affinity2.sh # Clean up -CLEANFILES = input.nml *.out* +CLEANFILES = input.nml *.out* *.dpi *.spi *.dyn *.spl diff --git a/test_fms/axis_utils/Makefile.am b/test_fms/axis_utils/Makefile.am index f514855e6d..2985efcbb1 100644 --- a/test_fms/axis_utils/Makefile.am +++ b/test_fms/axis_utils/Makefile.am @@ -41,4 +41,4 @@ TESTS = test_axis_utils2.sh EXTRA_DIST = test_axis_utils2.sh # Clean up -CLEANFILES = input.nml *.out* *.nc* +CLEANFILES = input.nml *.out* *.nc* *.dpi *.spi *.dyn *.spl diff --git a/test_fms/coupler/Makefile.am b/test_fms/coupler/Makefile.am index 68411531a6..a6665be6e5 100644 --- a/test_fms/coupler/Makefile.am +++ b/test_fms/coupler/Makefile.am @@ -42,4 +42,4 @@ TESTS = test_coupler.sh EXTRA_DIST = test_coupler.sh # Clean up -CLEANFILES = input.nml *.nc* *.out +CLEANFILES = input.nml *.nc* *.out *.dpi *.spi *.dyn *.spl diff --git a/test_fms/data_override/Makefile.am b/test_fms/data_override/Makefile.am index 7564bec265..23017e088b 100644 --- a/test_fms/data_override/Makefile.am +++ b/test_fms/data_override/Makefile.am @@ -44,4 +44,4 @@ EXTRA_DIST = input_base.nml diag_table_base data_table_base \ test_data_override2.sh # Clean up -CLEANFILES = input.nml *.nc* *.out diag_table data_table data_table.yaml +CLEANFILES = input.nml *.nc* *.out diag_table data_table data_table.yaml *.dpi *.spi *.dyn *.spl diff --git a/test_fms/diag_manager/Makefile.am b/test_fms/diag_manager/Makefile.am index cf5d063e7b..a0429e49bb 100644 --- a/test_fms/diag_manager/Makefile.am +++ b/test_fms/diag_manager/Makefile.am @@ -40,4 +40,4 @@ TESTS = test_diag_manager2.sh # Copy over other needed files to the srcdir EXTRA_DIST = input.nml_base diagTables test_diag_manager2.sh -CLEANFILES = input.nml *.nc *.out diag_table +CLEANFILES = input.nml *.nc *.out diag_table *.dpi *.spi *.dyn *.spl diff --git a/test_fms/drifters/Makefile.am b/test_fms/drifters/Makefile.am index 2addf4aad9..378658c29a 100644 --- a/test_fms/drifters/Makefile.am +++ b/test_fms/drifters/Makefile.am @@ -50,4 +50,4 @@ EXTRA_DIST = input_base.nml drifters_inp_test_3d.cdl \ test_drifters2.sh # Clean up -CLEANFILES = *out *__genmod.mod *__genmod.f90 input.nml *.nc +CLEANFILES = *out *__genmod.mod *__genmod.f90 input.nml *.nc *.dpi *.spi *.dyn *.spl diff --git a/test_fms/exchange/Makefile.am b/test_fms/exchange/Makefile.am index ff7c05756b..e13c19fdd7 100644 --- a/test_fms/exchange/Makefile.am +++ b/test_fms/exchange/Makefile.am @@ -41,4 +41,4 @@ TESTS = test_xgrid2.sh EXTRA_DIST = input_base.nml test_xgrid2.sh # Clean up -CLEANFILES = input.nml *.nc *.out +CLEANFILES = input.nml *.nc *.out *.dpi *.spi *.dyn *.spl diff --git a/test_fms/field_manager/Makefile.am b/test_fms/field_manager/Makefile.am index 6110149168..33beb1da33 100644 --- a/test_fms/field_manager/Makefile.am +++ b/test_fms/field_manager/Makefile.am @@ -41,4 +41,4 @@ TESTS = test_field_manager2.sh EXTRA_DIST = test_field_manager2.sh input_base.nml field_table_base # Clean up -CLEANFILES = input.nml *.out* field_table +CLEANFILES = input.nml *.out* field_table *.dpi *.spi *.dyn *.spl diff --git a/test_fms/fms/Makefile.am b/test_fms/fms/Makefile.am index 3e60cfff6c..05594fb439 100644 --- a/test_fms/fms/Makefile.am +++ b/test_fms/fms/Makefile.am @@ -39,7 +39,7 @@ TESTS = test_fms2.sh # These will also be included in the distribution. EXTRA_DIST = test_fms2.sh -CLEANFILES = input.nml logfile.*.out *.mod *.o +CLEANFILES = input.nml logfile.*.out *.mod *.o *.dpi *.spi *.dyn *.spl clean-local: rm -rf RESTART diff --git a/test_fms/fms2_io/Makefile.am b/test_fms/fms2_io/Makefile.am index a9624914ad..d6629dd6ad 100644 --- a/test_fms/fms2_io/Makefile.am +++ b/test_fms/fms2_io/Makefile.am @@ -63,4 +63,4 @@ TESTS = test_bc_restart.sh test_fms2_io.sh test_atmosphere_io.sh test_io_simple. # Set srcdir as evironment variable to be reference in the job script TESTS_ENVIRONMENT = srcdir="$(top_srcdir)"; -CLEANFILES = *.mod *.nc *.nc.* input.nml logfile.000000.out the_mask ascii_test1 +CLEANFILES = *.mod *.nc *.nc.* input.nml logfile.000000.out the_mask ascii_test1 *.dpi *.spi *.dyn *.spl diff --git a/test_fms/horiz_interp/Makefile.am b/test_fms/horiz_interp/Makefile.am index d2bb8a8545..37141ebee6 100644 --- a/test_fms/horiz_interp/Makefile.am +++ b/test_fms/horiz_interp/Makefile.am @@ -41,4 +41,4 @@ TESTS = test_horiz_interp2.sh EXTRA_DIST = input_base.nml test_horiz_interp2.sh # Clean up -CLEANFILES = input.nml *.out* +CLEANFILES = input.nml *.out* *.dpi *.spi *.dyn *.spl diff --git a/test_fms/intel_coverage.sh.in b/test_fms/intel_coverage.sh.in new file mode 100755 index 0000000000..bc452277be --- /dev/null +++ b/test_fms/intel_coverage.sh.in @@ -0,0 +1,89 @@ +#!/usr/bin/sh +#*********************************************************************** +# GNU Lesser General Public License +# +# This file is part of the GFDL Flexible Modeling System (FMS). +# +# FMS is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or (at +# your option) any later version. +# +# FMS is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with FMS. If not, see . +#*********************************************************************** +# Produces a code coverage report for each subdirectory using intel's codecov tool +# runs with `make check-code-coverage` after configuring with `--enable-code-coverage` + +# Ryan Mulhall 1/26/21 + +merge_dpis () { + + mkdir coverage-data + + for dir in `find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n' | grep -v test_fms` + do + cd $dir + if [ ! -z "`find . -type f -name "*.dyn" `" ]; then + profmerge -prof_dpi ${dir}.dpi + mv ${dir}.dpi ../coverage-data + echo ${1} ${dir} coverage data done. + fi + cd .. + done + + cd coverage-data + profmerge -a -prof_dpi ${1}.dpi *.dpi + cd .. +} + +# ensure working directory is at the top of the build directory +top_builddir='@abs_top_builddir@' +cd $top_builddir + +# remove previous runtime data/report +rm -rf coverage-data +rm -rf test_fms/coverage-data +rm -rf coverage-report + +# combine runtime generated coverage data from src and tests +merge_dpis src +cd test_fms +merge_dpis tests +cd .. +cp coverage-data/src.dpi ./ +cp test_fms/coverage-data/tests.dpi ./ +profmerge -a -prof_dpi fms-global-coverage.dpi src.dpi tests.dpi + +# basic html page to link the reports +mkdir coverage-report +cat <<_EOF > coverage-report/fms-coverage.html + + + + FMS Code Coverage +

FMS Code Coverage

+ + +_EOF + +# generate code coverage report and links for each (src) subdirectory +for dir in `find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n' | grep -v test_fms | sort` +do + cd $dir + if [ ! -z "`find . -type f -name "*.spi"`" ] ; then + mkdir ../coverage-report/$dir + codecov -prj $dir -spi pgopti.spi -dpi ../fms-global-coverage.dpi + mv CODE_COVERAGE.HTML ../coverage-report/$dir + mv CodeCoverage ../coverage-report/$dir + echo "

${dir}

" >> ../coverage-report/fms-coverage.html + fi + cd .. +done +echo "" >> coverage-report/fms-coverage.html +echo "" >> coverage-report/fms-coverage.html diff --git a/test_fms/interpolator/Makefile.am b/test_fms/interpolator/Makefile.am index ee6c42a34c..f0977e0a44 100644 --- a/test_fms/interpolator/Makefile.am +++ b/test_fms/interpolator/Makefile.am @@ -41,4 +41,4 @@ TESTS = test_interpolator2.sh EXTRA_DIST = test_interpolator2.sh input_base.nml diag_table_base # Clean up -CLEANFILES = input.nml diag_table +CLEANFILES = input.nml diag_table *.dpi *.spi *.dyn *.spl diff --git a/test_fms/monin_obukhov/Makefile.am b/test_fms/monin_obukhov/Makefile.am index bb7772d693..b36be75a96 100644 --- a/test_fms/monin_obukhov/Makefile.am +++ b/test_fms/monin_obukhov/Makefile.am @@ -41,4 +41,4 @@ TESTS = test_monin_obukhov2.sh EXTRA_DIST = input_base.nml test_monin_obukhov2.sh # Clean up -CLEANFILES = input.nml *.out +CLEANFILES = input.nml *.out *.dpi *.spi *.dyn *.spl diff --git a/test_fms/mosaic/Makefile.am b/test_fms/mosaic/Makefile.am index c1c438d715..1a8c324a7f 100644 --- a/test_fms/mosaic/Makefile.am +++ b/test_fms/mosaic/Makefile.am @@ -41,4 +41,4 @@ TESTS = test_mosaic2.sh EXTRA_DIST = test_mosaic2.sh # Clean up -CLEANFILES = input.nml *.nc *.out +CLEANFILES = input.nml *.nc *.out *.dpi *.spi *.dyn *.spl diff --git a/test_fms/mpp/Makefile.am b/test_fms/mpp/Makefile.am index 30ab2d93ae..249d168f3d 100644 --- a/test_fms/mpp/Makefile.am +++ b/test_fms/mpp/Makefile.am @@ -215,4 +215,4 @@ test_mpp_domains.$(OBJEXT): compare_data_checksums.mod test_domains_utility_mod. # Clean up CLEANFILES = input.nml input_alternative.nml input_blank.nml empty.nml *.out* *.tst* \ - ascii* test_numb* *.mod + ascii* test_numb* *.mod *.dpi *.spi *.dyn *.spl diff --git a/test_fms/mpp_io/Makefile.am b/test_fms/mpp_io/Makefile.am index 8ccae6dd0a..219691b519 100644 --- a/test_fms/mpp_io/Makefile.am +++ b/test_fms/mpp_io/Makefile.am @@ -47,4 +47,4 @@ TESTS = test_mpp_io2.sh \ EXTRA_DIST = test_mpp_io2.sh test_io_R4_R8.sh test_io_mosaic_R4_R8.sh input_base.nml # Clean up -CLEANFILES = input.nml *.nc* *.out +CLEANFILES = input.nml *.nc* *.out *.dpi *.spi *.dyn *.spl diff --git a/test_fms/parser/Makefile.am b/test_fms/parser/Makefile.am index 469538ce11..29139ba4a8 100644 --- a/test_fms/parser/Makefile.am +++ b/test_fms/parser/Makefile.am @@ -51,4 +51,4 @@ endif TESTS_ENVIRONMENT = parser_skip=${skipflag} # Clean up -CLEANFILES = input.nml *.nc* *.out *.yaml +CLEANFILES = input.nml *.nc* *.out *.yaml *.dpi *.spi *.dyn *.spl diff --git a/test_fms/time_interp/Makefile.am b/test_fms/time_interp/Makefile.am index b657481532..e556a0ad16 100644 --- a/test_fms/time_interp/Makefile.am +++ b/test_fms/time_interp/Makefile.am @@ -42,4 +42,4 @@ TESTS = test_time_interp2.sh EXTRA_DIST = test_time_interp2.sh # Clean up -CLEANFILES = input.nml *.out* +CLEANFILES = input.nml *.out* *.dpi *.spi *.dyn *.spl diff --git a/test_fms/time_manager/Makefile.am b/test_fms/time_manager/Makefile.am index 61c2dc5aa8..a6cf0efb3a 100644 --- a/test_fms/time_manager/Makefile.am +++ b/test_fms/time_manager/Makefile.am @@ -41,4 +41,4 @@ TESTS = test_time_manager2.sh EXTRA_DIST = test_time_manager2.sh input_base.nml # Clean up -CLEANFILES = input.nml *.out* +CLEANFILES = input.nml *.out* *.dpi *.spi *.dyn *.spl