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

Update MPI, HDF5, and Netcdf TriBITS find modules (#533, #534) #535

Merged
merged 10 commits into from
Oct 28, 2022
141 changes: 83 additions & 58 deletions tribits/common_tpls/FindTPLHDF5.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,78 +2,103 @@
# See associated tribits/Copyright.txt file for copyright and license! #
########################################################################

#
# First, set up the variables for the (backward-compatible) TriBITS way of
# finding HDF5. These are used in case find_package(HDF5 ...) is not called
# or does not find HDF5. Also, these variables need to be non-null in order
# to trigger the right behavior in the function
# tribits_tpl_find_include_dirs_and_libraries().
#

set(REQUIRED_HEADERS hdf5.h)
set(REQUIRED_LIBS_NAMES hdf5)

if (HDF5_REQUIRE_FORTRAN)
set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} hdf5_fortran)
endif()
set(HDF5_INTERNAL_IS_MODERN FALSE)

if (TPL_ENABLE_MPI)
set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} z)
endif()
if (Netcdf_ALLOW_MODERN)

set(minimum_modern_HDF5_version 1.13.2)
Copy link
Contributor

Choose a reason for hiding this comment

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

@ibaned @bartlettroscoe
Sorry for not noticing this prior to merging.
What is needed in the HDF5-1.10.X and HDF5-1.12.X versions to make them usable for this. Both of those versions are still in development, so it would be good to fix their CMake configurations if possible.

I can either contact the HDF5 group with the suggested changes, or one of you can also. Note that we have priority support with HDF5, so they will listen and most likely make useful changes that we suggest.

print_var(Netcdf_ALLOW_MODERN)
message("-- Using find_package(HDF5 ${minimum_modern_HDF5_version} CONFIG) ...")
find_package(HDF5 ${minimum_modern_HDF5_version} CONFIG)
if (HDF5_FOUND)
message("-- Found HDF5_CONFIG=${HDF5_CONFIG}")
message("-- Generating Netcdf::all_libs and NetcdfConfig.cmake")
message("-- HDF5_EXPORT_LIBRARIES=${HDF5_EXPORT_LIBRARIES}")
tribits_extpkg_create_imported_all_libs_target_and_config_file(
HDF5
INNER_FIND_PACKAGE_NAME HDF5
IMPORTED_TARGETS_FOR_ALL_LIBS ${HDF5_EXPORT_LIBRARIES})
set(HDF5_INTERNAL_IS_MODERN TRUE)
endif()

if (TPL_ENABLE_Netcdf)
set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} hdf5_hl)
endif()

#
# Second, search for HDF5 components (if allowed) using the standard
# find_package(HDF5 ...).
#
tribits_tpl_allow_pre_find_package(HDF5 HDF5_ALLOW_PREFIND)
if (HDF5_ALLOW_PREFIND)
set(HDF5_FOUND_MODERN_CONFIG_FILE ${HDF5_INTERNAL_IS_MODERN} CACHE INTERNAL "True if HDF5 was found by the modern method")

message("-- Using find_package(HDF5 ...) ...")
if (NOT TARGET HDF5::all_libs)

# First, set up the variables for the (backward-compatible) TriBITS way of
# finding HDF5. These are used in case find_package(HDF5 ...) is not called
# or does not find HDF5. Also, these variables need to be non-null in order
# to trigger the right behavior in the function
# tribits_tpl_find_include_dirs_and_libraries().

set(REQUIRED_HEADERS hdf5.h)
set(REQUIRED_LIBS_NAMES hdf5)

set(HDF5_COMPONENTS C)
if (HDF5_REQUIRE_FORTRAN)
list(APPEND HDF5_COMPONENTS Fortran)
set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} hdf5_fortran)
endif()

if (TPL_ENABLE_MPI)
set(HDF5_PREFER_PARALLEL TRUE)
set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} z)
endif()

find_package(HDF5 COMPONENTS ${HDF5_COMPONENTS})

# Make sure that HDF5 is parallel.
if (TPL_ENABLE_MPI AND NOT HDF5_IS_PARALLEL)
message(FATAL_ERROR "Trilinos is configured for MPI, HDF5 is not.
Did CMake find the correct libraries?
Try setting HDF5_INCLUDE_DIRS and/or HDF5_LIBRARY_DIRS explicitly.
")
if (TPL_ENABLE_Netcdf)
set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} hdf5_hl)
endif()

if (HDF5_FOUND)
# Tell TriBITS that we found HDF5 and there no need to look any further!
set(TPL_HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIRS} CACHE PATH
"HDF5 include dirs")
set(TPL_HDF5_LIBRARIES ${HDF5_LIBRARIES} CACHE FILEPATH
"HDF5 libraries")
set(TPL_HDF5_LIBRARY_DIRS ${HDF5_LIBRARY_DIRS} CACHE PATH
"HDF5 library dirs")
#
# Second, search for HDF5 components (if allowed) using the standard
# find_package(HDF5 ...).
#
tribits_tpl_allow_pre_find_package(HDF5 HDF5_ALLOW_PREFIND)
if (HDF5_ALLOW_PREFIND)

message("-- Using find_package(HDF5 ...) ...")

set(HDF5_COMPONENTS C)
if (HDF5_REQUIRE_FORTRAN)
list(APPEND HDF5_COMPONENTS Fortran)
endif()

if (TPL_ENABLE_MPI)
set(HDF5_PREFER_PARALLEL TRUE)
endif()

find_package(HDF5 COMPONENTS ${HDF5_COMPONENTS})

# Make sure that HDF5 is parallel.
if (TPL_ENABLE_MPI AND NOT HDF5_IS_PARALLEL)
message(FATAL_ERROR "Trilinos is configured for MPI, HDF5 is not.
Did CMake find the correct libraries?
Try setting HDF5_INCLUDE_DIRS and/or HDF5_LIBRARY_DIRS explicitly.
")
endif()

if (HDF5_FOUND)
# Tell TriBITS that we found HDF5 and there no need to look any further!
set(TPL_HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIRS} CACHE PATH
"HDF5 include dirs")
set(TPL_HDF5_LIBRARIES ${HDF5_LIBRARIES} CACHE FILEPATH
"HDF5 libraries")
set(TPL_HDF5_LIBRARY_DIRS ${HDF5_LIBRARY_DIRS} CACHE PATH
"HDF5 library dirs")
endif()

endif()

endif()
#
# Third, call tribits_tpl_find_include_dirs_and_libraries()
#
tribits_tpl_find_include_dirs_and_libraries( HDF5
REQUIRED_HEADERS ${REQUIRED_HEADERS}
REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES}
)
# NOTE: If find_package(HDF5 ...) was called and successfully found HDF5, then
# tribits_tpl_find_include_dirs_and_libraries() will use the already-set
# variables TPL_HDF5_INCLUDE_DIRS and TPL_HDF5_LIBRARIES and then print them
# out (and set some other standard variables as well). This is the final
# "hook" into the TriBITS TPL system.

#
# Third, call tribits_tpl_find_include_dirs_and_libraries()
#
tribits_tpl_find_include_dirs_and_libraries( HDF5
REQUIRED_HEADERS ${REQUIRED_HEADERS}
REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES}
)
# NOTE: If find_package(HDF5 ...) was called and successfully found HDF5, then
# tribits_tpl_find_include_dirs_and_libraries() will use the already-set
# variables TPL_HDF5_INCLUDE_DIRS and TPL_HDF5_LIBRARIES and then print them
# out (and set some other standard variables as well). This is the final
# "hook" into the TriBITS TPL system.
endif()
211 changes: 117 additions & 94 deletions tribits/common_tpls/FindTPLNetcdf.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -37,105 +37,128 @@
# ************************************************************************
# @HEADER

#
# First, set up the variables for the (backward-compatible) TriBITS way of
# finding Netcdf. These are used in case find_package(NetCDF ...) is not
# called or does not find NetCDF. Also, these variables need to be non-null
# in order to trigger the right behavior in the function
# tribits_tpl_find_include_dirs_and_libraries().
#
cmake_policy(SET CMP0074 NEW)

set(REQUIRED_HEADERS netcdf.h)
set(REQUIRED_LIBS_NAMES netcdf)
set(Netcdf_ALLOW_MODERN FALSE CACHE BOOL "Allow finding Netcdf as a modern CMake config file with exported targets (and only this way)")

if (TPL_ENABLE_MPI)
set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} pnetcdf)
endif()
if (Netcdf_ALLOW_MODERN AND HDF5_FOUND_MODERN_CONFIG_FILE)
Copy link
Contributor

Choose a reason for hiding this comment

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

After seeing how to use this in SEACAS --
This does not seem to work if HDF5 is added as a dependency only because of netCDF since at this point, I don't think that we have yet found HDF5, so HDF5_FOUND_MODERN_CONFIG_FILE will not be set?

At least for SEACAS, I think that the Netcdf_ALLOW_MODERN should drive this and determine whether to find HDF5 the modern/legacy way? Does that make sense?

Or, do I reorder things such that CGNS (which depends on HDF5) comes first and then netCDF?
@bartlettroscoe @ibaned

Copy link
Member Author

Choose a reason for hiding this comment

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

Or, do I reorder things such that CGNS (which depends on HDF5) comes first and then netCDF?

@gsjaardema, you specify the dependencies as: HDF5 <-- CGNS <-- Netcdf

See:

It looks like GGNS already has a required dependency on HDF5 as per:

tribits_extpkg_define_dependencies( CGNS
DEPENDENCIES HDF5)

But I had no idea that Netcdf depended on CGNS?

Also not that, currently, TriBITS does not automatically enable upstream TPL dependencies for an enabled TPL. So the configure script will need to manually enable all of the TPLs it wants. (See NOTES at bottom of slide 16 "TriBITS External Packages/TPLs Dependencies (New!)" in the presentation TriBITS Modernization Update I gave last Thursday, Oct 27, 2022.)


#
# Second, search for Netcdf components (if allowed) using the standard
# find_package(NetCDF ...).
#
tribits_tpl_allow_pre_find_package(Netcdf Netcdf_ALLOW_PREFIND)
if (Netcdf_ALLOW_PREFIND)

message("-- Using find_package(Netcdf ...) ...")

set(CMAKE_MODULE_PATH
"${CMAKE_MODULE_PATH}"
"${CMAKE_CURRENT_LIST_DIR}/find_modules"
"${CMAKE_CURRENT_LIST_DIR}/utils"
)

find_package(NetCDF)

if (NetCDF_FOUND)
set(DOCSTR "List of semi-colon separated paths to look for the TPL Netcdf")
set(TPL_Netcdf_Enables_Netcdf4 ${NetCDF_NEEDS_HDF5} CACHE BOOL
"True if netcdf enables netcdf-4")
set(TPL_Netcdf_Enables_PNetcdf ${NetCDF_NEEDS_PNetCDF} CACHE BOOL
"True if netcdf enables pnetcdf")
set(TPL_Netcdf_PARALLEL ${NetCDF_PARALLEL} CACHE INTERNAL
"True if netcdf compiled with parallel enabled")
set(TPL_Netcdf_LIBRARY_DIRS ${_hdf5_LIBRARY_SEARCH_DIRS} CACHE PATH
"${DOCSTR} library files")
set(TPL_Netcdf_LIBRARIES ${NetCDF_LIBRARIES} CACHE PATH
"List of semi-colon separated library names (not 'lib' or extension).")
set(TPL_Netcdf_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} CACHE PATH
"${DOCSTR} header files.")
set(minimum_modern_netCDF_version 4.7.4)
print_var(Netcdf_ALLOW_MODERN)
message("-- Using find_package(netCDF ${minimum_modern_netCDF_version} CONFIG) ...")
find_package(netCDF ${minimum_modern_netCDF_version} CONFIG)
if (netCDF_FOUND)
message("-- Found netCDF_CONFIG=${netCDF_CONFIG}")
message("-- Generating Netcdf::all_libs and NetcdfConfig.cmake")
tribits_extpkg_create_imported_all_libs_target_and_config_file(
Netcdf
INNER_FIND_PACKAGE_NAME netCDF
IMPORTED_TARGETS_FOR_ALL_LIBS netCDF::netcdf)
set(TPL_Netcdf_NOT_FOUND FALSE)
endif()
else()
# Curl library is only required if DAP is enabled; should detect inside
# FindNetCDF.cmake, but that is not being called... SEMS has DAP enabled;
# many HPC systems don't, but they override these settings...
find_program(NC_CONFIG "nc-config")
if (NC_CONFIG)
execute_process(COMMAND "nc-config --has-dap2"
OUTPUT_VARIABLE NETCDF_HAS_DAP2)
execute_process(COMMAND "nc-config --has-dap4"
OUTPUT_VARIABLE NETCDF_HAS_DAP4)

endif()

if (NOT TARGET Netcdf::all_libs)

# First, set up the variables for the (backward-compatible) TriBITS way of
# finding Netcdf. These are used in case find_package(Netcdf ...) is not
# called or does not find HDF5. Also, these variables need to be non-null
# in order to trigger the right behavior in the function
# tribits_tpl_find_include_dirs_and_libraries().

set(REQUIRED_HEADERS netcdf.h)
set(REQUIRED_LIBS_NAMES netcdf)

if (TPL_ENABLE_MPI)
set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} pnetcdf)
endif()
if ((NOT NC_CONFIG) OR NETCDF_HAS_DAP2 OR NETCDF_HAS_DAP4)
set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} curl)

#
# Second, search for Netcdf components (if allowed) using the standard
# find_package(NetCDF ...).
#
tribits_tpl_allow_pre_find_package(Netcdf Netcdf_ALLOW_PREFIND)
if (Netcdf_ALLOW_PREFIND)

message("-- Using find_package(Netcdf ...) ...")

set(CMAKE_MODULE_PATH
"${CMAKE_MODULE_PATH}"
"${CMAKE_CURRENT_LIST_DIR}/find_modules"
"${CMAKE_CURRENT_LIST_DIR}/utils"
)

find_package(NetCDF)

if (NetCDF_FOUND)
set(DOCSTR "List of semi-colon separated paths to look for the TPL Netcdf")
set(TPL_Netcdf_Enables_Netcdf4 ${NetCDF_NEEDS_HDF5} CACHE BOOL
"True if netcdf enables netcdf-4")
set(TPL_Netcdf_Enables_PNetcdf ${NetCDF_NEEDS_PNetCDF} CACHE BOOL
"True if netcdf enables pnetcdf")
set(TPL_Netcdf_PARALLEL ${NetCDF_PARALLEL} CACHE INTERNAL
"True if netcdf compiled with parallel enabled")
set(TPL_Netcdf_LIBRARY_DIRS ${_hdf5_LIBRARY_SEARCH_DIRS} CACHE PATH
"${DOCSTR} library files")
set(TPL_Netcdf_LIBRARIES ${NetCDF_LIBRARIES} CACHE PATH
"List of semi-colon separated library names (not 'lib' or extension).")
set(TPL_Netcdf_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} CACHE PATH
"${DOCSTR} header files.")
endif()
else()
# Curl library is only required if DAP is enabled; should detect inside
# FindNetCDF.cmake, but that is not being called... SEMS has DAP enabled;
# many HPC systems don't, but they override these settings...
find_program(NC_CONFIG "nc-config")
if (NC_CONFIG)
execute_process(COMMAND "nc-config --has-dap2"
OUTPUT_VARIABLE NETCDF_HAS_DAP2)
execute_process(COMMAND "nc-config --has-dap4"
OUTPUT_VARIABLE NETCDF_HAS_DAP4)
endif()
if ((NOT NC_CONFIG) OR NETCDF_HAS_DAP2 OR NETCDF_HAS_DAP4)
set(REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES} curl)
endif()
endif()
endif()

#
# Third, call tribits_tpl_find_include_dirs_and_libraries()
#
tribits_tpl_find_include_dirs_and_libraries( Netcdf
REQUIRED_HEADERS ${REQUIRED_HEADERS}
REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES}
)
# NOTE: If find_package(Netcdf ...) was called and successfully found Netcdf,
# then tribits_tpl_find_include_dirs_and_libraries() will use the already-set
# variables TPL_Netcdf_INCLUDE_DIRS and TPL_Netcdf_LIBRARIES and then print
# them out (and set some other standard variables as well). This is the final
# "hook" into the TriBITS TPL system.

# If the `find_package(NetCDF)` is not run, then this may not be set
# Need to determine how this is set in the library that is being used...

if ("${TPL_Netcdf_PARALLEL}" STREQUAL "")
assert_defined(TPL_Netcdf_INCLUDE_DIRS)
find_path(meta_path
NAMES "netcdf_meta.h"
HINTS ${TPL_Netcdf_INCLUDE_DIRS}
NO_DEFAULT_PATH)

if (meta_path)
# Search meta for NC_HAS_PARALLEL setting...
# Note that there is both NC_HAS_PARALLEL and NC_HAS_PARALLEL4, only want first...
file(STRINGS "${meta_path}/netcdf_meta.h" netcdf_par_string REGEX "NC_HAS_PARALLEL ")
string(REGEX MATCH "[01]" netcdf_par_val "${netcdf_par_string}")
if (netcdf_par_val EQUAL 1)
set(TPL_Netcdf_PARALLEL True CACHE INTERNAL
"True if netcdf compiled with parallel enabled")
endif()
endif()
if ("${TPL_Netcdf_PARALLEL}" STREQUAL "")
set(TPL_Netcdf_PARALLEL False CACHE INTERNAL
"True if netcdf compiled with parallel enabled")
endif()
#
# Third, call tribits_tpl_find_include_dirs_and_libraries()
#
tribits_tpl_find_include_dirs_and_libraries( Netcdf
REQUIRED_HEADERS ${REQUIRED_HEADERS}
REQUIRED_LIBS_NAMES ${REQUIRED_LIBS_NAMES}
)
# NOTE: If find_package(Netcdf ...) was called and successfully found Netcdf,
# then tribits_tpl_find_include_dirs_and_libraries() will use the already-set
# variables TPL_Netcdf_INCLUDE_DIRS and TPL_Netcdf_LIBRARIES and then print
# them out (and set some other standard variables as well). This is the final
# "hook" into the TriBITS TPL system.

# If the `find_package(NetCDF)` is not run, then this may not be set
# Need to determine how this is set in the library that is being used...

if ("${TPL_Netcdf_PARALLEL}" STREQUAL "")
assert_defined(TPL_Netcdf_INCLUDE_DIRS)
find_path(meta_path
NAMES "netcdf_meta.h"
HINTS ${TPL_Netcdf_INCLUDE_DIRS}
NO_DEFAULT_PATH)

if (meta_path)
# Search meta for NC_HAS_PARALLEL setting...
# Note that there is both NC_HAS_PARALLEL and NC_HAS_PARALLEL4, only want first...
file(STRINGS "${meta_path}/netcdf_meta.h" netcdf_par_string REGEX "NC_HAS_PARALLEL ")
string(REGEX MATCH "[01]" netcdf_par_val "${netcdf_par_string}")
if (netcdf_par_val EQUAL 1)
set(TPL_Netcdf_PARALLEL True CACHE INTERNAL
"True if netcdf compiled with parallel enabled")
endif()
endif()
if ("${TPL_Netcdf_PARALLEL}" STREQUAL "")
set(TPL_Netcdf_PARALLEL False CACHE INTERNAL
"True if netcdf compiled with parallel enabled")
endif()
endif()
message(STATUS "TPL_Netcdf_PARALLEL is ${TPL_Netcdf_PARALLEL}")
endif()
message(STATUS "TPL_Netcdf_PARALLEL is ${TPL_Netcdf_PARALLEL}")
2 changes: 2 additions & 0 deletions tribits/common_tpls/FindTPLNetcdfDependencies.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tribits_extpkg_define_dependencies( Netcdf
DEPENDENCIES HDF5)
Loading