From 482525d0f9e11038e0b645740c406dd2a6797af5 Mon Sep 17 00:00:00 2001 From: Alex Richert <82525672+AlexanderRichert-NOAA@users.noreply.github.com> Date: Fri, 6 Oct 2023 15:04:51 -0700 Subject: [PATCH] Update bufr recipe (#40033) * Update bufr recipe * Add v12.0.1 * style fixes * remove test-related functionality for bufr * Re-add testing --------- Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com> --- .../builtin/packages/bufr/c-tests-libm.patch | 11 ++ .../bufr/cmakelists-apple-llvm-ranlib.patch | 15 +++ .../repos/builtin/packages/bufr/package.py | 102 +++++++++++++++--- .../packages/bufr/python-version.patch | 12 +++ 4 files changed, 126 insertions(+), 14 deletions(-) create mode 100644 var/spack/repos/builtin/packages/bufr/c-tests-libm.patch create mode 100644 var/spack/repos/builtin/packages/bufr/cmakelists-apple-llvm-ranlib.patch create mode 100644 var/spack/repos/builtin/packages/bufr/python-version.patch diff --git a/var/spack/repos/builtin/packages/bufr/c-tests-libm.patch b/var/spack/repos/builtin/packages/bufr/c-tests-libm.patch new file mode 100644 index 0000000000..1183659116 --- /dev/null +++ b/var/spack/repos/builtin/packages/bufr/c-tests-libm.patch @@ -0,0 +1,11 @@ +--- a/test/CMakeLists.txt 2022-07-28 11:25:13.000000000 -0400 ++++ b/test/CMakeLists.txt 2022-07-28 11:26:40.000000000 -0400 +@@ -205,7 +205,7 @@ + set(test_exe ${test}.x) + add_executable(${test_exe} ${test_src}) + add_dependencies(${test_exe} bufr_${kind}) +- target_link_libraries(${test_exe} PRIVATE bufr::bufr_${kind}) ++ target_link_libraries(${test_exe} PRIVATE bufr::bufr_${kind} m) + add_test(NAME ${test} COMMAND ${CMAKE_BINARY_DIR}/test/${test_exe}) + endforeach() + endforeach() diff --git a/var/spack/repos/builtin/packages/bufr/cmakelists-apple-llvm-ranlib.patch b/var/spack/repos/builtin/packages/bufr/cmakelists-apple-llvm-ranlib.patch new file mode 100644 index 0000000000..8f2e363e58 --- /dev/null +++ b/var/spack/repos/builtin/packages/bufr/cmakelists-apple-llvm-ranlib.patch @@ -0,0 +1,15 @@ +--- a/CMakeLists.txt 2022-02-08 10:03:55.000000000 -0700 ++++ b/CMakeLists.txt 2022-02-08 10:03:51.000000000 -0700 +@@ -39,9 +39,9 @@ + find_package(Python3 REQUIRED COMPONENTS Interpreter) + endif() + +-if(APPLE) +- # The linker on macOS does not include `common symbols` by default +- # Passing the -c flag includes them and fixes an error with undefined symbols ++if(APPLE AND NOT "${CMAKE_RANLIB}" MATCHES "^.*(llvm-ranlib)$") ++ # The linker on macOS does not include `common symbols` by default, Intel requires ++ # passing the -c flag to include them and fix an error with undefined symbols + set(CMAKE_Fortran_ARCHIVE_FINISH " -c ") + set(CMAKE_C_ARCHIVE_FINISH " -c ") + endif() diff --git a/var/spack/repos/builtin/packages/bufr/package.py b/var/spack/repos/builtin/packages/bufr/package.py index e02ebbe134..f475c0afd0 100644 --- a/var/spack/repos/builtin/packages/bufr/package.py +++ b/var/spack/repos/builtin/packages/bufr/package.py @@ -3,6 +3,8 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import os + from spack.package import * @@ -11,37 +13,109 @@ class Bufr(CMakePackage): utilities that can be used to read (decode) and write (encode) data in BUFR, which is a WMO standard format for the exchange of meteorological data. This is part of the NCEPLIBS project. - + The library also includes a Python interface. """ homepage = "https://noaa-emc.github.io/NCEPLIBS-bufr" url = "https://github.com/NOAA-EMC/NCEPLIBS-bufr/archive/refs/tags/bufr_v11.5.0.tar.gz" + git = "https://github.com/NOAA-EMC/NCEPLIBS-bufr" - maintainers("t-brown", "AlexanderRichert-NOAA", "edwardhartnett", "Hang-Lei-NOAA", "jbathegit") + maintainers("AlexanderRichert-NOAA", "edwardhartnett", "Hang-Lei-NOAA", "jbathegit") + version("develop", branch="develop") + version("12.0.1", sha256="525f26238dba6511a453fc71cecc05f59e4800a603de2abbbbfb8cbb5adf5708") + version("12.0.0", sha256="d01c02ea8e100e51fd150ff1c4a1192ca54538474acb1b7f7a36e8aeab76ee75") version("11.7.1", sha256="6533ce6eaa6b02c0cb5424cfbc086ab120ccebac3894980a4daafd4dfadd71f8") version("11.7.0", sha256="6a76ae8e7682bbc790321bf80c2f9417775c5b01a5c4f10763df92e01b20b9ca") version("11.6.0", sha256="af4c04e0b394aa9b5f411ec5c8055888619c724768b3094727e8bb7d3ea34a54") version("11.5.0", sha256="d154839e29ef1fe82e58cf20232e9f8a4f0610f0e8b6a394b7ca052e58f97f43") + version("11.4.0", sha256="946482405e675b99e8e0c221d137768f246076f5e9ba92eed6cae47fb68b7a26") + + # Patch to not add "-c" to ranlib flags when using llvm-ranlib on Apple systems + patch("cmakelists-apple-llvm-ranlib.patch", when="@11.5.0:11.6.0") + # C test does not explicity link to -lm causing DSO error when building shared libs + patch("c-tests-libm.patch", when="@11.5.0:11.7.0") + # Patch to identify Python version correctly + patch("python-version.patch", when="@11.5:12.0.0 +python") + + variant("python", default=False, description="Enable Python interface?") + variant("shared", default=True, description="Build shared libraries", when="@11.5:") + + extends("python", when="+python") + + depends_on("python@3:", type=("build", "run"), when="+python") + depends_on("py-setuptools", type="build", when="+python") + depends_on("py-numpy", type=("build", "run"), when="+python") + depends_on("py-pip", type="build", when="+python") + depends_on("py-wheel", type="build", when="+python") + + def url_for_version(self, version): + pre = "bufr_" if version < Version("12.0.1") else "" + return ( + f"https://github.com/NOAA-EMC/NCEPLIBS-bufr/archive/refs/tags/{pre}v{version}.tar.gz" + ) + + # Need to make the lines shorter at least on some systems + def patch(self): + with when("@:11.7.1"): + filter_file("_lenslmax 120", "_lenslmax 60", "CMakeLists.txt") + + def cmake_args(self): + args = [ + self.define_from_variant("ENABLE_PYTHON", "python"), + self.define_from_variant("BUILD_SHARED_LIBS", "shared"), + self.define("BUILD_TESTS", self.run_tests), + ] + + return args + + def flag_handler(self, name, flags): + """ + On macOS if a library built with the ar utility contains objects + with Fortran module data but no executable functions, + the symbols corresponding to the module data may not be resolved + when an object referencing them is linked against the library. + You can work around this by compiling with option -fno-common. + """ + fc = self.compiler.fc + if self.spec.satisfies("platform=darwin"): + if name == "fflags": + if "ifort" in fc or "gfortran" in fc: + flags.append("-fno-common") + + # Bufr inserts a path into source code which may be longer than 132 + if name == "fflags" and "gfortran" in fc: + flags.append("-ffree-line-length-none") + + # Inject flags into CMake build + return (None, None, flags) def _setup_bufr_environment(self, env, suffix): libname = "libbufr_{0}".format(suffix) - lib = find_libraries(libname, root=self.prefix, shared=False, recursive=True) - lib_envname = "BUFR_LIB{0}".format(suffix) - inc_envname = "BUFR_INC{0}".format(suffix) - include_dir = "include_{0}".format(suffix) + shared = True if "+shared" in self.spec else False + # Bufr has _DA (dynamic allocation) libs in versions <= 11.5.0 + append = "" if self.spec.satisfies("@11.5.0:") else "_DA" + lib = find_libraries(libname + append, root=self.prefix, shared=shared, recursive=True) + lib_envname = "BUFR_LIB{0}".format(suffix) + append + inc_envname = "BUFR_INC{0}".format(suffix) + append + include_dir = "{0}_{1}".format(self.prefix.include.bufr, suffix) env.set(lib_envname, lib[0]) env.set(inc_envname, include_dir) - # Bufr has _DA (dynamic allocation) libs in versions <= 11.5.0 - if self.spec.satisfies("@:11.5.0"): - da_lib = find_libraries( - libname + "_DA", root=self.prefix, shared=False, recursive=True - ) - env.set(lib_envname + "_DA", da_lib[0]) - env.set(inc_envname + "_DA", include_dir) + if self.spec.satisfies("+python"): + pyver = self.spec["python"].version.up_to(2) + pydir = join_path(os.path.dirname(lib[0]), f"python{pyver}", "site-packages") + env.prepend_path("PYTHONPATH", pydir) def setup_run_environment(self, env): - for suffix in ("4", "8", "d"): + suffixes = ["4"] + if not self.spec.satisfies("@12:"): + suffixes += ["8", "d"] + for suffix in suffixes: self._setup_bufr_environment(env, suffix) + + def check(self): + if self.spec.satisfies("~python"): + with working_dir(self.builder.build_directory): + make("test") diff --git a/var/spack/repos/builtin/packages/bufr/python-version.patch b/var/spack/repos/builtin/packages/bufr/python-version.patch new file mode 100644 index 0000000000..8b4b979d66 --- /dev/null +++ b/var/spack/repos/builtin/packages/bufr/python-version.patch @@ -0,0 +1,12 @@ +--- a/python/CMakeLists.txt 2023-06-08 12:39:26.000000000 -0600 ++++ b/python/CMakeLists.txt 2023-07-19 13:45:11.000000000 -0600 +@@ -8,8 +8,7 @@ + file( COPY ncepbufr utils DESTINATION . ) + + # Library installation directory +-execute_process(COMMAND ${Python3_EXECUTABLE} -c "from __future__ import print_function; import sys; print(sys.version[:3], end='')" +- OUTPUT_VARIABLE _PYVER) ++set(_PYVER "${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}") + set(_install_dir "${CMAKE_INSTALL_FULL_LIBDIR}/python${_PYVER}/site-packages") + + # Build the extension module for use in install tree