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:
		| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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") | ||||
|   | ||||
| @@ -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: | ||||
|   | ||||
							
								
								
									
										42
									
								
								var/spack/repos/builtin/packages/msmpi/package.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								var/spack/repos/builtin/packages/msmpi/package.py
									
									
									
									
									
										Normal 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") | ||||
| @@ -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: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jared Popelar
					Jared Popelar