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

Add find-package modules for GPTL, PnetCDF, udunits (unify JCSDA and EMC cmakemodules) #64

Merged
Merged
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
180 changes: 180 additions & 0 deletions Modules/FindGPTL.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# (C) Copyright 2020- UCAR.
#
# Find the GPTL: General Purpose Timing Library (https://jmrosinski.github.io/GPTL/)
#
# This find module sets the following variables and targets:
#
# Variables:
# GPTL_FOUND - True if GPTL was found
# GPTL_VERSION_STRING - Version of installed GPTL
# GPTL_BIN_DIR - GPTL binary directory
# GPTL_HAS_PKG_CONFIG - GPTL was found with installed `gptl.pc` and pkg-config. This indicates full support
# for compiler and linker flags as exported by GPTL.
# Targets:
# GPTL::GPTL - Imported interface target to pass to target_link_libraries()
#
# NOTE: This find modules uses `pkg-config` to locate GPTL and glean the appropriate flags, directories,
# and link dependency ordering. For this to work, both a `pkg-config` executable and a `gptl.pc`
# config file need to be found.
# * To find the `pkg-config` executable, ensure it is on your PATH.
# * For non-standard locations the official CMake FindPkgConfig uses Cmake variable `PKG_CONFIG_EXECUTABLE`
# or environment variable `PKG_CONFIG`. See: https://cmake.org/cmake/help/latest/module/FindPkgConfig.html
# * To find `gptl.pc` ensure it is on the (colon-separated) directories listed in standard pkg-config
# environment variable `PKG_CONFIG_PATH`.
# * See: https://linux.die.net/man/1/pkg-config
# * A working GPTL pkg-config install can be confirmed on the command line, e.g.,
# ```
# $ pkg-config --modversion gptl
# 8.0.2
# ```
# To set a non-standard location for GPTL, ensure the correct `gptl.pc` pkg config file is found first
# on the environment's `PKG_CONFIG_PATH`. This can be checked with the pkg-config executable, e.g.,
# ```
# $ pkg-config --variable=prefix gptl
# /usr/local
# ```
# Only when pkg-config is not supported or available, GPTL will be searched by the standard CMake search procedures.
# Set environment or CMake variable GPTL_ROOT to control this search. The GPTL_ROOT variable will have no effect
# if GPTL_HAS_PKG_CONFIG=True.
#

find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
message(DEBUG "[FindGPTL] Using PKG_CONFIG_EXECUTABLE:${PKG_CONFIG_EXECUTABLE}")
endif()

#Helper:
#check_pkg_config(ret_var pcname pcflags...)
# Check if pcname is known to pkg-config
# Returns:
# Boolean: true if ${pcname}.pc file is found by pkg-config).
# Args:
# ret_var: return variable name.
# pcname: pkg-config name to look for (.pc file)
function(check_pkg_config ret_var pcname)
if(NOT PKG_CONFIG_FOUND OR NOT EXISTS ${PKG_CONFIG_EXECUTABLE})
set(${ret_var} False PARENT_SCOPE)
else()
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --exists ${pcname} RESULT_VARIABLE _found)
if(_found EQUAL 0)
set(${ret_var} True PARENT_SCOPE)
else()
set(${ret_var} False PARENT_SCOPE)
endif()
endif()
endfunction()

#Helper:
#get_pkg_config(ret_var pcname pcflags...)
# Get the output of pkg-config
# Args:
# ret_var: return variable name
# pcname: pkg-config name to look for (.pc file)
# pcflags: pkg-config flags to pass
function(get_pkg_config ret_var pcname pcflags)
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} ${ARGN} ${pcname} ${pcflags} OUTPUT_VARIABLE _out RESULT_VARIABLE _ret OUTPUT_STRIP_TRAILING_WHITESPACE)
if(_ret EQUAL 0)
separate_arguments(_out)
set(${ret_var} ${_out} PARENT_SCOPE)
else()
set(${ret_var} "" PARENT_SCOPE)
endif()
endfunction()

check_pkg_config(GPTL_HAS_PKG_CONFIG gptl)
if(GPTL_HAS_PKG_CONFIG)
#Use pkg-config to find the prefix, flags, directories, executables, and libraries
get_pkg_config(GPTL_VERSION_STRING gptl --modversion)
get_pkg_config(GPTL_PREFIX gptl --variable=prefix)
get_pkg_config(GPTL_INCLUDE_DIR gptl --cflags-only-I)
if(GPTL_INCLUDE_DIR)
string(REGEX REPLACE "-I([^ ]+)" "\\1" GPTL_INCLUDE_DIR ${GPTL_INCLUDE_DIR}) #Remove -I
endif()
if(NOT EXISTS ${GPTL_INCLUDE_DIR})
find_path(GPTL_INCLUDE_DIR NAMES gptl.h PATH_SUFFIXES include include/gptl PATHS ${GPTL_PREFIX} NO_DEFAULT_PATH)
endif()
find_path(GPTL_MODULE_DIR NAMES gptl.mod PATH_SUFFIXES include include/gptl module module/gptl PATHS ${GPTL_PREFIX} NO_DEFAULT_PATH)
get_pkg_config(GPTL_COMPILE_OPTIONS gptl --cflags-only-other)
get_pkg_config(GPTL_LINK_LIBRARIES gptl --libs-only-l)
get_pkg_config(GPTL_LINK_DIRECTORIES gptl --libs-only-L)
if(GPTL_LINK_DIRECTORIES)
string(REGEX REPLACE "-L([^ ]+)" "\\1" GPTL_LINK_DIRECTORIES ${GPTL_LINK_DIRECTORIES}) #Remove -L
endif()
get_pkg_config(GPTL_LINK_OPTIONS gptl --libs-only-other)
find_library(GPTL_LIBRARY NAMES gptl PATH_SUFFIXES lib lib64 PATHS ${GPTL_PREFIX} NO_DEFAULT_PATH)
find_path(GPTL_BIN_DIR NAMES gptl_avail gran_overhead print_mpistatus_size PATH_SUFFIXES bin PATHS ${GPTL_PREFIX} NO_DEFAULT_PATH)
else()
#Attempt to find GPTL without pkg-config as last resort.
if(NOT EXISTS ${PKG_CONFIG_EXECUTABLE})
message(WARNING "\
FindGPTL: The `pkg-config` executable was not found. Ensure it is on your path or set \
environment variable PKG_CONFIG to your pkg-config executable. \
Attempting to find GPTL without pkg-config support may cause some required compiler and linker options to be unset.")
else()
message(WARNING "\
FindGPTL: The `pkg-config` executable was found at: ${PKG_CONFIG_EXECUTABLE}. However no `gptl.pc` file was found on \
PKG_CONFIG_PATH='$ENV{PKG_CONFIG_PATH}'. \
Attempting to find GPTL without pkg-config support may cause some required compiler and linker options to be unset.")
endif()
find_path(GPTL_INCLUDE_DIR NAMES gptl.h PATH_SUFFIXES include include/gptl)
find_path(GPTL_MODULE_DIR NAMES gptl.mod PATH_SUFFIXES include include/gptl module module/gptl)
find_library(GPTL_LIBRARY NAMES gptl PATH_SUFFIXES lib lib64)
find_path(GPTL_BIN_DIR NAMES gptl_avail gran_overhead print_mpistatus_size PATH_SUFFIXES bin)
endif()

#Hide non-documented cache variables reserved for internal/advanced usage
mark_as_advanced( GPTL_INCLUDE_DIR
GPTL_MODULE_DIR
GPTL_LIBRARY )

#Debugging output
message(DEBUG "[FindGPTL] GPTL_FOUND: ${GPTL_FOUND}")
message(DEBUG "[FindGPTL] GPTL_VERSION_STRING: ${GPTL_VERSION_STRING}")
message(DEBUG "[FindGPTL] GPTL_HAS_PKG_CONFIG: ${GPTL_HAS_PKG_CONFIG}")
message(DEBUG "[FindGPTL] GPTL_PREFIX: ${GPTL_PREFIX}")
message(DEBUG "[FindGPTL] GPTL_BIN_DIR: ${GPTL_BIN_DIR}")
message(DEBUG "[FindGPTL] GPTL_INCLUDE_DIR: ${GPTL_INCLUDE_DIR}")
message(DEBUG "[FindGPTL] GPTL_MODULE_DIR: ${GPTL_MODULE_DIR}")
message(DEBUG "[FindGPTL] GPTL_LIBRARY: ${GPTL_LIBRARY}")
message(DEBUG "[FindGPTL] GPTL_LINK_LIBRARIES: ${GPTL_LINK_LIBRARIES}")
message(DEBUG "[FindGPTL] GPTL_LINK_DIRECTORIES: ${GPTL_LINK_DIRECTORIES}")
message(DEBUG "[FindGPTL] GPTL_LINK_OPTIONS: ${GPTL_LINK_OPTIONS}")

#Check package has been found correctly
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
GPTL
REQUIRED_VARS
GPTL_LIBRARY
GPTL_INCLUDE_DIR
GPTL_MODULE_DIR
GPTL_BIN_DIR
VERSION_VAR
GPTL_VERSION_STRING
)

#Create GPTL::GPTL imported interface target
if(GPTL_FOUND AND NOT TARGET GPTL::GPTL)
add_library(GPTL::GPTL INTERFACE IMPORTED)
set_property(TARGET GPTL::GPTL PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${GPTL_INCLUDE_DIR})
if(GPTL_MODULE_DIR)
set_property(TARGET GPTL::GPTL APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${GPTL_MODULE_DIR})
endif()
if(GPTL_COMPILE_OPTIONS)
set_property(TARGET GPTL::GPTL PROPERTY INTERFACE_COMPILE_OPTIONS ${GPTL_COMPILE_OPTIONS})
endif()
if(GPTL_LINK_DIRECTORIES)
set_property(TARGET GPTL::GPTL PROPERTY INTERFACE_LINK_DIRECTORIES ${GPTL_LINK_DIRECTORIES})
endif()
if(GPTL_LINK_OPTIONS)
set_property(TARGET GPTL::GPTL PROPERTY INTERFACE_LINK_OPTIONS ${GPTL_LINK_OPTIONS})
endif()
if(GPTL_LINK_LIBRARIES)
set_property(TARGET GPTL::GPTL PROPERTY INTERFACE_LINK_LIBRARIES ${GPTL_LINK_LIBRARIES})
else()
set_property(TARGET GPTL::GPTL PROPERTY INTERFACE_LINK_LIBRARIES ${GPTL_LIBRARY})
get_filename_component(_lib_dir ${GPTL_LIBRARY} DIRECTORY)
set_property(TARGET GPTL::GPTL APPEND PROPERTY INTERFACE_LINK_DIRECTORIES ${_lib_dir})
unset(_lib_dir)
endif()
endif()
174 changes: 174 additions & 0 deletions Modules/FindPnetCDF.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# (C) Copyright 2020- UCAR.
#
# Find PnetCDF: A Parallel I/O Library for NetCDF File Access
# https://parallel-netcdf.github.io/
#
# Components available for query:
# C - Has C support
# CXX - Has CXX support
# Fortran - Has Fortran support
# NetCDF4 - Has NetCDF4 output support
# GPTL - Has profiling support with GPTL enabled
# Threads - Has thread safety enabled
#
# Variables provided:
# PnetCDF_FOUND - True if PnetCDFL was found
# PnetCDF_CONFIG_EXE - pnetcdf-config executable if found
# PnetCDF_VERSION - Version of installed PnetCDF
# PnetCDF_BIN_DIR - PnetCDF binary directory
# PnetCDF_DEBUG - True if PnetCDF is built in debug mode
#
# Targets provided:
# PnetCDF::PnetCDF_Fortran - Fortran interface target
# PnetCDF::PnetCDF_C - C interface target
# PnetCDF::PnetCDF_CXX - CXX interface target
#
# Functions provided:
# pnetcdf_get_config(ret_var flags) - Call `pnetcdf-config` with flags and set ret_var with output on execution success.
#
#
# This module requires the `pnetcdf-config` executable to detect the directories and compiler and linker flags
# necessary for the PnetCDF::PnetCDF target. To control where PnetCDF is found:
# * Option 1: Set an environment or cmake variable `PnetCDF_ROOT` to the install prefix for PnetCDF (e.g. /usr/local)
# * Option 2: Set an environment or cmake variable `PnetCDF_CONFIG_EXE` to the full path to the `pnetcdf-config`
# (e.g., /usr/local/bin/pnetcdf-config)
#

find_program(PnetCDF_CONFIG_EXE NAMES pnetcdf-config PATH_SUFFIXES bin bin64 PATHS
$ENV{PnetCDF_CONFIG_EXE} ${PnetCDF_ROOT} $ENV{PnetCDF_ROOT} ${PNETCDF_ROOT} $ENV{PNETCDF_ROOT})
message(DEBUG "[FindPnetCDF] Using PnetCDF_CONFIG_EXE:${PnetCDF_CONFIG_EXE}")

# pnetcdf_get_config(ret_var flags...)
# Get the output of pnetcdf-config
# Args:
# ret_var: return variable name
# flags: flags to pass to pnetcdf-config
function(pnetcdf_get_config ret_var pcflags)
execute_process(COMMAND ${PnetCDF_CONFIG_EXE} ${pcflags} OUTPUT_VARIABLE _out RESULT_VARIABLE _ret OUTPUT_STRIP_TRAILING_WHITESPACE)
if(_ret EQUAL 0)
separate_arguments(_out)
set(${ret_var} ${_out} PARENT_SCOPE)
else()
set(${ret_var} "" PARENT_SCOPE)
endif()
endfunction()

## Find libraries and paths, and determine found components
if(EXISTS ${PnetCDF_CONFIG_EXE})
#Use pnetcdf-config to find the prefix, flags, directories, executables, and libraries
pnetcdf_get_config(PnetCDF_VERSION --version)
string(REGEX MATCH "([0-9.]+)" PnetCDF_VERSION "${PnetCDF_VERSION}") #Match only version actual number

pnetcdf_get_config(PnetCDF_PREFIX --prefix)
pnetcdf_get_config(PnetCDF_CXX_FOUND --has-c++)
pnetcdf_get_config(PnetCDF_Fortran_FOUND --has-fortran)
pnetcdf_get_config(PnetCDF_NetCDF4_FOUND --netcdf4)
pnetcdf_get_config(PnetCDF_GPTL_FOUND --profiling)
pnetcdf_get_config(PnetCDF_Threads_FOUND --thread-safe)
pnetcdf_get_config(PnetCDF_DEBUG --debug)
pnetcdf_get_config(PnetCDF_INCLUDE_DIR --includedir)
pnetcdf_get_config(PnetCDF_LIB_DIR --libdir)

#Translate boolean variables from pnetcdf-config enabled/disabled to True/False
foreach(_var IN ITEMS PnetCDF_CXX_FOUND PnetCDF_Fortran_FOUND PnetCDF_NetCDF4_FOUND PnetCDF_GPTL_FOUND PnetCDF_Threads_FOUND PnetCDF_DEBUG)
if( ${_var} MATCHES "(enabled)|([Yy][Ee][Ss])")
set(${_var} True)
else()
set(${_var} False)
endif()
endforeach()

find_path(PnetCDF_MODULE_DIR NAMES pnetcdf.mod HINTS ${PnetCDF_PREFIX} ${PnetCDF_INCLUDE_DIR}
PATH_SUFFIXES include include/pnetcdf module module/pnetcdf lib/pnetcdf/module NO_DEFAULT_PATH)
if(PnetCDF_Fortran_FOUND AND NOT EXISTS ${PnetCDF_MODULE_DIR})
message(WARNING "[PnetCDF] pnetcdf-config --has-fortran=yes, but could not find pnetcdf.mod. Set PnetCDF_MODULE_DIR to path containing pnetcdf.mod")
set(PnetCDF_Fortran_FOUND NO)
endif()

if(PnetCDF_INCLUDE_DIR AND PnetCDF_LIB_DIR)
set(PnetCDF_C_FOUND True)
endif()

find_path(PnetCDF_BIN_DIR NAMES pnetcdf-config PATH_SUFFIXES bin PATHS ${PnetCDF_PREFIX} NO_DEFAULT_PATH)
find_library(PnetCDF_LIBRARY NAMES pnetcdf PATH_SUFFIXES lib lib64 PATHS ${PnetCDF_PREFIX} NO_DEFAULT_PATH)
#Hide non-documented cache variables reserved for internal/advanced usage
mark_as_advanced( PnetCDF_MODULE_DIR PnetCDF_LIBRARY )
endif()

## Debugging output
message(DEBUG "[FindPnetCDF] PnetCDF_CONFIG_EXE: ${PnetCDF_CONFIG_EXE}")
message(DEBUG "[FindPnetCDF] PnetCDF_VERSION: ${PnetCDF_VERSION}")
message(DEBUG "[FindPnetCDF] PnetCDF_C_FOUND: ${PnetCDF_C_FOUND}")
message(DEBUG "[FindPnetCDF] PnetCDF_CXX_FOUND: ${PnetCDF_CXX_FOUND}")
message(DEBUG "[FindPnetCDF] PnetCDF_Fortran_FOUND: ${PnetCDF_Fortran_FOUND}")
message(DEBUG "[FindPnetCDF] PnetCDF_NetCDF4_FOUND: ${PnetCDF_NetCDF4_FOUND}")
message(DEBUG "[FindPnetCDF] PnetCDF_GPTL_FOUND: ${PnetCDF_GPTL_FOUND}")
message(DEBUG "[FindPnetCDF] PnetCDF_Threads_FOUND: ${PnetCDF_Threads_FOUND}")
message(DEBUG "[FindPnetCDF] PnetCDF_DEBUG: ${PnetCDF_DEBUG}")
message(DEBUG "[FindPnetCDF] PnetCDF_PREFIX: ${PnetCDF_PREFIX}")
message(DEBUG "[FindPnetCDF] PnetCDF_BIN_DIR: ${PnetCDF_BIN_DIR}")
message(DEBUG "[FindPnetCDF] PnetCDF_INCLUDE_DIR: ${PnetCDF_INCLUDE_DIR}")
message(DEBUG "[FindPnetCDF] PnetCDF_MODULE_DIR: ${PnetCDF_MODULE_DIR}")
message(DEBUG "[FindPnetCDF] PnetCDF_LIB_DIR: ${PnetCDF_LIB_DIR}")

## Check package has been found correctly
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
PnetCDF
REQUIRED_VARS
PnetCDF_CONFIG_EXE
PnetCDF_PREFIX
VERSION_VAR
PnetCDF_VERSION
HANDLE_COMPONENTS
)
message(DEBUG "[FindPnetCDF] PnetCDF_FOUND: ${PnetCDF_FOUND}")

## Create targets
set(_new_components)

# PnetCDF::PnetCDF_Fortran imported interface target
if(PnetCDF_Fortran_FOUND AND NOT TARGET PnetCDF::PnetCDF_Fortran)
add_library(PnetCDF::PnetCDF_Fortran INTERFACE IMPORTED)
set_target_properties(PnetCDF::PnetCDF_Fortran PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${PnetCDF_INCLUDE_DIR}
INTERFACE_LINK_DIRECTORIES ${PnetCDF_LIB_DIR})
if(PnetCDF_MODULE_DIR AND NOT PnetCDF_MODULE_DIR STREQUAL PnetCDF_INCLUDE_DIR )
set_property(TARGET PnetCDF::PnetCDF_Fortran APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PnetCDF_MODULE_DIR})
endif()
set(_new_components 1)
target_link_libraries(PnetCDF::PnetCDF_Fortran INTERFACE -lpnetcdf)
endif()

# PnetCDF::PnetCDF_C imported interface target
if(PnetCDF_C_FOUND AND NOT TARGET PnetCDF::PnetCDF_C)
add_library(PnetCDF::PnetCDF_C INTERFACE IMPORTED)
set_target_properties(PnetCDF::PnetCDF_C PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${PnetCDF_INCLUDE_DIR}
INTERFACE_LINK_DIRECTORIES ${PnetCDF_LIB_DIR})
set(_new_components 1)
target_link_libraries(PnetCDF::PnetCDF_C INTERFACE -lpnetcdf)
endif()

# PnetCDF::PnetCDF_CXX imported interface target
if(PnetCDF_CXX_FOUND AND NOT TARGET PnetCDF::PnetCDF_CXX)
add_library(PnetCDF::PnetCDF_CXX INTERFACE IMPORTED)
set_target_properties(PnetCDF::PnetCDF_CXX PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${PnetCDF_INCLUDE_DIR}
INTERFACE_LINK_DIRECTORIES ${PnetCDF_LIB_DIR})
set(_new_components 1)
target_link_libraries(PnetCDF::PnetCDF_CXX INTERFACE -lpnetcdf)
endif()

## Print status
if(${CMAKE_FIND_PACKAGE_NAME}_FOUND AND NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY AND _new_components)
message( STATUS "Find${CMAKE_FIND_PACKAGE_NAME}:" )
message( STATUS " - ${CMAKE_FIND_PACKAGE_NAME}_VERSION [${${CMAKE_FIND_PACKAGE_NAME}_VERSION}]")
message( STATUS " - ${CMAKE_FIND_PACKAGE_NAME}_PREFIX [${${CMAKE_FIND_PACKAGE_NAME}_PREFIX}]")
set(_found_comps)
foreach( _comp IN ITEMS Fortran C CXX NetCDF4 GPTL Threads )
if( ${CMAKE_FIND_PACKAGE_NAME}_${_comp}_FOUND )
list(APPEND _found_comps ${_comp})
endif()
endforeach()
message( STATUS " - ${CMAKE_FIND_PACKAGE_NAME} Components Found: ${_found_comps}")
unset(_found_comps)
endif()
unset(_new_components)
Loading