From 340b07a7b38529c9dbe0164f4339557be23c937e Mon Sep 17 00:00:00 2001 From: Bruce Nairn Date: Fri, 3 Jul 2020 22:07:01 -0700 Subject: [PATCH 1/3] Provide stub functions when built without parallel I/O Parallel I/O stub functions in new file nf_nc_noparallel.f90 Included in compile when netcdf-c library built without parallel I/O Return NC_ENOPAR, same as netcdf-c --- fortran/CMakeLists.txt | 11 +++++- fortran/nf_nc_noparallel.f90 | 66 ++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 fortran/nf_nc_noparallel.f90 diff --git a/fortran/CMakeLists.txt b/fortran/CMakeLists.txt index 3dd53e53..eb3fb4ee 100644 --- a/fortran/CMakeLists.txt +++ b/fortran/CMakeLists.txt @@ -12,7 +12,16 @@ SET(netcdff_SOURCES nf_varmio.F90 nf_varsio.F90 ) -SET(netcdff_SOURCES ${netcdff_SOURCES} nf_nc.f90) +# Check if netcdf-c has parallel I/O functions +check_symbol_exists(nc_create_par "netcdf.h" HAVE_PARALLEL) +message (STATUS "found netcdf-c parallel support: ${HAVE_PARALLEL}") +IF (${USE_NETCDF4} AND HAVE_PARALLEL) + SET(netcdff_SOURCES ${netcdff_SOURCES} nf_nc.f90) + message (STATUS "including netcdf-f parallel support") +ELSE () + SET(netcdff_SOURCES ${netcdff_SOURCES} nf_nc_noparallel.f90) + message (STATUS "no netcdf-f parallel support") +ENDIF(${USE_NETCDF4} AND HAVE_PARALLEL) IF (USE_NETCDF4) SET(netcdff_SOURCES ${netcdff_SOURCES} diff --git a/fortran/nf_nc_noparallel.f90 b/fortran/nf_nc_noparallel.f90 new file mode 100644 index 00000000..df44bc5b --- /dev/null +++ b/fortran/nf_nc_noparallel.f90 @@ -0,0 +1,66 @@ +! -- This file provides functions for parallel I/O when +! -- netCDF is built without parallel support +! +! -- C functions return NC_ENOPAR when built without parallel support +! -- so do the same here + +! Parallel I/O access is only available in library build which support +! parallel I/O. To support parallel I/O, netCDF must be built with +! netCDF-4 enabled (configure options --enable-netcdf-4 and --enable-parallel4) +! and with a HDF5 library that supports parallel I/O, or with support for the +! PnetCDF library via the --enable-pnetcdf option. + +!-------------------------------- nf_create_par ------------------------------- + Function nf_create_par (path, cmode, comm, info, ncid) RESULT(status) + +! create parallel file + + USE netcdf_nc_interfaces + + Implicit NONE + + Integer, Intent(IN) :: cmode, comm, info + Character(LEN=*), Intent(IN) :: path + Integer, Intent(OUT) :: ncid + + Integer :: status + + ncid = 0 + status = NC_ENOPAR + + End Function nf_create_par +!-------------------------------- nf_open_par -------------------------------- + Function nf_open_par (path, mode, comm, info, ncid) RESULT(status) + +! open a parallel file + + USE netcdf_nc_interfaces + + Implicit NONE + + Integer, Intent(IN) :: mode, comm, info + Character(LEN=*), Intent(IN) :: path + Integer, Intent(OUT) :: ncid + + Integer :: status + + ncid = 0 + status = NC_ENOPAR + + End Function nf_open_par +!-------------------------------- nf_var_par_access ------------------------- + Function nf_var_par_access( ncid, varid, iaccess) RESULT (status) + +! set parallel variable access + + USE netcdf_nc_interfaces + + Implicit NONE + + Integer, Intent(IN) :: ncid, varid, iaccess + + Integer :: status + + status = NC_ENOPAR + + End Function nf_var_par_access From 9c446f4399c4b28728b6654d14564fae9b91a9c4 Mon Sep 17 00:00:00 2001 From: Bruce Nairn Date: Fri, 3 Jul 2020 22:07:59 -0700 Subject: [PATCH 2/3] Separate C and Fortran code Compilation Separate C code from Fortran so C code gets C flags at compile Allows proper build on Windows --- CMakeLists.txt | 3 ++- fortran/CMakeLists.txt | 31 ++++++++++++++++++++++++++++--- nf_test/CMakeLists.txt | 31 +++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc2b6cf9..c74f1e7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -458,6 +458,7 @@ ENDIF() IF (netCDF_FOUND) SET(NETCDF_C_LIBRARY ${netCDF_LIBRARIES}) SET(NETCDF_C_INCLUDE_DIR ${netCDF_INCLUDE_DIR}) + include_directories(${NETCDF_C_INCLUDE_DIR}) message(STATUS "Found netCDF CMake package: ${NETCDF_C_LIBRARY}") ELSE() # netCDF not properly packaged. Try to find it manually. @@ -490,7 +491,6 @@ endif() ### # Check for various header files -### CHECK_INCLUDE_FILE("alloca.h" HAVE_ALLOCA_H) CHECK_INCLUDE_FILE("malloc.h" HAVE_MALLOC_H) CHECK_INCLUDE_FILE("ctype.h" HAVE_CTYPE_H) @@ -522,6 +522,7 @@ CHECK_INCLUDE_FILE("endian.h" HAVE_ENDIAN_H) CHECK_INCLUDE_FILE("BaseTsd.h" HAVE_BASETSD_H) CHECK_INCLUDE_FILE("stddef.h" HAVE_STDDEF_H) CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H) +SET(CMAKE_REQUIRED_INCLUDES ${NETCDF_C_INCLUDE_DIR}) CHECK_INCLUDE_FILE("netcdf.h" HAVE_NETCDF_H) diff --git a/fortran/CMakeLists.txt b/fortran/CMakeLists.txt index eb3fb4ee..db6e198f 100644 --- a/fortran/CMakeLists.txt +++ b/fortran/CMakeLists.txt @@ -27,10 +27,12 @@ IF (USE_NETCDF4) SET(netcdff_SOURCES ${netcdff_SOURCES} module_netcdf4_nc_interfaces.f90 module_netcdf4_nf_interfaces.F90 module_netcdf4_f03.f90 - nf_lib.c nf_nc4.f90 + nf_nc4.f90 ) + SET(netcdff_C_SOURCES ${netcdff_C_SOURCES} nf_lib.c) ENDIF(USE_NETCDF4) + IF (${USE_LOGGING}) SET(netcdff_SOURCES ${netcdff_SOURCES} nf_logging.F90 @@ -61,8 +63,9 @@ ENDIF(${USE_NETCDF4}) if (${BUILD_V2}) SET(netcdff_SOURCES ${netcdff_SOURCES} - nf_v2compat.c module_netcdf_fortv2_c_interfaces.f90 nf_fortv2.f90 + module_netcdf_fortv2_c_interfaces.f90 nf_fortv2.f90 ) + SET(netcdff_C_SOURCES ${netcdff_C_SOURCES} nf_v2compat.c ) endif (${BUILD_V2}) if (${BUILD_F03}) @@ -126,6 +129,8 @@ endif (${USE_LOGGING}) SET(BUILT_SOURCES ${BUILT_SOURCES} netcdf.inc) +include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/libsrc) + # Default to shared libs on OPTION(BUILD_SHARED_LIBS "Configure netCDF as a shared library." ON) SET (LIB_TYPE STATIC) @@ -140,8 +145,19 @@ ENDIF() # This just builds SHARED, even though STATIC is also specified # ADD_LIBRARY(netcdff STATIC SHARED ${netcdff_SOURCES}) # Builds only static, not shared +# Compile C-code to object, then link with Fortran +ADD_LIBRARY(netcdff_c OBJECT ${netcdff_C_SOURCES}) +install(TARGETS netcdff_c OBJECTS DESTINATION lib) +# or is this better? list(APPEND NETCDF_C_LIBRARY netcdff_c) +SET(NETCDF_C_LIBRARY ${NETCDF_C_LIBRARY} netcdff_c) +set_target_properties(netcdff_c PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${NETCDF_C_INCLUDE_DIR}" + ) +target_include_directories(netcdff_c PUBLIC "${NETCDF_C_INCLUDE_DIR}") + ADD_LIBRARY(netcdff ${netcdff_SOURCES}) TARGET_LINK_LIBRARIES(netcdff PUBLIC netCDF::netcdf) +TARGET_LINK_LIBRARIES(netcdff ${NETCDF_C_LIBRARY}) TARGET_LINK_LIBRARIES(netcdff PUBLIC ${EXTRA_DEPS}) SET_TARGET_PROPERTIES(netcdff PROPERTIES VERSION ${NC4F_LIB_VERSION} @@ -157,6 +173,15 @@ if (HAVE_NC_USE_PARALLEL_ENABLED) target_link_libraries(netcdff PUBLIC MPI::MPI_Fortran) endif() +# copied from netcdf-c... Changed from ADD_DEFINITIONS to TARGET_COMPILE_DEFINITIONS +# Option to Build DLL +IF(WIN32) + OPTION(LINK_TO_SHARED_LIBS "Link to netcdf-c shared library" ON) + IF(LINK_TO_SHARED_LIBS) + TARGET_COMPILE_DEFINITIONS(netcdff_c PRIVATE DLL_NETCDF) + ENDIF() +ENDIF() + ## # Configuration for post-install RPath # Adapted from http://www.cmake.org/Wiki/CMake_RPATH_handling @@ -183,7 +208,7 @@ IF(NOT MSVC) ENDIF() # Installation of the program -INSTALL(TARGETS netcdff +INSTALL(TARGETS netcdff netcdff_c EXPORT netcdffTargets RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib diff --git a/nf_test/CMakeLists.txt b/nf_test/CMakeLists.txt index 924b8c7c..da1a36df 100644 --- a/nf_test/CMakeLists.txt +++ b/nf_test/CMakeLists.txt @@ -10,9 +10,11 @@ foreach (f ${m4_SOURCES}) GEN_m4(${f}) endforeach(f) +# Separate C and Fortran Sources SET(nf_test_SOURCES f03lib_f_interfaces.f90 test_get.F test_put.F nf_error.F nf_test.F - test_read.F test_write.F util.F f03lib.c tests.inc) + test_read.F test_write.F util.F tests.inc) +SET(nf_test_C_SOURCES f03lib.c) SET(tst_int64_SOURCES tst_int64.F) @@ -26,7 +28,8 @@ IF (BUILD_V2) # to generate its input file. SET(check_PROGRAMS ${check_PROGRAMS} ftest) SET(TESTS ${TESTS} ftest) - SET(ftest_SOURCES ftest.F f03lib.c) + SET(ftest_SOURCES ftest.F) + SET(ftest_C_SOURCES f03lib.c) ENDIF(BUILD_V2) FIND_LIBRARY(NETCDF_C_LIBRARY NAMES netcdf libnetcdf) @@ -39,9 +42,33 @@ ENDIF() execute_process(COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/ref_fills.nc ${CMAKE_CURRENT_BINARY_DIR}/fills.nc) +INCLUDE_DIRECTORIES(BEFORE + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR}/fortran + ${CMAKE_BINARY_DIR}/libsrc + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/fortran + ${CMAKE_SOURCE_DIR}/libsrc) + +INCLUDE_DIRECTORIES( + ${CMAKE_CPP_FLAGS} + ${NETCDF_C_INCLUDE_DIR}) + +LINK_DIRECTORIES(${CMAKE_SOURCE_DIR}/fortran ${CMAKE_SOURCE_DIR}/libsrc + ${NC4F_BINARY_DIR}/fortran) + # Create pre-compiled tests. +message ("Create pre-compiled tests.") FOREACH(t ${TESTS}) ADD_EXECUTABLE(${t} ${${t}_SOURCES}) + message(" " ${t} " C_SOURCES: " ${${t}_C_SOURCES}) + IF(${t}_C_SOURCES) + message ("Adding C code for Test ${t} to Library") + ADD_LIBRARY(${t}_c OBJECT ${${t}_C_SOURCES}) + install(TARGETS ${t}_c DESTINATION lib) + SET(${t}_C_LIBRARY ${t}_c) + TARGET_LINK_LIBRARIES(${t} ${${t}_C_LIBRARY}) + ENDIF() TARGET_LINK_LIBRARIES(${t} netcdff) ADD_TEST(${t} ${t}) ENDFOREACH() From e58f483abbc2d9f20b4e60bd4d6ecc4b1e67210d Mon Sep 17 00:00:00 2001 From: Bruce Nairn Date: Thu, 13 Aug 2020 13:25:00 -0700 Subject: [PATCH 3/3] Add PRIVATE keyword to NETCDF_C_LIBRARY in fortran\CMakeLists.txt Previous target_link_libraries have keywoord signatures, so NETCDF_C_LIBRARY needs one, per Cmake CMP0023 PRIVATE libraries are linked to, but are not made part of the link interface. --- fortran/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fortran/CMakeLists.txt b/fortran/CMakeLists.txt index db6e198f..83f17dac 100644 --- a/fortran/CMakeLists.txt +++ b/fortran/CMakeLists.txt @@ -157,7 +157,7 @@ target_include_directories(netcdff_c PUBLIC "${NETCDF_C_INCLUDE_DIR}") ADD_LIBRARY(netcdff ${netcdff_SOURCES}) TARGET_LINK_LIBRARIES(netcdff PUBLIC netCDF::netcdf) -TARGET_LINK_LIBRARIES(netcdff ${NETCDF_C_LIBRARY}) +TARGET_LINK_LIBRARIES(netcdff PRIVATE ${NETCDF_C_LIBRARY}) TARGET_LINK_LIBRARIES(netcdff PUBLIC ${EXTRA_DEPS}) SET_TARGET_PROPERTIES(netcdff PROPERTIES VERSION ${NC4F_LIB_VERSION}