Skip to content

Commit

Permalink
Merge branch 'release/8.7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
oehmke committed Oct 3, 2024
2 parents bf35bb7 + 6f0d6a1 commit 963a03e
Show file tree
Hide file tree
Showing 31 changed files with 581 additions and 26 deletions.
36 changes: 36 additions & 0 deletions ESMCXX_HelloWorld_CMake/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
################################################################################
# Configuration step: cmake -S . -B ./build
# Build step: cmake --build ./build -v
# Execution step: mpirun -np 8 ./build/ESMCXX_HelloWorld
# Clean-up step: rm -rf ./build PET*
################################################################################

cmake_minimum_required(VERSION 3.22)

# Where to look for the local Find<Package>.cmake files
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

# Find ESMF
find_package(ESMF 8.3.0 MODULE REQUIRED)

# Set compilers consistent with ESMF
set(CMAKE_Fortran_COMPILER "${ESMF_F90COMPILER}")
set(CMAKE_CXX_COMPILER "${ESMF_CXXCOMPILER}")
set(CMAKE_C_COMPILER "${ESMF_CCOMPILER}")

# Optionally set compiler options consistent with ESMF
set(CMAKE_Fortran_FLAGS "${ESMF_F90COMPILEOPTS}")
set(CMAKE_CXX_FLAGS "${ESMF_CXXCOMPILEOPTS}")
set(CMAKE_C_FLAGS "${ESMF_CCOMPILEOPTS}")

# Project
project(ESMCXX_HelloWorld_CMake
VERSION 1.0
LANGUAGES Fortran CXX C
)

# Executable
add_executable(ESMCXX_HelloWorld ESMCXX_HelloWorld.C)

# Executable depends on ESMF
target_link_libraries(ESMCXX_HelloWorld ESMF::ESMC)
25 changes: 25 additions & 0 deletions ESMCXX_HelloWorld_CMake/ESMCXX_HelloWorld.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Earth System Modeling Framework
// Copyright (c) 2002-2024, University Corporation for Atmospheric Research,
// Massachusetts Institute of Technology, Geophysical Fluid Dynamics
// Laboratory, University of Michigan, National Centers for Environmental
// Prediction, Los Alamos National Laboratory, Argonne National Laboratory,
// NASA Goddard Space Flight Center.
// Licensed under the University of Illinois-NCSA License.

#include "ESMC.h"

int main(int argc, char *argv[]){

// local variables
int rc;

rc = ESMC_Initialize(nullptr, ESMC_ArgLast);
if (rc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

rc = ESMC_LogWrite(">>> Hello ESMC World from C++ <<<", ESMC_LOGMSG_INFO);
if (rc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

rc = ESMC_Finalize();

return 0;
}
33 changes: 33 additions & 0 deletions ESMCXX_HelloWorld_CMake/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
ESMCXX_HelloWorld_CMake
=======================

This directory contains code that is based on the ESMF C API (commonly referred to as ESMC) from C++.

The application writes ">>> Hello ESMC World from C++ <<<" to the ESMF default log (see PET*.ESMF_LogFile's).

The main purpose of this example is to demonstrate the use of CMake for ESMF applications written in C++. The code is accompanied by `CMakeLists.txt` and `cmake/FindESMF.cmake` files.

Notice the dependency of the example on a relatively recent release of CMake: version 3.22. This is specified in file `CMakeLists.txt`. The primary reason for this restictive dependency is that not until version 3.22 was it supported to use the `find_package()` and `set()` functions before `project()`. Hence it was more difficult in the older versions to specified the compilers consistent with those used by ESMF.

Notice that it is possible to get the desired end result with previous versions of CMake, requiring some re-arranging of the order of functions in `CMakeLists.txt`. However, the more recently supported order of functions leads to a simpler and more intuitive version of `CMakeLists.txt` file shown here.

The code can be built using any of the usual CMake build procedures:

mkdir build; cd build
cmake ..
make

or alternatively using the `-S`, `-B`, and `--build` CMake options:

cmake -S . -B ./build
cmake --build ./build

And execute on 8 PETs, e.g. via mpirun:

mpirun -np 8 ./build/ESMCXX_HelloWorld

================================================================================

Please contact [email protected] with any questions or problems.

================================================================================
167 changes: 167 additions & 0 deletions ESMCXX_HelloWorld_CMake/cmake/FindESMF.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# - Try to find ESMF
#
# Uses ESMFMKFILE to find the filepath of esmf.mk. If this is NOT set, then this
# module will attempt to find esmf.mk. If ESMFMKFILE exists, then
# ESMF_FOUND=TRUE and all ESMF makefile variables will be set in the global
# scope. Optionally, set ESMF_MKGLOBALS to a string list to filter makefile
# variables. For example, to globally scope only ESMF_LIBSDIR and ESMF_APPSDIR
# variables, use this CMake command in CMakeLists.txt:
#
# set(ESMF_MKGLOBALS "LIBSDIR" "APPSDIR")

# Set ESMFMKFILE as defined by system env variable. If it's not explicitly set
# try to find esmf.mk file in default locations (ESMF_ROOT, CMAKE_PREFIX_PATH,
# etc)
if(NOT DEFINED ESMFMKFILE)
if(NOT DEFINED ENV{ESMFMKFILE})
find_path(ESMFMKFILE_PATH esmf.mk PATH_SUFFIXES lib lib64)
if(ESMFMKFILE_PATH)
set(ESMFMKFILE ${ESMFMKFILE_PATH}/esmf.mk)
message(STATUS "Found esmf.mk file ${ESMFMKFILE}")
endif()
else()
set(ESMFMKFILE $ENV{ESMFMKFILE})
endif()
endif()

# Only parse the mk file if it is found
if(EXISTS ${ESMFMKFILE})
set(ESMFMKFILE ${ESMFMKFILE} CACHE FILEPATH "Path to esmf.mk file")
set(ESMF_FOUND TRUE CACHE BOOL "esmf.mk file found" FORCE)

# Read the mk file
file(STRINGS "${ESMFMKFILE}" esmfmkfile_contents)
# Parse each line in the mk file
foreach(str ${esmfmkfile_contents})
# Only consider uncommented lines
string(REGEX MATCH "^[^#]" def ${str})
# Line is not commented
if(def)
# Extract the variable name
string(REGEX MATCH "^[^=]+" esmf_varname ${str})
# Extract the variable's value
string(REGEX MATCH "=.+$" esmf_vardef ${str})
# Only for variables with a defined value
if(esmf_vardef)
# Get rid of the assignment string
string(SUBSTRING ${esmf_vardef} 1 -1 esmf_vardef)
# Remove whitespace
string(STRIP ${esmf_vardef} esmf_vardef)
# A string or single-valued list
if(NOT DEFINED ESMF_MKGLOBALS)
# Set in global scope
set(${esmf_varname} ${esmf_vardef})
# Don't display by default in GUI
mark_as_advanced(esmf_varname)
else() # Need to filter global promotion
foreach(m ${ESMF_MKGLOBALS})
string(FIND ${esmf_varname} ${m} match)
# Found the string
if(NOT ${match} EQUAL -1)
# Promote to global scope
set(${esmf_varname} ${esmf_vardef})
# Don't display by default in the GUI
mark_as_advanced(esmf_varname)
# No need to search for the current string filter
break()
endif()
endforeach()
endif()
endif()
endif()
endforeach()

# Construct ESMF_VERSION from ESMF_VERSION_STRING_GIT
# ESMF_VERSION_MAJOR and ESMF_VERSION_MINOR are defined in ESMFMKFILE
set(ESMF_VERSION 0)
set(ESMF_VERSION_PATCH ${ESMF_VERSION_REVISION})
set(ESMF_BETA_RELEASE FALSE)
if(ESMF_VERSION_BETASNAPSHOT MATCHES "^('T')$")
set(ESMF_BETA_RELEASE TRUE)
if(ESMF_VERSION_STRING_GIT MATCHES "^ESMF.*beta_snapshot")
set(ESMF_BETA_SNAPSHOT ${ESMF_VERSION_STRING_GIT})
elseif(ESMF_VERSION_STRING_GIT MATCHES "^v.\..\..b")
set(ESMF_BETA_SNAPSHOT ${ESMF_VERSION_STRING_GIT})
else()
set(ESMF_BETA_SNAPSHOT 0)
endif()
message(STATUS "Detected ESMF Beta snapshot: ${ESMF_BETA_SNAPSHOT}")
endif()
set(ESMF_VERSION "${ESMF_VERSION_MAJOR}.${ESMF_VERSION_MINOR}.${ESMF_VERSION_PATCH}")

# Find the ESMF library
if(USE_ESMF_STATIC_LIBS)
find_library(ESMF_LIBRARY_LOCATION NAMES libesmf.a PATHS ${ESMF_LIBSDIR} NO_DEFAULT_PATH)
if(ESMF_LIBRARY_LOCATION MATCHES "ESMF_LIBRARY_LOCATION-NOTFOUND")
message(WARNING "Static ESMF library (libesmf.a) not found in \
${ESMF_LIBSDIR}. Try setting USE_ESMF_STATIC_LIBS=OFF")
endif()
if(NOT TARGET ESMF::ESMF)
add_library(ESMF::ESMF STATIC IMPORTED)
endif()
if(NOT TARGET ESMF::ESMC)
add_library(ESMF::ESMC STATIC IMPORTED)
endif()
else()
find_library(ESMF_LIBRARY_LOCATION NAMES esmf PATHS ${ESMF_LIBSDIR} NO_DEFAULT_PATH)
if(ESMF_LIBRARY_LOCATION MATCHES "ESMF_LIBRARY_LOCATION-NOTFOUND")
message(WARNING "ESMF library not found in ${ESMF_LIBSDIR}.")
endif()
if(NOT TARGET ESMF::ESMF)
add_library(ESMF::ESMF UNKNOWN IMPORTED)
endif()
if(NOT TARGET ESMF::ESMC)
add_library(ESMF::ESMC UNKNOWN IMPORTED)
endif()
endif()

# Add ESMF as an alias to ESMF::ESMF for backward compatibility
if(NOT TARGET ESMF)
add_library(ESMF ALIAS ESMF::ESMF)
endif()

# Add ESMF include directories
set(ESMF_INCLUDE_DIRECTORIES "")
separate_arguments(_ESMF_F90COMPILEPATHS UNIX_COMMAND ${ESMF_F90COMPILEPATHS})
foreach(_ITEM ${_ESMF_F90COMPILEPATHS})
string(REGEX REPLACE "^-I" "" _ITEM "${_ITEM}")
list(APPEND ESMF_INCLUDE_DIRECTORIES ${_ITEM})
endforeach()
set(ESMC_INCLUDE_DIRECTORIES "")
separate_arguments(_ESMF_CCOMPILEPATHS UNIX_COMMAND ${ESMF_CCOMPILEPATHS})
foreach(_ITEM ${_ESMF_CCOMPILEPATHS})
string(REGEX REPLACE "^-I" "" _ITEM "${_ITEM}")
list(APPEND ESMC_INCLUDE_DIRECTORIES ${_ITEM})
endforeach()

# Add ESMF link libraries
string(STRIP "${ESMF_F90LINKRPATHS} ${ESMF_F90ESMFLINKRPATHS} ${ESMF_F90ESMFLINKPATHS} ${ESMF_F90LINKPATHS} ${ESMF_F90LINKLIBS} ${ESMF_F90LINKOPTS}" ESMF_INTERFACE_LINK_LIBRARIES)
string(STRIP "${ESMF_CLINKRPATHS} ${ESMF_CESMFLINKRPATHS} ${ESMF_CESMFLINKPATHS} ${ESMF_CLINKPATHS} ${ESMF_CLINKLIBS} ${ESMF_CLINKOPTS}" ESMC_INTERFACE_LINK_LIBRARIES)

# Finalize find_package
include(FindPackageHandleStandardArgs)

find_package_handle_standard_args(
${CMAKE_FIND_PACKAGE_NAME}
REQUIRED_VARS ESMF_LIBRARY_LOCATION
ESMF_INCLUDE_DIRECTORIES
ESMC_INCLUDE_DIRECTORIES
ESMF_INTERFACE_LINK_LIBRARIES
ESMC_INTERFACE_LINK_LIBRARIES
VERSION_VAR ESMF_VERSION)

set_target_properties(ESMF::ESMF PROPERTIES
IMPORTED_LOCATION "${ESMF_LIBRARY_LOCATION}"
INTERFACE_INCLUDE_DIRECTORIES "${ESMF_INCLUDE_DIRECTORIES}"
INTERFACE_LINK_LIBRARIES "${ESMF_INTERFACE_LINK_LIBRARIES}")

set_target_properties(ESMF::ESMC PROPERTIES
IMPORTED_LOCATION "${ESMF_LIBRARY_LOCATION}"
INTERFACE_INCLUDE_DIRECTORIES "${ESMC_INCLUDE_DIRECTORIES}"
INTERFACE_LINK_LIBRARIES "${ESMC_INTERFACE_LINK_LIBRARIES}")

else()
set(ESMF_FOUND FALSE CACHE BOOL "esmf.mk file NOT found" FORCE)
message(WARNING "ESMFMKFILE ${ESMFMKFILE} not found. Try setting ESMFMKFILE \
to esmf.mk location.")
endif()
39 changes: 39 additions & 0 deletions ESMC_HelloWorld_CMake/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
################################################################################
# Configuration step: cmake -S . -B ./build
# Build step: cmake --build ./build -v
# Execution step: mpirun -np 8 ./build/ESMC_HelloWorld
# Clean-up step: rm -rf ./build PET*
################################################################################

cmake_minimum_required(VERSION 3.22)

# Where to look for the local Find<Package>.cmake files
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

# Find ESMF
find_package(ESMF 8.3.0 MODULE REQUIRED)

# Set compilers consistent with ESMF
set(CMAKE_Fortran_COMPILER "${ESMF_F90COMPILER}")
set(CMAKE_CXX_COMPILER "${ESMF_CXXCOMPILER}")
set(CMAKE_C_COMPILER "${ESMF_CCOMPILER}")

# Optionally set compiler options consistent with ESMF
set(CMAKE_Fortran_FLAGS "${ESMF_F90COMPILEOPTS}")
set(CMAKE_CXX_FLAGS "${ESMF_CXXCOMPILEOPTS}")
set(CMAKE_C_FLAGS "${ESMF_CCOMPILEOPTS}")

# Project
project(ESMC_HelloWorld_CMake
VERSION 1.0
LANGUAGES Fortran CXX C
)

# Executable
add_executable(ESMC_HelloWorld ESMC_HelloWorld.c)

# Executable depends on ESMF
target_link_libraries(ESMC_HelloWorld ESMF::ESMC)

# Support C99 standard
set_target_properties(ESMC_HelloWorld PROPERTIES C_STANDARD 99)
26 changes: 26 additions & 0 deletions ESMC_HelloWorld_CMake/ESMC_HelloWorld.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Earth System Modeling Framework
// Copyright (c) 2002-2024, University Corporation for Atmospheric Research,
// Massachusetts Institute of Technology, Geophysical Fluid Dynamics
// Laboratory, University of Michigan, National Centers for Environmental
// Prediction, Los Alamos National Laboratory, Argonne National Laboratory,
// NASA Goddard Space Flight Center.
// Licensed under the University of Illinois-NCSA License.

#include <stddef.h>
#include "ESMC.h"

int main(int argc, char *argv[]){

// local variables
int rc;

rc = ESMC_Initialize(NULL, ESMC_ArgLast);
if (rc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

rc = ESMC_LogWrite(">>> Hello ESMC World <<<", ESMC_LOGMSG_INFO);
if (rc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

rc = ESMC_Finalize();

return 0;
}
33 changes: 33 additions & 0 deletions ESMC_HelloWorld_CMake/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
ESMC_HelloWorld_CMake
=====================

This directory contains code that is based on the ESMF C API (commonly referred to as ESMC).

The application writes ">>> Hello ESMC World <<<" to the ESMF default log (see PET*.ESMF_LogFile's).

The main purpose of this example is to demonstrate the use of CMake for ESMF applications written in C. The code is accompanied by `CMakeLists.txt` and `cmake/FindESMF.cmake` files.

Notice the dependency of the example on a relatively recent release of CMake: version 3.22. This is specified in file `CMakeLists.txt`. The primary reason for this restictive dependency is that not until version 3.22 was it supported to use the `find_package()` and `set()` functions before `project()`. Hence it was more difficult in the older versions to specified the compilers consistent with those used by ESMF.

Notice that it is possible to get the desired end result with previous versions of CMake, requiring some re-arranging of the order of functions in `CMakeLists.txt`. However, the more recently supported order of functions leads to a simpler and more intuitive version of `CMakeLists.txt` file shown here.

The code can be built using any of the usual CMake build procedures:

mkdir build; cd build
cmake ..
make

or alternatively using the `-S`, `-B`, and `--build` CMake options:

cmake -S . -B ./build
cmake --build ./build

And execute on 8 PETs, e.g. via mpirun:

mpirun -np 8 ./build/ESMC_HelloWorld

================================================================================

Please contact [email protected] with any questions or problems.

================================================================================
Loading

0 comments on commit 963a03e

Please sign in to comment.