Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing refactor #612

Draft
wants to merge 19 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .github/workflows/capgen_unit_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,20 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: update repos and install dependencies
run: sudo apt-get update && sudo apt-get install -y build-essential ${{matrix.fortran-compiler}} cmake python3 git libxml2-utils
run: sudo apt-get update && sudo apt-get install -y build-essential libopenmpi-dev ${{matrix.fortran-compiler}} cmake python3 git libxml2-utils

- name: Build the framework
run: |
cmake -S. -B./build -DCCPP_FRAMEWORK_ENABLE_TESTS=ON
cd build
make

- name: Run unit tests
run: cd test && ./run_fortran_tests.sh
run: |
cd build
ctest --rerun-failed --output-on-failure . --verbose

- name: Run python tests
run: |
pip install --user pytest
BUILD_DIR=./build pytest test/capgen_test/test_reports.py
28 changes: 0 additions & 28 deletions .travis.yml

This file was deleted.

75 changes: 65 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,80 @@ project(ccpp_framework
VERSION 5.0.0
LANGUAGES Fortran)

enable_language(C CXX)
include(FetchContent)
include(cmake/ccpp_capgen.cmake)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/cmake")


#------------------------------------------------------------------------------
# Set package definitions
set(PACKAGE "ccpp-framework")
set(AUTHORS "Dom Heinzeller" "Grant Firl" "Mike Kavulich" "Dustin Swales" "Courtney Peverley")
string(TIMESTAMP YEAR "%Y")

option(CCPP_FRAMEWORK_BUILD_DOCUMENTATION
"Create and install the HTML documentation (requires Doxygen)" OFF)
option(CCPP_FRAMEWORK_ENABLE_OPENMP "Enable OpenMP support for the framework" OFF)
option(CCPP_FRAMEWORK_ENABLE_TESTS "Enable building/running tests" OFF)
option(BUILD_SHARED_LIBS "Build a static library" OFF)
set(CCPP_VERBOSITY "0" CACHE STRING "Verbosity level of output (default: 0)")

if(CCPP_FRAMEWORK_ENABLE_TESTS)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If CCPP_FRAMEWORK_ENABLE_TESTS is ON, then there needs to be a find_package call for pFUnit with the REQUIRED keyword. pfunit must come from the user-provided software stack. No implicit installs during cmake calls/build steps.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood, happy to make that change. I'm actually looking to make a container with all the dependencies/packages already installed so the environment better mimics our development environments to make the cmake call clean as well (we can pass in the pfunit path at configure time but it's clunky without modules).

FetchContent_Declare(
pFUnit
GIT_REPOSITORY https://github.com/Goddard-Fortran-Ecosystem/pFUnit.git
GIT_TAG 26dadb1157819ea1bd9c355c60ed52f42dd36432 # v4.10.0
)
FetchContent_MakeAvailable(pFUnit)
enable_testing()
endif()

# Use rpaths on MacOSX
set(CMAKE_MACOSX_RPATH 1)

ADD_COMPILE_OPTIONS(-O0)
message(STATUS "Compiling Fortran with ${CMAKE_Fortran_COMPILER_ID}")
if(${CMAKE_Fortran_COMPILER_ID} MATCHES "GNU")
ADD_COMPILE_OPTIONS(-fcheck=all)
ADD_COMPILE_OPTIONS(-fbacktrace)
ADD_COMPILE_OPTIONS(-ffpe-trap=zero)
ADD_COMPILE_OPTIONS(-finit-real=nan)
ADD_COMPILE_OPTIONS(-ggdb)
ADD_COMPILE_OPTIONS(-ffree-line-length-none)
ADD_COMPILE_OPTIONS(-cpp)
elseif(${CMAKE_Fortran_COMPILER_ID} MATCHES "IntelLLVM")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ifort will be staying around for quite a while longer, we need this as an option, too.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay, I'll add those back in and differentiate between ifort and ifx.

#ADD_COMPILE_OPTIONS(-check all)
ADD_COMPILE_OPTIONS(-fpe0)
ADD_COMPILE_OPTIONS(-warn)
ADD_COMPILE_OPTIONS(-traceback)
ADD_COMPILE_OPTIONS(-debug full)
ADD_COMPILE_OPTIONS(-fpp)
else()
message (WARNING "This program has only been compiled with gfortran and ifx.")
endif()

#------------------------------------------------------------------------------
# Set MPI flags for Fortran with MPI F08 interface
find_package(MPI REQUIRED Fortran)
find_package(MPI REQUIRED COMPONENTS Fortran)
if(NOT MPI_Fortran_HAVE_F08_MODULE)
message(FATAL_ERROR "MPI implementation does not support the Fortran 2008 mpi_f08 interface")
endif()

#------------------------------------------------------------------------------
# Set OpenMP flags for C/C++/Fortran
if (OPENMP)
if (CCPP_FRAMEWORK_ENABLE_OPENMP)
find_package(OpenMP REQUIRED)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}")
endif (OPENMP)
endif (CCPP_FRAMEWORK_ENABLE_OPENMP)

#------------------------------------------------------------------------------
# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "Coverage")
endif()

#------------------------------------------------------------------------------
Expand All @@ -39,11 +86,19 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DDEBUG)
endif()

#------------------------------------------------------------------------------
# Request a static build
option(BUILD_SHARED_LIBS "Build a static library" OFF)

#------------------------------------------------------------------------------
# Add the sub-directories
add_subdirectory(src)
add_subdirectory(doc)

if(CCPP_FRAMEWORK_ENABLE_TESTS)
add_subdirectory(test)
endif()

if (CCPP_FRAMEWORK_BUILD_DOCUMENTATION)
find_package(Doxygen REQUIRED)
if(NOT DOXYGEN_FOUND)
message(FATAL_ERROR "Doxygen is needed to build the documentation.")
endif()
add_subdirectory(doc)
endif()

94 changes: 94 additions & 0 deletions cmake/ccpp_capgen.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
function(ccpp_capgen)
set(optionalArgs CAPGEN_DEBUG)
set(oneValueArgs HOSTFILES SCHEMEFILES SUITES HOST_NAME OUTPUT_ROOT VERBOSITY)

cmake_parse_arguments(arg "${optionalArgs}" "${oneValueArgs}" "" ${ARGN})

list(APPEND CCPP_CAPGEN_CMD "${CMAKE_SOURCE_DIR}/scripts/ccpp_capgen.py")

if(DEFINED arg_CAPGEN_DEBUG AND arg_CAPGEN_DEBUG)
list(APPEND CCPP_CAPGEN_CMD "--debug")
endif()

if(DEFINED arg_HOSTFILES)
list(APPEND CCPP_CAPGEN_CMD "--host-files" "${arg_HOSTFILES}")
endif()
if(DEFINED arg_SCHEMEFILES)
list(APPEND CCPP_CAPGEN_CMD "--scheme-files" "${arg_SCHEMEFILES}")
endif()
if(DEFINED arg_SUITES)
list(APPEND CCPP_CAPGEN_CMD "--suites" "${arg_SUITES}")
endif()
if(DEFINED arg_HOST_NAME)
list(APPEND CCPP_CAPGEN_CMD "--host-name" "${arg_HOST_NAME}")
endif()
if(DEFINED arg_OUTPUT_ROOT)
message(STATUS "Creating output directory: ${arg_OUTPUT_ROOT}")
file(MAKE_DIRECTORY "${arg_OUTPUT_ROOT}")
list(APPEND CCPP_CAPGEN_CMD "--output-root" "${arg_OUTPUT_ROOT}")
endif()
if(DEFINED arg_VERBOSITY)
string(REPEAT "--verbose" ${arg_VERBOSITY} VERBOSE_PARAMS_SEPERATED)
separate_arguments(VERBOSE_PARAMS UNIX_COMMAND "${VERBOSE_PARAMS_SEPERATED}")
list(APPEND CCPP_CAPGEN_CMD ${VERBOSE_PARAMS})
endif()

message(STATUS "Running ccpp_capgen from ${CMAKE_CURRENT_SOURCE_DIR}")

string(REPLACE ";" " " CAPGEN_CMD_PARAMS_LIST "${CCPP_CAPGEN_CMD}")
message(STATUS "Running ccpp_capgen: ${CAPGEN_CMD_PARAMS_LIST}")

execute_process(COMMAND ${CCPP_CAPGEN_CMD}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE CAPGEN_OUT
ERROR_VARIABLE CAPGEN_OUT
RESULT_VARIABLE RES)

message(STATUS "ccpp-capgen stdout:" ${CAPGEN_OUT})

if(RES EQUAL 0)
message(STATUS "ccpp-capgen completed successfully")
else()
message(FATAL_ERROR "CCPP cap generation FAILED: result = ${RES}")
endif()
endfunction()



function(ccpp_datafile)
set(oneValueArgs DATATABLE REPORT_NAME CCPP_CAPS_LIB_FILES)
cmake_parse_arguments(arg "" "${oneValueArgs}" "" ${ARGN})

set(CCPP_DATAFILE_CMD "${CMAKE_SOURCE_DIR}/scripts/ccpp_datafile.py")

if(NOT DEFINED arg_DATATABLE)
message(FATAL_ERROR "function(ccpp_datafile): DATATABLE not set. A datatable file must be configured to call ccpp_datafile.")
endif()
list(APPEND CCPP_DATAFILE_CMD "${arg_DATATABLE}")

if(NOT DEFINED arg_REPORT_NAME)
message(FATAL_ERROR "function(ccpp_datafile): REPORT_NAME not set. Must specify the report to generate to run cpp_datafile.py")
endif()
list(APPEND CCPP_DATAFILE_CMD "${arg_REPORT_NAME}")

message(STATUS "${CCPP_DATAFILE_CMD}")
message(STATUS "Running ccpp_datafile from ${CMAKE_CURRENT_SOURCE_DIR}")

string(REPLACE ";" " " CCPP_DATAFILE_CMD_SEPERATED "${CCPP_DATAFILE_CMD}")
message(STATUS "Running ccpp_datafile.py command: ${CCPP_DATAFILE_CMD_SEPERATED}")

execute_process(COMMAND ${CCPP_DATAFILE_CMD}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE CCPP_CAPS
RESULT_VARIABLE RES
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE)
message(STATUS "CCPP_CAPS = ${CCPP_CAPS}")
if(RES EQUAL 0)
message(STATUS "CCPP cap files retrieved")
else()
message(FATAL_ERROR "CCPP cap file retrieval FAILED: result = ${RES}")
endif()
set(CCPP_CAPS "${CCPP_CAPS}" PARENT_SCOPE)
endfunction()

28 changes: 8 additions & 20 deletions doc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,16 @@
# Doxygen rules
#
# Add a target to generate API documentation with Doxygen
find_package(Doxygen)
option(BUILD_DOCUMENTATION
"Create and install the HTML documentation (requires Doxygen)"
${DOXYGEN_FOUND})
set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)

#
if(BUILD_DOCUMENTATION)
if(NOT DOXYGEN_FOUND)
message(FATAL_ERROR "Doxygen is needed to build the documentation.")
endif()

set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)

configure_file(${doxyfile_in} ${doxyfile} @ONLY)
configure_file(${doxyfile_in} ${doxyfile} @ONLY)

add_custom_target(doc
COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)
endif()
add_custom_target(doc
COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)

set(gmtb_sty_in ${CMAKE_CURRENT_SOURCE_DIR}/DevelopersGuide/gmtb.sty)
set(gmtb_sty ${CMAKE_CURRENT_BINARY_DIR}/DevelopersGuide/gmtb.sty)
Expand Down
54 changes: 25 additions & 29 deletions scripts/ccpp_datafile.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,51 +159,49 @@ def _command_line_parser():
the list of optional arguments below.
Note that exactly one action is required.
"""
parser = argparse.ArgumentParser(description=description)
parser = argparse.ArgumentParser(description=description,
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("datatable", type=str,
help="Path to a data table XML file created by capgen")
### Only one action per call
group = parser.add_mutually_exclusive_group(required=True)
for report in _VALID_REPORTS:
rep_type = "--{}".format(report["report"].replace("_", "-"))
report_name = report["report"].replace("_", "-")
report_name_option = f"--{report_name}"
if report["type"] is bool:
group.add_argument(rep_type, action='store_true', default=False,
group.add_argument(report_name_option, action='store_true', default=False,
help=report["help"])
elif report["type"] is str:
if "metavar" in report:
group.add_argument(rep_type, required=False, type=str,
metavar=report["metavar"], default='',
help=report["help"])
report_help = report["help"]
default_str = ''
group.add_argument(report_name_option, required=False, type=str,
default=default_str, help=report_help,
metavar=report["metavar"],)
else:
group.add_argument(rep_type, required=False, type=str,
default='', help=report["help"])
group.add_argument(report_name_option, required=False, type=str,
default=default_str, help=report_help)
# end if
else:
raise ValueError("Unknown report type, '{}'".format(report["type"]))
raise ValueError(f"Unknown report type, '{report['type']}'")
# end if
# end for
###
defval = ","
help_str = "String to separate items in a list (default: '{}')"
parser.add_argument("--separator", type=str, required=False, default=defval,
metavar="SEP", dest="sep", help=help_str.format(defval))
defval = False

parser.add_argument("--separator", type=str, required=False, default=",",
metavar="SEP", dest="sep",
help="String to separate items in a list")

help_str = ("Exclude protected variables (only has an effect if the "
"requested report is returning a list of variables)."
" (default: {})")
"requested report is returning a list of variables).")
parser.add_argument("--exclude-protected", action='store_true',
required=False,
default=defval, help=help_str.format(defval))
defval = -1
help_str = ("Screen width for '--show' line wrapping. -1 means do not "
"wrap. (default: {})")
required=False, default=False, help=help_str)
parser.add_argument("--line-wrap", type=int, required=False,
metavar="LINE_WIDTH", dest="line_wrap",
default=defval, help=help_str.format(defval))
defval = 2
help_str = "Indent depth for '--show' output (default: {})"
default=-1,
help="Screen width for '--show' line wrapping. -1 means do not wrap.")
parser.add_argument("--indent", type=int, required=False, default=2,
help=help_str.format(defval))
help="Indent depth for '--show' output")
return parser

###############################################################################
Expand Down Expand Up @@ -1195,12 +1193,10 @@ def generate_ccpp_datatable(run_env, host_model, api, scheme_headers,
ARG_VARS = vars(PARGS)
_ACTION = None
_ERRMSG = ''
_ESEP = ''
for opt in ARG_VARS:
if (opt in DatatableReport.valid_actions()) and ARG_VARS[opt]:
if _ACTION:
_ERRMSG += _ESEP + "Duplicate action, '{}'".format(opt)
_ESEP = '\n'
_ERRMSG += f"Duplicate action, '{opt}'\n"
else:
_ACTION = DatatableReport(opt, ARG_VARS[opt])
# end if
Expand All @@ -1212,5 +1208,5 @@ def generate_ccpp_datatable(run_env, host_model, api, scheme_headers,
REPORT = datatable_report(PARGS.datatable, _ACTION,
PARGS.sep, PARGS.exclude_protected)
# end if
print("{}".format(REPORT.rstrip()))
print(f"{REPORT.rstrip()}")
sys.exit(0)
Loading
Loading