builtin: changes to packages

This commit is contained in:
Massimiliano Culpo 2024-11-11 12:24:22 +01:00
parent d6f0ce3e5a
commit cf9a148708
No known key found for this signature in database
GPG Key ID: 3E52BB992233066C
49 changed files with 892 additions and 269 deletions

View File

@ -2,6 +2,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import os.path
import spack.platforms
from spack.package import *
@ -356,6 +357,11 @@ class Acfl(Package, CompilerPackage):
provides("lapack")
provides("fftw-api@3")
provides("c", "cxx")
provides("fortran")
requires("platform=linux", msg="acfl is only available for linux")
depends_on("gmake", type="build")
# Licensing - Not required from 22.0.1 on.
@ -377,6 +383,23 @@ def install(self, spec, prefix):
r"Arm C\/C\+\+\/Fortran Compiler version ([\d\.]+) \(build number \d+\) "
)
opt_flags = ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast"]
link_paths = {
"c": os.path.join("arm", "armclang"),
"cxx": os.path.join("arm", "armclang++"),
"fortran": os.path.join("arm", "armflang"),
}
required_libs = ["libclang", "libflang"]
def _standard_flag(self, *, language, standard):
flags = {
"cxx": {"11": "-std=c++11", "14": "-std=c++14", "17": "-std=c++1z"},
"c": {"99": "-std=c99", "11": "-std=c11"},
}
return flags[language][standard]
@property
def cc(self):
msg = "cannot retrieve C compiler [spec is not concrete]"
@ -464,6 +487,9 @@ def setup_run_environment(self, env):
env.prepend_path("LIBRARY_PATH", join_path(arm_dir, "lib"))
env.prepend_path("MANPATH", join_path(arm_dir, "share", "man"))
def archspec_name(self):
return "arm"
@run_after("install")
def check_install(self):
arm_dir = get_acfl_prefix(self.spec)

View File

@ -1,7 +1,7 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
from spack.package import *
from spack.pkg.builtin.llvm import LlvmDetection
@ -60,6 +60,9 @@ class Aocc(Package, LlvmDetection, CompilerPackage):
depends_on("c", type="build") # generated
provides("c", "cxx")
provides("fortran")
# Licensing
license_url = "https://www.amd.com/en/developer/aocc/aocc-compiler/eula.html"
@ -114,3 +117,31 @@ def cfg_files(self):
compiler_version_regex = r"AOCC_(\d+[._]\d+[._]\d+)"
fortran_names = ["flang"]
debug_flags = [
"-gcodeview",
"-gdwarf-2",
"-gdwarf-3",
"-gdwarf-4",
"-gdwarf-5",
"-gline-tables-only",
"-gmodules",
"-g",
]
opt_flags = ["-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os", "-Oz", "-Og", "-O", "-O4"]
link_paths = {
"c": os.path.join("aocc", "clang"),
"cxx": os.path.join("aocc", "clang++"),
"fortran": os.path.join("aocc", "flang"),
}
required_libs = ["libclang"]
def _standard_flag(self, *, language: str, standard: str) -> str:
flags = {
"cxx": {"11": "-std=c++11", "14": "-std=c++14", "17": "-std=c++17"},
"c": {"99": "-std=c99", "11": "-std=c11"},
}
return flags[language][standard]

View File

@ -1,6 +1,8 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
from spack.package import *
from spack.pkg.builtin.llvm import LlvmDetection
@ -16,6 +18,14 @@ class AppleClang(BundlePackage, LlvmDetection, CompilerPackage):
compiler_languages = ["c", "cxx"]
compiler_version_regex = r"^Apple (?:LLVM|clang) version ([^ )]+)"
openmp_flag = "-Xpreprocessor -fopenmp"
link_paths = {"c": os.path.join("clang", "clang"), "cxx": os.path.join("clang", "clang++")}
required_libs = ["libclang"]
provides("c", "cxx")
requires("platform=darwin")
@classmethod
@ -38,3 +48,28 @@ def cxx(self):
msg = "apple-clang is expected to be an external spec"
assert self.spec.concrete and self.spec.external, msg
return self.spec.extra_attributes["compilers"].get("cxx", None)
def _standard_flag(self, *, language, standard):
flags = {
"cxx": {
"11": [("@4.0:", "-std=c++11")],
"14": [("@6.1:", "-std=c++14")],
"17": [("@6.1:10.0", "-std=c++1z"), ("10.1:", "-std=c++17")],
"20": [("@10.0:13.0", "-std=c++2a"), ("13.1:", "-std=c++20")],
"23": [("13.0:", "-std=c++2b")],
},
"c": {
"99": [("@4.0:", "-std=c99")],
"11": [("@4.0:", "-std=c11")],
"17": [("@11.1:", "-std=c17")],
"23": [("@11.1:", "-std=c2x")],
},
}
for condition, flag in flags[language][standard]:
if self.spec.satisfies(condition):
return flag
else:
raise RuntimeError(
f"{self.spec} does not support the '{standard}' standard "
f"for the '{language}' language"
)

View File

@ -4,7 +4,6 @@
import os
import spack.error
import spack.platforms
from spack.package import *
@ -406,6 +405,10 @@ class ArmplGcc(Package):
provides("lapack")
provides("fftw-api@3")
depends_on("c", type="build")
depends_on("fortran", type="build")
requires("^[virtuals=c,fortran] gcc", msg="armpl-gcc is only compatible with the GCC compiler")
depends_on("gmake", type="build")
# Run the installer with the desired install directory
@ -431,8 +434,6 @@ def install(self, spec, prefix):
# Unmount image
hdiutil("detach", mountpoint)
return
if self.compiler.name != "gcc":
raise spack.error.SpackError(("Only compatible with GCC.\n"))
with when("@:22"):
armpl_version = spec.version.up_to(3).string.split("_")[0]

View File

@ -22,7 +22,7 @@ def spec_uses_gccname(spec):
def llnl_link_helpers(options, spec, compiler):
# From local package:
if compiler.fc:
if "fortran" in spec:
fortran_compilers = ["gfortran", "xlf"]
if any(f_comp in compiler.fc for f_comp in fortran_compilers) and (
"clang" in compiler.cxx
@ -37,7 +37,7 @@ def llnl_link_helpers(options, spec, compiler):
if flags:
options.append(cmake_cache_string("BLT_EXE_LINKER_FLAGS", flags, description))
if "cce" in compiler.cxx:
if "cxx" in spec and spec["cxx"].name == "cce":
description = "Adds a missing rpath for libraries " "associated with the fortran compiler"
# Here is where to find libs that work for fortran
libdir = "/opt/cray/pe/cce/{0}/cce-clang/x86_64/lib".format(compiler.version)

View File

@ -1,6 +1,8 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
from spack.package import *
@ -20,10 +22,29 @@ class Cce(Package, CompilerPackage):
r"[Cc]ray (?:clang|C :|C\+\+ :|Fortran :) [Vv]ersion.*?(\d+(?:\.\d+)+)"
)
# notify when the package is updated.
debug_flags = ["-g", "-G0", "-G1", "-G2", "-Gfast"]
liink_paths = {
"c": os.path.join("cce", "craycc"),
"cxx": os.path.join("cce", "case-insensitive", "crayCC"),
"fortran": os.path.join("cce", "crayftn"),
}
maintainers("becker33")
version("16.0.0")
provides("c", "cxx")
provides("fortran")
requires("platform=linux")
def _standard_flag(self, *, language, standard):
flags = {
"cxx": {"11": "-std=c++11", "14": "-std=c++14", "17": "-std=c++17"},
"c": {"99": "-std=c99", "11": "-std=c11"},
}
return flags[language][standard]
def install(self, spec, prefix):
raise NotImplementedError("cray compiler must be configured as external")

View File

@ -1,11 +1,6 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import spack.compilers
import spack.spec
from spack.package import *
@ -87,8 +82,6 @@ class Claw(CMakePackage):
def flag_handler(self, name, flags):
if name == "cflags":
compiler_spec = self.spec.compiler
if spack.compilers.is_mixed_toolchain(self.compiler):
compiler_spec = self._get_real_compiler_spec("cc") or compiler_spec
if any(
[
compiler_spec.satisfies(s)
@ -105,25 +98,3 @@ def cmake_args(self):
args = ["-DOMNI_CONF_OPTION=--with-libxml2=%s" % self.spec["libxml2"].prefix]
return args
def _get_real_compiler_spec(self, language):
lang_compiler = getattr(self.compiler, language)
if not lang_compiler:
return None
for compiler_name in spack.compilers.supported_compilers():
compiler_cls = spack.compilers.class_for_compiler_name(compiler_name)
lang_version_fn = getattr(compiler_cls, "{0}_version".format(language))
for regexp in compiler_cls.search_regexps(language):
if regexp.match(os.path.basename(lang_compiler)):
try:
detected_version = lang_version_fn(lang_compiler)
if detected_version:
compiler_version = Version(detected_version)
if compiler_version != Version("unknown"):
return spack.spec.CompilerSpec(compiler_name, compiler_version)
except Exception:
continue
return None

View File

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from spack.compiler import UnsupportedCompilerFlag
from spack.compilers.error import UnsupportedCompilerFlag
from spack.package import *
@ -38,8 +38,8 @@ class Clingo(CMakePackage):
version("5.3.0", sha256="b0d406d2809352caef7fccf69e8864d55e81ee84f4888b0744894977f703f976")
version("5.2.2", sha256="da1ef8142e75c5a6f23c9403b90d4f40b9f862969ba71e2aaee9a257d058bfcf")
depends_on("c", type="build") # generated
depends_on("cxx", type="build") # generated
depends_on("c", type="build")
depends_on("cxx", type="build")
variant("docs", default=False, description="build documentation with Doxygen")
variant("python", default=True, description="build with python bindings")
@ -100,7 +100,7 @@ def cmake_py_shared(self):
def cmake_args(self):
try:
self.compiler.cxx14_flag
self.spec["cxx"].package.standard_flag(language="cxx", standard="14")
except UnsupportedCompilerFlag:
InstallError("clingo requires a C++14-compliant C++ compiler")

View File

@ -243,16 +243,6 @@ def determine_version(cls, exe):
match = re.search(r"cmake.*version\s+(\S+)", output)
return match.group(1) if match else None
def flag_handler(self, name, flags):
if name == "cxxflags" and self.compiler.name == "fj":
cxx11plus_flags = (self.compiler.cxx11_flag, self.compiler.cxx14_flag)
cxxpre11_flags = self.compiler.cxx98_flag
if any(f in flags for f in cxxpre11_flags):
raise ValueError("cannot build cmake pre-c++11 standard")
elif not any(f in flags for f in cxx11plus_flags):
flags.append(self.compiler.cxx11_flag)
return (flags, None, None)
def bootstrap_args(self):
spec = self.spec
args = []

View File

@ -79,10 +79,15 @@ def setup_run_environment(self, env):
self.setup_mpi_wrapper_variables(env)
return
env.set("MPICC", self.compiler.cc)
env.set("MPICXX", self.compiler.cxx)
env.set("MPIFC", self.compiler.fc)
env.set("MPIF77", self.compiler.f77)
if self.spec.dependencies(virtuals=("c",)):
env.set("MPICC", self.spec["c"].package.cc)
if self.spec.dependencies(virtuals=("cxx",)):
env.set("MPICXX", self.spec["cxx"].package.cxx)
if self.spec.dependencies(virtuals=("fortran",)):
env.set("MPIFC", self.spec["fortran"].package.fc)
env.set("MPIF77", self.spec["fortran"].package.fc)
def setup_dependent_package(self, module, dependent_spec):
spec = self.spec

View File

@ -29,10 +29,15 @@ class CrayMvapich2(MpichEnvironmentModifications, Package):
requires("platform=linux", msg="Cray MVAPICH2 is only available on Cray")
def setup_run_environment(self, env):
env.set("MPICC", self.compiler.cc)
env.set("MPICXX", self.compiler.cxx)
env.set("MPIFC", self.compiler.fc)
env.set("MPIF77", self.compiler.f77)
if self.spec.dependencies(virtuals=("c",)):
env.set("MPICC", self.spec["c"].package.cc)
if self.spec.dependencies(virtuals=("cxx",)):
env.set("MPICXX", self.spec["cxx"].package.cxx)
if self.spec.dependencies(virtuals=("fortran",)):
env.set("MPIFC", self.spec["fortran"].package.fc)
env.set("MPIF77", self.spec["fortran"].package.fc)
def install(self, spec, prefix):
raise InstallError(

View File

@ -727,7 +727,8 @@ def setup_build_environment(self, env):
env.append_path("LD_LIBRARY_PATH", libxml2_home.lib)
def setup_dependent_build_environment(self, env, dependent_spec):
env.set("CUDAHOSTCXX", dependent_spec.package.compiler.cxx)
if "cxx" in dependent_spec:
env.set("CUDAHOSTCXX", dependent_spec["cxx"].package.cxx)
env.set("CUDA_HOME", self.prefix)
env.set("NVHPC_CUDA_HOME", self.prefix)

View File

@ -4,8 +4,6 @@
import os
import spack.compilers
import spack.spec
from spack.package import *
@ -17,25 +15,14 @@ class Cxx(Package):
def test_cxx(self):
"""Compile and run 'Hello World'"""
cxx = which(os.environ["CXX"])
expected = ["Hello world", "YES!"]
cxx = Executable(self.cxx)
test_source = self.test_suite.current_test_data_dir
for test in os.listdir(test_source):
exe_name = f"{test}.exe"
filepath = test_source.join(test)
with test_part(self, f"test_cxx_{test}", f"build and run {exe_name}"):
# standard options
# Hack to get compiler attributes
# TODO: remove this when compilers are dependencies
c_name = clang if self.spec.satisfies("llvm+clang") else self.name
c_spec = spack.spec.CompilerSpec(c_name, self.spec.version)
c_cls = spack.compilers.class_for_compiler_name(c_name)
compiler = c_cls(c_spec, None, None, ["fakecc", "fakecxx"])
cxx_opts = [compiler.cxx11_flag] if "c++11" in test else []
cxx_opts += ["-o", exe_name, filepath]
cxx(*cxx_opts)
filepath = join_path(test_source, test)
cxx("-o", exe_name, filepath)
exe = which(exe_name)
out = exe(output=str.split, error=str.split)
check_outputs(expected, out)

View File

@ -54,9 +54,9 @@ class Dealii(CMakePackage, CudaPackage):
version("8.2.1", sha256="d75674e45fe63cd9fa294460fe45228904d51a68f744dbb99cd7b60720f3b2a0")
version("8.1.0", sha256="d666bbda2a17b41b80221d7029468246f2658051b8c00d9c5907cd6434c4df99")
depends_on("c", type="build") # generated
depends_on("cxx", type="build") # generated
depends_on("fortran", type="build") # generated
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("fortran", type="build")
# Configuration variants
variant(
@ -685,7 +685,7 @@ def cmake_args(self):
# Add flags for machine vectorization, used when tutorials
# and user code is built.
# See https://github.com/dealii/dealii/issues/9164
options.append(self.define("DEAL_II_CXX_FLAGS", os.environ["SPACK_TARGET_ARGS"]))
options.append(self.define("DEAL_II_CXX_FLAGS", os.environ["SPACK_TARGET_ARGS_CXX"]))
# platform introspection - needs to be disabled in some environments
if spec.satisfies("+platform-introspection"):

View File

@ -7,7 +7,6 @@
import spack.build_systems.makefile
import spack.build_systems.python
import spack.compiler
from spack.build_environment import dso_suffix, stat_suffix
from spack.package import *
@ -259,29 +258,16 @@ def setup_build_environment(self, env):
# ESMF_COMPILER must be set to select which Fortran and
# C++ compilers are being used to build the ESMF library.
if self.pkg.compiler.name == "gcc":
if spec["fortran"].name == "gcc" and spec["c"].name == "gcc":
gfortran_major_version = int(spec["fortran"].version[0])
env.set("ESMF_COMPILER", "gfortran")
with self.pkg.compiler.compiler_environment():
gfortran_major_version = int(
spack.compiler.get_compiler_version_output(
self.pkg.compiler.fc, "-dumpversion"
).split(".")[0]
)
elif self.pkg.compiler.name == "intel" or self.pkg.compiler.name == "oneapi":
env.set("ESMF_COMPILER", "intel")
elif self.pkg.compiler.name in ["clang", "apple-clang"]:
if "flang" in self.pkg.compiler.fc:
env.set("ESMF_COMPILER", "llvm")
elif "gfortran" in self.pkg.compiler.fc:
env.set("ESMF_COMPILER", "gfortranclang")
with self.pkg.compiler.compiler_environment():
gfortran_major_version = int(
spack.compiler.get_compiler_version_output(
self.pkg.compiler.fc, "-dumpversion"
).split(".")[0]
)
else:
raise InstallError("Unsupported C/C++/Fortran compiler combination")
elif spec["fortran"].name == "gcc" and spec["c"].name in ["clang", "apple-clang"]:
gfortran_major_version = int(spec["fortran"].version[0])
env.set("ESMF_COMPILER", "gfortranclang")
elif spec["fortran"].name == "llvm":
env.set("ESMF_COMPILER", "llvm")
elif self.pkg.compiler.name == "nag":
env.set("ESMF_COMPILER", "nag")
elif self.pkg.compiler.name == "nvhpc":

View File

@ -1,6 +1,8 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
from spack.package import *
@ -14,6 +16,9 @@ class Fj(Package, CompilerPackage):
maintainers("t-karatsu")
provides("c", "cxx")
provides("fortran")
def install(self, spec, prefix):
raise InstallError(
"Fujitsu compilers are not installable yet, but can be "
@ -26,3 +31,29 @@ def install(self, spec, prefix):
fortran_names = ["frt"]
compiler_version_regex = r"\((?:FCC|FRT)\) ([a-z\d.]+)"
compiler_version_argument = "--version"
debug_flags = ["-g"]
opt_flags = ["-O0", "-O1", "-O2", "-O3", "-Ofast"]
pic_flag = "-KPIC"
openmp_flag = "-Kopenmp"
link_paths = {
"c": os.path.join("fj", "fcc"),
"cxx": os.path.join("fj", "case-insensitive", "FCC"),
"fortran": os.path.join("fj", "frt"),
}
required_libs = ["libfj90i", "libfj90f", "libfjsrcinfo"]
def _standard_flag(self, *, language, standard):
flags = {
"cxx": {
"98": "-std=c++98",
"11": "-std=c++11",
"14": "-std=c++14",
"17": "-std=c++17",
},
"c": {"99": "-std=c99", "11": "-std=c11"},
}
return flags[language][standard]

View File

@ -27,8 +27,6 @@ class GccRuntime(Package):
license("GPL-3.0-or-later WITH GCC-exception-3.1")
requires("%gcc")
LIBRARIES = [
"asan",
"atomic",
@ -47,15 +45,18 @@ class GccRuntime(Package):
# libgfortran ABI
provides("fortran-rt", "libgfortran")
provides("libgfortran@3", when="%gcc@:6")
provides("libgfortran@4", when="%gcc@7")
provides("libgfortran@5", when="%gcc@8:")
provides("libgfortran@3", when="@:6")
provides("libgfortran@4", when="@7")
provides("libgfortran@5", when="@8:")
depends_on("libc", type="link", when="platform=linux")
depends_on("gcc", type="build")
def install(self, spec, prefix):
gcc_pkg = self["gcc"]
if spec.platform in ["linux", "freebsd"]:
libraries = get_elf_libraries(compiler=self.compiler, libraries=self.LIBRARIES)
libraries = get_elf_libraries(compiler=gcc_pkg, libraries=self.LIBRARIES)
elif spec.platform == "darwin":
libraries = self._get_libraries_macho()
else:
@ -75,7 +76,7 @@ def install(self, spec, prefix):
def _get_libraries_macho(self):
"""Same as _get_libraries_elf but for Mach-O binaries"""
cc = Executable(self.compiler.cc)
cc = Executable(self.spec["gcc"].package.cc)
path_and_install_name = []
for name in self.LIBRARIES:

View File

@ -9,7 +9,7 @@
from llnl.util.symlink import readlink
import spack.compiler
import spack.build_systems.compiler
import spack.platforms
import spack.repo
import spack.util.libc
@ -32,9 +32,9 @@ class Gcc(AutotoolsPackage, GNUMirrorPackage, CompilerPackage):
license("GPL-2.0-or-later AND LGPL-2.1-or-later")
provides("c")
provides("cxx")
provides("fortran")
provides("c", when="languages=c")
provides("cxx", when="languages=c++")
provides("fortran", when="languages=fortran")
version("master", branch="master")
@ -594,7 +594,12 @@ def supported_languages(self):
# This weirdness is because it could be called on an abstract spec
if "languages" not in self.spec.variants:
return self.compiler_languages
return [x for x in self.compiler_languages if x in self.spec.variants["languages"].value]
variant_value = {"cxx": "c++"}
return [
x
for x in self.compiler_languages
if self.spec.satisfies(f"languages={variant_value.get(x, x)}")
]
c_names = ["gcc"]
cxx_names = ["g++"]
@ -605,6 +610,40 @@ def supported_languages(self):
compiler_version_regex = r"([0-9.]+)"
compiler_version_argument = ("-dumpfullversion", "-dumpversion")
link_paths = {
"c": os.path.join("gcc", "gcc"),
"cxx": os.path.join("gcc", "g++"),
"fortran": os.path.join("gcc", "gfortran"),
}
debug_flags = ["-g", "-gstabs+", "-gstabs", "-gxcoff+", "-gxcoff", "-gvms"]
opt_flags = ["-O", "-O0", "-O1", "-O2", "-O3", "-Os", "-Ofast", "-Og"]
required_libs = ["libgcc", "libgfortran"]
stdcxx_libs = "-lstdc++"
def _standard_flag(self, *, language, standard):
flags = {
"cxx": {
"98": [("@6:", "-std=c++98"), ("@:5", "")],
"11": [("@4.3:4.6", "-std=c++0x"), ("@4.7:", "-std=c++11")],
"14": [("@4.8", "-std=c++1y"), ("@4.9:", "-std=c++14")],
"17": [("@5", "-std=c++1z"), ("@6:", "-std=c++17")],
"20": [("@8:10", "-std=c++2a"), ("@11:", "-std=c++20")],
"23": [("@11:13", "-std=c++2b"), ("@14:", "-std=c++23")],
},
"c": {"99": [("@4.5:", "-std=c99")], "11": [("@4.7:", "-std=c11")]},
}
for condition, flag in flags[language][standard]:
if self.spec.satisfies(condition):
return flag
else:
raise RuntimeError(
f"{self.spec} does not support the '{standard}' standard "
f"for the '{language}' language"
)
@classmethod
def filter_detected_exes(cls, prefix, exes_in_prefix):
# Apple's gcc is actually apple clang, so skip it.
@ -612,7 +651,9 @@ def filter_detected_exes(cls, prefix, exes_in_prefix):
not_apple_clang = []
for exe in exes_in_prefix:
try:
output = spack.compiler.get_compiler_version_output(exe, "--version")
output = spack.build_systems.compiler.compiler_output(
exe, version_argument="--version"
)
except Exception:
output = ""
if "clang version" in output:
@ -1157,7 +1198,7 @@ def runtime_constraints(cls, *, spec, pkg):
)
pkg("*").depends_on(
f"gcc-runtime@{str(spec.version)}:",
when=f"%{str(spec)}",
when=f"^[deptypes=build] {spec.name}@{spec.versions}",
type="link",
description=f"If any package uses %{str(spec)}, "
f"it depends on gcc-runtime@{str(spec.version)}:",
@ -1172,18 +1213,21 @@ def runtime_constraints(cls, *, spec, pkg):
for fortran_virtual in ("fortran-rt", gfortran_str):
pkg("*").depends_on(
fortran_virtual,
when=f"%{str(spec)}",
languages=["fortran"],
when=f"^[virtuals=fortran deptypes=build] {spec.name}@{spec.versions}",
type="link",
description=f"Add a dependency on '{gfortran_str}' for nodes compiled with "
f"{str(spec)} and using the 'fortran' language",
)
# The version of gcc-runtime is the same as the %gcc used to "compile" it
pkg("gcc-runtime").requires(f"@={str(spec.version)}", when=f"%{str(spec)}")
pkg("gcc-runtime").requires(
f"@{str(spec.versions)}", when=f"^[deptypes=build] {spec.name}@{spec.versions}"
)
# If a node used %gcc@X.Y its dependencies must use gcc-runtime@:X.Y
# (technically @:X is broader than ... <= @=X but this should work in practice)
pkg("*").propagate(f"%gcc@:{str(spec.version)}", when=f"%{str(spec)}")
pkg("*").propagate(
f"gcc@:{str(spec.version)}", when=f"^[deptypes=build] {spec.name}@{spec.versions}"
)
def _post_buildcache_install_hook(self):
if not self.spec.satisfies("platform=linux"):

View File

@ -111,6 +111,8 @@ class Glibc(AutotoolsPackage, GNUMirrorPackage):
# include_next <limits.h> not working
patch("67fbfa5.patch", when="@:2.7")
conflicts("musl")
def setup_build_environment(self, env):
if self.spec.satisfies("@:2.21"):
env.append_flags("LDFLAGS", "-no-pie")

View File

@ -83,6 +83,9 @@ class Go(Package):
phases = ["build", "install"]
depends_on("c", type="build")
depends_on("cxx", type="build")
def url_for_version(self, version):
return f"https://go.dev/dl/go{version}.src.tar.gz"
@ -95,8 +98,8 @@ def determine_version(cls, exe):
def setup_build_environment(self, env):
# We need to set CC/CXX_FOR_TARGET, otherwise cgo will use the
# internal Spack wrappers and fail.
env.set("CC_FOR_TARGET", self.compiler.cc)
env.set("CXX_FOR_TARGET", self.compiler.cxx)
env.set("CC_FOR_TARGET", self.spec["c"].package.cc)
env.set("CXX_FOR_TARGET", self.spec["cxx"].package.cxx)
env.set("GOMAXPROCS", make_jobs)
def build(self, spec, prefix):

View File

@ -108,3 +108,30 @@ def symlink_dir(self, src, dest):
link_tree.merge(dest_path)
else:
os.symlink(src_path, dest_path)
@property
def cc(self):
msg = "cannot retrieve C compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes["compilers"].get("c", None)
return str(self.prefix.bin.icc)
@property
def cxx(self):
msg = "cannot retrieve C++ compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes["compilers"].get("cxx", None)
return str(self.prefix.bin.icpc)
@property
def fortran(self):
msg = "cannot retrieve Fortran compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes["compilers"].get("fortran", None)
return str(self.prefix.bin.ifort)
def archspec_name(self):
return "intel"

View File

@ -1,9 +1,11 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import os.path
import pathlib
import platform
import warnings
from spack.build_environment import dso_suffix
from spack.package import *
@ -329,6 +331,47 @@ class IntelOneapiCompilers(IntelOneApiPackage, CompilerPackage):
r"(?:(?:oneAPI DPC\+\+(?:\/C\+\+)? Compiler)|(?:\(IFORT\))|(?:\(IFX\))) (\S+)"
)
debug_flags = ["-debug", "-g", "-g0", "-g1", "-g2", "-g3"]
opt_flags = ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os"]
openmp_flag = "-fiopenmp"
link_paths = {
"c": os.path.join("oneapi", "icx"),
"cxx": os.path.join("oneapi", "icpx"),
"fortran": os.path.join("oneapi", "ifx"),
}
required_libs = [
"libirc",
"libifcore",
"libifcoremt",
"libirng",
"libsvml",
"libintlc",
"libimf",
"libsycl",
"libOpenCL",
]
stdcxx_libs = ("-cxxlib",)
provides("c")
provides("cxx")
provides("fortran")
def _standard_flag(self, *, language, standard):
flags = {
"cxx": {
"11": "-std=c++11",
"14": "-std=c++14",
"17": "-std=c++17",
"20": "-std=c++20",
},
"c": {"99": "-std=c99", "11": "-std=c1x"},
}
return flags[language][standard]
# See https://github.com/spack/spack/issues/39252
depends_on("patchelf@:0.17", type="build", when="@:2024.1")
# Add the nvidia variant
@ -337,10 +380,8 @@ class IntelOneapiCompilers(IntelOneApiPackage, CompilerPackage):
# Add the amd variant
variant("amd", default=False, description="Install AMD plugin for OneAPI")
conflicts("@:2022.2.1", when="+amd", msg="Codeplay AMD plugin requires newer release")
# TODO: effectively gcc is a direct dependency of intel-oneapi-compilers, but we
# cannot express that properly. For now, add conflicts for non-gcc compilers
# instead.
requires("%gcc", msg="intel-oneapi-compilers must be installed with %gcc")
depends_on("gcc languages=c,c++", type="run")
for v in versions:
version(v["version"], expand=False, **v["cpp"])
@ -419,6 +460,31 @@ def setup_run_environment(self, env):
env.set("F77", self._llvm_bin.ifx)
env.set("FC", self._llvm_bin.ifx)
def setup_dependent_build_environment(self, env, dependent_spec):
super().setup_dependent_build_environment(env, dependent_spec)
# workaround bug in icpx driver where it requires sycl-post-link is on the PATH
# It is located in the same directory as the driver. Error message:
# clang++: error: unable to execute command:
# Executable "sycl-post-link" doesn't exist!
# also ensures that shared objects and libraries required by the compiler,
# e.g. libonnx, can be found succesfully
# due to a fix, this is no longer required for OneAPI versions >= 2024.2
bin_dir = os.path.dirname(self.cxx)
lib_dir = os.path.join(os.path.dirname(bin_dir), "lib")
if self.cxx and self.spec.satisfies("%oneapi@:2024.1"):
env.prepend_path("PATH", bin_dir)
env.prepend_path("LD_LIBRARY_PATH", lib_dir)
# 2024 release bumped the libsycl version because of an ABI
# change, 2024 compilers are required. You will see this
# error:
#
# /usr/bin/ld: warning: libsycl.so.7, needed by ...., not found
if self.spec.satisfies("%oneapi@:2023"):
for c in ["dnn"]:
if self.spec.satisfies(f"^intel-oneapi-{c}@2024:"):
warnings.warn(f"intel-oneapi-{c}@2024 SYCL APIs requires %oneapi@2024:")
def install(self, spec, prefix):
# Copy instead of install to speed up debugging
# install_tree("/opt/intel/oneapi/compiler", self.prefix)
@ -514,9 +580,9 @@ def extend_config_flags(self):
common_flags = ["-Wl,-rpath,{}".format(d) for d in self._ld_library_path()]
# Make sure that underlying clang gets the right GCC toolchain by default
llvm_flags = ["--gcc-toolchain={}".format(self.compiler.prefix)]
classic_flags = ["-gcc-name={}".format(self.compiler.cc)]
classic_flags.append("-gxx-name={}".format(self.compiler.cxx))
gcc = self.spec["gcc"].package
llvm_flags = [f"--gcc-toolchain={gcc.prefix}"]
classic_flags = [f"-gcc-name={gcc.cc}", f"-gxx-name={gcc.cxx}"]
# Older versions trigger -Wunused-command-line-argument warnings whenever
# linker flags are passed in preprocessor (-E) or compilation mode (-c).
@ -551,6 +617,24 @@ def _ld_library_path(self):
if find(p, "*." + dso_suffix, recursive=False):
yield p
def archspec_name(self):
return "oneapi"
@classmethod
def determine_variants(cls, exes, version_str):
variant, extra_attributes = super().determine_variants(exes, version_str)
bin_dirs = {pathlib.Path(x).parent for x in exes}
if len(bin_dirs) != 1:
dirs = ", ".join([str(x) for x in sorted(bin_dirs)])
raise RuntimeError(f"executables found in multiple dirs: {dirs}")
bin_dir = bin_dirs.pop()
prefix_parts = bin_dir.parts[: bin_dir.parts.index("compiler")]
computed_prefix = pathlib.Path(*prefix_parts)
extra_attributes["prefix"] = str(computed_prefix)
return variant, extra_attributes
@classmethod
def runtime_constraints(cls, *, spec, pkg):
pkg("*").depends_on(
@ -561,7 +645,7 @@ def runtime_constraints(cls, *, spec, pkg):
)
pkg("*").depends_on(
f"intel-oneapi-runtime@{str(spec.version)}:",
when=f"%{str(spec)}",
when=f"^[deptypes=build] {spec.name}@{spec.versions}",
type="link",
description=f"If any package uses %{str(spec)}, "
f"it depends on intel-oneapi-runtime@{str(spec.version)}:",
@ -570,11 +654,43 @@ def runtime_constraints(cls, *, spec, pkg):
for fortran_virtual in ("fortran-rt", "libifcore@5"):
pkg("*").depends_on(
fortran_virtual,
when=f"%{str(spec)}",
languages=["fortran"],
when=f"^[virtuals=fortran deptypes=build] {spec.name}@{spec.versions}",
type="link",
description=f"Add a dependency on 'libifcore' for nodes compiled with "
f"{str(spec)} and using the 'fortran' language",
)
# The version of intel-oneapi-runtime is the same as the %oneapi used to "compile" it
pkg("intel-oneapi-runtime").requires(f"@={str(spec.version)}", when=f"%{str(spec)}")
pkg("intel-oneapi-runtime").requires(
f"@{str(spec.versions)}", when=f"^[deptypes=build] {spec.name}@{spec.versions}"
)
# If a node used %intel-oneapi=runtime@X.Y its dependencies must use @:X.Y
# (technically @:X is broader than ... <= @=X but this should work in practice)
pkg("*").propagate(
f"intel-oneapi-compilers@:{str(spec.version)}",
when=f"^[deptypes=build] {spec.name}@{spec.versions}",
)
@property
def cc(self):
msg = "cannot retrieve C compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes["compilers"].get("c", None)
return str(self._llvm_bin.icx)
@property
def cxx(self):
msg = "cannot retrieve C++ compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes["compilers"].get("cxx", None)
return str(self._llvm_bin.icpx)
@property
def fortran(self):
msg = "cannot retrieve Fortran compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes["compilers"].get("fortran", None)
return str(self._llvm_bin.ifx)

View File

@ -200,11 +200,17 @@ def setup_dependent_package(self, module, dep_spec):
def setup_dependent_build_environment(self, env, dependent_spec):
dependent_module = dependent_spec.package.module
env.set("I_MPI_CC", dependent_module.spack_cc)
env.set("I_MPI_CXX", dependent_module.spack_cxx)
env.set("I_MPI_F77", dependent_module.spack_f77)
env.set("I_MPI_F90", dependent_module.spack_fc)
env.set("I_MPI_FC", dependent_module.spack_fc)
for var_name, attr_name in (
("I_MPI_CC", "spack_cc"),
("I_MPI_CXX", "spack_cxx"),
("I_MPI_FC", "spack_fc"),
("I_MPI_F90", "spack_fc"),
("I_MPI_F77", "spack_f77"),
):
if not hasattr(dependent_module, attr_name):
continue
env.set(var_name, getattr(dependent_module, attr_name))
# Set compiler wrappers for dependent build stage
wrappers = self.wrapper_paths()

View File

@ -19,8 +19,7 @@ class IntelOneapiRuntime(Package):
tags = ["runtime"]
requires("%oneapi")
depends_on("intel-oneapi-compilers", type="build")
depends_on("gcc-runtime", type="link")
LIBRARIES = [
@ -46,7 +45,8 @@ class IntelOneapiRuntime(Package):
depends_on("libc", type="link", when="platform=linux")
def install(self, spec, prefix):
libraries = get_elf_libraries(compiler=self.compiler, libraries=self.LIBRARIES)
oneapi_pkg = self.spec["intel-oneapi-compilers"].package
libraries = get_elf_libraries(compiler=oneapi_pkg, libraries=self.LIBRARIES)
mkdir(prefix.lib)
if not libraries:

View File

@ -3,7 +3,9 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import re
import spack.compiler
import llnl.util.tty as tty
import spack.build_systems.compiler
from spack.package import *
@ -234,7 +236,9 @@ class Intel(IntelPackage):
def determine_version(cls, exe):
version_regex = re.compile(r"\((?:IFORT|ICC)\) ([^ ]+)")
try:
output = spack.compiler.get_compiler_version_output(exe, "--version")
output = spack.build_systems.compiler.compiler_output(
exe, version_argument="--version"
)
match = version_regex.search(output)
if match:
return match.group(1)

View File

@ -110,7 +110,7 @@ def url_for_version(self, version):
def flag_handler(self, name, flags):
if name == "cflags" and self.spec.satisfies("+pic"):
flags.append(self.compiler.cc_pic_flag)
flags.append(self.spec["c"].package.pic_flag)
flags.append("-DPIC")
return (flags, None, None)

View File

@ -6,17 +6,23 @@
import shutil
from spack.package import *
from spack.pkg.builtin.llvm import LlvmDetection
class LlvmAmdgpu(CMakePackage, CompilerPackage):
class LlvmAmdgpu(CMakePackage, LlvmDetection, CompilerPackage):
"""Toolkit for the construction of highly optimized compilers,
optimizers, and run-time environments."""
homepage = "https://github.com/ROCm/llvm-project"
git = "https://github.com/ROCm/llvm-project.git"
url = "https://github.com/ROCm/llvm-project/archive/rocm-6.2.4.tar.gz"
tags = ["rocm"]
tags = ["rocm", "compiler"]
executables = [r"amdclang", r"amdclang\+\+", r"amdflang", r"clang.*", r"flang.*", "llvm-.*"]
link_paths = {"c": "rocmcc/amdclang", "cxx": "rocmcc/amdclang++", "fortran": "rocmcc/amdflang"}
stdcxx_libs = ("-lstdc++",)
generator("ninja")
maintainers("srekolam", "renjithravindrankannath", "haampie", "afzpatel")
@ -215,6 +221,15 @@ class LlvmAmdgpu(CMakePackage, CompilerPackage):
when="@master",
)
stdcxx_libs = ("-lstdc++",)
def _standard_flag(self, *, language, standard):
flags = {
"cxx": {"11": "-std=c++11", "14": "-std=c++14", "17": "-std=c++17"},
"c": {"99": "-std=c99", "11": "-std=c1x"},
}
return flags[language][standard]
def cmake_args(self):
llvm_projects = ["clang", "lld", "clang-tools-extra", "compiler-rt"]
llvm_runtimes = ["libcxx", "libcxxabi"]
@ -338,3 +353,27 @@ def setup_dependent_build_environment(self, env, dependent_spec):
if "libclang_rt.asan-x86_64.so" in files:
env.prepend_path("LD_LIBRARY_PATH", root)
env.prune_duplicate_paths("LD_LIBRARY_PATH")
@property
def cc(self):
msg = "cannot retrieve C compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes["compilers"].get("c", None)
return os.path.join(self.spec.prefix.bin, "amdclang")
@property
def cxx(self):
msg = "cannot retrieve C++ compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes["compilers"].get("cxx", None)
return os.path.join(self.spec.prefix.bin, "amdclang++")
@property
def fc(self):
msg = "cannot retrieve Fortran compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes["compilers"].get("fc", None)
return os.path.join(self.spec.prefix.bin, "amdflang")

View File

@ -7,7 +7,6 @@
from llnl.util.lang import classproperty
import spack.compilers
from spack.build_systems.cmake import get_cmake_prefix_path
from spack.operating_systems.mac_os import macos_sdk_path
from spack.package import *
@ -394,6 +393,9 @@ class Llvm(CMakePackage, CudaPackage, LlvmDetection, CompilerPackage):
provides("libllvm@4", when="@4.0.0:4")
provides("libllvm@3", when="@3.0.0:3")
provides("c", "cxx", when="+clang")
provides("fortran", when="+flang")
extends("python", when="+python")
# Build dependency
@ -495,9 +497,9 @@ class Llvm(CMakePackage, CudaPackage, LlvmDetection, CompilerPackage):
},
}.items():
with when(v):
for comp in spack.compilers.supported_compilers():
conflicts("%{0}{1}".format(comp, compiler_conflicts.get(comp, "")))
del v, compiler_conflicts, comp
for _name, _constraint in compiler_conflicts.items():
conflicts(f"%{_name}{_constraint}")
del v, compiler_conflicts, _name, _constraint
# libomptarget
conflicts("+cuda", when="@15:") # +cuda variant is obselete since LLVM 15
@ -875,6 +877,55 @@ def f77(self):
result = os.path.join(self.spec.prefix.bin, "flang")
return result
debug_flags = [
"-gcodeview",
"-gdwarf-2",
"-gdwarf-3",
"-gdwarf-4",
"-gdwarf-5",
"-gline-tables-only",
"-gmodules",
"-g",
]
opt_flags = ["-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os", "-Oz", "-Og", "-O", "-O4"]
link_paths = {
"c": os.path.join("clang", "clang"),
"cxx": os.path.join("clang", "clang++"),
"fortran": os.path.join("clang", "flang"),
}
required_libs = ["libclang"]
def _standard_flag(self, *, language, standard):
flags = {
"cxx": {
"11": [("@3.3:", "-std=c++11")],
"14": [("@3.5:", "-std=c++14")],
"17": [("@3.5:4", "-std=c++1z"), ("@5:", "-std=c++17")],
"20": [("@5:10", "-std=c++2a"), ("@11:", "-std=c++20")],
"23": [("@12:16", "-std=c++2b"), ("@17:", "-std=c++23")],
},
"c": {
"99": [("@:", "-std=c99")],
"11": [("@3.1:", "-std=c11")],
"17": [("@6:", "-std=c17")],
"23": [("@9:17", "-std=c2x"), ("@18:", "-std=c23")],
},
}
for condition, flag in flags[language][standard]:
if self.spec.satisfies(condition):
return flag
else:
raise RuntimeError(
f"{self.spec} does not support the '{standard}' standard "
f"for the '{language}' language"
)
def archspec_name(self):
return "clang"
@property
def libs(self):
return LibraryList(self.llvm_config("--libfiles", "all", result="list"))

View File

@ -4,7 +4,6 @@
import subprocess
import spack.compiler
from spack.package import *
@ -256,9 +255,7 @@ class Mapl(CMakePackage):
# MAPL can use ifx only from MAPL 2.51 onwards and only supports
# ifx 2025.0 and newer due to bugs in ifx.
conflicts("%oneapi@2025:", when="@:2.50")
# NOTE there is a further check on oneapi in the cmake_args below
# that is hard to conflict since we don't know the fortran compiler
# at this point
conflicts("^[virtuals=fortran] intel-oneapi-compilers")
variant("flap", default=False, description="Build with FLAP support", when="@:2.39")
variant("pflogger", default=True, description="Build with pFlogger support")
@ -381,33 +378,14 @@ def cmake_args(self):
fflags = []
if self.compiler.name in ["gcc", "clang", "apple-clang"]:
fflags.append("-ffree-line-length-none")
gfortran_major_ver = int(
spack.compiler.get_compiler_version_output(self.compiler.fc, "-dumpversion").split(
"."
)[0]
)
gfortran_major_ver = int(self.spec["fortran"].version[0])
if gfortran_major_ver >= 10:
fflags.append("-fallow-invalid-boz")
fflags.append("-fallow-argument-mismatch")
if fflags:
args.append(self.define("CMAKE_Fortran_FLAGS", " ".join(fflags)))
# If oneapi@:2024 is used and it gets past the conflict above, we might be
# using ifx or ifort. If we are using ifx and the MAPL version is 2.50 or older
# we need to raise an error
if self.spec.satisfies("@:2.50 %oneapi@:2024"):
# We now need to get which Fortran compiler is used here but there
# isn't an easy way like:
# if self.spec["fortran"].name == "ifx":
# yet (see https://github.com/spack/spack/pull/45189)
# So we need to parse the output of $FC --version
output = spack.compiler.get_compiler_version_output(
self.compiler.fc, "-diag-disable=10448 --version", ignore_errors=True
)
if "ifx" in output:
raise InstallError("MAPL versions 2.50 and older do not support ifx")
# Scripts often need to know the MPI stack used to setup the environment.
# Normally, we can autodetect this, but building with Spack does not
# seem to work. We need to pass in the MPI stack used to CMake

View File

@ -6,7 +6,7 @@
import re
import sys
import spack.compilers
import spack.compilers.config
import spack.package_base
from spack.package import *
@ -383,7 +383,7 @@ def determine_version(cls, exe):
@classmethod
def determine_variants(cls, exes, version):
def get_spack_compiler_spec(compiler):
spack_compilers = spack.compilers.find_compilers([os.path.dirname(compiler)])
spack_compilers = spack.compilers.config.find_compilers([os.path.dirname(compiler)])
actual_compiler = None
# check if the compiler actually matches the one we want
for spack_compiler in spack_compilers:
@ -509,25 +509,6 @@ def autoreconf(self, spec, prefix):
bash = which("bash")
bash("./autogen.sh")
@run_before("autoreconf")
def die_without_fortran(self):
# Until we can pass variants such as +fortran through virtual
# dependencies depends_on('mpi'), require Fortran compiler to
# avoid delayed build errors in dependents.
# The user can work around this by disabling Fortran explicitly
# with ~fortran
f77 = self.compiler.f77
fc = self.compiler.fc
fortran_missing = f77 is None or fc is None
if "+fortran" in self.spec and fortran_missing:
raise InstallError(
"mpich +fortran requires Fortran compilers. Configure "
"Fortran compiler or disable Fortran support with ~fortran"
)
def configure_args(self):
spec = self.spec
config_args = [

View File

@ -1,9 +1,15 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
import re
import subprocess
import spack.compiler
import archspec.cpu
import spack.build_systems.compiler
import spack.platforms
import spack.version
from spack.package import *
@ -26,13 +32,26 @@ def install(self, spec, prefix):
compiler_version_argument = ""
compiler_version_regex = r"([1-9][0-9]*\.[0-9]*\.[0-9]*)"
# Named wrapper links within build_env_path
# Due to the challenges of supporting compiler wrappers
# in Windows, we leave these blank, and dynamically compute
# based on proper versions of MSVC from there
# pending acceptance of #28117 for full support using
# compiler wrappers
link_paths = {"c": "", "cxx": "", "fortran": ""}
provides("c", "cxx")
requires("platform=windows", msg="MSVC is only supported on Windows")
@classmethod
def determine_version(cls, exe):
# MSVC compiler does not have a proper version argument
# Errors out and prints version info with no args
match = re.search(
cls.compiler_version_regex,
spack.compiler.get_compiler_version_output(exe, version_arg=None, ignore_errors=True),
spack.build_systems.compiler.compiler_output(
exe, version_argument=None, ignore_errors=1
),
)
if match:
return match.group(1)
@ -58,9 +77,164 @@ def cxx(self):
msg = "cannot retrieve C++ compiler [spec is not concrete]"
assert self.spec.concrete, msg
def setup_dependent_build_environment(self, env, dependent_spec):
self.init_msvc()
# Set the build environment variables for spack. Just using
# subprocess.call() doesn't work since that operates in its own
# environment which is destroyed (along with the adjusted variables)
# once the process terminates. So go the long way around: examine
# output, sort into dictionary, use that to make the build
# environment.
# vcvars can target specific sdk versions, force it to pick up concretized sdk
# version, if needed by spec
if dependent_spec.name != "win-sdk" and "win-sdk" in dependent_spec:
self.vcvars_call.sdk_ver = dependent_spec["win-sdk"].version.string
out = self.msvc_compiler_environment()
int_env = dict(
(key, value)
for key, _, value in (line.partition("=") for line in out.splitlines())
if key and value
)
for env_var in int_env:
if os.pathsep not in int_env[env_var]:
env.set(env_var, int_env[env_var])
else:
env.set_path(env_var, int_env[env_var].split(os.pathsep))
env.set("CC", self.cc)
env.set("CXX", self.cxx)
def init_msvc(self):
# To use the MSVC compilers, VCVARS must be invoked
# VCVARS is located at a fixed location, referencable
# idiomatically by the following relative path from the
# compiler.
# Spack first finds the compilers via VSWHERE
# and stores their path, but their respective VCVARS
# file must be invoked before useage.
env_cmds = []
compiler_root = os.path.join(os.path.dirname(self.cc), "../../../../../..")
vcvars_script_path = os.path.join(compiler_root, "Auxiliary", "Build", "vcvars64.bat")
# get current platform architecture and format for vcvars argument
arch = spack.platforms.real_host().default.lower()
arch = arch.replace("-", "_")
if str(archspec.cpu.host().family) == "x86_64":
arch = "amd64"
msvc_version = spack.version.Version(
re.search(Msvc.compiler_version_regex, self.cc).group(1)
)
self.vcvars_call = VCVarsInvocation(vcvars_script_path, arch, msvc_version)
env_cmds.append(self.vcvars_call)
self.msvc_compiler_environment = CmdCall(*env_cmds)
def _standard_flag(self, *, language: str, standard: str) -> str:
flags = {
"cxx": {
"11": "/std:c++11",
"14": "/std:c++14",
"17": "/std:c++17",
"20": "/std:c++20",
},
"c": {"11": "/std:c11", "17": "/std:c17"},
}
return flags[language][standard]
class CmdCall:
"""Compose a call to `cmd` for an ordered series of cmd commands/scripts"""
def __init__(self, *cmds):
if not cmds:
raise RuntimeError(
"""Attempting to run commands from CMD without specifying commands.
Please add commands to be run."""
)
self._cmds = cmds
def __call__(self):
out = subprocess.check_output(self.cmd_line, stderr=subprocess.STDOUT) # novermin
return out.decode("utf-16le", errors="replace") # novermin
@property
def fortran(self):
if self.spec.external:
return self.spec.extra_attributes["compilers"]["fortran"]
msg = "cannot retrieve Fortran compiler [spec is not concrete]"
assert self.spec.concrete, msg
def cmd_line(self):
base_call = "cmd /u /c "
commands = " && ".join([x.command_str() for x in self._cmds])
# If multiple commands are being invoked by a single subshell
# they must be encapsulated by a double quote. Always double
# quote to be sure of proper handling
# cmd will properly resolve nested double quotes as needed
#
# `set`` writes out the active env to the subshell stdout,
# and in this context we are always trying to obtain env
# state so it should always be appended
return base_call + f'"{commands} && set"'
class VarsInvocation:
def __init__(self, script):
self._script = script
def command_str(self):
return f'"{self._script}"'
@property
def script(self):
return self._script
class VCVarsInvocation(VarsInvocation):
def __init__(self, script, arch, msvc_version):
super(VCVarsInvocation, self).__init__(script)
self._arch = arch
self._msvc_version = msvc_version
@property
def sdk_ver(self):
"""Accessor for Windows SDK version property
Note: This property may not be set by
the calling context and as such this property will
return an empty string
This property will ONLY be set if the SDK package
is a dependency somewhere in the Spack DAG of the package
for which we are constructing an MSVC compiler env.
Otherwise this property should be unset to allow the VCVARS
script to use its internal heuristics to determine appropriate
SDK version
"""
if getattr(self, "_sdk_ver", None):
return self._sdk_ver + ".0"
return ""
@sdk_ver.setter
def sdk_ver(self, val):
self._sdk_ver = val
@property
def arch(self):
return self._arch
@property
def vcvars_ver(self):
return f"-vcvars_ver={self._msvc_version}"
def command_str(self):
script = super(VCVarsInvocation, self).command_str()
return f"{script} {self.arch} {self.sdk_ver} {self.vcvars_ver}"
FC_PATH = {}
def get_valid_fortran_pth():
"""Assign maximum available fortran compiler version"""
# TODO (johnwparent): validate compatibility w/ try compiler
# functionality when added
sort_fn = lambda fc_ver: spack.version.Version(fc_ver)
sort_fc_ver = sorted(list(FC_PATH.keys()), key=sort_fn)
return FC_PATH[sort_fc_ver[-1]] if sort_fc_ver else None

View File

@ -48,6 +48,8 @@ class Musl(MakefilePackage):
depends_on("c", type="build") # generated
conflicts("glibc")
def patch(self):
config = FileFilter("configure")
if self.compiler.name == "gcc":

View File

@ -6,7 +6,7 @@
import re
import sys
import spack.compilers
import spack.compilers.config
from spack.package import *
from spack.pkg.builtin.mpich import MpichEnvironmentModifications
@ -172,7 +172,7 @@ def determine_version(cls, exe):
@classmethod
def determine_variants(cls, exes, version):
def get_spack_compiler_spec(path):
spack_compilers = spack.compilers.find_compilers([path])
spack_compilers = spack.compilers.config.find_compilers([path])
for spack_compiler in spack_compilers:
if os.path.dirname(spack_compiler.cc) == path:
return spack_compiler.spec

View File

@ -2,6 +2,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import os.path
from spack.package import *
@ -72,6 +73,48 @@ def setup_run_environment(self, env):
compiler_version_regex = r"NAG Fortran Compiler Release (\d+).(\d+)\(.*\) Build (\d+)"
compiler_version_argument = "-V"
# Unlike other compilers, the NAG compiler passes options to GCC, which
# then passes them to the linker. Therefore, we need to doubly wrap the
# options with '-Wl,-Wl,,'
rpath_arg = "-Wl,-Wl,,-rpath,,"
linker_arg = "-Wl,-Wl,,"
disable_new_dtags = ""
enable_new_dtags = ""
debug_flags = ["-g", "-gline", "-g90"]
opt_flags = ["-O", "-O0", "-O1", "-O2", "-O3", "-O4"]
link_paths = {"fortran": os.path.join("nag", "nagfor")}
# NAG does not support a flag that would enable verbose output and
# compilation/linking at the same time (with either '-#' or '-dryrun'
# the compiler only prints the commands but does not run them).
# Therefore, the only thing we can do is to pass the '-v' argument to
# the underlying GCC. In order to get verbose output from the latter
# at both compile and linking stages, we need to call NAG with two
# additional flags: '-Wc,-v' and '-Wl,-v'. However, we return only
# '-Wl,-v' for the following reasons:
# 1) the interface of this method does not support multiple flags in
# the return value and, at least currently, verbose output at the
# linking stage has a higher priority for us;
# 2) NAG is usually mixed with GCC compiler, which also accepts
# '-Wl,-v' and produces meaningful result with it: '-v' is passed
# to the linker and the latter produces verbose output for the
# linking stage ('-Wc,-v', however, would break the compilation
# with a message from GCC that the flag is not recognized).
#
# This way, we at least enable the implicit rpath detection, which is
# based on compilation of a C file (see method
# spack.compiler._compile_dummy_c_source): in the case of a mixed
# NAG/GCC toolchain, the flag will be passed to g++ (e.g.
# 'g++ -Wl,-v ./main.c'), otherwise, the flag will be passed to nagfor
# (e.g. 'nagfor -Wl,-v ./main.c' - note that nagfor recognizes '.c'
# extension and treats the file accordingly). The list of detected
# rpaths will contain only GCC-related directories and rpaths to
# NAG-related directories are injected by nagfor anyway.
verbose_flag = "-Wl,-v"
openmp_flag = "-openmp"
@property
def fortran(self):
msg = "cannot retrieve Fortran compiler [spec is not concrete]"

View File

@ -106,9 +106,9 @@ def setup_build_environment(self, env):
def flag_handler(self, name, flags):
if name == "cflags":
flags.append(self.compiler.cc_pic_flag)
flags.append(self.spec["c"].package.pic_flag)
elif name == "cxxflags":
flags.append(self.compiler.cxx_pic_flag)
flags.append(self.spec["cxx"].package.pic_flag)
# ncurses@:6.0 fails in definition of macro 'mouse_trafo' without -P
if self.spec.satisfies("@:6.0 %gcc@5.0:"):
@ -118,7 +118,7 @@ def flag_handler(self, name, flags):
# ncurses@:6.0 uses dynamic exception specifications not allowed in c++17
if self.spec.satisfies("@:5"):
if name == "cxxflags":
flags.append(self.compiler.cxx14_flag)
flags.append(self.spec["cxx"].package.standard_flag(language="cxx", standard="14"))
return (flags, None, None)

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
#
# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
import os.path
import platform
from spack.package import *
@ -446,9 +446,7 @@ class Nvhpc(Package, CompilerPackage):
if pkg:
version(ver, sha256=pkg[0], url=pkg[1])
depends_on("c", type="build") # generated
depends_on("cxx", type="build") # generated
depends_on("fortran", type="build") # generated
depends_on("gcc languages=c,c++,fortran", type="run")
variant("blas", default=True, description="Enable BLAS")
variant(
@ -469,7 +467,8 @@ class Nvhpc(Package, CompilerPackage):
provides("lapack", when="+lapack")
provides("mpi", when="+mpi")
requires("%gcc", msg="nvhpc must be installed with %gcc")
provides("c", "cxx")
provides("fortran")
# For now we only detect compiler components
# It will require additional work to detect mpi/lapack/blas components
@ -480,6 +479,28 @@ class Nvhpc(Package, CompilerPackage):
compiler_version_argument = "--version"
compiler_version_regex = r"nv[^ ]* (?:[^ ]+ Dev-r)?([0-9.]+)(?:-[0-9]+)?"
debug_flags = ["-g", "-gopt"]
opt_flags = ["-O", "-O0", "-O1", "-O2", "-O3", "-O4"]
pic_flag = "-fpic"
openmp_flag = "-mp"
link_paths = {
"c": os.path.join("nvhpc", "nvc"),
"cxx": os.path.join("nvhpc", "nvc++"),
"fortran": os.path.join("nvhpc", "nvfortran"),
}
required_libs = ["libnvc", "libnvf"]
stdcxx_libs = ("-c++libs",)
def _standard_flag(self, *, language, standard):
flags = {
"cxx": {"11": "--c++11", "14": "--c++14", "17": "--c++17"},
"c": {"99": "-c99", "11": "-c11"},
}
return flags[language][standard]
@classmethod
def determine_variants(cls, exes, version_str):
# TODO: use other exes to determine default_cuda/install_type/blas/lapack/mpi variants
@ -509,11 +530,11 @@ def install(self, spec, prefix):
makelocalrc_args = [
"-gcc",
self.compiler.cc,
spec["gcc"].package.cc,
"-gpp",
self.compiler.cxx,
spec["gcc"].package.cxx,
"-g77",
self.compiler.f77,
spec["gcc"].package.fortran,
"-x",
compilers_bin,
]

View File

@ -918,7 +918,12 @@ class OpenfoamArch:
#: Map spack compiler names to OpenFOAM compiler names
# By default, simply capitalize the first letter
compiler_mapping = {"aocc": "Amd", "fj": "Fujitsu", "intel": "Icc", "oneapi": "Icx"}
compiler_mapping = {
"aocc": "Amd",
"fj": "Fujitsu",
"intel": "Icc",
"intel-oneapi-compilers": "Icx",
}
def __init__(self, spec, **kwargs):
# Some user settings, to be adjusted manually or via variants

View File

@ -7,7 +7,9 @@
import re
import sys
import spack.compilers
import llnl.util.tty as tty
import spack.compilers.config
from spack.package import *
@ -898,10 +900,16 @@ def setup_run_environment(self, env):
def setup_dependent_build_environment(self, env, dependent_spec):
# Use the spack compiler wrappers under MPI
dependent_module = dependent_spec.package.module
env.set("OMPI_CC", dependent_module.spack_cc)
env.set("OMPI_CXX", dependent_module.spack_cxx)
env.set("OMPI_FC", dependent_module.spack_fc)
env.set("OMPI_F77", dependent_module.spack_f77)
for var_name, attr_name in (
("OMPI_CC", "spack_cc"),
("OMPI_CXX", "spack_cxx"),
("OMPI_FC", "spack_fc"),
("OMPI_F77", "spack_f77"),
):
if not hasattr(dependent_module, attr_name):
continue
env.set(var_name, getattr(dependent_module, attr_name))
# See https://www.open-mpi.org/faq/?category=building#installdirs
for suffix in [
@ -1351,7 +1359,7 @@ def test_example(self):
def get_spack_compiler_spec(compiler):
spack_compilers = spack.compilers.find_compilers([os.path.dirname(compiler)])
spack_compilers = spack.compilers.config.find_compilers([os.path.dirname(compiler)])
actual_compiler = None
# check if the compiler actually matches the one we want
for spack_compiler in spack_compilers:

View File

@ -154,7 +154,7 @@ def install(self, spec, prefix):
if spec.satisfies("@1.0"):
options.append("no-krb5")
# clang does not support the .arch directive in assembly files.
if "clang" in self.compiler.cc and spec.target.family == "aarch64":
if "clang" in self.spec["c"].package.cc and spec.target.family == "aarch64":
options.append("no-asm")
elif "%nvhpc" in spec:
# Last tested on nvidia@22.3 for x86_64:

View File

@ -337,7 +337,7 @@ def do_stage(self, mirror_only=False):
def nmake_arguments(self):
args = []
if self.spec.satisfies("%msvc"):
args.append("CCTYPE=%s" % self.compiler.short_msvc_version)
args.append("CCTYPE=%s" % self.spec["msvc"].package.short_msvc_version)
else:
raise RuntimeError("Perl unsupported for non MSVC compilers on Windows")
args.append("INST_TOP=%s" % windows_sfn(self.prefix.replace("/", "\\")))
@ -384,7 +384,7 @@ def configure_args(self):
# https://github.com/spack/spack/pull/3081 and
# https://github.com/spack/spack/pull/4416
if spec.satisfies("%intel"):
config_args.append("-Accflags={0}".format(self.compiler.cc_pic_flag))
config_args.append("-Accflags={0}".format(self.spec["cc"].package.pic_flag))
if "+shared" in spec:
config_args.append("-Duseshrplib")
@ -546,9 +546,10 @@ def filter_config_dot_pm(self):
"-MModule::Loaded", "-MConfig", "-e", "print is_loaded(Config)", output=str
)
c_compiler = self.spec["c"].package.cc
with self.make_briefly_writable(config_dot_pm):
match = "cc *=>.*"
substitute = "cc => '{cc}',".format(cc=self.compiler.cc)
substitute = "cc => '{cc}',".format(cc=c_compiler)
filter_file(match, substitute, config_dot_pm, **kwargs)
# And the path Config_heavy.pl
@ -557,11 +558,11 @@ def filter_config_dot_pm(self):
with self.make_briefly_writable(config_heavy):
match = "^cc=.*"
substitute = "cc='{cc}'".format(cc=self.compiler.cc)
substitute = "cc='{cc}'".format(cc=c_compiler)
filter_file(match, substitute, config_heavy, **kwargs)
match = "^ld=.*"
substitute = "ld='{ld}'".format(ld=self.compiler.cc)
substitute = "ld='{ld}'".format(ld=c_compiler)
filter_file(match, substitute, config_heavy, **kwargs)
match = "^ccflags='"

View File

@ -692,7 +692,7 @@ def configure_args(self):
config_args.append("--without-ensurepip")
if "+pic" in spec:
cflags.append(self.compiler.cc_pic_flag)
cflags.append(self.spec["c"].package.pic_flag)
if "+ssl" in spec:
config_args.append("--with-openssl={0}".format(spec["openssl"].prefix))
@ -810,9 +810,9 @@ def filter_compilers(self):
filenames = [self.get_sysconfigdata_name(), self.config_vars["makefile_filename"]]
filter_file(spack_cc, self.compiler.cc, *filenames, **kwargs)
if spack_cxx and self.compiler.cxx:
filter_file(spack_cxx, self.compiler.cxx, *filenames, **kwargs)
filter_file(spack_cc, self.spec["c"].package.cc, *filenames, **kwargs)
if spack_cxx:
filter_file(spack_cxx, self.spec["cxx"].package.cxx, *filenames, **kwargs)
@run_after("install")
def symlink(self):
@ -1288,7 +1288,13 @@ def setup_dependent_build_environment(self, env, dependent_spec):
# try to modify LDSHARED (LDCXXSHARED), the second variable, which is
# used for linking, in a consistent manner.
for compile_var, link_var in [("CC", "LDSHARED"), ("CXX", "LDCXXSHARED")]:
for language, compile_var, link_var in [
("c", "CC", "LDSHARED"),
("cxx", "CXX", "LDCXXSHARED"),
]:
if not dependent_spec.dependencies(virtuals=(language,)):
continue
# First, we get the values from the sysconfigdata:
config_compile = self.config_vars[compile_var]
config_link = self.config_vars[link_var]
@ -1296,8 +1302,7 @@ def setup_dependent_build_environment(self, env, dependent_spec):
# The dependent environment will have the compilation command set to
# the following:
new_compile = join_path(
spack.paths.build_env_path,
dependent_spec.package.compiler.link_paths[compile_var.lower()],
spack.paths.build_env_path, dependent_spec[language].package.link_paths[language]
)
# Normally, the link command starts with the compilation command:

View File

@ -4,7 +4,7 @@
import os
import re
import spack.compilers
import spack.compilers.config
from spack.package import *
@ -48,7 +48,7 @@ def get_host_compiler(exe):
def get_spack_compiler_spec(compilers_found):
# check using cc for now, as everyone should have that defined.
path = os.path.dirname(compilers_found["cc"])
spack_compilers = spack.compilers.find_compilers([path])
spack_compilers = spack.compilers.config.find_compilers([path])
actual_compiler = None
# check if the compiler actually matches the one we want
for spack_compiler in spack_compilers:

View File

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from spack.compiler import UnsupportedCompilerFlag
from spack.compilers.error import UnsupportedCompilerFlag
from spack.package import *

View File

@ -86,7 +86,7 @@ class Vasp(MakefilePackage, CudaPackage):
depends_on("nccl", when="@6.3: +cuda")
depends_on("hdf5+fortran+mpi", when="+hdf5")
# at the very least the nvhpc mpi seems required
depends_on("nvhpc+mpi+lapack+blas", when="%nvhpc")
requires("^nvhpc+mpi+lapack+blas", when="%nvhpc")
conflicts(
"%gcc@:8", msg="GFortran before 9.x does not support all features needed to build VASP"

View File

@ -22,6 +22,8 @@ class WinFile(Package):
version("5.45", sha256="11b8f3abf647c711bc50ef8451c8d6e955f11c4afd8b0a98f2ac65e9b6e10d5e")
depends_on("c", type="build")
@classmethod
def determine_version(cls, exe):
output = Executable(exe)("--version", output=str, error=str)

View File

@ -23,6 +23,8 @@ class WinGpg(Package):
version("2.4.5", sha256="249ab87bd06abea3140054089bad44d9a5d1531413590576da609142db2673ec")
depends_on("c", type="build")
@classmethod
def determine_version(cls, exe):
output = Executable(exe)("--version", output=str, error=str)

View File

@ -1,6 +1,8 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
from spack.package import *
@ -14,6 +16,9 @@ class Xl(Package, CompilerPackage):
variant("r", default=True, description="The _r version of compilers")
provides("c", "cxx")
provides("fortran")
def install(self, spec, prefix):
raise InstallError(
"XL compilers are not installable yet, but can be "
@ -27,6 +32,48 @@ def install(self, spec, prefix):
compiler_version_argument = "-qversion"
compiler_version_regex = r"([0-9]?[0-9]\.[0-9])"
pic_flag = "-qpic"
openmp_flag = "-qsmp=omp"
debug_flags = ["-g", "-g0", "-g1", "-g2", "-g8", "-g9"]
opt_flags = ["-O", "-O0", "-O1", "-O2", "-O3", "-O4", "-O5", "-Ofast"]
verbose_flag = "-V"
@property
def link_paths(self):
if self.spec.satisfies("~r"):
return {
"c": os.path.join("xl", "xlc"),
"cxx": os.path.join("xl", "xlc++"),
"fortran": os.path.join("xl", "xlf"),
}
return {
"c": os.path.join("xl", "xlc_r"),
"cxx": os.path.join("xl", "xlc++_r"),
"fortran": os.path.join("xl", "xlf_r"),
}
def _standard_flag(self, *, language, standard):
flags = {
"cxx": {
"11": [("@13.1:", "-qlanglvl=extended0x")],
"14": [("@16.1.1.8:", "-std=c++14")],
},
"c": {
"99": [("@10.1:13.0", "-qlanglvl=extc99"), ("@13.1:", "-std=gnu99")],
"11": [("@12.1:13.1.1", "-qlanglvl=extc1x"), ("@13.1.2:", "-std=gnu11")],
},
}
for condition, flag in flags[language][standard]:
if self.spec.satisfies(condition):
return flag
else:
raise RuntimeError(
f"{self.spec} does not support the '{standard}' standard "
f"for the '{language}' language"
)
@classmethod
def determine_variants(cls, exes, version_str):
_r_exes = [e for e in exes if e.endswith("_r")]

View File

@ -3,9 +3,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import re
import spack.compiler
from spack.package import *
@ -65,35 +63,8 @@ class Yafyaml(CMakePackage):
msg="yaFyaml only works with the Fujitsu compiler from 1.3.0 onwards",
)
# GCC 13.3 and higher only work with yafyaml 1.4.0 onwards
# First we can check if the spec is gcc@13.3...
conflicts("%gcc@13.3:", when="@:1.3.0", msg="GCC 13.3+ only works with yafyaml 1.4.0 onwards")
# ...but if it is not (say apple-clang with gfortran as a fc), there is
# no easy way to check this. So we hijack flag_handler to raise an
# exception if we detect gfortran 13.3 or 14.
# NOTE: This will only error out at install time, so `spack spec` will
# not catch this.
def flag_handler(self, name, flags):
# We need to match any compiler that has a name of gfortran or gfortran-*
pattern = re.compile(r"gfortran(-\d+)?$")
if pattern.search(self.compiler.fc):
gfortran_version = spack.compiler.get_compiler_version_output(
self.compiler.fc, "-dumpfullversion"
).strip()
# gfortran_version is now a string like "13.3.0". We now need to just capture
# the major and minor version numbers
gfortran_version = ".".join(gfortran_version.split(".")[:2])
if self.spec.satisfies("@:1.3.0") and (float(gfortran_version) >= 13.3):
raise InstallError(
f"Your gfortran version {gfortran_version} is not compatible with "
f"yafyaml 1.3.0 and below. Use yafyaml 1.4.0 or higher."
)
return None, None, None
variant(
"build_type",
default="Release",

View File

@ -71,7 +71,7 @@ def libs(self):
def flag_handler(self, name, flags):
if name == "cflags" and self.spec.satisfies("+pic build_system=autotools"):
flags.append(self.compiler.cc_pic_flag)
flags.append(self.spec["c"].package.pic_flag)
return (flags, None, None)