diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a311a91..4f61a3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,15 @@ jobs: sudo apt update sudo apt install --no-install-recommends libhdf5-dev - - run: cmake -B build -DCMAKE_INSTALL_PREFIX=${{ runner.temp }} + - name: Configure NetCDF4 + run: cmake -S scripts -B scripts/build -DCMAKE_INSTALL_PREFIX=${{ runner.temp }} -DBUILD_SHARED_LIBS:BOOL=${{ matrix.shared }} + + - name: Build/install NetCDF4 + run: cmake --build scripts/build --parallel + + - name: configure nc4fortran + run: cmake -B build -DCMAKE_INSTALL_PREFIX=${{ runner.temp }} -DCMAKE_PREFIX_PATH=${{ runner.temp }} + - run: cmake --build build --parallel - run: ctest --test-dir build --preset default - run: cmake --install build @@ -127,7 +135,15 @@ jobs: - name: install libs run: brew install hdf5 - - run: cmake -B build --install-prefix=${{ runner.temp }} + - name: Configure NetCDF4 + run: cmake -S scripts -B scripts/build -DCMAKE_INSTALL_PREFIX=${{ runner.temp }} -DBUILD_SHARED_LIBS:BOOL=${{ matrix.shared }} + + - name: Build/install NetCDF4 + run: cmake --build scripts/build --parallel + + - name: configure nc4fortran + run: cmake -B build -DCMAKE_INSTALL_PREFIX=${{ runner.temp }} -DCMAKE_PREFIX_PATH=${{ runner.temp }} + - run: cmake --build build - run: ctest --test-dir build --preset default - run: cmake --install build diff --git a/.github/workflows/ci_windows.yml b/.github/workflows/ci_windows.yml index 6dcb8ca..0508c31 100644 --- a/.github/workflows/ci_windows.yml +++ b/.github/workflows/ci_windows.yml @@ -35,7 +35,14 @@ jobs: - uses: actions/checkout@v2 - - run: cmake --preset multi -DCMAKE_INSTALL_PREFIX=${{ runner.temp }} + - name: Configure NetCDF4 + run: cmake -S scripts -B scripts/build -DCMAKE_INSTALL_PREFIX=${{ runner.temp }} -DBUILD_SHARED_LIBS:BOOL=${{ matrix.shared }} + + - name: Build/install NetCDF4 + run: cmake --build scripts/build --parallel + + - name: configure nc4fortran + run: cmake --preset multi -DCMAKE_INSTALL_PREFIX=${{ runner.temp }} -DCMAKE_PREFIX_PATH=${{ runner.temp }} - run: cmake --build --preset debug - run: ctest --preset debug diff --git a/CITATION.cff b/CITATION.cff index ddd80de..3546d17 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -5,4 +5,3 @@ authors: orcid: https://orcid.org/0000-0002-1637-6526 title: nc4fortran doi: 10.5281/zenodo.3598941 -date-released: 2021-11-21 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ca1b40..c283ede 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,9 +23,19 @@ endif() include(cmake/options.cmake) include(cmake/compilers.cmake) -# --- find or build NetCDF4 +find_package(NetCDF COMPONENTS C Fortran) +if(NOT NetCDF_FOUND) +message(FATAL_ERROR "NetCDF not found or working on the system. First build: -include(cmake/netcdf.cmake) +cmake -S scripts -B scripts/build -DCMAKE_INSTALL_PREFIX=~/mylibs +cmake --build scripts/build + +Then build nc4fortran: + +cmake -B build -DCMAKE_PREFIX_PATH=~/mylibs +cmake --build build +") +endif() # --- build diff --git a/cmake/Modules/FindHDF5.cmake b/cmake/Modules/FindHDF5.cmake index 4ce11dd..d94fa56 100644 --- a/cmake/Modules/FindHDF5.cmake +++ b/cmake/Modules/FindHDF5.cmake @@ -160,8 +160,19 @@ if(NOT ZLIB_ROOT) set(ZLIB_ROOT "${HDF5_ROOT};${zlib_dir}") endif() + +set(hdf5_prereqs true PARENT_SCOPE) + if(hdf5_have_zlib) - find_package(ZLIB) + if(HDF5_FIND_REQUIRED) + find_package(ZLIB REQUIRED) + else() + find_package(ZLIB) + endif() + if(NOT ZLIB_FOUND) + set(hdf5_prereqs false PARENT_SCOPE) + return() + endif() if(hdf5_have_szip) # Szip even though not used by default. @@ -170,7 +181,16 @@ if(hdf5_have_zlib) if(NOT SZIP_ROOT) set(SZIP_ROOT ${ZLIB_ROOT}) endif() - find_package(SZIP) + if(HDF5_FIND_REQUIRED) + find_package(SZIP REQUIRED) + else() + find_package(SZIP) + endif() + if(NOT SZIP_FOUND) + set(hdf5_prereqs false PARENT_SCOPE) + return() + endif() + list(APPEND CMAKE_REQUIRED_INCLUDES ${SZIP_INCLUDE_DIRS}) list(APPEND CMAKE_REQUIRED_LIBRARIES ${SZIP_LIBRARIES}) endif() @@ -656,7 +676,7 @@ endfunction(check_fortran_links) function(check_hdf5_link) -if(NOT HDF5_C_FOUND) +if(NOT (hdf5_prereqs AND HDF5_C_FOUND)) return() endif() @@ -777,11 +797,11 @@ if(HDF5_C_FOUND) detect_config() endif(HDF5_C_FOUND) -if(HDF5_C_FOUND AND CXX IN_LIST HDF5_FIND_COMPONENTS) +if(hdf5_prereqs AND HDF5_C_FOUND AND CXX IN_LIST HDF5_FIND_COMPONENTS) find_hdf5_cxx() endif() -if(HDF5_C_FOUND AND Fortran IN_LIST HDF5_FIND_COMPONENTS) +if(hdf5_prereqs AND HDF5_C_FOUND AND Fortran IN_LIST HDF5_FIND_COMPONENTS) find_hdf5_fortran() endif() @@ -795,9 +815,10 @@ set(CMAKE_REQUIRED_INCLUDES) # pop off ignored paths so rest of script can find Python list(REMOVE_ITEM CMAKE_IGNORE_PATH ${h5_ignore_path}) + include(FindPackageHandleStandardArgs) find_package_handle_standard_args(HDF5 -REQUIRED_VARS HDF5_C_LIBRARIES HDF5_links +REQUIRED_VARS HDF5_C_LIBRARIES HDF5_links hdf5_prereqs VERSION_VAR HDF5_VERSION HANDLE_COMPONENTS HANDLE_VERSION_RANGE diff --git a/cmake/Modules/FindSZIP.cmake b/cmake/Modules/FindSZIP.cmake index bbff875..940c276 100644 --- a/cmake/Modules/FindSZIP.cmake +++ b/cmake/Modules/FindSZIP.cmake @@ -27,24 +27,22 @@ Targets SZIP Imported Target #]=======================================================================] -find_package(libaec QUIET) -if(NOT SZIP_FOUND) +find_library(SZIP_LIBRARY +NAMES szip sz +NAMES_PER_DIR +DOC "SZIP API" +) - find_library(SZIP_LIBRARY - NAMES szip sz - NAMES_PER_DIR - DOC "SZIP API") - - find_path(SZIP_INCLUDE_DIR - NAMES szlib.h - DOC "SZIP header") - -endif() +find_path(SZIP_INCLUDE_DIR +NAMES szlib.h +DOC "SZIP header" +) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(SZIP - REQUIRED_VARS SZIP_LIBRARY SZIP_INCLUDE_DIR) +REQUIRED_VARS SZIP_LIBRARY SZIP_INCLUDE_DIR +) if(SZIP_FOUND) set(SZIP_INCLUDE_DIRS ${SZIP_INCLUDE_DIR}) @@ -53,8 +51,9 @@ if(SZIP_FOUND) if(NOT TARGET SZIP::SZIP) add_library(SZIP::SZIP INTERFACE IMPORTED) set_target_properties(SZIP::SZIP PROPERTIES - INTERFACE_LINK_LIBRARIES "${SZIP_LIBRARIES}" - INTERFACE_INCLUDE_DIRECTORIES "${SZIP_INCLUDE_DIRS}") + INTERFACE_LINK_LIBRARIES "${SZIP_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${SZIP_INCLUDE_DIRS}" + ) endif() endif() diff --git a/cmake/abi_check/CMakeLists.txt b/cmake/abi_check/CMakeLists.txt index fa8da57..7703c4f 100644 --- a/cmake/abi_check/CMakeLists.txt +++ b/cmake/abi_check/CMakeLists.txt @@ -1,6 +1,21 @@ -cmake_minimum_required(VERSION 3.14...3.23) +cmake_minimum_required(VERSION 3.19...3.23) project(abi_check LANGUAGES C Fortran) +enable_testing() + add_library(addone OBJECT addone.c) +add_executable(main_f main.f90 $) +if(CMAKE_Fortran_COMPILER_ID MATCHES "^Intel") + set_target_properties(main_f PROPERTIES LINKER_LANGUAGE Fortran) +else() + set_target_properties(main_f PROPERTIES LINKER_LANGUAGE C) +endif() +add_test(NAME Fortran_main COMMAND main_f) + +add_library(addone_f OBJECT addone.f90) + +add_executable(main_c main.c $) +set_target_properties(main_c PROPERTIES LINKER_LANGUAGE C) +add_test(NAME C_main COMMAND main_c) -add_executable(main main.f90 $) +set_tests_properties(Fortran_main C_main PROPERTIES TIMEOUT 10) diff --git a/cmake/abi_check/addone.c b/cmake/abi_check/addone.c index 9807f85..d8c2a12 100644 --- a/cmake/abi_check/addone.c +++ b/cmake/abi_check/addone.c @@ -1,3 +1,5 @@ +extern int addone(int); + int addone(int N){ return N + 1; } diff --git a/cmake/abi_check/addone.f90 b/cmake/abi_check/addone.f90 new file mode 100644 index 0000000..3751eb6 --- /dev/null +++ b/cmake/abi_check/addone.f90 @@ -0,0 +1,13 @@ +module adder + +use, intrinsic :: iso_c_binding, only : C_INT +implicit none (type, external) + +contains + +pure integer(C_INT) function addone(N) bind(C) +integer(C_INT), intent(in), value :: N +addone = N + 1 +end function addone + +end module adder diff --git a/cmake/abi_check/main.c b/cmake/abi_check/main.c new file mode 100644 index 0000000..c2664e9 --- /dev/null +++ b/cmake/abi_check/main.c @@ -0,0 +1,14 @@ +#include + +extern int addone(int); + + +int main(void) { + + if(addone(2) != 3) { + fprintf(stderr, "2 + 1 != %d", addone(2)); + return 1; + } + + return 0; +} diff --git a/cmake/abi_check/main.f90 b/cmake/abi_check/main.f90 index 27c785d..0ba6cb8 100644 --- a/cmake/abi_check/main.f90 +++ b/cmake/abi_check/main.f90 @@ -1,17 +1,24 @@ program adder -implicit none +use, intrinsic :: iso_fortran_env, only : stderr=>error_unit + +implicit none (type, external) interface + integer function addone(N) bind(C) integer, intent(in), value :: N end function addone + end interface -if (addone(2) /= 3) error stop "unexpected addone result" +if (addone(2) /= 3) then + write(stderr,*) "ERROR: 2+1 /= ", addone(2) + error stop +endif -print *, "OK: 2+1=3" +print *, "OK: Fortran main with C libraries" end program diff --git a/cmake/hdf5.cmake b/cmake/hdf5.cmake index c8d53c7..30d5be1 100644 --- a/cmake/hdf5.cmake +++ b/cmake/hdf5.cmake @@ -1,11 +1,7 @@ # builds HDF5 library from scratch -# note: the use of "lib" vs. CMAKE_*_LIBRARY_PREFIX is deliberate based on HDF5 -# across Intel Fortran on Windows (MSVC-like) vs. Gfortran on Windows vs. Linux. include(ExternalProject) -set(hdf5_external true CACHE BOOL "autobuild HDF5") - if(hdf5_parallel) find_package(MPI REQUIRED COMPONENTS C) endif() @@ -15,25 +11,7 @@ if(NOT MPI_ROOT AND DEFINED ENV{MPI_ROOT}) set(MPI_ROOT $ENV{MPI_ROOT}) endif() -set(HDF5_LIBRARIES) -foreach(_name hdf5_hl_fortran hdf5_hl_f90cstub hdf5_fortran hdf5_f90cstub hdf5_hl hdf5) - if(BUILD_SHARED_LIBS) - if(WIN32) - list(APPEND HDF5_LIBRARIES ${CMAKE_INSTALL_PREFIX}/bin/lib${_name}${CMAKE_SHARED_LIBRARY_SUFFIX}) - else() - list(APPEND HDF5_LIBRARIES ${CMAKE_INSTALL_PREFIX}/lib/lib${_name}${CMAKE_SHARED_LIBRARY_SUFFIX}) - endif() - else() - list(APPEND HDF5_LIBRARIES ${CMAKE_INSTALL_PREFIX}/lib/lib${_name}${CMAKE_STATIC_LIBRARY_SUFFIX}) - endif() -endforeach() - -set(HDF5_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/include) - -# --- Zlib -if(NOT TARGET ZLIB::ZLIB) - include(${CMAKE_CURRENT_LIST_DIR}/zlib.cmake) -endif() +include(${CMAKE_CURRENT_LIST_DIR}/zlib.cmake) # --- HDF5 # https://forum.hdfgroup.org/t/issues-when-using-hdf5-as-a-git-submodule-and-using-cmake-with-add-subdirectory/7189/2 @@ -73,43 +51,7 @@ URL ${hdf5_url} URL_HASH SHA256=${hdf5_sha256} CMAKE_ARGS ${hdf5_cmake_args} CMAKE_GENERATOR ${EXTPROJ_GENERATOR} -BUILD_BYPRODUCTS ${HDF5_LIBRARIES} -DEPENDS ZLIB::ZLIB +DEPENDS ZLIB CONFIGURE_HANDLED_BY_BUILD ON INACTIVITY_TIMEOUT 15 ) - -# --- imported target - -file(MAKE_DIRECTORY ${HDF5_INCLUDE_DIRS}) -# avoid race condition - -# this GLOBAL is required to be visible via other project's FetchContent of h5fortran -add_library(HDF5::HDF5 INTERFACE IMPORTED GLOBAL) -target_include_directories(HDF5::HDF5 INTERFACE "${HDF5_INCLUDE_DIRS}") -target_link_libraries(HDF5::HDF5 INTERFACE "${HDF5_LIBRARIES}") - -add_dependencies(HDF5::HDF5 HDF5) - -# --- HDF5 parallel compression support -# this could be improved by making it an ExternalProject post-build step instead of assumptions made here -if(hdf5_parallel) - if(MPI_VERSION VERSION_GREATER_EQUAL 3) - message(STATUS "Building HDF5-MPI: MPI-3 available, assuming HDF5 parallel compression enabled") - set(hdf5_parallel_compression ".true." CACHE STRING "configure variable for HDF5 parallel compression") - else() - message(STATUS "Building HDF5-MPI: MPI-3 NOT available => HDF5 parallel compression disabled") - set(hdf5_parallel_compression ".false." CACHE STRING "configure variable for HDF5 parallel compression: MPI < 3") - endif() -endif(hdf5_parallel) - -# --- external deps -find_package(Threads) - -target_link_libraries(HDF5::HDF5 INTERFACE -ZLIB::ZLIB -${CMAKE_THREAD_LIBS_INIT} -${CMAKE_DL_LIBS} -$<$:m> -) -# libdl and libm are needed on some systems diff --git a/cmake/nc4fortran.cmake b/cmake/nc4fortran.cmake index 4e2846a..cd464a2 100644 --- a/cmake/nc4fortran.cmake +++ b/cmake/nc4fortran.cmake @@ -32,7 +32,6 @@ set(nc4fortran_cmake_args -DBUILD_SHARED_LIBS:BOOL=${BUILD_SHARED_LIBS} -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING:BOOL=false --Dautobuild:BOOL=false -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_Fortran_COMPILER=${CMAKE_Fortran_COMPILER} ) diff --git a/cmake/netcdf.cmake b/cmake/netcdf.cmake index bcefebc..e5dbd4a 100644 --- a/cmake/netcdf.cmake +++ b/cmake/netcdf.cmake @@ -3,31 +3,11 @@ include(ExternalProject) # due to limitations of NetCDF-C 4.7.4 and NetCDF-Fortran 4.5.3, as per their docs, # we MUST use shared libraries or they don't archive/link properly. -if(NOT hdf5_external) - if(autobuild) - find_package(HDF5 COMPONENTS C Fortran) - endif() - if(NOT (HDF5_FOUND OR TARGET HDF5::HDF5)) - include(${CMAKE_CURRENT_LIST_DIR}/hdf5.cmake) - endif() -else() - find_package(HDF5 COMPONENTS C Fortran REQUIRED) -endif() - -if(NOT netcdf_external) - if(autobuild) - find_package(NetCDF COMPONENTS Fortran) - else() - find_package(NetCDF COMPONENTS Fortran REQUIRED) - endif() +find_package(HDF5 COMPONENTS C Fortran) +if(NOT HDF5_FOUND) + include(${CMAKE_CURRENT_LIST_DIR}/hdf5.cmake) endif() -if(NetCDF_FOUND) - return() -endif() - -set(netcdf_external true CACHE BOOL "autobuild NetCDF") - cmake_path(SET NetCDF_C_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/include) if(WIN32) diff --git a/cmake/options.cmake b/cmake/options.cmake index f2496e8..b46c916 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -1,5 +1,3 @@ -option(autobuild "auto-build NetCDF4 if missing/broken" on) - option(ENABLE_COVERAGE "Code coverage tests") set(CMAKE_TLS_VERIFY true) @@ -10,8 +8,6 @@ cmake_path(SET CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/Modules) file(READ ${CMAKE_CURRENT_LIST_DIR}/libraries.json json) -set_directory_properties(PROPERTIES EP_UPDATE_DISCONNECTED true) - if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config") set(EXTPROJ_GENERATOR "Ninja") else() diff --git a/cmake/zlib.cmake b/cmake/zlib.cmake index 01b90af..5b25aaf 100644 --- a/cmake/zlib.cmake +++ b/cmake/zlib.cmake @@ -4,7 +4,6 @@ include(ExternalProject) - set(ZLIB_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/include) if(BUILD_SHARED_LIBS) @@ -42,13 +41,3 @@ BUILD_BYPRODUCTS ${ZLIB_LIBRARIES} CONFIGURE_HANDLED_BY_BUILD ON INACTIVITY_TIMEOUT 15 ) - -# --- imported target - -file(MAKE_DIRECTORY ${ZLIB_INCLUDE_DIRS}) -# avoid race condition - -add_library(ZLIB::ZLIB INTERFACE IMPORTED GLOBAL) -add_dependencies(ZLIB::ZLIB ZLIB) # to avoid include directory race condition -target_link_libraries(ZLIB::ZLIB INTERFACE ${ZLIB_LIBRARIES}) -target_include_directories(ZLIB::ZLIB INTERFACE ${ZLIB_INCLUDE_DIRS}) diff --git a/codemeta.json b/codemeta.json index 1672328..e458d87 100644 --- a/codemeta.json +++ b/codemeta.json @@ -3,11 +3,11 @@ "@type": "SoftwareSourceCode", "codeRepository": "https://github.com/geospace-code/nc4fortran", "contIntegration": "https://github.com/geospace-code/nc4fortran/actions", - "dateModified": "2022-01-26", + "dateModified": "2022-03-27", "downloadUrl": "https://github.com/geospace-code/nc4fortran/releases", "issueTracker": "https://github.com/geospace-code/nc4fortran/issues", "name": "nc4fortran", - "version": "1.5.2", + "version": "1.6.0", "identifier": "10.5281/zenodo.3757221", "description": "Lightweight object-oriented NetCDF4 Fortran interface", "applicationCategory": "file I/O", diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index e60522d..0459d64 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -3,8 +3,6 @@ project(NetCDF_build LANGUAGES C Fortran ) -set(autobuild on) - # --- system checks if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) message(FATAL_ERROR "please specify where to install NetCDF under, like