├── .gitignore ├── CESM_utils.cmake ├── ChangeLog ├── Compilers.cmake ├── FindNETCDF.cmake ├── FindNETCDF_C.cmake ├── FindNETCDF_Fortran.cmake ├── FindPnetcdf.cmake ├── FindpFUnit.cmake ├── LICENSE ├── LibFindMacros.cmake ├── README.md ├── Sourcelist_utils.cmake ├── TryCSizeOf.f90 ├── TryMPIIO.f90 ├── TryMPIMod.f90 ├── TryMPISERIAL.f90 ├── TryPnetcdf_inc.f90 ├── TryPnetcdf_mod.f90 ├── genf90_utils.cmake ├── mpiexec.cmake └── pFUnit_utils.cmake /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeCache.txt 2 | CMakeFiles 3 | Makefile 4 | cmake_install.cmake 5 | install_manifest.txt 6 | -------------------------------------------------------------------------------- /CESM_utils.cmake: -------------------------------------------------------------------------------- 1 | # Module used for CESM testing. 2 | # 3 | # This module contains statements that would otherwise be boilerplate in 4 | # most CESM tests. It enables CTest testing, handles the USE_COLOR and 5 | # ENABLE_GENF90 arguments, and includes several other modules. 6 | 7 | #========================================================================== 8 | # Copyright (c) 2013-2014, University Corporation for Atmospheric Research 9 | # 10 | # This software is distributed under a two-clause BSD license, with no 11 | # warranties, express or implied. See the accompanying LICENSE file for 12 | # details. 13 | #========================================================================== 14 | 15 | #================================================= 16 | # Enable CTest tests. 17 | #================================================= 18 | 19 | enable_testing() 20 | 21 | #================================================= 22 | # Color output 23 | #================================================= 24 | 25 | option(USE_COLOR "Allow color from the build output." ON) 26 | 27 | set(CMAKE_COLOR_MAKEFILE "${USE_COLOR}") 28 | 29 | #================================================= 30 | # Compiler info 31 | #================================================= 32 | 33 | if("${CMAKE_BUILD_TYPE}" MATCHES CESM) 34 | include(${CMAKE_BINARY_DIR}/CESM_Macros.cmake) 35 | else() 36 | include(Compilers) 37 | endif() 38 | 39 | #================================================= 40 | # GenF90 41 | #================================================= 42 | 43 | option(ENABLE_GENF90 44 | "Use genf90.pl to regenerate out-of-date Fortran files from .in files." 45 | OFF) 46 | 47 | if(ENABLE_GENF90) 48 | find_program(GENF90 genf90.pl) 49 | 50 | if(NOT GENF90) 51 | message(FATAL_ERROR "ENABLE_GENF90 enabled, but genf90.pl not found!") 52 | endif() 53 | 54 | endif() 55 | 56 | # Preprocessing utility functions. 57 | include(genf90_utils) 58 | 59 | #================================================= 60 | # pFUnit 61 | #================================================= 62 | 63 | # pFUnit and its preprocessor 64 | find_package(pFUnit) 65 | 66 | # Preprocessor and driver handling. 67 | include(pFUnit_utils) 68 | 69 | #================================================= 70 | # Source list and path utilities. 71 | #================================================= 72 | 73 | include(Sourcelist_utils) 74 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | This repository tracks changes using the Git log. 2 | 3 | For small changes, e.g. fixing typos, use a one line, 50 character summary. 4 | 5 | For larger changes, this summary should be followed by a blank line and a 6 | longer description. The following link gives good advice: 7 | 8 | http://justinhileman.info/article/changing-history/#make-the-most-of-your-commit-message 9 | -------------------------------------------------------------------------------- /Compilers.cmake: -------------------------------------------------------------------------------- 1 | # Flags for builds with different machines/compilers. 2 | # 3 | # This module is currently a catch-all for compiler-specific functionality 4 | # needed by CESM. It defines OS and compiler CPP macros and CESM build 5 | # types, as well as including the file containing CESM compiler flags, if 6 | # necessary. 7 | # 8 | # There is also one function intended for CTest test writers, described 9 | # below. 10 | # 11 | #========================================================================== 12 | # 13 | # define_Fortran_stop_failure 14 | # 15 | # Arguments: 16 | # test_name - Name of a CTest test. 17 | # 18 | # Ensures that if the named test uses "STOP 1" to signal failure, that this 19 | # is detected by CTest. Currently this is only necessary for NAG, which 20 | # prints the stop code rather than using it as an error code. 21 | # 22 | #========================================================================== 23 | 24 | #========================================================================== 25 | # Copyright (c) 2013-2014, University Corporation for Atmospheric Research 26 | # 27 | # This software is distributed under a two-clause BSD license, with no 28 | # warranties, express or implied. See the accompanying LICENSE file for 29 | # details. 30 | #========================================================================== 31 | 32 | #================================================= 33 | # Define OS and compiler macros. 34 | #================================================= 35 | 36 | # Define OS. 37 | string(TOUPPER ${CMAKE_SYSTEM_NAME} os) 38 | add_definitions(-D${os}) 39 | 40 | # Define CESM-compatible compiler names. 41 | if(${CMAKE_Fortran_COMPILER_ID} STREQUAL NAG) 42 | set(compiler_name nag) 43 | elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL GNU) 44 | set(compiler_name gnu) 45 | elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL XL) 46 | set(compiler_name ibm) 47 | elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL Intel) 48 | set(compiler_name intel) 49 | elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL PGI) 50 | set(compiler_name pgi) 51 | endif() 52 | 53 | # Define CPP macro for the compiler. 54 | string(TOUPPER -DCPR${compiler_name} compiler_cppdef) 55 | add_definitions(${compiler_cppdef}) 56 | 57 | #================================================= 58 | # Utility functions. 59 | #================================================= 60 | 61 | # Add flags to space-separated list rather than normal CMake list. 62 | function(add_flags list) 63 | string(REPLACE ";" " " flags "${ARGN}") 64 | set(${list} "${${list}} ${flags}" PARENT_SCOPE) 65 | endfunction() 66 | 67 | 68 | # Add configuration-specific preprocessor definitions. 69 | function(add_config_definitions configuration) 70 | get_directory_property(cppdefs COMPILE_DEFINITIONS_${configuration}) 71 | foreach(flag IN LISTS ARGN) 72 | string(REPLACE "-D" "" def "${flag}") 73 | list(APPEND cppdefs ${def}) 74 | endforeach() 75 | set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_${configuration} 76 | "${cppdefs}") 77 | endfunction() 78 | 79 | 80 | #================================================= 81 | # Build flags required to use pFUnit. 82 | #================================================= 83 | 84 | if(${CMAKE_Fortran_COMPILER_ID} STREQUAL Intel) 85 | add_flags(CMAKE_Fortran_FLAGS -assume realloc_lhs) 86 | endif() 87 | 88 | #================================================= 89 | # Add flags for debugging output. 90 | #================================================= 91 | 92 | # Define Fortran compiler flags. 93 | 94 | # Add pretty output and extra warnings regardless of build type. However, 95 | # don't set any options in the generic flags that would affect the 96 | # generated binary, because we want to be able to get binaries that 97 | # resemble what you get from the CESM flags. 98 | 99 | if(${CMAKE_Fortran_COMPILER_ID} STREQUAL NAG) 100 | add_flags(CMAKE_Fortran_FLAGS -strict95) 101 | if(USE_COLOR) 102 | add_flags(CMAKE_Fortran_FLAGS -colour) 103 | endif() 104 | 105 | elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL GNU) 106 | # Turn on warnings, but leave out uninitialized check as it was producing 107 | # a lot of false positives. 108 | add_flags(CMAKE_Fortran_FLAGS -Wall -Wextra -Wno-uninitialized) 109 | 110 | elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL XL) 111 | elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL Intel) 112 | elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL PGI) 113 | endif() 114 | 115 | # Define C flags, analogous to the above Fortran block. 116 | if(CMAKE_C_COMPILER_LOADED) 117 | if(${CMAKE_C_COMPILER_ID} STREQUAL GNU) 118 | add_flags(CMAKE_C_FLAGS -Wall -Wextra -pedantic) 119 | endif() 120 | endif() 121 | 122 | #================================================= 123 | # Help CTest tests recognize when "stop X" is called with non-zero X. 124 | #================================================= 125 | 126 | # Detect "STOP" for CTest. 127 | if(${CMAKE_Fortran_COMPILER_ID} STREQUAL NAG) 128 | # NAG prints the stop code instead of yielding a non-zero return, so we 129 | # have to use a regex to catch that. 130 | function(define_Fortran_stop_failure test_name) 131 | set_tests_properties(${test_name} PROPERTIES 132 | FAIL_REGULAR_EXPRESSION "STOP: [1-9]") 133 | endfunction(define_Fortran_stop_failure) 134 | else() 135 | # Usually, stop /= 0 is already detected with the return code. 136 | function(define_Fortran_stop_failure test_name) 137 | endfunction(define_Fortran_stop_failure) 138 | endif() 139 | -------------------------------------------------------------------------------- /FindNETCDF.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find Netcdf 2 | # Once done this will define 3 | # NETCDF_FOUND - System has Netcdf 4 | # NETCDF_INCLUDE_DIRS - The Netcdf include directories 5 | # NETCDF_C_LIBRARIES - The C libraries needed to use Netcdf 6 | # NETCDF_Fortran_LIBRARIES - The Fortran libraries needed to use Netcdf 7 | # NETCDF_LIBRARIES - All the libraries needed to use Netcdf 8 | # NETCDF_DEFINITIONS - Compiler switches required for using Netcdf 9 | 10 | # If we weren't given a hint via a CMake variable, check the environment. 11 | if(NOT NETCDF_DIR) 12 | set(NETCDF_DIR $ENV{NETCDF}) 13 | endif() 14 | 15 | find_path(NETCDF_INCLUDE_DIR netcdf.h 16 | HINTS ${NETCDF_DIR}/include ) 17 | 18 | find_path(NETCDF_LIB_DIR NAMES libnetcdf.a libnetcdf.so 19 | HINTS ${NETCDF_DIR}/lib ${NETCDF_DIR}/lib64 ) 20 | 21 | find_path(NETCDF_FORTRAN_LIB_DIR NAMES libnetcdff.a libnetcdff.so 22 | HINTS ${NETCDF_DIR}/lib ${NETCDF_DIR}/lib64 ) 23 | 24 | 25 | find_file(NETCDF4_PAR_H netcdf_par.h 26 | HINTS ${NETCDF_INCLUDE_DIR} 27 | NO_DEFAULT_PATH ) 28 | 29 | #MESSAGE("PAR_H: ${NETCDF4_PAR_H}") 30 | find_library(NETCDF_C_LIBRARY NAMES libnetcdf.a netcdf HINTS ${NETCDF_LIB_DIR}) 31 | 32 | if(NOT NETCDF_FORTRAN_LIB_DIR) 33 | MESSAGE(WARNING "Did not find netCDF Fortran library.") 34 | else() 35 | find_library(NETCDF_Fortran_LIBRARY NAMES libnetcdff.a netcdff HINTS ${NETCDF_FORTRAN_LIB_DIR}) 36 | endif() 37 | if(NOT NETCDF4_PAR_H) 38 | set(NETCDF4_PARALLEL "no") 39 | MESSAGE("NETCDF built without MPIIO") 40 | else() 41 | set(NETCDF4_PARALLEL "yes") 42 | MESSAGE("NETCDF built with hdf5 MPIIO support") 43 | endif() 44 | 45 | set(NETCDF_INCLUDE_DIRS ${NETCDF_INCLUDE_DIR} ) 46 | 47 | FIND_PACKAGE(HDF5 COMPONENTS C HL CONFIG) 48 | 49 | if(${HDF5_FOUND}) 50 | MESSAGE(STATUS "Adding hdf5 libraries ") 51 | set(NETCDF_C_LIBRARY ${NETCDF_C_LIBRARY} ${HDF5_LIBRARIES} 52 | ${SZIP_LIBRARIES} ${ZLIB_LIBRARIES}) 53 | endif() 54 | 55 | # If netCDF was configured with DAP, it depends on libcurl. 56 | find_program(NETCDF_NC_CONFIG nc-config HINTS ${NETCDF_INCLUDE_DIR}/../bin) 57 | if(NETCDF_NC_CONFIG) 58 | execute_process(COMMAND ${NETCDF_NC_CONFIG} --has-dap 59 | OUTPUT_VARIABLE nc_config_output) 60 | if(nc_config_output MATCHES yes) 61 | find_package(CURL) 62 | if(CURL_FOUND) 63 | MESSAGE(STATUS "Adding curl libraries for netCDF DAP.") 64 | set(NETCDF_C_LIBRARY ${NETCDF_C_LIBRARY} ${CURL_LIBRARIES}) 65 | else() 66 | MESSAGE(WARNING "netCDF DAP appears enabled, but libcurl was not found.") 67 | endif() 68 | endif() 69 | endif() 70 | 71 | set(NETCDF_LIBRARIES ${NETCDF_Fortran_LIBRARY} ${NETCDF_C_LIBRARY}) 72 | 73 | # Export variables so other projects can use them as well 74 | # ie. if pio is added with add_subdirectory 75 | SET(NETCDF_INCLUDE_DIR ${NETCDF_INCLUDE_DIR} CACHE STRING "Location of NetCDF include files.") 76 | SET(NETCDF_LIBRARIES ${NETCDF_LIBRARIES} CACHE STRING "Link line for NetCDF.") 77 | 78 | include(FindPackageHandleStandardArgs) 79 | # handle the QUIETLY and REQUIRED arguments and set NETCDF_FOUND to TRUE 80 | # if all listed variables are TRUE 81 | # (Note that the Fortran interface is not always a separate library, so 82 | # don't require it to be found.) 83 | find_package_handle_standard_args(NETCDF DEFAULT_MSG NETCDF_LIBRARIES 84 | NETCDF_C_LIBRARY NETCDF_INCLUDE_DIR) 85 | 86 | mark_as_advanced(NETCDF_INCLUDE_DIR NETCDF_LIBRARIES NETCDF_C_LIBRARY NETCDF_Fortran_LIBRARY NETCDF4_PARALLEL ) 87 | -------------------------------------------------------------------------------- /FindNETCDF_C.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find Netcdf 2 | # Once done this will define 3 | # NETCDF_C_FOUND - System has Netcdf 4 | # NETCDF_C_INCLUDE_DIRS - The Netcdf include directories 5 | # NETCDF_C_LIBRARY - The C libraries needed to use Netcdf 6 | # NETCDF_C_LIBRARIES - All the libraries needed to use Netcdf 7 | # NETCDF_C_DEFINITIONS - Compiler switches required for using Netcdf 8 | # 9 | include(LibFindMacros) 10 | set(NETCDF_C_PARALLEL FALSE) 11 | find_path(NETCDF_C_INCLUDE_DIR 12 | NAMES netcdf.h 13 | PATHS ${NETCDF_C_PKGCONF_INCLUDE_DIRS} 14 | HINTS ${NETCDF_DIR}/include ${NETCDF_C_DIR}/include) 15 | 16 | # See if netcdf includes parallel support 17 | find_path(NETCDF_C_PAR_INCLUDE_DIR 18 | NAMES netcdf_par.h 19 | PATHS ${NETCDF_C_PKGCONF_INCLUDE_DIRS} 20 | HINTS ${NETCDF_DIR}/include ${NETCDF_C_DIR}/include) 21 | 22 | set(NETCDF_C_DEFINITIONS "-D_NETCDF") 23 | if(${NETCDF_C_PAR_INCLUDE_DIR} STREQUAL "NETCDF_C_PAR_INCLUDE_DIR-NOTFOUND") 24 | MESSAGE("Netcdf library does not appear to have parallel IO support") 25 | else() 26 | MESSAGE("Netcdf library includes HDF5 parallel support") 27 | LIST(APPEND NETCDF_C_DEFINITIONS "-D_NETCDF4") 28 | endif() 29 | find_library(NETCDF_C_LIBRARY 30 | NAMES libnetcdf.a netcdf 31 | PATHS ${NETCDF_C_PKGCONF_LIBRARY_DIRS} 32 | HINTS ${NETCDF_DIR}/lib ${NETCDF_C_DIR}/lib) 33 | 34 | set(NETCDF_C_PROCESS_INCLUDES NETCDF_C_INCLUDE_DIR) 35 | 36 | set(NETCDF_C_PROCESS_LIBS NETCDF_C_LIBRARY) 37 | 38 | libfind_process(NETCDF_C) 39 | -------------------------------------------------------------------------------- /FindNETCDF_Fortran.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find Netcdf 2 | # Once done this will define 3 | # NETCDF_Fortran_FOUND - System has Netcdf 4 | # NETCDF_Fortran_INCLUDE_DIRS - The Netcdf include directories 5 | # NETCDF_Fortran_LIBRARY - The C libraries needed to use Netcdf 6 | # NETCDF_Fortran_LIBRARIES - All the libraries needed to use Netcdf 7 | # NETCDF_Fortran_DEFINITIONS - Compiler switches required for using Netcdf 8 | # 9 | include(LibFindMacros) 10 | 11 | find_path(NETCDF_Fortran_INCLUDE_DIR 12 | NAMES netcdf.inc 13 | PATHS ${NETCDF_Fortran_PKGCONF_INCLUDE_DIRS} 14 | HINTS ${NETCDF_DIR}/include ${NETCDF_Fortran_DIR}/include) 15 | libfind_package(NETCDF_Fortran NETCDF_C) 16 | find_library(NETCDF_Fortran_LIBRARY 17 | NAMES libnetcdff.a netcdff 18 | PATHS ${NETCDF_Fortran_PKGCONF_LIBRARY_DIRS} 19 | HINTS ${NETCDF_DIR}/lib ${NETCDF_Fortran_DIR}/lib) 20 | 21 | set(NETCDF_Fortran_PROCESS_INCLUDES NETCDF_Fortran_INCLUDE_DIR) 22 | 23 | set(NETCDF_Fortran_PROCESS_LIBS NETCDF_Fortran_LIBRARY) 24 | 25 | libfind_process(NETCDF_Fortran) 26 | -------------------------------------------------------------------------------- /FindPnetcdf.cmake: -------------------------------------------------------------------------------- 1 | include(FindPackageHandleStandardArgs) 2 | include(CheckFunctionExists) 3 | 4 | FIND_PATH(PNETCDF_INCLUDE_DIR 5 | pnetcdf.h 6 | HINTS ${PNETCDF_DIR}/include 7 | CACHE) 8 | MESSAGE("PNETCDF_INCLUDE_DIR: ${PNETCDF_INCLUDE_DIR}") 9 | IF (${PREFER_SHARED}) 10 | FIND_LIBRARY(PNETCDF_LIBRARY 11 | NAMES pnetcdf 12 | HINTS ${PNETCDF_DIR}/lib 13 | CACHE) 14 | ELSE () 15 | FIND_LIBRARY(PNETCDF_LIBRARY 16 | NAMES libpnetcdf.a pnetcdf 17 | HINTS ${PNETCDF_DIR}/lib 18 | CACHE) 19 | ENDIF () 20 | 21 | if(${PNETCDF_LIBRARY} STREQUAL "PNETCDF_LIBRARY-NOTFOUND") 22 | MESSAGE("PNETCDF library not found") 23 | return() 24 | endif() 25 | 26 | find_file( PNETCDFTEST NAMES TryPnetcdf_mod.f90 PATHS ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH) 27 | get_filename_component( CMAKE_TEST_PATH ${PNETCDFTEST} PATH) 28 | 29 | TRY_COMPILE(PNETCDF_MOD ${CMAKE_CURRENT_BINARY_DIR}/tryPnetcdf_mod 30 | ${CMAKE_TEST_PATH}/TryPnetcdf_mod.f90 31 | COMPILE_DEFINITIONS -I${PNETCDF_INCLUDE_DIR} 32 | CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${PNETCDF_LIBRARY}" 33 | OUTPUT_VARIABLE Pnet_OUT) 34 | 35 | if(NOT PNETCDF_MOD) 36 | TRY_COMPILE(PNETCDF_INC ${CMAKE_CURRENT_BINARY_DIR}/tryPnetcdf_inc 37 | ${CMAKE_TEST_PATH}/TryPnetcdf_inc.f90 38 | COMPILE_DEFINITIONS -I${PNETCDF_INCLUDE_DIR} 39 | CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${PNETCDF_LIBRARY}" 40 | OUTPUT_VARIABLE Pnet_OUT) 41 | endif() 42 | 43 | SET(CMAKE_REQUIRED_LIBRARIES ${PNETCDF_LIBRARY}) 44 | CHECK_FUNCTION_EXISTS(ncmpi_get_varn PNETCDF_VARN) 45 | if(PNETCDF_VARN) 46 | LIST(APPEND PNETCDF_CPPDEFS -DUSE_PNETCDF_VARN) 47 | LIST(APPEND PNETCDF_CPPDEFS -DUSE_PNETCDF_VARN_ON_READ) 48 | endif() 49 | 50 | SET(PNETCDF_LIBRARIES ${PNETCDF_LIBRARY} ) 51 | SET(PNETCDF_INCLUDE_DIRS ${PNETCDF_INCLUDE_DIR} ) 52 | 53 | # Handle QUIETLY and REQUIRED. 54 | find_package_handle_standard_args(pnetcdf DEFAULT_MSG 55 | PNETCDF_LIBRARY PNETCDF_INCLUDE_DIR ) 56 | 57 | mark_as_advanced(PNETCDF_INCLUDE_DIR PNETCDF_LIBRARY PNETCDF_INC PNETCDF_MOD PNETCDF_CPPDEFS) 58 | -------------------------------------------------------------------------------- /FindpFUnit.cmake: -------------------------------------------------------------------------------- 1 | # Find module for pFUnit 2 | # 3 | # For this module to work, either the pFUnit parser must be discoverable 4 | # (e.g. in the user's PATH), or else the environment variable "PFUNIT" must 5 | # be defined, and point to the root directory for the PFUNIT installation. 6 | # 7 | # This module sets some typical variables: 8 | # PFUNIT_FOUND 9 | # PFUNIT_LIBRARY(/LIBRARIES) 10 | # PFUNIT_INCLUDE_DIR(/DIRS) 11 | # 12 | # The module also sets: 13 | # PFUNIT_DRIVER - Path to the pFUnit driver source. 14 | # PFUNIT_MODULE_DIR - Directory containing pFUnit's module files. 15 | # PFUNIT_PARSER - Path to pFUnitParser.py (the preprocessor). 16 | 17 | #========================================================================== 18 | # Copyright (c) 2013-2014, University Corporation for Atmospheric Research 19 | # 20 | # This software is distributed under a two-clause BSD license, with no 21 | # warranties, express or implied. See the accompanying LICENSE file for 22 | # details. 23 | #========================================================================== 24 | 25 | include(FindPackageHandleStandardArgs) 26 | 27 | find_program(PFUNIT_PARSER pFUnitParser.py 28 | HINTS $ENV{PFUNIT}/bin) 29 | 30 | string(REGEX REPLACE "bin/pFUnitParser\\.py\$" "" 31 | pfunit_directory ${PFUNIT_PARSER}) 32 | 33 | find_library(PFUNIT_LIBRARY pfunit 34 | HINTS ${pfunit_directory}/lib) 35 | 36 | find_path(PFUNIT_INCLUDE_DIR driver.F90 37 | HINTS ${pfunit_directory}/include) 38 | 39 | set(PFUNIT_DRIVER ${PFUNIT_INCLUDE_DIR}/driver.F90) 40 | 41 | find_path(PFUNIT_MODULE_DIR NAMES pfunit.mod PFUNIT.MOD 42 | HINTS ${pfunit_directory}/include ${pfunit_directory}/mod) 43 | 44 | set(PFUNIT_LIBRARIES ${PFUNIT_LIBRARY}) 45 | set(PFUNIT_INCLUDE_DIRS ${PFUNIT_INCLUDE_DIR} ${PFUNIT_MODULE_DIR}) 46 | 47 | # Handle QUIETLY and REQUIRED. 48 | find_package_handle_standard_args(pFUnit DEFAULT_MSG 49 | PFUNIT_LIBRARY PFUNIT_INCLUDE_DIR PFUNIT_MODULE_DIR PFUNIT_PARSER) 50 | 51 | mark_as_advanced(PFUNIT_INCLUDE_DIR PFUNIT_LIBRARY PFUNIT_MODULE_DIR 52 | PFUNIT_PARSER) 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2014, University Corporation for Atmospheric Research 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /LibFindMacros.cmake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESM-Development/CMake_Fortran_utils/05ff8d8e4c88786e94a02c853d3ff921113d785c/LibFindMacros.cmake -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CMake_Fortran_utils 2 | =================== 3 | 4 | CMake modules dealing with Fortran-specific issues and Fortran libraries 5 | 6 | Currently, these modules should work with CMake version 2.8.8 and later 7 | versions. Earlier CMake versions may work but are untested. 8 | 9 | Below is a brief listing of modules. More detailed information on the 10 | purpose and use of these modules can be found in comments at the top of 11 | each file. 12 | 13 | Find modules for specific libraries: 14 | 15 | FindNETCDF 16 | 17 | FindpFUnit 18 | 19 | FindPnetcdf 20 | 21 | Utility modules: 22 | 23 | genf90_utils - Generate Fortran code from genf90.pl templates. 24 | 25 | pFUnit_utils - Create executables using the pFUnit parser and driver. 26 | 27 | Sourcelist_utils - Use source file lists defined over multiple directories. 28 | 29 | Modules that are CESM-specific and/or incomplete: 30 | 31 | CESM_utils - Handles a few options, and includes several other modules. 32 | 33 | Compilers - Specify compiler-specific behavior, add build types for CESM. 34 | -------------------------------------------------------------------------------- /Sourcelist_utils.cmake: -------------------------------------------------------------------------------- 1 | # Utility functions to work with accumulated lists of sources. 2 | # 3 | #========================================================================== 4 | # 5 | # sourcelist_to_parent 6 | # 7 | # Arguments: 8 | # source_list_name - Name of list to send. 9 | # 10 | # Expands relative paths to absolute locations in the source list, then 11 | # copies the value of the list to the list with the same name in the parent 12 | # scope. 13 | # 14 | #========================================================================== 15 | # 16 | # extract_sources 17 | # 18 | # Arguments: 19 | # sources_needed - Base names of sources required for a target. 20 | # all_sources - Absolute locations of available source files. 21 | # source_list_name - Absolute locations of sources to build the target. 22 | # 23 | # Scans through a list of all source files, selects files with the 24 | # requested names, and *appends* them to an output list. If there is more 25 | # than one file with the same name, the *last* match is selected. 26 | # 27 | # This allows you to simulate Makefile idioms that choose from multiple 28 | # versions of a file, based on the order in which they are encountered. 29 | # 30 | #========================================================================== 31 | # 32 | # declare_generated_dependencies. 33 | # 34 | # Arguments: 35 | # target - The target that needs to depend on generated files. 36 | # generated_list - The generated source code files the target requires. 37 | # 38 | # Ensures that generated sources in a different directory are produced 39 | # before compiling and linking the target. This is done by assuming that 40 | # each generated source file corresponds to an existing target. For 41 | # instance, a file called "foo.F90" would be generated by a target called 42 | # "generate_foo". The input target can then be made to depend on each of 43 | # the "generate" targets. 44 | # 45 | # This is unnecessary when source code generation occurs in the directory 46 | # where the target was added. However, CMake does not propagate information 47 | # about source code generation to parent directories, so the intermediate 48 | # "generate" targets must be created to enforce generation in the correct 49 | # order. 50 | # 51 | #========================================================================== 52 | 53 | #========================================================================== 54 | # Copyright (c) 2013-2014, University Corporation for Atmospheric Research 55 | # 56 | # This software is distributed under a two-clause BSD license, with no 57 | # warranties, express or implied. See the accompanying LICENSE file for 58 | # details. 59 | #========================================================================== 60 | 61 | # For each relative path in ${file_list}, prepend ${base_directory} to make 62 | # an absolute path, and put result in list named by ${new_list_name}. 63 | function(expand_relative_paths file_list base_directory new_list_name) 64 | 65 | unset(${new_list_name}) 66 | foreach(file IN LISTS file_list) 67 | if(IS_ABSOLUTE "${file}") 68 | set(new_file "${file}") 69 | else() 70 | set(new_file "${base_directory}/${file}") 71 | endif() 72 | list(APPEND ${new_list_name} "${new_file}") 73 | endforeach() 74 | 75 | set(${new_list_name} "${${new_list_name}}" PARENT_SCOPE) 76 | 77 | endfunction(expand_relative_paths) 78 | 79 | # Expand relative paths in a named source list, and export to parent scope. 80 | # The idea here is to communicate the list between a directory added with 81 | # add_subdirectory, and the directory above it. 82 | macro(sourcelist_to_parent source_list_name) 83 | expand_relative_paths("${${source_list_name}}" 84 | ${CMAKE_CURRENT_SOURCE_DIR} ${source_list_name}) 85 | set(${source_list_name} "${${source_list_name}}" PARENT_SCOPE) 86 | endmacro(sourcelist_to_parent) 87 | 88 | # Find an absolute file path in ${all_sources} for each base name in 89 | # ${sources_needed}, and append found paths to the list named by 90 | # ${source_list_name}. 91 | function(extract_sources sources_needed all_sources source_list_name) 92 | 93 | foreach(needed_source IN LISTS sources_needed) 94 | 95 | set(source_match source-NOTFOUND) 96 | 97 | foreach(source IN LISTS all_sources) 98 | get_filename_component(basename ${source} NAME) 99 | if(${basename} STREQUAL ${needed_source}) 100 | set(source_match ${source}) 101 | endif() 102 | endforeach() 103 | 104 | if(NOT source_match) 105 | message(FATAL_ERROR 106 | "Source file not found: ${needed_source} 107 | After searching in list: ${${all_sources}}") 108 | endif() 109 | 110 | list(APPEND ${source_list_name} ${source_match}) 111 | 112 | endforeach() 113 | 114 | set(${source_list_name} "${${source_list_name}}" PARENT_SCOPE) 115 | 116 | endfunction(extract_sources) 117 | 118 | # Handles dependencies between files generated in one directory and a 119 | # target in another. 120 | # Given a target and a list of files, sets the GENERATED property for each 121 | # file, and makes the target depend on a custom target generated from the 122 | # extensionless base file name. (E.g. for /path/to/foo.F90, it will assume 123 | # that it is generated by a custom target called generate_foo). 124 | function(declare_generated_dependencies target generated_list) 125 | foreach(file IN LISTS generated_list) 126 | 127 | set_source_files_properties(${file} PROPERTIES GENERATED 1) 128 | 129 | get_filename_component(stripped_name ${file} NAME_WE) 130 | 131 | add_dependencies(${target} generate_${stripped_name}) 132 | 133 | endforeach() 134 | endfunction(declare_generated_dependencies) 135 | -------------------------------------------------------------------------------- /TryCSizeOf.f90: -------------------------------------------------------------------------------- 1 | program trycsizeof 2 | use iso_c_binding, only : c_sizeof 3 | integer :: b 4 | integer :: a(5) 5 | b = c_sizeof(a(1)) 6 | end program trycsizeof 7 | -------------------------------------------------------------------------------- /TryMPIIO.f90: -------------------------------------------------------------------------------- 1 | program mpicheck 2 | use mpi 3 | integer :: fh, ierr 4 | 5 | call mpi_file_open(mpi_comm_world, 'stupid.file',MPI_MODE_RDWR,MPI_INFO_NULL,fh,ierr) 6 | end program 7 | -------------------------------------------------------------------------------- /TryMPIMod.f90: -------------------------------------------------------------------------------- 1 | program mpimodcheck 2 | use mpi, only : MPI_ROOT, MPI_OFFSET 3 | integer,parameter:: a = MPI_ROOT 4 | end program mpimodcheck 5 | -------------------------------------------------------------------------------- /TryMPISERIAL.f90: -------------------------------------------------------------------------------- 1 | ! Test for the mct mpiserial library 2 | ! in which mpi_cart is not defined (and likely never will be) 3 | ! Failure to compile means mpi-serial is being used. 4 | ! 5 | program mpiserial_test 6 | use mpi 7 | implicit none 8 | integer :: i 9 | select case(i) 10 | case(mpi_cart) 11 | end select 12 | end program mpiserial_test 13 | -------------------------------------------------------------------------------- /TryPnetcdf_inc.f90: -------------------------------------------------------------------------------- 1 | program freeform 2 | include "pnetcdf.inc" 3 | end program 4 | -------------------------------------------------------------------------------- /TryPnetcdf_mod.f90: -------------------------------------------------------------------------------- 1 | program freeform 2 | use pnetcdf 3 | integer ierr 4 | ierr = nfmpi_put_att(4, 1, 'fred', 7) 5 | end program 6 | -------------------------------------------------------------------------------- /genf90_utils.cmake: -------------------------------------------------------------------------------- 1 | # Utility for invoking genf90 on a template file. 2 | # 3 | # If ENABLE_GENF90 is set to a true value, the functions here will behave 4 | # as described below. In this case, the variable GENF90 must be defined and 5 | # contain the genf90.pl command. 6 | # 7 | # If ENABLE_GENF90 is not true, no source code generation or other side 8 | # effects will occur, but output variables will be set as if the generation 9 | # had occurred. 10 | # 11 | #========================================================================== 12 | # 13 | # process_genf90_source_list 14 | # 15 | # Arguments: 16 | # genf90_file_list - A list of template files to process. 17 | # output_directory - Directory where generated sources will be placed. 18 | # fortran_list_name - The name of a list used as output. 19 | # 20 | # Produces generated sources for each of the input templates. Then 21 | # this function *appends* the location of each generated file to the output 22 | # list. 23 | # 24 | # As a side effect, this function will add a target for each generated 25 | # file. For a generated file named "foo.F90", the target will be named 26 | # "generate_foo". 27 | # 28 | # Limitations: 29 | # This function adds targets to work around a deficiency in CMake (see 30 | # "declare_generated_dependencies" in Sourcelist_utils). Unfortunately, 31 | # this means that you cannot use this function to generate two files 32 | # with the same name in a single project. 33 | # 34 | #========================================================================== 35 | 36 | #========================================================================== 37 | # Copyright (c) 2013-2014, University Corporation for Atmospheric Research 38 | # 39 | # This software is distributed under a two-clause BSD license, with no 40 | # warranties, express or implied. See the accompanying LICENSE file for 41 | # details. 42 | #========================================================================== 43 | 44 | if(ENABLE_GENF90) 45 | 46 | # Notify CMake that a Fortran file can be generated from a genf90 47 | # template. 48 | function(preprocess_genf90_template genf90_file fortran_file) 49 | 50 | add_custom_command(OUTPUT ${fortran_file} 51 | COMMAND ${GENF90} ${genf90_file} >${fortran_file} 52 | MAIN_DEPENDENCY ${genf90_file}) 53 | 54 | get_filename_component(stripped_name ${fortran_file} NAME_WE) 55 | 56 | add_custom_target(generate_${stripped_name} DEPENDS ${fortran_file}) 57 | 58 | endfunction(preprocess_genf90_template) 59 | 60 | else() 61 | 62 | # Stub if genf90 is off. 63 | function(preprocess_genf90_template) 64 | endfunction() 65 | 66 | endif() 67 | 68 | # Auto-generate source names. 69 | function(process_genf90_source_list genf90_file_list output_directory 70 | fortran_list_name) 71 | 72 | foreach(genf90_file IN LISTS genf90_file_list) 73 | 74 | # If a file is a relative path, expand it (relative to current source 75 | # directory. 76 | get_filename_component(genf90_file "${genf90_file}" ABSOLUTE) 77 | 78 | # Get extensionless base name from input. 79 | get_filename_component(genf90_file_stripped "${genf90_file}" NAME_WE) 80 | 81 | # Add generated file to the test list. 82 | set(fortran_file ${output_directory}/${genf90_file_stripped}.F90) 83 | preprocess_genf90_template(${genf90_file} ${fortran_file}) 84 | list(APPEND ${fortran_list_name} ${fortran_file}) 85 | endforeach() 86 | 87 | # Export ${fortran_list_name} to the caller. 88 | set(${fortran_list_name} "${${fortran_list_name}}" PARENT_SCOPE) 89 | 90 | endfunction(process_genf90_source_list) 91 | -------------------------------------------------------------------------------- /mpiexec.cmake: -------------------------------------------------------------------------------- 1 | function( add_mpi_test _testName _testExe _testArgs _numProc _timeout) 2 | 3 | if ("${PLATFORM}" STREQUAL "cetus" ) 4 | ### 5 | ### 6 | #set(PIO_RUNJOB ${CMAKE_BINARY_DIR}/scripts/pio_runjob.sh) 7 | set(REQUIRED_OPTION --block \$ENV{COBALT_PARTNAME}) 8 | set(RUNJOB_NPF --np ${_numProc}) 9 | if (DEFINED ENV{BGQ_RUNJOB}) 10 | set(RUNJOB $ENV{BGQ_RUNJOB}) 11 | else() 12 | set(RUNJOB runjob) 13 | endif() 14 | set(EXE_CMD ${RUNJOB} ${RUNJOB_NPF} ${REQUIRED_OPTION} ${MPIEXEC_PREFLAGS} : ${_testExe} ${_testArgs}) 15 | else() 16 | set(MPIEXEC_NPF ${MPIEXEC_NUMPROC_FLAG} ${_numProc}) 17 | set(EXE_CMD ${MPIEXEC} ${MPIEXEC_NPF} ${MPIEXEC_PREFLAGS} ${_testExe} ${_testArgs}) 18 | endif() 19 | add_test(NAME ${_testName} COMMAND ${EXE_CMD}) 20 | set_tests_properties(${_testName} PROPERTIES TIMEOUT ${_timeout}) 21 | 22 | endfunction(add_mpi_test) 23 | -------------------------------------------------------------------------------- /pFUnit_utils.cmake: -------------------------------------------------------------------------------- 1 | # Utilities for using pFUnit's preprocessor and provided driver file. 2 | # 3 | # This module relies upon the variables defined by the FindpFUnit module. 4 | # 5 | #========================================================================== 6 | # 7 | # add_pFUnit_executable 8 | # 9 | # Arguments: 10 | # name - Name of the executable to add. 11 | # pf_file_list - List of .pf files to process. 12 | # output_directory - Directory where generated sources will be placed. 13 | # fortran_source_list - List of Fortran files to include. 14 | # 15 | # Preprocesses the input .pf files to create test suites, then creates an 16 | # executable that drives those suites with the pFUnit driver. 17 | # 18 | # Limitations: 19 | # add_pFUnit_executable cannot currently handle cases where the user 20 | # choses to do certain things "manually", such as: 21 | # 22 | # - Test suites written in normal Fortran (not .pf) files. 23 | # - User-specified testSuites.inc 24 | # - User-specified driver file in fortran_source_list. 25 | # 26 | #========================================================================== 27 | # 28 | # define_pFUnit_failure 29 | # 30 | # Arguments: 31 | # test_name - Name of a CTest test. 32 | # 33 | # Defines FAIL_REGULAR_EXPRESSION and PASS_REGULAR_EXPRESSION for the given 34 | # test, so that pFUnit's overall pass/fail status can be detected. 35 | # 36 | #========================================================================== 37 | # 38 | # create_pFUnit_test 39 | # 40 | # Required arguments: 41 | # test_name - Name of a CTest test. 42 | # executable_name - Name of the executable associated with this test. 43 | # pf_file_list - List of .pf files to process. 44 | # fortran_source_list - List of Fortran files to include. 45 | # 46 | # Optional arguments, specified via keyword: 47 | # GEN_OUTPUT_DIRECTORY - directory for generated source files, relative to CMAKE_CURRENT_BINARY_DIR 48 | # - Defaults to CMAKE_CURRENT_BINARY_DIR 49 | # - Needs to be given if you have multiple separate pFUnit tests defined in the same directory 50 | # COMMAND - Command to run the pFUnit test 51 | # - Defaults to ./executable_name 52 | # - Needs to be given if you need more on the command line than just the executable 53 | # name, such as setting the number of threads 54 | # - A multi-part command should NOT be enclosed in quotes (see example below) 55 | # - COMMAND should NOT contain the mpirun command: this is specified 56 | # separately, via the PFUNIT_MPIRUN CMake variable 57 | # - The name of the executable should be prefixed with ./ for this to work 58 | # when dot is not in your path (e.g., ./foo_exe rather than simply foo_exe) 59 | # 60 | # Non-standard CMake variables used: 61 | # PFUNIT_MPIRUN - If executables need to be prefixed with an mpirun command, 62 | # PFUNIT_MPIRUN gives this prefix (e.g., "mpirun") 63 | # 64 | # Does everything needed to create a pFUnit-based test, wrapping 65 | # add_pFUnit_executable, add_test, and define_pFUnit_failure. 66 | # 67 | # Example, using defaults for the optional arguments: 68 | # create_pFUnit_test(mytest mytest_exe "${pfunit_sources}" "${test_sources}") 69 | # 70 | # Example, specifying values for the optional arguments: 71 | # create_pFUnit_test(mytest mytest_exe "${pfunit_sources}" "${test_sources}" 72 | # GEN_OUTPUT_DIRECTORY mytest_dir 73 | # COMMAND env OMP_NUM_THREADS=3 ./mytest_exe) 74 | # 75 | #========================================================================== 76 | 77 | #========================================================================== 78 | # Copyright (c) 2013-2014, University Corporation for Atmospheric Research 79 | # 80 | # This software is distributed under a two-clause BSD license, with no 81 | # warranties, express or implied. See the accompanying LICENSE file for 82 | # details. 83 | #========================================================================== 84 | 85 | include(CMakeParseArguments) 86 | 87 | # Notify CMake that a given Fortran file can be produced by preprocessing a 88 | # pFUnit file. 89 | function(preprocess_pf_suite pf_file fortran_file) 90 | 91 | add_custom_command(OUTPUT ${fortran_file} 92 | COMMAND python ${PFUNIT_PARSER} ${pf_file} ${fortran_file} 93 | MAIN_DEPENDENCY ${pf_file}) 94 | 95 | endfunction(preprocess_pf_suite) 96 | 97 | # This function manages most of the work involved in preprocessing pFUnit 98 | # files. You provide every *.pf file for a given executable, an output 99 | # directory where generated sources should be output, and a list name. It 100 | # will generate the sources, and append them and the pFUnit driver to the 101 | # named list. 102 | function(process_pFUnit_source_list pf_file_list output_directory 103 | fortran_list_name) 104 | 105 | foreach(pf_file IN LISTS pf_file_list) 106 | 107 | # If a file is a relative path, expand it (relative to current source 108 | # directory. 109 | get_filename_component(pf_file "${pf_file}" ABSOLUTE) 110 | 111 | # Get extensionless base name from input. 112 | get_filename_component(pf_file_stripped "${pf_file}" NAME_WE) 113 | 114 | # Add the generated Fortran files to the source list. 115 | set(fortran_file ${output_directory}/${pf_file_stripped}.F90) 116 | preprocess_pf_suite(${pf_file} ${fortran_file}) 117 | list(APPEND ${fortran_list_name} ${fortran_file}) 118 | 119 | # Add the file to testSuites.inc 120 | set(testSuites_contents 121 | "${testSuites_contents}ADD_TEST_SUITE(${pf_file_stripped}_suite)\n") 122 | endforeach() 123 | 124 | # Regenerate testSuites.inc if and only if necessary. 125 | if(EXISTS ${output_directory}/testSuites.inc) 126 | file(READ ${output_directory}/testSuites.inc old_testSuites_contents) 127 | endif() 128 | 129 | if(NOT testSuites_contents STREQUAL old_testSuites_contents) 130 | file(WRITE ${output_directory}/testSuites.inc ${testSuites_contents}) 131 | endif() 132 | 133 | # Export ${fortran_list_name} to the caller, and add ${PFUNIT_DRIVER} 134 | # to it. 135 | set(${fortran_list_name} "${${fortran_list_name}}" "${PFUNIT_DRIVER}" 136 | PARENT_SCOPE) 137 | 138 | endfunction(process_pFUnit_source_list) 139 | 140 | # Creates an executable of the given name using the pFUnit driver. Input 141 | # variables are the executable name, a list of .pf files, the output 142 | # directory for generated sources, and a list of regular Fortran files. 143 | function(add_pFUnit_executable name pf_file_list output_directory 144 | fortran_source_list) 145 | 146 | # Handle source code generation, add to list of sources. 147 | process_pFUnit_source_list("${pf_file_list}" ${output_directory} 148 | fortran_source_list) 149 | 150 | # Create the executable itself. 151 | add_executable(${name} ${fortran_source_list}) 152 | 153 | # Handle pFUnit linking. 154 | target_link_libraries(${name} "${PFUNIT_LIBRARIES}") 155 | 156 | # Necessary to include testSuites.inc 157 | get_target_property(includes ${name} INCLUDE_DIRECTORIES) 158 | if(NOT includes) 159 | unset(includes) 160 | endif() 161 | list(APPEND includes ${output_directory} "${PFUNIT_INCLUDE_DIRS}") 162 | set_target_properties(${name} PROPERTIES 163 | INCLUDE_DIRECTORIES "${includes}") 164 | 165 | # The above lines are equivalent to: 166 | # target_include_directories(${name} PRIVATE ${output_directory}) 167 | # However, target_include_directories was not added until 2.8.11, and at 168 | # the time of this writing, we can't depend on having such a recent 169 | # version of CMake available on HPC systems. 170 | 171 | endfunction(add_pFUnit_executable) 172 | 173 | # Tells CTest what regular expressions are used to signal pass/fail from 174 | # pFUnit output. 175 | function(define_pFUnit_failure test_name) 176 | # Set both pass and fail regular expressions to minimize the chance that 177 | # the system under test will interfere with output and cause a false 178 | # negative. 179 | set_tests_properties(${test_name} PROPERTIES 180 | FAIL_REGULAR_EXPRESSION "FAILURES!!!") 181 | set_tests_properties(${test_name} PROPERTIES 182 | PASS_REGULAR_EXPRESSION "OK") 183 | endfunction(define_pFUnit_failure) 184 | 185 | # Does everything needed to create a pFUnit-based test, wrapping add_pFUnit_executable, 186 | # add_test, and define_pFUnit_failure. 187 | # 188 | # Required input variables are the test name, the executable name, a list of .pf files, 189 | # and a list of regular Fortran files. 190 | # 191 | # Optional input variables are GEN_OUTPUT_DIRECTORY and COMMAND (see usage notes at the 192 | # top of this file for details). 193 | # 194 | # If executables need to be prefixed with an mpirun command, this prefix (e.g., 195 | # "mpirun") should be given in the CMAKE variable PFUNIT_MPIRUN. 196 | function(create_pFUnit_test test_name executable_name pf_file_list fortran_source_list) 197 | 198 | # Parse optional arguments 199 | set(options "") 200 | set(oneValueArgs GEN_OUTPUT_DIRECTORY) 201 | set(multiValueArgs COMMAND) 202 | cmake_parse_arguments(MY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 203 | if (MY_UNPARSED_ARGUMENTS) 204 | message(FATAL_ERROR "Unknown keywords given to create_pFUnit_test(): \"${MY_UNPARSED_ARGUMENTS}\"") 205 | endif() 206 | 207 | # Change GEN_OUTPUT_DIRECTORY to an absolute path, relative to CMAKE_CURRENT_BINARY_DIR 208 | # Note that, if GEN_OUTPUT_DIRECTORY isn't given, this logic will make the output 209 | # directory default to CMAKE_CURRENT_BINARY_DIR 210 | set(MY_GEN_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${MY_GEN_OUTPUT_DIRECTORY}) 211 | 212 | # Give default values to optional arguments that aren't present 213 | if (NOT MY_COMMAND) 214 | set(MY_COMMAND ./${executable_name}) 215 | endif() 216 | 217 | # Prefix command with an mpirun command 218 | set (MY_COMMAND ${PFUNIT_MPIRUN} ${MY_COMMAND}) 219 | 220 | # Do the work 221 | add_pFUnit_executable(${executable_name} "${pf_file_list}" 222 | ${MY_GEN_OUTPUT_DIRECTORY} "${fortran_source_list}") 223 | add_test(NAME ${test_name} COMMAND ${MY_COMMAND}) 224 | define_pFUnit_failure(${test_name}) 225 | 226 | endfunction(create_pFUnit_test) 227 | --------------------------------------------------------------------------------