Hdf5 package: build on Windows (#31141)

* Enable hdf5 build (including +mpi) on Windows
* This includes updates to hdf5 dependencies openssl (minor edit) and
  bzip2 (more-extensive edits)
* Add binary-based installation of msmpi (this is currently the only
  supported MPI implementation in Spack for Windows). Note that this
  does not install to the Spack-specified prefix. This implementation
  will be replaced with a source-based implementation

Co-authored-by: John Parent <john.parent@kitware.com>
This commit is contained in:
Jared Popelar 2022-11-17 11:40:53 -07:00 committed by GitHub
parent 6811651a0f
commit 381bedf369
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 94 additions and 21 deletions

View file

@ -1704,9 +1704,11 @@ dependencies or incompatible build tools like autoconf. Here are several
packages known to work on Windows:
* abseil-cpp
* bzip2
* clingo
* cpuinfo
* cmake
* hdf5
* glm
* nasm
* netlib-lapack (requires Intel Fortran)

View file

@ -1089,7 +1089,7 @@ def _libs_default_handler(descriptor, spec, cls):
home = getattr(spec.package, "home")
# Avoid double 'lib' for packages whose names already start with lib
if not name.startswith("lib"):
if not name.startswith("lib") and not spec.satisfies("platform=windows"):
name = "lib" + name
# If '+shared' search only for shared library; if '~shared' search only for

View file

@ -4,6 +4,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import re
import sys
from spack.package import *
@ -24,10 +25,22 @@ class Bzip2(Package, SourcewarePackage):
version("1.0.7", sha256="e768a87c5b1a79511499beb41500bcc4caf203726fff46a6f5f9ad27fe08ab2b")
version("1.0.6", sha256="a2848f34fcd5d6cf47def00461fcb528a0484d8edef8208d6d2e2909dc61d9cd")
variant("shared", default=True, description="Enables the build of shared libraries.")
variant(
"shared",
default=(sys.platform != "win32"),
description="Enables the build of shared libraries.",
)
variant("pic", default=False, description="Build static libraries with PIC")
variant("debug", default=False, description="Enable debug symbols and disable optimization")
# makefile.msc doesn't provide a shared recipe
conflicts(
"+shared",
when="platform=windows",
msg="Windows makefile has no recipe for shared builds, use ~shared.",
)
if sys.platform != "win32":
depends_on("diffutils", type="build")
@classmethod
@ -52,9 +65,10 @@ def flag_handler(self, name, flags):
def patch(self):
if self.spec.satisfies("+debug"):
for makefile in ["Makefile", "Makefile-libbz2_so"]:
for makefile in ["Makefile", "Makefile-libbz2_so", "makefile.msc"]:
filter_file(r"-O ", "-O0 ", makefile)
filter_file(r"-O2 ", "-O0 ", makefile)
filter_file(r"-Ox ", "-O0 ", makefile)
# bzip2 comes with two separate Makefiles for static and dynamic builds
# Tell both to use Spack's compiler wrapper instead of GCC
@ -82,13 +96,13 @@ def patch(self):
"$(CC) -dynamiclib -Wl,-install_name -Wl,@rpath/libbz2.{0}.dylib "
"-current_version {1} -compatibility_version {2} -o libbz2.{3}.dylib $(OBJS)"
).format(v1, v2, v3, v3),
**kwargs
**kwargs,
)
mf.filter(
"$(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.so.{0}".format(v3),
"$(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.{0}.dylib".format(v3),
**kwargs
**kwargs,
)
mf.filter(
"rm -f libbz2.so.{0}".format(v2), "rm -f libbz2.{0}.dylib".format(v2), **kwargs
@ -96,7 +110,7 @@ def patch(self):
mf.filter(
"ln -s libbz2.so.{0} libbz2.so.{1}".format(v3, v2),
"ln -s libbz2.{0}.dylib libbz2.{1}.dylib".format(v3, v2),
**kwargs
**kwargs,
)
def install(self, spec, prefix):
@ -105,6 +119,21 @@ def install(self, spec, prefix):
make("-f", "Makefile-libbz2_so")
# Build the static library and everything else
if self.spec.satisfies("platform=windows"):
# Build step
nmake = Executable("nmake.exe")
nmake("-f", "makefile.msc")
# Install step
mkdirp(self.prefix.include)
mkdirp(self.prefix.lib)
mkdirp(self.prefix.bin)
mkdirp(self.prefix.man)
mkdirp(self.prefix.man.man1)
install("*.h", self.prefix.include)
install("*.lib", self.prefix.lib)
install("*.exe", self.prefix.bin)
install("*.1", self.prefix.man.man1)
else:
make()
make("install", "PREFIX={0}".format(prefix))
@ -124,6 +153,8 @@ def install(self, spec, prefix):
for libname in (lib, lib1, lib2):
symlink(lib3, libname)
# These files won't be in a Windows installation
if not self.spec.satisfies("platform=windows"):
with working_dir(prefix.bin):
force_remove("bunzip2", "bzcat")
symlink("bzip2", "bunzip2")

View file

@ -196,13 +196,16 @@ class Hdf5(CMakePackage):
depends_on("cmake@3.12:", type="build")
depends_on("msmpi", when="+mpi platform=windows")
depends_on("mpi", when="+mpi")
depends_on("java", type=("build", "run"), when="+java")
depends_on("szip", when="+szip")
depends_on("zlib@1.1.2:")
# The compiler wrappers (h5cc, h5fc, etc.) run 'pkg-config'.
depends_on("pkgconfig", type="run")
# Skip this on Windows since pkgconfig is autotools
for plat in ["cray", "darwin", "linux"]:
depends_on("pkgconfig", when="platform=%s" % plat, type="run")
conflicts("api=v114", when="@1.6:1.12", msg="v114 is not compatible with this release")
conflicts("api=v112", when="@1.6:1.10", msg="v112 is not compatible with this release")
@ -498,7 +501,7 @@ def cmake_args(self):
if api != "default":
args.append(self.define("DEFAULT_API_VERSION", api))
if "+mpi" in spec:
if "+mpi" in spec and "platform=windows" not in spec:
args.append(self.define("CMAKE_C_COMPILER", spec["mpi"].mpicc))
if "+cxx" in self.spec:
@ -567,7 +570,7 @@ def fix_package_config(self):
r"(Requires(?:\.private)?:.*)(hdf5[^\s,]*)(?:-[^\s,]*)(.*)",
r"\1\2\3",
*pc_files,
backup=False
backup=False,
)
# Create non-versioned symlinks to the versioned pkg-config files:

View file

@ -0,0 +1,42 @@
# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from spack.package import *
class Msmpi(Package):
"""A Windows-specced build of MPICH provided directly by
Microsoft Support Team
"""
homepage = "https://www.microsoft.com/en-us/download/default.aspx"
maintainers = ["jpopelar"]
executable = ["mpiexec.exe"]
version(
"10.0",
sha256="7dae13797627726f67fab9c1d251aec2df9ecd25939984645ec05748bdffd396",
extension="exe",
expand=False,
)
provides("mpi")
conflicts("platform=linux")
conflicts("platform=darwin")
conflicts("platform=cray")
def url_for_version(self, version):
return "https://download.microsoft.com/download/A/E/0/AE002626-9D9D-448D-8197-1EA510E297CE/msmpisetup.exe"
def determine_version(self, exe):
output = Executable("mpiexec.exe")
ver_str = re.search("[Version ([0-9.]+)]", output)
return Version(ver_str.group(0)) if ver_str else None
def install(self, spec, prefix):
installer = Executable("msmpisetup.exe")
installer("-unattend")

View file

@ -420,11 +420,6 @@ def install(self, spec, prefix):
# (e.g. gcc) will not accept them.
filter_file(r"-arch x86_64", "", "Makefile")
if spec.satisfies("+dynamic"):
# This variant only makes sense for Windows
if spec.satisfies("platform=windows"):
filter_file(r"MT", "MD", "makefile")
if spec.satisfies("platform=windows"):
host_make = nmake
else: