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: | packages known to work on Windows: | ||||||
|  |  | ||||||
| * abseil-cpp | * abseil-cpp | ||||||
|  | * bzip2 | ||||||
| * clingo | * clingo | ||||||
| * cpuinfo | * cpuinfo | ||||||
| * cmake | * cmake | ||||||
|  | * hdf5 | ||||||
| * glm | * glm | ||||||
| * nasm | * nasm | ||||||
| * netlib-lapack (requires Intel Fortran) | * netlib-lapack (requires Intel Fortran) | ||||||
|   | |||||||
| @@ -1089,7 +1089,7 @@ def _libs_default_handler(descriptor, spec, cls): | |||||||
|     home = getattr(spec.package, "home") |     home = getattr(spec.package, "home") | ||||||
| 
 | 
 | ||||||
|     # Avoid double 'lib' for packages whose names already start with lib |     # 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 |         name = "lib" + name | ||||||
| 
 | 
 | ||||||
|     # If '+shared' search only for shared library; if '~shared' search only for |     # If '+shared' search only for shared library; if '~shared' search only for | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| # SPDX-License-Identifier: (Apache-2.0 OR MIT) | # SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||||||
| 
 | 
 | ||||||
| import re | import re | ||||||
|  | import sys | ||||||
| 
 | 
 | ||||||
| from spack.package import * | from spack.package import * | ||||||
| 
 | 
 | ||||||
| @@ -24,11 +25,23 @@ class Bzip2(Package, SourcewarePackage): | |||||||
|     version("1.0.7", sha256="e768a87c5b1a79511499beb41500bcc4caf203726fff46a6f5f9ad27fe08ab2b") |     version("1.0.7", sha256="e768a87c5b1a79511499beb41500bcc4caf203726fff46a6f5f9ad27fe08ab2b") | ||||||
|     version("1.0.6", sha256="a2848f34fcd5d6cf47def00461fcb528a0484d8edef8208d6d2e2909dc61d9cd") |     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("pic", default=False, description="Build static libraries with PIC") | ||||||
|     variant("debug", default=False, description="Enable debug symbols and disable optimization") |     variant("debug", default=False, description="Enable debug symbols and disable optimization") | ||||||
| 
 | 
 | ||||||
|     depends_on("diffutils", type="build") |     # 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 |     @classmethod | ||||||
|     def determine_version(cls, exe): |     def determine_version(cls, exe): | ||||||
| @@ -52,9 +65,10 @@ def flag_handler(self, name, flags): | |||||||
| 
 | 
 | ||||||
|     def patch(self): |     def patch(self): | ||||||
|         if self.spec.satisfies("+debug"): |         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"-O ", "-O0 ", makefile) | ||||||
|                 filter_file(r"-O2 ", "-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 |         # bzip2 comes with two separate Makefiles for static and dynamic builds | ||||||
|         # Tell both to use Spack's compiler wrapper instead of GCC |         # 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 " |                     "$(CC) -dynamiclib -Wl,-install_name -Wl,@rpath/libbz2.{0}.dylib " | ||||||
|                     "-current_version {1} -compatibility_version {2} -o libbz2.{3}.dylib $(OBJS)" |                     "-current_version {1} -compatibility_version {2} -o libbz2.{3}.dylib $(OBJS)" | ||||||
|                 ).format(v1, v2, v3, v3), |                 ).format(v1, v2, v3, v3), | ||||||
|                 **kwargs |                 **kwargs, | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|             mf.filter( |             mf.filter( | ||||||
|                 "$(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.so.{0}".format(v3), |                 "$(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.so.{0}".format(v3), | ||||||
|                 "$(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.{0}.dylib".format(v3), |                 "$(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.{0}.dylib".format(v3), | ||||||
|                 **kwargs |                 **kwargs, | ||||||
|             ) |             ) | ||||||
|             mf.filter( |             mf.filter( | ||||||
|                 "rm -f libbz2.so.{0}".format(v2), "rm -f libbz2.{0}.dylib".format(v2), **kwargs |                 "rm -f libbz2.so.{0}".format(v2), "rm -f libbz2.{0}.dylib".format(v2), **kwargs | ||||||
| @@ -96,7 +110,7 @@ def patch(self): | |||||||
|             mf.filter( |             mf.filter( | ||||||
|                 "ln -s libbz2.so.{0} libbz2.so.{1}".format(v3, v2), |                 "ln -s libbz2.so.{0} libbz2.so.{1}".format(v3, v2), | ||||||
|                 "ln -s libbz2.{0}.dylib libbz2.{1}.dylib".format(v3, v2), |                 "ln -s libbz2.{0}.dylib libbz2.{1}.dylib".format(v3, v2), | ||||||
|                 **kwargs |                 **kwargs, | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|     def install(self, spec, prefix): |     def install(self, spec, prefix): | ||||||
| @@ -105,8 +119,23 @@ def install(self, spec, prefix): | |||||||
|             make("-f", "Makefile-libbz2_so") |             make("-f", "Makefile-libbz2_so") | ||||||
| 
 | 
 | ||||||
|         # Build the static library and everything else |         # Build the static library and everything else | ||||||
|         make() |         if self.spec.satisfies("platform=windows"): | ||||||
|         make("install", "PREFIX={0}".format(prefix)) |             # 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)) | ||||||
| 
 | 
 | ||||||
|         if "+shared" in spec: |         if "+shared" in spec: | ||||||
|             install("bzip2-shared", join_path(prefix.bin, "bzip2")) |             install("bzip2-shared", join_path(prefix.bin, "bzip2")) | ||||||
| @@ -124,7 +153,9 @@ def install(self, spec, prefix): | |||||||
|                 for libname in (lib, lib1, lib2): |                 for libname in (lib, lib1, lib2): | ||||||
|                     symlink(lib3, libname) |                     symlink(lib3, libname) | ||||||
| 
 | 
 | ||||||
|         with working_dir(prefix.bin): |         # These files won't be in a Windows installation | ||||||
|             force_remove("bunzip2", "bzcat") |         if not self.spec.satisfies("platform=windows"): | ||||||
|             symlink("bzip2", "bunzip2") |             with working_dir(prefix.bin): | ||||||
|             symlink("bzip2", "bzcat") |                 force_remove("bunzip2", "bzcat") | ||||||
|  |                 symlink("bzip2", "bunzip2") | ||||||
|  |                 symlink("bzip2", "bzcat") | ||||||
|   | |||||||
| @@ -196,13 +196,16 @@ class Hdf5(CMakePackage): | |||||||
| 
 | 
 | ||||||
|     depends_on("cmake@3.12:", type="build") |     depends_on("cmake@3.12:", type="build") | ||||||
| 
 | 
 | ||||||
|  |     depends_on("msmpi", when="+mpi platform=windows") | ||||||
|     depends_on("mpi", when="+mpi") |     depends_on("mpi", when="+mpi") | ||||||
|     depends_on("java", type=("build", "run"), when="+java") |     depends_on("java", type=("build", "run"), when="+java") | ||||||
|     depends_on("szip", when="+szip") |     depends_on("szip", when="+szip") | ||||||
|     depends_on("zlib@1.1.2:") |     depends_on("zlib@1.1.2:") | ||||||
| 
 | 
 | ||||||
|     # The compiler wrappers (h5cc, h5fc, etc.) run 'pkg-config'. |     # 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=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") |     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": |         if api != "default": | ||||||
|             args.append(self.define("DEFAULT_API_VERSION", api)) |             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)) |             args.append(self.define("CMAKE_C_COMPILER", spec["mpi"].mpicc)) | ||||||
| 
 | 
 | ||||||
|             if "+cxx" in self.spec: |             if "+cxx" in self.spec: | ||||||
| @@ -567,7 +570,7 @@ def fix_package_config(self): | |||||||
|             r"(Requires(?:\.private)?:.*)(hdf5[^\s,]*)(?:-[^\s,]*)(.*)", |             r"(Requires(?:\.private)?:.*)(hdf5[^\s,]*)(?:-[^\s,]*)(.*)", | ||||||
|             r"\1\2\3", |             r"\1\2\3", | ||||||
|             *pc_files, |             *pc_files, | ||||||
|             backup=False |             backup=False, | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         # Create non-versioned symlinks to the versioned pkg-config files: |         # 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. |         # (e.g. gcc) will not accept them. | ||||||
|         filter_file(r"-arch x86_64", "", "Makefile") |         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"): |         if spec.satisfies("platform=windows"): | ||||||
|             host_make = nmake |             host_make = nmake | ||||||
|         else: |         else: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jared Popelar
					Jared Popelar