Trilinos package: build on Windows (#34622)
Update Trilinos and dependencies to build a limited version of Trilinos on Windows. * Support trilinos~mpi~shared on Windows * superlu: force CMake build on Windows * boost: update to build on Windows (proper option formatting and build tool names) * pcre, openblas: add CMake-based build (keep prior build system as default on platforms other than Windows) * openblas: add patch when using Intel Fortran compiler (currently this is included as part of the hybrid %msvc compiler in Spack) Co-authored-by: John Parent <john.parent@kitware.com>
This commit is contained in:
parent
c90c946d52
commit
d9724597ed
@ -498,6 +498,8 @@ def determine_bootstrap_options(self, spec, with_libs, options):
|
||||
with open("user-config.jam", "w") as f:
|
||||
# Boost may end up using gcc even though clang+gfortran is set in
|
||||
# compilers.yaml. Make sure this does not happen:
|
||||
if not spec.satisfies("platform=windows"):
|
||||
# Skip this on Windows since we don't have a cl.exe wrapper in spack
|
||||
f.write("using {0} : : {1} ;\n".format(boost_toolset_id, spack_cxx))
|
||||
|
||||
if "+mpi" in spec:
|
||||
@ -584,7 +586,7 @@ def determine_b2_options(self, spec, options):
|
||||
|
||||
options.extend(["link=%s" % ",".join(link_types), "--layout=%s" % layout])
|
||||
|
||||
if not spec.satisfies("@:1.75 %intel"):
|
||||
if not spec.satisfies("@:1.75 %intel") and not spec.satisfies("platform=windows"):
|
||||
# When building any version >= 1.76, the toolset must be specified.
|
||||
# Earlier versions could not specify Intel as the toolset
|
||||
# as that was considered to be redundant/conflicting with
|
||||
@ -634,7 +636,7 @@ def determine_b2_options(self, spec, options):
|
||||
return threading_opts
|
||||
|
||||
def add_buildopt_symlinks(self, prefix):
|
||||
with working_dir(prefix.lib):
|
||||
with working_dir(prefix.lib, create=True):
|
||||
for lib in os.listdir(os.curdir):
|
||||
if os.path.isfile(lib):
|
||||
prefix, remainder = lib.split(".", 1)
|
||||
@ -687,11 +689,14 @@ def install(self, spec, prefix):
|
||||
# to make Boost find the user-config.jam
|
||||
env["BOOST_BUILD_PATH"] = self.stage.source_path
|
||||
|
||||
bootstrap = Executable("./bootstrap.sh")
|
||||
|
||||
bootstrap_options = ["--prefix=%s" % prefix]
|
||||
self.determine_bootstrap_options(spec, with_libs, bootstrap_options)
|
||||
|
||||
if self.spec.satisfies("platform=windows"):
|
||||
bootstrap = Executable("cmd.exe")
|
||||
bootstrap("/c", ".\\bootstrap.bat", *bootstrap_options)
|
||||
else:
|
||||
bootstrap = Executable("./bootstrap.sh")
|
||||
bootstrap(*bootstrap_options)
|
||||
|
||||
# strip the toolchain to avoid double include errors (intel) or
|
||||
@ -704,6 +709,8 @@ def install(self, spec, prefix):
|
||||
|
||||
# b2 used to be called bjam, before 1.47 (sigh)
|
||||
b2name = "./b2" if spec.satisfies("@1.47:") else "./bjam"
|
||||
if self.spec.satisfies("platform=windows"):
|
||||
b2name = "b2.exe" if spec.satisfies("@1.47:") else "bjam.exe"
|
||||
|
||||
b2 = Executable(b2name)
|
||||
jobs = make_jobs
|
||||
@ -711,11 +718,14 @@ def install(self, spec, prefix):
|
||||
if jobs > 64 and spec.satisfies("@:1.58"):
|
||||
jobs = 64
|
||||
|
||||
b2_options = [
|
||||
"-j",
|
||||
"%s" % jobs,
|
||||
"--user-config=%s" % os.path.join(self.stage.source_path, "user-config.jam"),
|
||||
]
|
||||
# Windows just wants a b2 call with no args
|
||||
b2_options = []
|
||||
if not self.spec.satisfies("platform=windows"):
|
||||
path_to_config = "--user-config=%s" % os.path.join(
|
||||
self.stage.source_path, "user-config.jam"
|
||||
)
|
||||
b2_options = ["-j", "%s" % jobs]
|
||||
b2_options.append(path_to_config)
|
||||
|
||||
threading_opts = self.determine_b2_options(spec, b2_options)
|
||||
|
||||
@ -727,8 +737,11 @@ def install(self, spec, prefix):
|
||||
|
||||
# In theory it could be done on one call but it fails on
|
||||
# Boost.MPI if the threading options are not separated.
|
||||
if not self.spec.satisfies("platform=windows"):
|
||||
for threading_opt in threading_opts:
|
||||
b2("install", "threading=%s" % threading_opt, *b2_options)
|
||||
else:
|
||||
b2("install", *b2_options)
|
||||
|
||||
if "+multithreaded" in spec and "~taggedlayout" in spec:
|
||||
self.add_buildopt_symlinks(prefix)
|
||||
|
13
var/spack/repos/builtin/packages/openblas/ifort-msvc.patch
Normal file
13
var/spack/repos/builtin/packages/openblas/ifort-msvc.patch
Normal file
@ -0,0 +1,13 @@
|
||||
diff -ruN spack-src/cmake/fc.cmake spack-src-new/cmake/fc.cmake
|
||||
--- spack-src/cmake/fc.cmake 2023-04-01 14:18:01.000000000 -0600
|
||||
+++ spack-src-new/cmake/fc.cmake 2023-06-06 09:34:12.921982500 -0600
|
||||
@@ -89,6 +89,9 @@
|
||||
|
||||
if (${F_COMPILER} STREQUAL "INTEL")
|
||||
set(CCOMMON_OPT "${CCOMMON_OPT} -DF_INTERFACE_INTEL")
|
||||
+ if (MSVC)
|
||||
+ set(FCOMMON_OPT "${FCOMMON_OPT} -names:uppercase -assume:underscore")
|
||||
+ endif ()
|
||||
if (INTERFACE64)
|
||||
set(FCOMMON_OPT "${FCOMMON_OPT} -i8")
|
||||
endif ()
|
@ -6,11 +6,13 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
import spack.build_systems.cmake
|
||||
import spack.build_systems.makefile
|
||||
from spack.package import *
|
||||
from spack.package_test import compare_output_file, compile_c_and_execute
|
||||
|
||||
|
||||
class Openblas(MakefilePackage):
|
||||
class Openblas(CMakePackage, MakefilePackage):
|
||||
"""OpenBLAS: An optimized BLAS library"""
|
||||
|
||||
homepage = "https://www.openblas.net"
|
||||
@ -19,7 +21,7 @@ class Openblas(MakefilePackage):
|
||||
)
|
||||
git = "https://github.com/OpenMathLib/OpenBLAS.git"
|
||||
|
||||
libraries = ["libopenblas"]
|
||||
libraries = ["libopenblas", "openblas"]
|
||||
|
||||
version("develop", branch="develop")
|
||||
version("0.3.24", sha256="ceadc5065da97bd92404cac7254da66cc6eb192679cf1002098688978d4d5132")
|
||||
@ -91,6 +93,9 @@ class Openblas(MakefilePackage):
|
||||
provides("lapack@3.9.1:", when="@0.3.15:")
|
||||
provides("lapack@3.7.0", when="@0.2.20")
|
||||
|
||||
# https://github.com/xianyi/OpenBLAS/pull/2519/files
|
||||
patch("ifort-msvc.patch", when="%msvc")
|
||||
|
||||
# https://github.com/OpenMathLib/OpenBLAS/pull/3712
|
||||
patch("cce.patch", when="@0.3.20 %cce")
|
||||
|
||||
@ -213,6 +218,8 @@ class Openblas(MakefilePackage):
|
||||
|
||||
depends_on("perl", type="build")
|
||||
|
||||
build_system("makefile", "cmake", default="makefile")
|
||||
|
||||
def flag_handler(self, name, flags):
|
||||
spec = self.spec
|
||||
iflags = []
|
||||
@ -242,13 +249,37 @@ def check_compilers(self):
|
||||
# require both.
|
||||
# As of 08/2022 (0.3.21), we can build purely with a C compiler using
|
||||
# a f2c translated LAPACK version
|
||||
# https://github.com/OpenMathLib/OpenBLAS/releases/tag/v0.3.21
|
||||
# https://github.com/xianyi/OpenBLAS/releases/tag/v0.3.21
|
||||
if self.compiler.fc is None and "~fortran" not in self.spec:
|
||||
raise InstallError(
|
||||
self.compiler.cc
|
||||
+ " has no Fortran compiler added in spack. Add it or use openblas~fortran!"
|
||||
)
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
# The only public headers for cblas and lapacke in
|
||||
# openblas are cblas.h and lapacke.h. The remaining headers are private
|
||||
# headers either included in one of these two headers, or included in
|
||||
# one of the source files implementing functions declared in these
|
||||
# headers.
|
||||
return find_headers(["cblas", "lapacke"], self.prefix.include)
|
||||
|
||||
@property
|
||||
def libs(self):
|
||||
spec = self.spec
|
||||
|
||||
# Look for openblas{symbol_suffix}
|
||||
name = ["libopenblas", "openblas"]
|
||||
search_shared = bool(spec.variants["shared"].value)
|
||||
suffix = spec.variants["symbol_suffix"].value
|
||||
if suffix != "none":
|
||||
name += suffix
|
||||
|
||||
return find_libraries(name, spec.prefix, shared=search_shared, recursive=True)
|
||||
|
||||
|
||||
class MakefileBuilder(spack.build_systems.makefile.MakefileBuilder):
|
||||
@staticmethod
|
||||
def _read_targets(target_file):
|
||||
"""Parse a list of available targets from the OpenBLAS/TargetList.txt
|
||||
@ -304,7 +335,7 @@ def _microarch_target_args(self):
|
||||
if microarch.name in available_targets:
|
||||
break
|
||||
|
||||
if self.version >= Version("0.3"):
|
||||
if self.spec.version >= Version("0.3"):
|
||||
# 'ARCH' argument causes build errors in older OpenBLAS
|
||||
# see https://github.com/spack/spack/issues/15385
|
||||
arch_name = microarch.family.name
|
||||
@ -379,9 +410,9 @@ def make_defs(self):
|
||||
|
||||
if "~shared" in self.spec:
|
||||
if "+pic" in self.spec:
|
||||
make_defs.append("CFLAGS={0}".format(self.compiler.cc_pic_flag))
|
||||
make_defs.append("CFLAGS={0}".format(self.pkg.compiler.cc_pic_flag))
|
||||
if "~fortran" not in self.spec:
|
||||
make_defs.append("FFLAGS={0}".format(self.compiler.f77_pic_flag))
|
||||
make_defs.append("FFLAGS={0}".format(self.pkg.compiler.f77_pic_flag))
|
||||
make_defs += ["NO_SHARED=1"]
|
||||
# fix missing _dggsvd_ and _sggsvd_
|
||||
if self.spec.satisfies("@0.2.16"):
|
||||
@ -442,28 +473,6 @@ def make_defs(self):
|
||||
|
||||
return make_defs
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
# As in netlib-lapack, the only public headers for cblas and lapacke in
|
||||
# openblas are cblas.h and lapacke.h. The remaining headers are private
|
||||
# headers either included in one of these two headers, or included in
|
||||
# one of the source files implementing functions declared in these
|
||||
# headers.
|
||||
return find_headers(["cblas", "lapacke"], self.prefix.include)
|
||||
|
||||
@property
|
||||
def libs(self):
|
||||
spec = self.spec
|
||||
|
||||
# Look for openblas{symbol_suffix}
|
||||
name = "libopenblas"
|
||||
search_shared = bool(spec.variants["shared"].value)
|
||||
suffix = spec.variants["symbol_suffix"].value
|
||||
if suffix != "none":
|
||||
name += suffix
|
||||
|
||||
return find_libraries(name, spec.prefix, shared=search_shared, recursive=True)
|
||||
|
||||
@property
|
||||
def build_targets(self):
|
||||
return ["-s"] + self.make_defs + ["all"]
|
||||
@ -499,3 +508,28 @@ def check_install(self):
|
||||
|
||||
output = compile_c_and_execute(source_file, [include_flags], link_flags.split())
|
||||
compare_output_file(output, blessed_file)
|
||||
|
||||
|
||||
class CMakeBuilder(spack.build_systems.cmake.CMakeBuilder):
|
||||
def cmake_args(self):
|
||||
cmake_defs = [self.define("TARGET", "GENERIC")]
|
||||
if self.spec.satisfies("platform=windows"):
|
||||
cmake_defs += [
|
||||
self.define("DYNAMIC_ARCH", "OFF"),
|
||||
self.define("BUILD_WITHOUT_LAPACK", "ON"),
|
||||
]
|
||||
|
||||
if "~fortran" in self.spec:
|
||||
cmake_defs += [self.define("NOFORTRAN", "ON")]
|
||||
|
||||
if "+shared" in self.spec:
|
||||
cmake_defs += [self.define("BUILD_SHARED_LIBS", "ON")]
|
||||
|
||||
if self.spec.satisfies("threads=openmp"):
|
||||
cmake_defs += [self.define("USE_OPENMP", "ON"), self.define("USE_THREAD", "ON")]
|
||||
elif self.spec.satisfies("threads=pthreads"):
|
||||
cmake_defs += [self.define("USE_OPENMP", "OFF"), self.define("USE_THREAD", "ON")]
|
||||
else:
|
||||
cmake_defs += [self.define("USE_OPENMP", "OFF"), self.define("USE_THREAD", "OFF")]
|
||||
|
||||
return cmake_defs
|
||||
|
@ -3,10 +3,12 @@
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import spack.build_systems.autotools
|
||||
import spack.build_systems.cmake
|
||||
from spack.package import *
|
||||
|
||||
|
||||
class Pcre(AutotoolsPackage):
|
||||
class Pcre(AutotoolsPackage, CMakePackage):
|
||||
"""The PCRE package contains Perl Compatible Regular Expression
|
||||
libraries. These are useful for implementing regular expression
|
||||
pattern matching using the same syntax and semantics as Perl 5."""
|
||||
@ -26,6 +28,8 @@ class Pcre(AutotoolsPackage):
|
||||
maintainers("drkennetz")
|
||||
patch("intel.patch", when="@8.38")
|
||||
|
||||
build_system("autotools", "cmake", default="autotools")
|
||||
|
||||
variant("jit", default=False, description="Enable JIT support.")
|
||||
|
||||
variant("multibyte", default=True, description="Enable support for 16 and 32 bit characters.")
|
||||
@ -36,6 +40,8 @@ class Pcre(AutotoolsPackage):
|
||||
description="Enable support for UTF-8/16/32, " "incompatible with EBCDIC.",
|
||||
)
|
||||
|
||||
|
||||
class AutotoolsBuilder(spack.build_systems.autotools.AutotoolsBuilder):
|
||||
def configure_args(self):
|
||||
args = []
|
||||
|
||||
@ -51,3 +57,21 @@ def configure_args(self):
|
||||
args.append("--enable-unicode-properties")
|
||||
|
||||
return args
|
||||
|
||||
|
||||
class CMakeBuilder(spack.build_systems.cmake.CMakeBuilder):
|
||||
def cmake_args(self):
|
||||
args = []
|
||||
|
||||
if "+jit" in self.spec:
|
||||
args.append("-DPCRE_SUPPORT_JIT:BOOL=ON")
|
||||
|
||||
if "+multibyte" in self.spec:
|
||||
args.append("-DPCRE_BUILD_PCRE16:BOOL=ON")
|
||||
args.append("-DPCRE_BUILD_PCRE32:BOOL=ON")
|
||||
|
||||
if "+utf" in self.spec:
|
||||
args.append("-DPCRE_SUPPORT_UTF:BOOL=ON")
|
||||
args.append("-DPCRE_SUPPORT_UNICODE_PROPERTIES:BOOL=ON")
|
||||
|
||||
return args
|
||||
|
@ -46,6 +46,8 @@ class Superlu(CMakePackage, Package):
|
||||
conditional("cmake", when="@5:"), conditional("generic", when="@:4"), default="cmake"
|
||||
)
|
||||
|
||||
requires("build_system=cmake", when="platform=windows")
|
||||
|
||||
variant("pic", default=True, description="Build with position independent code")
|
||||
|
||||
depends_on("blas")
|
||||
|
@ -4,6 +4,7 @@
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
from spack.build_environment import dso_suffix
|
||||
@ -366,6 +367,18 @@ class Trilinos(CMakePackage, CudaPackage, ROCmPackage):
|
||||
conflicts("+stokhos", when="%xl")
|
||||
conflicts("+stokhos", when="%xl_r")
|
||||
|
||||
# Current Windows support, only have serial static builds
|
||||
conflicts(
|
||||
"+shared",
|
||||
when="platform=windows",
|
||||
msg="Only static builds are supported on Windows currently.",
|
||||
)
|
||||
conflicts(
|
||||
"+mpi",
|
||||
when="platform=windows",
|
||||
msg="Only serial builds are supported on Windows currently.",
|
||||
)
|
||||
|
||||
# ###################### Dependencies ##########################
|
||||
|
||||
# External Kokkos
|
||||
@ -393,7 +406,9 @@ class Trilinos(CMakePackage, CudaPackage, ROCmPackage):
|
||||
depends_on("cgns", when="+exodus")
|
||||
depends_on("cmake@3.23:", type="build", when="@14.0.0:")
|
||||
depends_on("hdf5+hl", when="+hdf5")
|
||||
depends_on("hypre~internal-superlu~int64", when="+hypre")
|
||||
for plat in ["cray", "darwin", "linux"]:
|
||||
depends_on("hypre~internal-superlu~int64", when="+hypre platform=%s" % plat)
|
||||
depends_on("hypre-cmake~int64", when="+hypre platform=windows")
|
||||
depends_on("kokkos-nvcc-wrapper", when="+wrapper")
|
||||
depends_on("lapack")
|
||||
# depends_on('perl', type=('build',)) # TriBITS finds but doesn't use...
|
||||
@ -811,7 +826,7 @@ def define_tpl(trilinos_name, spack_name, have_dep):
|
||||
define("CMAKE_C_COMPILER", spec["mpi"].mpicc),
|
||||
define("CMAKE_CXX_COMPILER", spec["mpi"].mpicxx),
|
||||
define("CMAKE_Fortran_COMPILER", spec["mpi"].mpifc),
|
||||
define("MPI_BASE_DIR", spec["mpi"].prefix),
|
||||
define("MPI_BASE_DIR", str(pathlib.PurePosixPath(spec["mpi"].prefix))),
|
||||
]
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user