From 8b750968579555d19a8d45802b702330e654b7bd Mon Sep 17 00:00:00 2001 From: Christopher Albert Date: Mon, 7 Apr 2025 20:16:39 +0000 Subject: [PATCH 1/6] Added NetCDF metapackage --- src/fpm/manifest/meta.f90 | 8 +++- src/fpm_meta.f90 | 8 ++++ src/metapackage/fpm_meta_netcdf.f90 | 61 +++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/metapackage/fpm_meta_netcdf.f90 diff --git a/src/fpm/manifest/meta.f90 b/src/fpm/manifest/meta.f90 index 41bd113a99..b9f419be38 100644 --- a/src/fpm/manifest/meta.f90 +++ b/src/fpm/manifest/meta.f90 @@ -52,6 +52,9 @@ module fpm_manifest_metapackages !> HDF5 type(metapackage_request_t) :: hdf5 + !> NetCDF + type(metapackage_request_t) :: netcdf + end type metapackage_config_t @@ -203,6 +206,9 @@ subroutine new_meta_config(self, table, meta_allowed, error) call new_meta_request(self%hdf5, "hdf5", table, meta_allowed, error) if (allocated(error)) return + call new_meta_request(self%netcdf, "netcdf", table, meta_allowed, error) + if (allocated(error)) return + end subroutine new_meta_config !> Check local schema for allowed entries @@ -214,7 +220,7 @@ logical function is_meta_package(key) select case (key) !> Supported metapackages - case ("openmp","stdlib","mpi","minpack","hdf5") + case ("openmp","stdlib","mpi","minpack","hdf5","netcdf") is_meta_package = .true. case default diff --git a/src/fpm_meta.f90 b/src/fpm_meta.f90 index 6d5f6a46ce..d52284aecd 100644 --- a/src/fpm_meta.f90 +++ b/src/fpm_meta.f90 @@ -30,6 +30,7 @@ module fpm_meta use fpm_meta_minpack, only: init_minpack use fpm_meta_mpi, only: init_mpi use fpm_meta_hdf5, only: init_hdf5 + use fpm_meta_netcdf, only: init_netcdf use shlex_module, only: shlex_split => split use regex_module, only: regex @@ -61,6 +62,7 @@ subroutine init_from_name(this,name,compiler,error) case("minpack"); call init_minpack(this,compiler,error) case("mpi"); call init_mpi (this,compiler,error) case("hdf5"); call init_hdf5 (this,compiler,error) + case("netcdf"); call init_netcdf (this,compiler,error) case default call syntax_error(error, "Package "//name//" is not supported in [metapackages]") return @@ -153,6 +155,12 @@ subroutine resolve_metapackage_model(model,package,settings,error) if (allocated(error)) return endif + ! netcdf + if (package%meta%netcdf%on) then + call add_metapackage_model(model,package,settings,"netcdf",error) + if (allocated(error)) return + endif + end subroutine resolve_metapackage_model end module fpm_meta diff --git a/src/metapackage/fpm_meta_netcdf.f90 b/src/metapackage/fpm_meta_netcdf.f90 new file mode 100644 index 0000000000..c483c1e949 --- /dev/null +++ b/src/metapackage/fpm_meta_netcdf.f90 @@ -0,0 +1,61 @@ +module fpm_meta_netcdf + use fpm_compiler, only: compiler_t, get_include_flag + use fpm_meta_base, only: metapackage_t, destroy + use fpm_meta_util, only: add_pkg_config_compile_options + use fpm_pkg_config, only: assert_pkg_config, pkgcfg_has_package, pkgcfg_list_all + use fpm_strings, only: string_t + use fpm_error, only: error_t, fatal_error + + implicit none + + private + + public :: init_netcdf + + contains + + !> Initialize NetCDF metapackage for the current system + subroutine init_netcdf(this,compiler,error) + class(metapackage_t), intent(inout) :: this + type(compiler_t), intent(in) :: compiler + type(error_t), allocatable, intent(out) :: error + + logical :: s + character(len=:), allocatable :: include_flag, libdir + + include_flag = get_include_flag(compiler,"") + + !> Cleanup + call destroy(this) + allocate(this%link_libs(0),this%incl_dirs(0),this%external_modules(0)) + this%link_flags = string_t("") + this%flags = string_t("") + + !> Assert pkg-config is installed + if (.not.assert_pkg_config()) then + call fatal_error(error, 'netcdf metapackage requires pkg-config') + return + end if + + if (.not. pkgcfg_has_package('netcdf')) then + call fatal_error(error,'pkg-config could not find a suitable netcdf package.') + end if + call add_pkg_config_compile_options(this, 'netcdf', include_flag, libdir, error) + if (allocated(error)) return + + if (.not. pkgcfg_has_package('netcdf-fortran')) then + call fatal_error(error, & + 'pkg-config could not find a suitable netcdf-fortran package.') + end if + call add_pkg_config_compile_options(this, 'netcdf-fortran', include_flag, libdir, error) + if (allocated(error)) return + + + !> Add NetCDF modules as external + this%has_external_modules = .true. + this%external_modules = [string_t('netcdf')] + + print *, 'NetCDF metapackage initialized successfully.' + + end subroutine init_netcdf +end module fpm_meta_netcdf From 8c28594e45fe8853933c8d2aff9e7e528bda57c2 Mon Sep 17 00:00:00 2001 From: Christopher Albert Date: Sat, 5 Apr 2025 21:53:14 +0200 Subject: [PATCH 2/6] Testing NetCDF --- ci/meta_tests.sh | 11 +++++-- .../metapackage_netcdf/app/main.f90 | 14 ++++++++ example_packages/metapackage_netcdf/fpm.toml | 2 ++ src/metapackage/fpm_meta_netcdf.f90 | 32 ++++++++++++------- 4 files changed, 44 insertions(+), 15 deletions(-) create mode 100644 example_packages/metapackage_netcdf/app/main.f90 create mode 100644 example_packages/metapackage_netcdf/fpm.toml diff --git a/ci/meta_tests.sh b/ci/meta_tests.sh index d9749bb511..3d55cf07ac 100755 --- a/ci/meta_tests.sh +++ b/ci/meta_tests.sh @@ -33,17 +33,22 @@ pushd metapackage_minpack popd pushd metapackage_mpi -"$fpm" build --verbose +"$fpm" build --verbose "$fpm" run --verbose popd pushd metapackage_mpi_c -"$fpm" build --verbose +"$fpm" build --verbose "$fpm" run --verbose popd pushd metapackage_hdf5 -"$fpm" build --verbose +"$fpm" build --verbose +"$fpm" run --verbose +popd + +pushd metapackage_netcdf +"$fpm" build --verbose "$fpm" run --verbose popd diff --git a/example_packages/metapackage_netcdf/app/main.f90 b/example_packages/metapackage_netcdf/app/main.f90 new file mode 100644 index 0000000000..39e9172f59 --- /dev/null +++ b/example_packages/metapackage_netcdf/app/main.f90 @@ -0,0 +1,14 @@ +program metapackage_netcdf + use netcdf4_f03 + implicit none + + integer(c_int) :: ncid, retval + integer(c_int) :: ncsize = 16 + character(c_char), allocatable, target :: memfile(:) + + allocate (memfile(ncsize)) + + retval = nf_create("dummy.nc", NF_INMEMORY, ncid) + if (retval .ne. nf_noerr) error stop + stop 0 +end program metapackage_netcdf diff --git a/example_packages/metapackage_netcdf/fpm.toml b/example_packages/metapackage_netcdf/fpm.toml new file mode 100644 index 0000000000..f5fd4869d7 --- /dev/null +++ b/example_packages/metapackage_netcdf/fpm.toml @@ -0,0 +1,2 @@ +name = "metapackage_netcdf" +dependencies.netcdf="*" diff --git a/src/metapackage/fpm_meta_netcdf.f90 b/src/metapackage/fpm_meta_netcdf.f90 index c483c1e949..1cd1fab5dc 100644 --- a/src/metapackage/fpm_meta_netcdf.f90 +++ b/src/metapackage/fpm_meta_netcdf.f90 @@ -12,10 +12,10 @@ module fpm_meta_netcdf public :: init_netcdf - contains +contains !> Initialize NetCDF metapackage for the current system - subroutine init_netcdf(this,compiler,error) + subroutine init_netcdf(this, compiler, error) class(metapackage_t), intent(inout) :: this type(compiler_t), intent(in) :: compiler type(error_t), allocatable, intent(out) :: error @@ -23,37 +23,45 @@ subroutine init_netcdf(this,compiler,error) logical :: s character(len=:), allocatable :: include_flag, libdir - include_flag = get_include_flag(compiler,"") + include_flag = get_include_flag(compiler, "") !> Cleanup call destroy(this) - allocate(this%link_libs(0),this%incl_dirs(0),this%external_modules(0)) - this%link_flags = string_t("") - this%flags = string_t("") + allocate (this % link_libs(0), this % incl_dirs(0), this % external_modules(0)) + this % link_flags = string_t("") + this % flags = string_t("") !> Assert pkg-config is installed - if (.not.assert_pkg_config()) then + if (.not. assert_pkg_config()) then call fatal_error(error, 'netcdf metapackage requires pkg-config') return end if if (.not. pkgcfg_has_package('netcdf')) then - call fatal_error(error,'pkg-config could not find a suitable netcdf package.') + call fatal_error(error, 'pkg-config could not find a suitable netcdf package.') end if call add_pkg_config_compile_options(this, 'netcdf', include_flag, libdir, error) if (allocated(error)) return if (.not. pkgcfg_has_package('netcdf-fortran')) then call fatal_error(error, & - 'pkg-config could not find a suitable netcdf-fortran package.') + 'pkg-config could not find a suitable netcdf-fortran package.') end if call add_pkg_config_compile_options(this, 'netcdf-fortran', include_flag, libdir, error) if (allocated(error)) return - !> Add NetCDF modules as external - this%has_external_modules = .true. - this%external_modules = [string_t('netcdf')] + this % has_external_modules = .true. + this % external_modules = [string_t('netcdf'), & + string_t('netcdf4_f03'), & + string_t('netcdf4_nc_interfaces'), & + string_t('netcdf4_nf_interfaces'), & + string_t('netcdf_f03'), & + string_t('netcdf_fortv2_c_interfaces'), & + string_t('netcdf_nc_data'), & + string_t('netcdf_nc_interfaces'), & + string_t('netcdf_nf_data'), & + string_t('netcdf_nf_interfaces')] print *, 'NetCDF metapackage initialized successfully.' From 97d9dfd00b6bec4c84bf02016573e86d3c0cf9b7 Mon Sep 17 00:00:00 2001 From: Christopher Albert Date: Sat, 5 Apr 2025 22:25:38 +0200 Subject: [PATCH 3/6] GitHub CI for NetCDF test --- .github/workflows/meta.yml | 49 +++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/.github/workflows/meta.yml b/.github/workflows/meta.yml index cd00d820a7..ce97486950 100644 --- a/.github/workflows/meta.yml +++ b/.github/workflows/meta.yml @@ -4,17 +4,17 @@ on: # On push, only run if any of the metapackage files has changed push: paths: - - 'src/*meta*.f90' + - 'src/*meta*.f90' - 'src/fpm/*meta*.f90' - 'src/fpm/manifest/*meta*.f90' - 'src/ci/meta_tests.sh' - 'src/.github/workflows/meta.yml' - # Always run on PR or release + # Always run on PR or release pull_request: release: types: [published] # Allow manual triggering - workflow_dispatch: + workflow_dispatch: env: CI: "ON" # We can detect this in the build system and other vendors implement it @@ -51,7 +51,7 @@ jobs: - name: (Ubuntu/macOS) setup gcc version if: contains(matrix.os,'ubuntu') || contains(matrix.os,'macos') - run: | + run: | echo "GCC_V=14" >> $GITHUB_ENV - name: (Windows) Install MSYS2 @@ -67,6 +67,8 @@ jobs: unzip curl hdf5 + netcdf + netcdf-fortran - name: (Windows) Setup VS Build environment if: contains(matrix.os,'windows') && contains(matrix.mpi,'intel') @@ -84,7 +86,7 @@ jobs: Remove-Item "oneAPI" -Force -Recurse - name: (Ubuntu) Install gfortran - if: contains(matrix.os,'ubuntu') + if: contains(matrix.os,'ubuntu') run: | sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_V} 100 \ --slave /usr/bin/gfortran gfortran /usr/bin/gfortran-${GCC_V} \ @@ -94,13 +96,15 @@ jobs: if: contains(matrix.os,'ubuntu') && contains(matrix.mpi,'openmpi') run: | sudo apt-get update - sudo apt install -y -q openmpi-bin libopenmpi-dev hwloc fabric libhdf5-dev libhdf5-fortran-102 + sudo apt install -y -q openmpi-bin libopenmpi-dev hwloc fabric libhdf5-dev \ + libhdf5-fortran-102 libnetcdf-dev libnetcdff-dev - name: (Ubuntu) Install MPICH if: contains(matrix.os,'ubuntu') && contains(matrix.mpi,'mpich') run: | sudo apt-get update - sudo apt install -y -q mpich hwloc fabric libhdf5-dev libhdf5-fortran-102 + sudo apt install -y -q mpich hwloc fabric libhdf5-dev libhdf5-fortran-102 \ + libnetcdf-dev libnetcdff-dev - name: (Ubuntu) Retrieve Intel toolchain if: contains(matrix.os,'ubuntu') && contains(matrix.mpi,'intel') @@ -115,16 +119,16 @@ jobs: uses: fortran-lang/setup-fortran@v1.6.1 id: setup-fortran with: - compiler: intel - version: 2024.1.0 + compiler: intel + version: 2024.1.0 - - name: (Ubuntu) finalize oneAPI environment + - name: (Ubuntu) finalize oneAPI environment if: contains(matrix.os,'ubuntu') && contains(matrix.mpi,'intel') run: | # Install MPI - sudo apt-get install -y -q intel-oneapi-mpi-devel ninja-build cmake + sudo apt-get install -y -q intel-oneapi-mpi-devel ninja-build cmake libcurl4-gnutls-dev source /opt/intel/oneapi/setvars.sh --force - printenv >> $GITHUB_ENV + printenv >> $GITHUB_ENV # To run HDF5 with oneAPI, we need to build it from source. Use CMake to generate pkg-config info curl -O -L https://github.com/HDFGroup/hdf5/archive/refs/tags/snapshot-1.14.tar.gz tar zxf snapshot-1.14.tar.gz @@ -133,6 +137,17 @@ jobs: cd build make -j sudo make install + curl -L https://github.com/Unidata/netcdf-c/archive/refs/tags/v4.9.2.tar.gz -o - | tar xz + cd netcdf-c-4.9.2 + CC=icx CXX=icpx FC=ifx ./configure --prefix=/usr --with-hdf5=/usr + CC=icx CXX=icpx FC=ifx make -j + sudo make install + curl -L https://github.com/Unidata/netcdf-fortran/archive/refs/tags/v4.6.1.tar.gz -o - | tar xz + cd netcdf-fortran-4.6.1 + cmake -B build -DCMAKE_Fortran_COMPILER=ifx -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -DCMAKE_INSTALL_PREFIX=/usr + cd build + make -j + sudo make install - name: (Windows) Put MSYS2_MinGW64 on PATH if: contains(matrix.os,'windows') && (!contains(matrix.mpi,'intel')) @@ -214,8 +229,14 @@ jobs: - name: (macOS) Install homebrew HDF5 if: contains(matrix.os,'macos') - run: | - brew install hdf5 + run: | + brew install hdf5 + + - name: (macOS) Install homebrew NetCDF + if: contains(matrix.os,'macos') + run: | + brew install netcdf + brew install netcdf-fortran # Phase 1: Bootstrap fpm with existing version - name: Install fpm From 5dd6013e61ec38a9bc9db29554f8ce8d6429ae40 Mon Sep 17 00:00:00 2001 From: Christopher Albert Date: Sun, 6 Apr 2025 11:48:24 +0200 Subject: [PATCH 4/6] clean: remove output and unused import --- src/metapackage/fpm_meta_netcdf.f90 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/metapackage/fpm_meta_netcdf.f90 b/src/metapackage/fpm_meta_netcdf.f90 index 1cd1fab5dc..d28209e383 100644 --- a/src/metapackage/fpm_meta_netcdf.f90 +++ b/src/metapackage/fpm_meta_netcdf.f90 @@ -2,7 +2,7 @@ module fpm_meta_netcdf use fpm_compiler, only: compiler_t, get_include_flag use fpm_meta_base, only: metapackage_t, destroy use fpm_meta_util, only: add_pkg_config_compile_options - use fpm_pkg_config, only: assert_pkg_config, pkgcfg_has_package, pkgcfg_list_all + use fpm_pkg_config, only: assert_pkg_config, pkgcfg_has_package use fpm_strings, only: string_t use fpm_error, only: error_t, fatal_error @@ -62,8 +62,5 @@ subroutine init_netcdf(this, compiler, error) string_t('netcdf_nc_interfaces'), & string_t('netcdf_nf_data'), & string_t('netcdf_nf_interfaces')] - - print *, 'NetCDF metapackage initialized successfully.' - end subroutine init_netcdf end module fpm_meta_netcdf From 06a3893baf2a9ae65e5594bff79fbac92cfd8197 Mon Sep 17 00:00:00 2001 From: Christopher Albert Date: Wed, 9 Apr 2025 09:52:10 +0200 Subject: [PATCH 5/6] clean: remove unused variables Co-authored-by: Federico Perini --- example_packages/metapackage_netcdf/app/main.f90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/example_packages/metapackage_netcdf/app/main.f90 b/example_packages/metapackage_netcdf/app/main.f90 index 39e9172f59..5e010994fe 100644 --- a/example_packages/metapackage_netcdf/app/main.f90 +++ b/example_packages/metapackage_netcdf/app/main.f90 @@ -3,10 +3,6 @@ program metapackage_netcdf implicit none integer(c_int) :: ncid, retval - integer(c_int) :: ncsize = 16 - character(c_char), allocatable, target :: memfile(:) - - allocate (memfile(ncsize)) retval = nf_create("dummy.nc", NF_INMEMORY, ncid) if (retval .ne. nf_noerr) error stop From 7fbaac1ee3aa6c5d9c10b0af7ec2d8ac56dd2330 Mon Sep 17 00:00:00 2001 From: Christopher Albert Date: Wed, 9 Apr 2025 09:52:53 +0200 Subject: [PATCH 6/6] Modern syntax, output error Co-authored-by: Federico Perini --- example_packages/metapackage_netcdf/app/main.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_packages/metapackage_netcdf/app/main.f90 b/example_packages/metapackage_netcdf/app/main.f90 index 5e010994fe..6e3a2d11e8 100644 --- a/example_packages/metapackage_netcdf/app/main.f90 +++ b/example_packages/metapackage_netcdf/app/main.f90 @@ -5,6 +5,6 @@ program metapackage_netcdf integer(c_int) :: ncid, retval retval = nf_create("dummy.nc", NF_INMEMORY, ncid) - if (retval .ne. nf_noerr) error stop + if (retval /= nf_noerr) error stop nf_strerror(retval) stop 0 end program metapackage_netcdf