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) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os import os
import os.path
import spack.platforms import spack.platforms
from spack.package import * from spack.package import *
@ -356,6 +357,11 @@ class Acfl(Package, CompilerPackage):
provides("lapack") provides("lapack")
provides("fftw-api@3") provides("fftw-api@3")
provides("c", "cxx")
provides("fortran")
requires("platform=linux", msg="acfl is only available for linux")
depends_on("gmake", type="build") depends_on("gmake", type="build")
# Licensing - Not required from 22.0.1 on. # 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+\) " 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 @property
def cc(self): def cc(self):
msg = "cannot retrieve C compiler [spec is not concrete]" 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("LIBRARY_PATH", join_path(arm_dir, "lib"))
env.prepend_path("MANPATH", join_path(arm_dir, "share", "man")) env.prepend_path("MANPATH", join_path(arm_dir, "share", "man"))
def archspec_name(self):
return "arm"
@run_after("install") @run_after("install")
def check_install(self): def check_install(self):
arm_dir = get_acfl_prefix(self.spec) arm_dir = get_acfl_prefix(self.spec)

View File

@ -1,7 +1,7 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright Spack Project Developers. See COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
from spack.package import * from spack.package import *
from spack.pkg.builtin.llvm import LlvmDetection from spack.pkg.builtin.llvm import LlvmDetection
@ -60,6 +60,9 @@ class Aocc(Package, LlvmDetection, CompilerPackage):
depends_on("c", type="build") # generated depends_on("c", type="build") # generated
provides("c", "cxx")
provides("fortran")
# Licensing # Licensing
license_url = "https://www.amd.com/en/developer/aocc/aocc-compiler/eula.html" 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+)" compiler_version_regex = r"AOCC_(\d+[._]\d+[._]\d+)"
fortran_names = ["flang"] 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. # Copyright Spack Project Developers. See COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
from spack.package import * from spack.package import *
from spack.pkg.builtin.llvm import LlvmDetection from spack.pkg.builtin.llvm import LlvmDetection
@ -16,6 +18,14 @@ class AppleClang(BundlePackage, LlvmDetection, CompilerPackage):
compiler_languages = ["c", "cxx"] compiler_languages = ["c", "cxx"]
compiler_version_regex = r"^Apple (?:LLVM|clang) version ([^ )]+)" 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") requires("platform=darwin")
@classmethod @classmethod
@ -38,3 +48,28 @@ def cxx(self):
msg = "apple-clang is expected to be an external spec" msg = "apple-clang is expected to be an external spec"
assert self.spec.concrete and self.spec.external, msg assert self.spec.concrete and self.spec.external, msg
return self.spec.extra_attributes["compilers"].get("cxx", None) 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 os
import spack.error
import spack.platforms import spack.platforms
from spack.package import * from spack.package import *
@ -406,6 +405,10 @@ class ArmplGcc(Package):
provides("lapack") provides("lapack")
provides("fftw-api@3") 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") depends_on("gmake", type="build")
# Run the installer with the desired install directory # Run the installer with the desired install directory
@ -431,8 +434,6 @@ def install(self, spec, prefix):
# Unmount image # Unmount image
hdiutil("detach", mountpoint) hdiutil("detach", mountpoint)
return return
if self.compiler.name != "gcc":
raise spack.error.SpackError(("Only compatible with GCC.\n"))
with when("@:22"): with when("@:22"):
armpl_version = spec.version.up_to(3).string.split("_")[0] 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): def llnl_link_helpers(options, spec, compiler):
# From local package: # From local package:
if compiler.fc: if "fortran" in spec:
fortran_compilers = ["gfortran", "xlf"] fortran_compilers = ["gfortran", "xlf"]
if any(f_comp in compiler.fc for f_comp in fortran_compilers) and ( if any(f_comp in compiler.fc for f_comp in fortran_compilers) and (
"clang" in compiler.cxx "clang" in compiler.cxx
@ -37,7 +37,7 @@ def llnl_link_helpers(options, spec, compiler):
if flags: if flags:
options.append(cmake_cache_string("BLT_EXE_LINKER_FLAGS", flags, description)) 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" description = "Adds a missing rpath for libraries " "associated with the fortran compiler"
# Here is where to find libs that work for fortran # Here is where to find libs that work for fortran
libdir = "/opt/cray/pe/cce/{0}/cce-clang/x86_64/lib".format(compiler.version) 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. # Copyright Spack Project Developers. See COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
from spack.package import * from spack.package import *
@ -20,10 +22,29 @@ class Cce(Package, CompilerPackage):
r"[Cc]ray (?:clang|C :|C\+\+ :|Fortran :) [Vv]ersion.*?(\d+(?:\.\d+)+)" 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") maintainers("becker33")
version("16.0.0") 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): def install(self, spec, prefix):
raise NotImplementedError("cray compiler must be configured as external") raise NotImplementedError("cray compiler must be configured as external")

View File

@ -1,11 +1,6 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright Spack Project Developers. See COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import spack.compilers
import spack.spec
from spack.package import * from spack.package import *
@ -87,8 +82,6 @@ class Claw(CMakePackage):
def flag_handler(self, name, flags): def flag_handler(self, name, flags):
if name == "cflags": if name == "cflags":
compiler_spec = self.spec.compiler 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( if any(
[ [
compiler_spec.satisfies(s) compiler_spec.satisfies(s)
@ -105,25 +98,3 @@ def cmake_args(self):
args = ["-DOMNI_CONF_OPTION=--with-libxml2=%s" % self.spec["libxml2"].prefix] args = ["-DOMNI_CONF_OPTION=--with-libxml2=%s" % self.spec["libxml2"].prefix]
return args 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) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
from spack.compiler import UnsupportedCompilerFlag from spack.compilers.error import UnsupportedCompilerFlag
from spack.package import * from spack.package import *
@ -38,8 +38,8 @@ class Clingo(CMakePackage):
version("5.3.0", sha256="b0d406d2809352caef7fccf69e8864d55e81ee84f4888b0744894977f703f976") version("5.3.0", sha256="b0d406d2809352caef7fccf69e8864d55e81ee84f4888b0744894977f703f976")
version("5.2.2", sha256="da1ef8142e75c5a6f23c9403b90d4f40b9f862969ba71e2aaee9a257d058bfcf") version("5.2.2", sha256="da1ef8142e75c5a6f23c9403b90d4f40b9f862969ba71e2aaee9a257d058bfcf")
depends_on("c", type="build") # generated depends_on("c", type="build")
depends_on("cxx", type="build") # generated depends_on("cxx", type="build")
variant("docs", default=False, description="build documentation with Doxygen") variant("docs", default=False, description="build documentation with Doxygen")
variant("python", default=True, description="build with python bindings") variant("python", default=True, description="build with python bindings")
@ -100,7 +100,7 @@ def cmake_py_shared(self):
def cmake_args(self): def cmake_args(self):
try: try:
self.compiler.cxx14_flag self.spec["cxx"].package.standard_flag(language="cxx", standard="14")
except UnsupportedCompilerFlag: except UnsupportedCompilerFlag:
InstallError("clingo requires a C++14-compliant C++ compiler") 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) match = re.search(r"cmake.*version\s+(\S+)", output)
return match.group(1) if match else None 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): def bootstrap_args(self):
spec = self.spec spec = self.spec
args = [] args = []

View File

@ -79,10 +79,15 @@ def setup_run_environment(self, env):
self.setup_mpi_wrapper_variables(env) self.setup_mpi_wrapper_variables(env)
return return
env.set("MPICC", self.compiler.cc) if self.spec.dependencies(virtuals=("c",)):
env.set("MPICXX", self.compiler.cxx) env.set("MPICC", self.spec["c"].package.cc)
env.set("MPIFC", self.compiler.fc)
env.set("MPIF77", self.compiler.f77) 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): def setup_dependent_package(self, module, dependent_spec):
spec = self.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") requires("platform=linux", msg="Cray MVAPICH2 is only available on Cray")
def setup_run_environment(self, env): def setup_run_environment(self, env):
env.set("MPICC", self.compiler.cc) if self.spec.dependencies(virtuals=("c",)):
env.set("MPICXX", self.compiler.cxx) env.set("MPICC", self.spec["c"].package.cc)
env.set("MPIFC", self.compiler.fc)
env.set("MPIF77", self.compiler.f77) 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): def install(self, spec, prefix):
raise InstallError( raise InstallError(

View File

@ -727,7 +727,8 @@ def setup_build_environment(self, env):
env.append_path("LD_LIBRARY_PATH", libxml2_home.lib) env.append_path("LD_LIBRARY_PATH", libxml2_home.lib)
def setup_dependent_build_environment(self, env, dependent_spec): 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("CUDA_HOME", self.prefix)
env.set("NVHPC_CUDA_HOME", self.prefix) env.set("NVHPC_CUDA_HOME", self.prefix)

View File

@ -4,8 +4,6 @@
import os import os
import spack.compilers
import spack.spec
from spack.package import * from spack.package import *
@ -17,25 +15,14 @@ class Cxx(Package):
def test_cxx(self): def test_cxx(self):
"""Compile and run 'Hello World'""" """Compile and run 'Hello World'"""
cxx = which(os.environ["CXX"])
expected = ["Hello world", "YES!"] expected = ["Hello world", "YES!"]
cxx = Executable(self.cxx)
test_source = self.test_suite.current_test_data_dir test_source = self.test_suite.current_test_data_dir
for test in os.listdir(test_source): for test in os.listdir(test_source):
exe_name = f"{test}.exe" exe_name = f"{test}.exe"
filepath = test_source.join(test)
with test_part(self, f"test_cxx_{test}", f"build and run {exe_name}"): with test_part(self, f"test_cxx_{test}", f"build and run {exe_name}"):
# standard options filepath = join_path(test_source, test)
# Hack to get compiler attributes cxx("-o", exe_name, filepath)
# 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)
exe = which(exe_name) exe = which(exe_name)
out = exe(output=str.split, error=str.split) out = exe(output=str.split, error=str.split)
check_outputs(expected, out) check_outputs(expected, out)

View File

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

View File

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

View File

@ -1,6 +1,8 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright Spack Project Developers. See COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
from spack.package import * from spack.package import *
@ -14,6 +16,9 @@ class Fj(Package, CompilerPackage):
maintainers("t-karatsu") maintainers("t-karatsu")
provides("c", "cxx")
provides("fortran")
def install(self, spec, prefix): def install(self, spec, prefix):
raise InstallError( raise InstallError(
"Fujitsu compilers are not installable yet, but can be " "Fujitsu compilers are not installable yet, but can be "
@ -26,3 +31,29 @@ def install(self, spec, prefix):
fortran_names = ["frt"] fortran_names = ["frt"]
compiler_version_regex = r"\((?:FCC|FRT)\) ([a-z\d.]+)" compiler_version_regex = r"\((?:FCC|FRT)\) ([a-z\d.]+)"
compiler_version_argument = "--version" 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") license("GPL-3.0-or-later WITH GCC-exception-3.1")
requires("%gcc")
LIBRARIES = [ LIBRARIES = [
"asan", "asan",
"atomic", "atomic",
@ -47,15 +45,18 @@ class GccRuntime(Package):
# libgfortran ABI # libgfortran ABI
provides("fortran-rt", "libgfortran") provides("fortran-rt", "libgfortran")
provides("libgfortran@3", when="%gcc@:6") provides("libgfortran@3", when="@:6")
provides("libgfortran@4", when="%gcc@7") provides("libgfortran@4", when="@7")
provides("libgfortran@5", when="%gcc@8:") provides("libgfortran@5", when="@8:")
depends_on("libc", type="link", when="platform=linux") depends_on("libc", type="link", when="platform=linux")
depends_on("gcc", type="build")
def install(self, spec, prefix): def install(self, spec, prefix):
gcc_pkg = self["gcc"]
if spec.platform in ["linux", "freebsd"]: 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": elif spec.platform == "darwin":
libraries = self._get_libraries_macho() libraries = self._get_libraries_macho()
else: else:
@ -75,7 +76,7 @@ def install(self, spec, prefix):
def _get_libraries_macho(self): def _get_libraries_macho(self):
"""Same as _get_libraries_elf but for Mach-O binaries""" """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 = [] path_and_install_name = []
for name in self.LIBRARIES: for name in self.LIBRARIES:

View File

@ -9,7 +9,7 @@
from llnl.util.symlink import readlink from llnl.util.symlink import readlink
import spack.compiler import spack.build_systems.compiler
import spack.platforms import spack.platforms
import spack.repo import spack.repo
import spack.util.libc 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") license("GPL-2.0-or-later AND LGPL-2.1-or-later")
provides("c") provides("c", when="languages=c")
provides("cxx") provides("cxx", when="languages=c++")
provides("fortran") provides("fortran", when="languages=fortran")
version("master", branch="master") version("master", branch="master")
@ -594,7 +594,12 @@ def supported_languages(self):
# This weirdness is because it could be called on an abstract spec # This weirdness is because it could be called on an abstract spec
if "languages" not in self.spec.variants: if "languages" not in self.spec.variants:
return self.compiler_languages 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"] c_names = ["gcc"]
cxx_names = ["g++"] cxx_names = ["g++"]
@ -605,6 +610,40 @@ def supported_languages(self):
compiler_version_regex = r"([0-9.]+)" compiler_version_regex = r"([0-9.]+)"
compiler_version_argument = ("-dumpfullversion", "-dumpversion") 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 @classmethod
def filter_detected_exes(cls, prefix, exes_in_prefix): def filter_detected_exes(cls, prefix, exes_in_prefix):
# Apple's gcc is actually apple clang, so skip it. # 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 = [] not_apple_clang = []
for exe in exes_in_prefix: for exe in exes_in_prefix:
try: try:
output = spack.compiler.get_compiler_version_output(exe, "--version") output = spack.build_systems.compiler.compiler_output(
exe, version_argument="--version"
)
except Exception: except Exception:
output = "" output = ""
if "clang version" in output: if "clang version" in output:
@ -1157,7 +1198,7 @@ def runtime_constraints(cls, *, spec, pkg):
) )
pkg("*").depends_on( pkg("*").depends_on(
f"gcc-runtime@{str(spec.version)}:", f"gcc-runtime@{str(spec.version)}:",
when=f"%{str(spec)}", when=f"^[deptypes=build] {spec.name}@{spec.versions}",
type="link", type="link",
description=f"If any package uses %{str(spec)}, " description=f"If any package uses %{str(spec)}, "
f"it depends on gcc-runtime@{str(spec.version)}:", 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): for fortran_virtual in ("fortran-rt", gfortran_str):
pkg("*").depends_on( pkg("*").depends_on(
fortran_virtual, fortran_virtual,
when=f"%{str(spec)}", when=f"^[virtuals=fortran deptypes=build] {spec.name}@{spec.versions}",
languages=["fortran"],
type="link", type="link",
description=f"Add a dependency on '{gfortran_str}' for nodes compiled with " description=f"Add a dependency on '{gfortran_str}' for nodes compiled with "
f"{str(spec)} and using the 'fortran' language", f"{str(spec)} and using the 'fortran' language",
) )
# The version of gcc-runtime is the same as the %gcc used to "compile" it # 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 # 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) # (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): def _post_buildcache_install_hook(self):
if not self.spec.satisfies("platform=linux"): if not self.spec.satisfies("platform=linux"):

View File

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

View File

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

View File

@ -108,3 +108,30 @@ def symlink_dir(self, src, dest):
link_tree.merge(dest_path) link_tree.merge(dest_path)
else: else:
os.symlink(src_path, dest_path) 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. # Copyright Spack Project Developers. See COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os import os
import os.path
import pathlib
import platform import platform
import warnings
from spack.build_environment import dso_suffix from spack.build_environment import dso_suffix
from spack.package import * from spack.package import *
@ -329,6 +331,47 @@ class IntelOneapiCompilers(IntelOneApiPackage, CompilerPackage):
r"(?:(?:oneAPI DPC\+\+(?:\/C\+\+)? Compiler)|(?:\(IFORT\))|(?:\(IFX\))) (\S+)" 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 # See https://github.com/spack/spack/issues/39252
depends_on("patchelf@:0.17", type="build", when="@:2024.1") depends_on("patchelf@:0.17", type="build", when="@:2024.1")
# Add the nvidia variant # Add the nvidia variant
@ -337,10 +380,8 @@ class IntelOneapiCompilers(IntelOneApiPackage, CompilerPackage):
# Add the amd variant # Add the amd variant
variant("amd", default=False, description="Install AMD plugin for OneAPI") variant("amd", default=False, description="Install AMD plugin for OneAPI")
conflicts("@:2022.2.1", when="+amd", msg="Codeplay AMD plugin requires newer release") 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 depends_on("gcc languages=c,c++", type="run")
# instead.
requires("%gcc", msg="intel-oneapi-compilers must be installed with %gcc")
for v in versions: for v in versions:
version(v["version"], expand=False, **v["cpp"]) 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("F77", self._llvm_bin.ifx)
env.set("FC", 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): def install(self, spec, prefix):
# Copy instead of install to speed up debugging # Copy instead of install to speed up debugging
# install_tree("/opt/intel/oneapi/compiler", self.prefix) # 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()] 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 # Make sure that underlying clang gets the right GCC toolchain by default
llvm_flags = ["--gcc-toolchain={}".format(self.compiler.prefix)] gcc = self.spec["gcc"].package
classic_flags = ["-gcc-name={}".format(self.compiler.cc)] llvm_flags = [f"--gcc-toolchain={gcc.prefix}"]
classic_flags.append("-gxx-name={}".format(self.compiler.cxx)) classic_flags = [f"-gcc-name={gcc.cc}", f"-gxx-name={gcc.cxx}"]
# Older versions trigger -Wunused-command-line-argument warnings whenever # Older versions trigger -Wunused-command-line-argument warnings whenever
# linker flags are passed in preprocessor (-E) or compilation mode (-c). # 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): if find(p, "*." + dso_suffix, recursive=False):
yield p 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 @classmethod
def runtime_constraints(cls, *, spec, pkg): def runtime_constraints(cls, *, spec, pkg):
pkg("*").depends_on( pkg("*").depends_on(
@ -561,7 +645,7 @@ def runtime_constraints(cls, *, spec, pkg):
) )
pkg("*").depends_on( pkg("*").depends_on(
f"intel-oneapi-runtime@{str(spec.version)}:", f"intel-oneapi-runtime@{str(spec.version)}:",
when=f"%{str(spec)}", when=f"^[deptypes=build] {spec.name}@{spec.versions}",
type="link", type="link",
description=f"If any package uses %{str(spec)}, " description=f"If any package uses %{str(spec)}, "
f"it depends on intel-oneapi-runtime@{str(spec.version)}:", 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"): for fortran_virtual in ("fortran-rt", "libifcore@5"):
pkg("*").depends_on( pkg("*").depends_on(
fortran_virtual, fortran_virtual,
when=f"%{str(spec)}", when=f"^[virtuals=fortran deptypes=build] {spec.name}@{spec.versions}",
languages=["fortran"],
type="link", type="link",
description=f"Add a dependency on 'libifcore' for nodes compiled with " description=f"Add a dependency on 'libifcore' for nodes compiled with "
f"{str(spec)} and using the 'fortran' language", f"{str(spec)} and using the 'fortran' language",
) )
# The version of intel-oneapi-runtime is the same as the %oneapi used to "compile" it # 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): def setup_dependent_build_environment(self, env, dependent_spec):
dependent_module = dependent_spec.package.module dependent_module = dependent_spec.package.module
env.set("I_MPI_CC", dependent_module.spack_cc) for var_name, attr_name in (
env.set("I_MPI_CXX", dependent_module.spack_cxx) ("I_MPI_CC", "spack_cc"),
env.set("I_MPI_F77", dependent_module.spack_f77) ("I_MPI_CXX", "spack_cxx"),
env.set("I_MPI_F90", dependent_module.spack_fc) ("I_MPI_FC", "spack_fc"),
env.set("I_MPI_FC", dependent_module.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 # Set compiler wrappers for dependent build stage
wrappers = self.wrapper_paths() wrappers = self.wrapper_paths()

View File

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

View File

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

View File

@ -110,7 +110,7 @@ def url_for_version(self, version):
def flag_handler(self, name, flags): def flag_handler(self, name, flags):
if name == "cflags" and self.spec.satisfies("+pic"): 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") flags.append("-DPIC")
return (flags, None, None) return (flags, None, None)

View File

@ -6,17 +6,23 @@
import shutil import shutil
from spack.package import * 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, """Toolkit for the construction of highly optimized compilers,
optimizers, and run-time environments.""" optimizers, and run-time environments."""
homepage = "https://github.com/ROCm/llvm-project" homepage = "https://github.com/ROCm/llvm-project"
git = "https://github.com/ROCm/llvm-project.git" git = "https://github.com/ROCm/llvm-project.git"
url = "https://github.com/ROCm/llvm-project/archive/rocm-6.2.4.tar.gz" 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-.*"] 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") generator("ninja")
maintainers("srekolam", "renjithravindrankannath", "haampie", "afzpatel") maintainers("srekolam", "renjithravindrankannath", "haampie", "afzpatel")
@ -215,6 +221,15 @@ class LlvmAmdgpu(CMakePackage, CompilerPackage):
when="@master", 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): def cmake_args(self):
llvm_projects = ["clang", "lld", "clang-tools-extra", "compiler-rt"] llvm_projects = ["clang", "lld", "clang-tools-extra", "compiler-rt"]
llvm_runtimes = ["libcxx", "libcxxabi"] 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: if "libclang_rt.asan-x86_64.so" in files:
env.prepend_path("LD_LIBRARY_PATH", root) env.prepend_path("LD_LIBRARY_PATH", root)
env.prune_duplicate_paths("LD_LIBRARY_PATH") 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 from llnl.util.lang import classproperty
import spack.compilers
from spack.build_systems.cmake import get_cmake_prefix_path from spack.build_systems.cmake import get_cmake_prefix_path
from spack.operating_systems.mac_os import macos_sdk_path from spack.operating_systems.mac_os import macos_sdk_path
from spack.package import * from spack.package import *
@ -394,6 +393,9 @@ class Llvm(CMakePackage, CudaPackage, LlvmDetection, CompilerPackage):
provides("libllvm@4", when="@4.0.0:4") provides("libllvm@4", when="@4.0.0:4")
provides("libllvm@3", when="@3.0.0:3") provides("libllvm@3", when="@3.0.0:3")
provides("c", "cxx", when="+clang")
provides("fortran", when="+flang")
extends("python", when="+python") extends("python", when="+python")
# Build dependency # Build dependency
@ -495,9 +497,9 @@ class Llvm(CMakePackage, CudaPackage, LlvmDetection, CompilerPackage):
}, },
}.items(): }.items():
with when(v): with when(v):
for comp in spack.compilers.supported_compilers(): for _name, _constraint in compiler_conflicts.items():
conflicts("%{0}{1}".format(comp, compiler_conflicts.get(comp, ""))) conflicts(f"%{_name}{_constraint}")
del v, compiler_conflicts, comp del v, compiler_conflicts, _name, _constraint
# libomptarget # libomptarget
conflicts("+cuda", when="@15:") # +cuda variant is obselete since LLVM 15 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") result = os.path.join(self.spec.prefix.bin, "flang")
return result 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 @property
def libs(self): def libs(self):
return LibraryList(self.llvm_config("--libfiles", "all", result="list")) return LibraryList(self.llvm_config("--libfiles", "all", result="list"))

View File

@ -4,7 +4,6 @@
import subprocess import subprocess
import spack.compiler
from spack.package import * from spack.package import *
@ -256,9 +255,7 @@ class Mapl(CMakePackage):
# MAPL can use ifx only from MAPL 2.51 onwards and only supports # MAPL can use ifx only from MAPL 2.51 onwards and only supports
# ifx 2025.0 and newer due to bugs in ifx. # ifx 2025.0 and newer due to bugs in ifx.
conflicts("%oneapi@2025:", when="@:2.50") conflicts("%oneapi@2025:", when="@:2.50")
# NOTE there is a further check on oneapi in the cmake_args below conflicts("^[virtuals=fortran] intel-oneapi-compilers")
# that is hard to conflict since we don't know the fortran compiler
# at this point
variant("flap", default=False, description="Build with FLAP support", when="@:2.39") variant("flap", default=False, description="Build with FLAP support", when="@:2.39")
variant("pflogger", default=True, description="Build with pFlogger support") variant("pflogger", default=True, description="Build with pFlogger support")
@ -381,33 +378,14 @@ def cmake_args(self):
fflags = [] fflags = []
if self.compiler.name in ["gcc", "clang", "apple-clang"]: if self.compiler.name in ["gcc", "clang", "apple-clang"]:
fflags.append("-ffree-line-length-none") fflags.append("-ffree-line-length-none")
gfortran_major_ver = int(
spack.compiler.get_compiler_version_output(self.compiler.fc, "-dumpversion").split( gfortran_major_ver = int(self.spec["fortran"].version[0])
"."
)[0]
)
if gfortran_major_ver >= 10: if gfortran_major_ver >= 10:
fflags.append("-fallow-invalid-boz") fflags.append("-fallow-invalid-boz")
fflags.append("-fallow-argument-mismatch") fflags.append("-fallow-argument-mismatch")
if fflags: if fflags:
args.append(self.define("CMAKE_Fortran_FLAGS", " ".join(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. # Scripts often need to know the MPI stack used to setup the environment.
# Normally, we can autodetect this, but building with Spack does not # 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 # seem to work. We need to pass in the MPI stack used to CMake

View File

@ -6,7 +6,7 @@
import re import re
import sys import sys
import spack.compilers import spack.compilers.config
import spack.package_base import spack.package_base
from spack.package import * from spack.package import *
@ -383,7 +383,7 @@ def determine_version(cls, exe):
@classmethod @classmethod
def determine_variants(cls, exes, version): def determine_variants(cls, exes, version):
def get_spack_compiler_spec(compiler): 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 actual_compiler = None
# check if the compiler actually matches the one we want # check if the compiler actually matches the one we want
for spack_compiler in spack_compilers: for spack_compiler in spack_compilers:
@ -509,25 +509,6 @@ def autoreconf(self, spec, prefix):
bash = which("bash") bash = which("bash")
bash("./autogen.sh") 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): def configure_args(self):
spec = self.spec spec = self.spec
config_args = [ config_args = [

View File

@ -1,9 +1,15 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright Spack Project Developers. See COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
import re 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 * from spack.package import *
@ -26,13 +32,26 @@ def install(self, spec, prefix):
compiler_version_argument = "" compiler_version_argument = ""
compiler_version_regex = r"([1-9][0-9]*\.[0-9]*\.[0-9]*)" 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 @classmethod
def determine_version(cls, exe): def determine_version(cls, exe):
# MSVC compiler does not have a proper version argument # MSVC compiler does not have a proper version argument
# Errors out and prints version info with no args # Errors out and prints version info with no args
match = re.search( match = re.search(
cls.compiler_version_regex, 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: if match:
return match.group(1) return match.group(1)
@ -58,9 +77,164 @@ def cxx(self):
msg = "cannot retrieve C++ compiler [spec is not concrete]" msg = "cannot retrieve C++ compiler [spec is not concrete]"
assert self.spec.concrete, msg 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 @property
def fortran(self): def cmd_line(self):
if self.spec.external: base_call = "cmd /u /c "
return self.spec.extra_attributes["compilers"]["fortran"] commands = " && ".join([x.command_str() for x in self._cmds])
msg = "cannot retrieve Fortran compiler [spec is not concrete]" # If multiple commands are being invoked by a single subshell
assert self.spec.concrete, msg # 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 depends_on("c", type="build") # generated
conflicts("glibc")
def patch(self): def patch(self):
config = FileFilter("configure") config = FileFilter("configure")
if self.compiler.name == "gcc": if self.compiler.name == "gcc":

View File

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

View File

@ -2,6 +2,7 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os import os
import os.path
from spack.package import * 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_regex = r"NAG Fortran Compiler Release (\d+).(\d+)\(.*\) Build (\d+)"
compiler_version_argument = "-V" 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 @property
def fortran(self): def fortran(self):
msg = "cannot retrieve Fortran compiler [spec is not concrete]" 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): def flag_handler(self, name, flags):
if name == "cflags": if name == "cflags":
flags.append(self.compiler.cc_pic_flag) flags.append(self.spec["c"].package.pic_flag)
elif name == "cxxflags": 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 # ncurses@:6.0 fails in definition of macro 'mouse_trafo' without -P
if self.spec.satisfies("@:6.0 %gcc@5.0:"): 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 # ncurses@:6.0 uses dynamic exception specifications not allowed in c++17
if self.spec.satisfies("@:5"): if self.spec.satisfies("@:5"):
if name == "cxxflags": 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) return (flags, None, None)

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
# #
# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. # Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
import os.path
import platform import platform
from spack.package import * from spack.package import *
@ -446,9 +446,7 @@ class Nvhpc(Package, CompilerPackage):
if pkg: if pkg:
version(ver, sha256=pkg[0], url=pkg[1]) version(ver, sha256=pkg[0], url=pkg[1])
depends_on("c", type="build") # generated depends_on("gcc languages=c,c++,fortran", type="run")
depends_on("cxx", type="build") # generated
depends_on("fortran", type="build") # generated
variant("blas", default=True, description="Enable BLAS") variant("blas", default=True, description="Enable BLAS")
variant( variant(
@ -469,7 +467,8 @@ class Nvhpc(Package, CompilerPackage):
provides("lapack", when="+lapack") provides("lapack", when="+lapack")
provides("mpi", when="+mpi") 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 # For now we only detect compiler components
# It will require additional work to detect mpi/lapack/blas 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_argument = "--version"
compiler_version_regex = r"nv[^ ]* (?:[^ ]+ Dev-r)?([0-9.]+)(?:-[0-9]+)?" 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 @classmethod
def determine_variants(cls, exes, version_str): def determine_variants(cls, exes, version_str):
# TODO: use other exes to determine default_cuda/install_type/blas/lapack/mpi variants # 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 = [ makelocalrc_args = [
"-gcc", "-gcc",
self.compiler.cc, spec["gcc"].package.cc,
"-gpp", "-gpp",
self.compiler.cxx, spec["gcc"].package.cxx,
"-g77", "-g77",
self.compiler.f77, spec["gcc"].package.fortran,
"-x", "-x",
compilers_bin, compilers_bin,
] ]

View File

@ -918,7 +918,12 @@ class OpenfoamArch:
#: Map spack compiler names to OpenFOAM compiler names #: Map spack compiler names to OpenFOAM compiler names
# By default, simply capitalize the first letter # 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): def __init__(self, spec, **kwargs):
# Some user settings, to be adjusted manually or via variants # Some user settings, to be adjusted manually or via variants

View File

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

View File

@ -154,7 +154,7 @@ def install(self, spec, prefix):
if spec.satisfies("@1.0"): if spec.satisfies("@1.0"):
options.append("no-krb5") options.append("no-krb5")
# clang does not support the .arch directive in assembly files. # 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") options.append("no-asm")
elif "%nvhpc" in spec: elif "%nvhpc" in spec:
# Last tested on nvidia@22.3 for x86_64: # 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): def nmake_arguments(self):
args = [] args = []
if self.spec.satisfies("%msvc"): 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: else:
raise RuntimeError("Perl unsupported for non MSVC compilers on Windows") raise RuntimeError("Perl unsupported for non MSVC compilers on Windows")
args.append("INST_TOP=%s" % windows_sfn(self.prefix.replace("/", "\\"))) 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/3081 and
# https://github.com/spack/spack/pull/4416 # https://github.com/spack/spack/pull/4416
if spec.satisfies("%intel"): 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: if "+shared" in spec:
config_args.append("-Duseshrplib") config_args.append("-Duseshrplib")
@ -546,9 +546,10 @@ def filter_config_dot_pm(self):
"-MModule::Loaded", "-MConfig", "-e", "print is_loaded(Config)", output=str "-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): with self.make_briefly_writable(config_dot_pm):
match = "cc *=>.*" 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) filter_file(match, substitute, config_dot_pm, **kwargs)
# And the path Config_heavy.pl # And the path Config_heavy.pl
@ -557,11 +558,11 @@ def filter_config_dot_pm(self):
with self.make_briefly_writable(config_heavy): with self.make_briefly_writable(config_heavy):
match = "^cc=.*" match = "^cc=.*"
substitute = "cc='{cc}'".format(cc=self.compiler.cc) substitute = "cc='{cc}'".format(cc=c_compiler)
filter_file(match, substitute, config_heavy, **kwargs) filter_file(match, substitute, config_heavy, **kwargs)
match = "^ld=.*" match = "^ld=.*"
substitute = "ld='{ld}'".format(ld=self.compiler.cc) substitute = "ld='{ld}'".format(ld=c_compiler)
filter_file(match, substitute, config_heavy, **kwargs) filter_file(match, substitute, config_heavy, **kwargs)
match = "^ccflags='" match = "^ccflags='"

View File

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

View File

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

View File

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

View File

@ -86,7 +86,7 @@ class Vasp(MakefilePackage, CudaPackage):
depends_on("nccl", when="@6.3: +cuda") depends_on("nccl", when="@6.3: +cuda")
depends_on("hdf5+fortran+mpi", when="+hdf5") depends_on("hdf5+fortran+mpi", when="+hdf5")
# at the very least the nvhpc mpi seems required # 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( conflicts(
"%gcc@:8", msg="GFortran before 9.x does not support all features needed to build VASP" "%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") version("5.45", sha256="11b8f3abf647c711bc50ef8451c8d6e955f11c4afd8b0a98f2ac65e9b6e10d5e")
depends_on("c", type="build")
@classmethod @classmethod
def determine_version(cls, exe): def determine_version(cls, exe):
output = Executable(exe)("--version", output=str, error=str) output = Executable(exe)("--version", output=str, error=str)

View File

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

View File

@ -1,6 +1,8 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details. # Copyright Spack Project Developers. See COPYRIGHT file for details.
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
from spack.package import * from spack.package import *
@ -14,6 +16,9 @@ class Xl(Package, CompilerPackage):
variant("r", default=True, description="The _r version of compilers") variant("r", default=True, description="The _r version of compilers")
provides("c", "cxx")
provides("fortran")
def install(self, spec, prefix): def install(self, spec, prefix):
raise InstallError( raise InstallError(
"XL compilers are not installable yet, but can be " "XL compilers are not installable yet, but can be "
@ -27,6 +32,48 @@ def install(self, spec, prefix):
compiler_version_argument = "-qversion" compiler_version_argument = "-qversion"
compiler_version_regex = r"([0-9]?[0-9]\.[0-9])" 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 @classmethod
def determine_variants(cls, exes, version_str): def determine_variants(cls, exes, version_str):
_r_exes = [e for e in exes if e.endswith("_r")] _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) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os import os
import re
import spack.compiler
from spack.package import * from spack.package import *
@ -65,35 +63,8 @@ class Yafyaml(CMakePackage):
msg="yaFyaml only works with the Fujitsu compiler from 1.3.0 onwards", 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") 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( variant(
"build_type", "build_type",
default="Release", default="Release",

View File

@ -71,7 +71,7 @@ def libs(self):
def flag_handler(self, name, flags): def flag_handler(self, name, flags):
if name == "cflags" and self.spec.satisfies("+pic build_system=autotools"): 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) return (flags, None, None)