780 lines
31 KiB
Python
780 lines
31 KiB
Python
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
|
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
|
#
|
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
"""Test basic behavior of compilers in Spack"""
|
|
import json
|
|
import os
|
|
from copy import copy
|
|
from typing import Optional
|
|
|
|
import pytest
|
|
|
|
import llnl.util.filesystem as fs
|
|
|
|
import spack.compiler
|
|
import spack.compilers
|
|
import spack.config
|
|
import spack.spec
|
|
import spack.util.module_cmd
|
|
from spack.compiler import Compiler
|
|
from spack.util.executable import Executable
|
|
from spack.util.file_cache import FileCache
|
|
|
|
|
|
# FIXME (compiler as nodes): revisit this test
|
|
# def test_multiple_conflicting_compiler_definitions(mutable_config):
|
|
# compiler_def = {
|
|
# "compiler": {
|
|
# "flags": {},
|
|
# "modules": [],
|
|
# "paths": {"cc": "cc", "cxx": "cxx", "f77": "null", "fc": "null"},
|
|
# "extra_rpaths": [],
|
|
# "operating_system": "test",
|
|
# "target": "test",
|
|
# "environment": {},
|
|
# "spec": "clang@0.0.0",
|
|
# }
|
|
# }
|
|
#
|
|
# compiler_config = [compiler_def, compiler_def]
|
|
# compiler_config[0]["compiler"]["paths"]["f77"] = "f77"
|
|
# mutable_config.update_config("compilers", compiler_config)
|
|
#
|
|
# arch_spec = spack.spec.ArchSpec(("test", "test", "test"))
|
|
# cmp = spack.compilers.compiler_for_spec("clang@=0.0.0", arch_spec)
|
|
# assert cmp.f77 == "f77"
|
|
|
|
|
|
def test_compiler_flags_from_config_are_grouped():
|
|
compiler_entry = {
|
|
"spec": "intel@17.0.2",
|
|
"operating_system": "foo-os",
|
|
"paths": {"cc": "cc-path", "cxx": "cxx-path", "fc": None, "f77": None},
|
|
"flags": {"cflags": "-O0 -foo-flag foo-val"},
|
|
"modules": None,
|
|
}
|
|
|
|
compiler = spack.compilers.compiler_from_dict(compiler_entry)
|
|
assert any(x == "-foo-flag foo-val" for x in compiler.flags["cflags"])
|
|
|
|
|
|
# Test behavior of flags and UnsupportedCompilerFlag.
|
|
|
|
# Utility function to test most flags.
|
|
default_compiler_entry = {
|
|
"spec": "apple-clang@2.0.0",
|
|
"operating_system": "foo-os",
|
|
"paths": {"cc": "cc-path", "cxx": "cxx-path", "fc": "fc-path", "f77": "f77-path"},
|
|
"flags": {},
|
|
"modules": None,
|
|
}
|
|
|
|
|
|
# Fake up a mock compiler where everything is defaulted.
|
|
class MockCompiler(Compiler):
|
|
def __init__(self):
|
|
super().__init__(
|
|
cspec="badcompiler@1.0.0",
|
|
operating_system=default_compiler_entry["operating_system"],
|
|
target=None,
|
|
paths=[
|
|
default_compiler_entry["paths"]["cc"],
|
|
default_compiler_entry["paths"]["cxx"],
|
|
default_compiler_entry["paths"]["fc"],
|
|
default_compiler_entry["paths"]["f77"],
|
|
],
|
|
environment={},
|
|
)
|
|
|
|
@property
|
|
def name(self):
|
|
return "mockcompiler"
|
|
|
|
@property
|
|
def version(self):
|
|
return "1.0.0"
|
|
|
|
_verbose_flag = "--verbose"
|
|
|
|
@property
|
|
def verbose_flag(self):
|
|
return self._verbose_flag
|
|
|
|
required_libs = ["libgfortran"]
|
|
|
|
|
|
@pytest.mark.not_on_windows("Not supported on Windows (yet)")
|
|
def test_implicit_rpaths(dirs_with_libfiles, monkeypatch):
|
|
lib_to_dirs, all_dirs = dirs_with_libfiles
|
|
monkeypatch.setattr(
|
|
MockCompiler,
|
|
"_compile_dummy_c_source",
|
|
lambda self: "ld " + " ".join(f"-L{d}" for d in all_dirs),
|
|
)
|
|
retrieved_rpaths = MockCompiler().implicit_rpaths()
|
|
assert set(retrieved_rpaths) == set(lib_to_dirs["libstdc++"] + lib_to_dirs["libgfortran"])
|
|
|
|
|
|
without_flag_output = "ld -L/path/to/first/lib -L/path/to/second/lib64"
|
|
with_flag_output = "ld -L/path/to/first/with/flag/lib -L/path/to/second/lib64"
|
|
|
|
|
|
def call_compiler(exe, *args, **kwargs):
|
|
# This method can replace Executable.__call__ to emulate a compiler that
|
|
# changes libraries depending on a flag.
|
|
if "--correct-flag" in exe.exe:
|
|
return with_flag_output
|
|
return without_flag_output
|
|
|
|
|
|
@pytest.mark.not_on_windows("Not supported on Windows (yet)")
|
|
@pytest.mark.parametrize(
|
|
"exe,flagname",
|
|
[
|
|
("cxx", "cxxflags"),
|
|
("cxx", "cppflags"),
|
|
("cxx", "ldflags"),
|
|
("cc", "cflags"),
|
|
("cc", "cppflags"),
|
|
],
|
|
)
|
|
@pytest.mark.enable_compiler_execution
|
|
def test_compile_dummy_c_source_adds_flags(monkeypatch, exe, flagname):
|
|
# create fake compiler that emits mock verbose output
|
|
compiler = MockCompiler()
|
|
monkeypatch.setattr(Executable, "__call__", call_compiler)
|
|
|
|
if exe == "cxx":
|
|
compiler.cc = None
|
|
compiler.fc = None
|
|
compiler.f77 = None
|
|
elif exe == "cc":
|
|
compiler.cxx = None
|
|
compiler.fc = None
|
|
compiler.f77 = None
|
|
else:
|
|
assert False
|
|
|
|
# Test without flags
|
|
assert compiler._compile_dummy_c_source() == without_flag_output
|
|
|
|
if flagname:
|
|
# set flags and test
|
|
compiler.flags = {flagname: ["--correct-flag"]}
|
|
assert compiler._compile_dummy_c_source() == with_flag_output
|
|
|
|
|
|
@pytest.mark.enable_compiler_execution
|
|
def test_compile_dummy_c_source_no_path():
|
|
compiler = MockCompiler()
|
|
compiler.cc = None
|
|
compiler.cxx = None
|
|
assert compiler._compile_dummy_c_source() is None
|
|
|
|
|
|
@pytest.mark.enable_compiler_execution
|
|
def test_compile_dummy_c_source_no_verbose_flag():
|
|
compiler = MockCompiler()
|
|
compiler._verbose_flag = None
|
|
assert compiler._compile_dummy_c_source() is None
|
|
|
|
|
|
@pytest.mark.not_on_windows("Not supported on Windows (yet)")
|
|
@pytest.mark.enable_compiler_execution
|
|
def test_compile_dummy_c_source_load_env(working_env, monkeypatch, tmpdir):
|
|
gcc = str(tmpdir.join("gcc"))
|
|
with open(gcc, "w") as f:
|
|
f.write(
|
|
f"""#!/bin/sh
|
|
if [ "$ENV_SET" = "1" ] && [ "$MODULE_LOADED" = "1" ]; then
|
|
printf '{without_flag_output}'
|
|
fi
|
|
"""
|
|
)
|
|
fs.set_executable(gcc)
|
|
|
|
# Set module load to turn compiler on
|
|
def module(*args):
|
|
if args[0] == "show":
|
|
return ""
|
|
elif args[0] == "load":
|
|
os.environ["MODULE_LOADED"] = "1"
|
|
|
|
monkeypatch.setattr(spack.util.module_cmd, "module", module)
|
|
|
|
compiler = MockCompiler()
|
|
compiler.cc = gcc
|
|
compiler.environment = {"set": {"ENV_SET": "1"}}
|
|
compiler.modules = ["turn_on"]
|
|
|
|
assert compiler._compile_dummy_c_source() == without_flag_output
|
|
|
|
|
|
# Get the desired flag from the specified compiler spec.
|
|
def flag_value(flag, spec):
|
|
compiler = None
|
|
if spec is None:
|
|
compiler = MockCompiler()
|
|
else:
|
|
compiler_entry = copy(default_compiler_entry)
|
|
compiler_entry["spec"] = spec
|
|
compiler = spack.compilers.compiler_from_dict(compiler_entry)
|
|
|
|
return getattr(compiler, flag)
|
|
|
|
|
|
# Utility function to verify that the expected exception is thrown for
|
|
# an unsupported flag.
|
|
def unsupported_flag_test(flag, spec=None):
|
|
caught_exception = None
|
|
try:
|
|
flag_value(flag, spec)
|
|
except spack.compiler.UnsupportedCompilerFlag:
|
|
caught_exception = True
|
|
|
|
assert caught_exception and "Expected exception not thrown."
|
|
|
|
|
|
# Verify the expected flag value for the give compiler spec.
|
|
def supported_flag_test(flag, flag_value_ref, spec=None):
|
|
assert flag_value(flag, spec) == flag_value_ref
|
|
|
|
|
|
# Tests for UnsupportedCompilerFlag exceptions from default
|
|
# implementations of flags.
|
|
def test_default_flags():
|
|
supported_flag_test("cc_rpath_arg", "-Wl,-rpath,")
|
|
supported_flag_test("cxx_rpath_arg", "-Wl,-rpath,")
|
|
supported_flag_test("f77_rpath_arg", "-Wl,-rpath,")
|
|
supported_flag_test("fc_rpath_arg", "-Wl,-rpath,")
|
|
supported_flag_test("linker_arg", "-Wl,")
|
|
unsupported_flag_test("openmp_flag")
|
|
unsupported_flag_test("cxx11_flag")
|
|
unsupported_flag_test("cxx14_flag")
|
|
unsupported_flag_test("cxx17_flag")
|
|
supported_flag_test("cxx98_flag", "")
|
|
unsupported_flag_test("c99_flag")
|
|
unsupported_flag_test("c11_flag")
|
|
supported_flag_test("cc_pic_flag", "-fPIC")
|
|
supported_flag_test("cxx_pic_flag", "-fPIC")
|
|
supported_flag_test("f77_pic_flag", "-fPIC")
|
|
supported_flag_test("fc_pic_flag", "-fPIC")
|
|
supported_flag_test("debug_flags", ["-g"])
|
|
supported_flag_test("opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3"])
|
|
|
|
|
|
# Verify behavior of particular compiler definitions.
|
|
def test_arm_flags():
|
|
supported_flag_test("openmp_flag", "-fopenmp", "arm@1.0")
|
|
supported_flag_test("cxx11_flag", "-std=c++11", "arm@1.0")
|
|
supported_flag_test("cxx14_flag", "-std=c++14", "arm@1.0")
|
|
supported_flag_test("cxx17_flag", "-std=c++1z", "arm@1.0")
|
|
supported_flag_test("c99_flag", "-std=c99", "arm@1.0")
|
|
supported_flag_test("c11_flag", "-std=c11", "arm@1.0")
|
|
supported_flag_test("cc_pic_flag", "-fPIC", "arm@1.0")
|
|
supported_flag_test("cxx_pic_flag", "-fPIC", "arm@1.0")
|
|
supported_flag_test("f77_pic_flag", "-fPIC", "arm@1.0")
|
|
supported_flag_test("fc_pic_flag", "-fPIC", "arm@1.0")
|
|
supported_flag_test("opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast"], "arm@1.0")
|
|
|
|
|
|
def test_cce_flags():
|
|
supported_flag_test("version_argument", "--version", "cce@9.0.1")
|
|
supported_flag_test("version_argument", "-V", "cce@9.0.1-classic")
|
|
supported_flag_test("openmp_flag", "-fopenmp", "cce@9.0.1")
|
|
supported_flag_test("openmp_flag", "-h omp", "cce@9.0.1-classic")
|
|
supported_flag_test("openmp_flag", "-h omp", "cce@1.0")
|
|
supported_flag_test("cxx11_flag", "-std=c++11", "cce@9.0.1")
|
|
supported_flag_test("cxx11_flag", "-h std=c++11", "cce@9.0.1-classic")
|
|
supported_flag_test("cxx11_flag", "-h std=c++11", "cce@1.0")
|
|
unsupported_flag_test("c99_flag", "cce@8.0")
|
|
supported_flag_test("c99_flag", "-std=c99", "cce@9.0.1")
|
|
supported_flag_test("c99_flag", "-h c99,noconform,gnu", "cce@8.1")
|
|
supported_flag_test("c99_flag", "-h std=c99,noconform,gnu", "cce@8.4")
|
|
unsupported_flag_test("c11_flag", "cce@8.4")
|
|
supported_flag_test("c11_flag", "-std=c11", "cce@9.0.1")
|
|
supported_flag_test("c11_flag", "-h std=c11,noconform,gnu", "cce@8.5")
|
|
supported_flag_test("cc_pic_flag", "-h PIC", "cce@1.0")
|
|
supported_flag_test("cxx_pic_flag", "-h PIC", "cce@1.0")
|
|
supported_flag_test("f77_pic_flag", "-h PIC", "cce@1.0")
|
|
supported_flag_test("fc_pic_flag", "-h PIC", "cce@1.0")
|
|
supported_flag_test("cc_pic_flag", "-fPIC", "cce@9.1.0")
|
|
supported_flag_test("cxx_pic_flag", "-fPIC", "cce@9.1.0")
|
|
supported_flag_test("f77_pic_flag", "-fPIC", "cce@9.1.0")
|
|
supported_flag_test("fc_pic_flag", "-fPIC", "cce@9.1.0")
|
|
supported_flag_test("stdcxx_libs", (), "cce@1.0")
|
|
supported_flag_test("debug_flags", ["-g", "-G0", "-G1", "-G2", "-Gfast"], "cce@1.0")
|
|
|
|
|
|
def test_apple_clang_flags():
|
|
supported_flag_test("openmp_flag", "-Xpreprocessor -fopenmp", "apple-clang@2.0.0")
|
|
unsupported_flag_test("cxx11_flag", "apple-clang@2.0.0")
|
|
supported_flag_test("cxx11_flag", "-std=c++11", "apple-clang@4.0.0")
|
|
unsupported_flag_test("cxx14_flag", "apple-clang@5.0.0")
|
|
supported_flag_test("cxx14_flag", "-std=c++1y", "apple-clang@5.1.0")
|
|
supported_flag_test("cxx14_flag", "-std=c++14", "apple-clang@6.1.0")
|
|
unsupported_flag_test("cxx17_flag", "apple-clang@6.0.0")
|
|
supported_flag_test("cxx17_flag", "-std=c++1z", "apple-clang@6.1.0")
|
|
supported_flag_test("c99_flag", "-std=c99", "apple-clang@6.1.0")
|
|
unsupported_flag_test("c11_flag", "apple-clang@3.0.0")
|
|
supported_flag_test("c11_flag", "-std=c11", "apple-clang@6.1.0")
|
|
supported_flag_test("cc_pic_flag", "-fPIC", "apple-clang@2.0.0")
|
|
supported_flag_test("cxx_pic_flag", "-fPIC", "apple-clang@2.0.0")
|
|
supported_flag_test("f77_pic_flag", "-fPIC", "apple-clang@2.0.0")
|
|
supported_flag_test("fc_pic_flag", "-fPIC", "apple-clang@2.0.0")
|
|
|
|
|
|
def test_clang_flags():
|
|
supported_flag_test("version_argument", "--version", "clang@foo.bar")
|
|
supported_flag_test("openmp_flag", "-fopenmp", "clang@3.3")
|
|
unsupported_flag_test("cxx11_flag", "clang@3.2")
|
|
supported_flag_test("cxx11_flag", "-std=c++11", "clang@3.3")
|
|
unsupported_flag_test("cxx14_flag", "clang@3.3")
|
|
supported_flag_test("cxx14_flag", "-std=c++1y", "clang@3.4")
|
|
supported_flag_test("cxx14_flag", "-std=c++14", "clang@3.5")
|
|
unsupported_flag_test("cxx17_flag", "clang@3.4")
|
|
supported_flag_test("cxx17_flag", "-std=c++1z", "clang@3.5")
|
|
supported_flag_test("cxx17_flag", "-std=c++17", "clang@5.0")
|
|
unsupported_flag_test("cxx20_flag", "clang@4.0")
|
|
supported_flag_test("cxx20_flag", "-std=c++2a", "clang@5.0")
|
|
supported_flag_test("cxx20_flag", "-std=c++20", "clang@11.0")
|
|
unsupported_flag_test("cxx23_flag", "clang@11.0")
|
|
supported_flag_test("cxx23_flag", "-std=c++2b", "clang@12.0")
|
|
supported_flag_test("cxx23_flag", "-std=c++23", "clang@17.0")
|
|
supported_flag_test("c99_flag", "-std=c99", "clang@3.3")
|
|
unsupported_flag_test("c11_flag", "clang@2.0")
|
|
supported_flag_test("c11_flag", "-std=c11", "clang@6.1.0")
|
|
unsupported_flag_test("c23_flag", "clang@8.0")
|
|
supported_flag_test("c23_flag", "-std=c2x", "clang@9.0")
|
|
supported_flag_test("c23_flag", "-std=c23", "clang@18.0")
|
|
supported_flag_test("cc_pic_flag", "-fPIC", "clang@3.3")
|
|
supported_flag_test("cxx_pic_flag", "-fPIC", "clang@3.3")
|
|
supported_flag_test("f77_pic_flag", "-fPIC", "clang@3.3")
|
|
supported_flag_test("fc_pic_flag", "-fPIC", "clang@3.3")
|
|
supported_flag_test(
|
|
"debug_flags",
|
|
[
|
|
"-gcodeview",
|
|
"-gdwarf-2",
|
|
"-gdwarf-3",
|
|
"-gdwarf-4",
|
|
"-gdwarf-5",
|
|
"-gline-tables-only",
|
|
"-gmodules",
|
|
"-g",
|
|
],
|
|
"clang@3.3",
|
|
)
|
|
supported_flag_test(
|
|
"opt_flags",
|
|
["-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os", "-Oz", "-Og", "-O", "-O4"],
|
|
"clang@3.3",
|
|
)
|
|
|
|
|
|
def test_aocc_flags():
|
|
supported_flag_test(
|
|
"debug_flags",
|
|
[
|
|
"-gcodeview",
|
|
"-gdwarf-2",
|
|
"-gdwarf-3",
|
|
"-gdwarf-4",
|
|
"-gdwarf-5",
|
|
"-gline-tables-only",
|
|
"-gmodules",
|
|
"-g",
|
|
],
|
|
"aocc@2.2.0",
|
|
)
|
|
supported_flag_test(
|
|
"opt_flags",
|
|
["-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os", "-Oz", "-Og", "-O", "-O4"],
|
|
"aocc@2.2.0",
|
|
)
|
|
|
|
supported_flag_test("stdcxx_libs", ("-lstdc++",), "aocc@2.2.0")
|
|
supported_flag_test("openmp_flag", "-fopenmp", "aocc@2.2.0")
|
|
supported_flag_test("cxx11_flag", "-std=c++11", "aocc@2.2.0")
|
|
supported_flag_test("cxx14_flag", "-std=c++14", "aocc@2.2.0")
|
|
supported_flag_test("cxx17_flag", "-std=c++17", "aocc@2.2.0")
|
|
supported_flag_test("c99_flag", "-std=c99", "aocc@2.2.0")
|
|
supported_flag_test("c11_flag", "-std=c11", "aocc@2.2.0")
|
|
supported_flag_test("cc_pic_flag", "-fPIC", "aocc@2.2.0")
|
|
supported_flag_test("cxx_pic_flag", "-fPIC", "aocc@2.2.0")
|
|
supported_flag_test("f77_pic_flag", "-fPIC", "aocc@2.2.0")
|
|
supported_flag_test("fc_pic_flag", "-fPIC", "aocc@2.2.0")
|
|
supported_flag_test("version_argument", "--version", "aocc@2.2.0")
|
|
flg = "-Wno-unused-command-line-argument -mllvm -eliminate-similar-expr=false"
|
|
supported_flag_test("cflags", flg, "aocc@3.0.0")
|
|
supported_flag_test("cxxflags", flg, "aocc@3.0.0")
|
|
supported_flag_test("fflags", flg, "aocc@3.0.0")
|
|
|
|
|
|
def test_fj_flags():
|
|
supported_flag_test("openmp_flag", "-Kopenmp", "fj@4.0.0")
|
|
supported_flag_test("cxx98_flag", "-std=c++98", "fj@4.0.0")
|
|
supported_flag_test("cxx11_flag", "-std=c++11", "fj@4.0.0")
|
|
supported_flag_test("cxx14_flag", "-std=c++14", "fj@4.0.0")
|
|
supported_flag_test("cxx17_flag", "-std=c++17", "fj@4.0.0")
|
|
supported_flag_test("c99_flag", "-std=c99", "fj@4.0.0")
|
|
supported_flag_test("c11_flag", "-std=c11", "fj@4.0.0")
|
|
supported_flag_test("cc_pic_flag", "-KPIC", "fj@4.0.0")
|
|
supported_flag_test("cxx_pic_flag", "-KPIC", "fj@4.0.0")
|
|
supported_flag_test("f77_pic_flag", "-KPIC", "fj@4.0.0")
|
|
supported_flag_test("fc_pic_flag", "-KPIC", "fj@4.0.0")
|
|
supported_flag_test("opt_flags", ["-O0", "-O1", "-O2", "-O3", "-Ofast"], "fj@4.0.0")
|
|
supported_flag_test("debug_flags", "-g", "fj@4.0.0")
|
|
|
|
|
|
def test_gcc_flags():
|
|
supported_flag_test("openmp_flag", "-fopenmp", "gcc@4.1")
|
|
supported_flag_test("cxx98_flag", "", "gcc@5.2")
|
|
supported_flag_test("cxx98_flag", "-std=c++98", "gcc@6.0")
|
|
unsupported_flag_test("cxx11_flag", "gcc@4.2")
|
|
supported_flag_test("cxx11_flag", "-std=c++0x", "gcc@4.3")
|
|
supported_flag_test("cxx11_flag", "-std=c++11", "gcc@4.7")
|
|
unsupported_flag_test("cxx14_flag", "gcc@4.7")
|
|
supported_flag_test("cxx14_flag", "-std=c++1y", "gcc@4.8")
|
|
supported_flag_test("cxx14_flag", "-std=c++14", "gcc@4.9")
|
|
supported_flag_test("cxx14_flag", "-std=c++14", "gcc@6.0")
|
|
unsupported_flag_test("cxx17_flag", "gcc@4.9")
|
|
supported_flag_test("cxx17_flag", "-std=c++1z", "gcc@5.0")
|
|
supported_flag_test("cxx17_flag", "-std=c++17", "gcc@6.0")
|
|
unsupported_flag_test("c99_flag", "gcc@4.4")
|
|
supported_flag_test("c99_flag", "-std=c99", "gcc@4.5")
|
|
unsupported_flag_test("c11_flag", "gcc@4.6")
|
|
supported_flag_test("c11_flag", "-std=c11", "gcc@4.7")
|
|
supported_flag_test("cc_pic_flag", "-fPIC", "gcc@4.0")
|
|
supported_flag_test("cxx_pic_flag", "-fPIC", "gcc@4.0")
|
|
supported_flag_test("f77_pic_flag", "-fPIC", "gcc@4.0")
|
|
supported_flag_test("fc_pic_flag", "-fPIC", "gcc@4.0")
|
|
supported_flag_test("stdcxx_libs", ("-lstdc++",), "gcc@4.1")
|
|
supported_flag_test(
|
|
"debug_flags", ["-g", "-gstabs+", "-gstabs", "-gxcoff+", "-gxcoff", "-gvms"], "gcc@4.0"
|
|
)
|
|
supported_flag_test(
|
|
"opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-Os", "-Ofast", "-Og"], "gcc@4.0"
|
|
)
|
|
|
|
|
|
def test_intel_flags():
|
|
supported_flag_test("openmp_flag", "-openmp", "intel@=15.0")
|
|
supported_flag_test("openmp_flag", "-qopenmp", "intel@=16.0")
|
|
unsupported_flag_test("cxx11_flag", "intel@=11.0")
|
|
supported_flag_test("cxx11_flag", "-std=c++0x", "intel@=12.0")
|
|
supported_flag_test("cxx11_flag", "-std=c++11", "intel@=13")
|
|
unsupported_flag_test("cxx14_flag", "intel@=14.0")
|
|
supported_flag_test("cxx14_flag", "-std=c++1y", "intel@=15.0")
|
|
supported_flag_test("cxx14_flag", "-std=c++14", "intel@=15.0.2")
|
|
unsupported_flag_test("cxx17_flag", "intel@=18")
|
|
supported_flag_test("cxx17_flag", "-std=c++17", "intel@=19.0")
|
|
unsupported_flag_test("c99_flag", "intel@=11.0")
|
|
supported_flag_test("c99_flag", "-std=c99", "intel@=12.0")
|
|
unsupported_flag_test("c11_flag", "intel@=15.0")
|
|
supported_flag_test("c18_flag", "-std=c18", "intel@=21.5.0")
|
|
unsupported_flag_test("c18_flag", "intel@=21.4.0")
|
|
supported_flag_test("c11_flag", "-std=c1x", "intel@=16.0")
|
|
supported_flag_test("cc_pic_flag", "-fPIC", "intel@=1.0")
|
|
supported_flag_test("cxx_pic_flag", "-fPIC", "intel@=1.0")
|
|
supported_flag_test("f77_pic_flag", "-fPIC", "intel@=1.0")
|
|
supported_flag_test("fc_pic_flag", "-fPIC", "intel@=1.0")
|
|
supported_flag_test("stdcxx_libs", ("-cxxlib",), "intel@=1.0")
|
|
supported_flag_test("debug_flags", ["-debug", "-g", "-g0", "-g1", "-g2", "-g3"], "intel@=1.0")
|
|
supported_flag_test(
|
|
"opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os"], "intel@=1.0"
|
|
)
|
|
|
|
|
|
def test_oneapi_flags():
|
|
supported_flag_test("openmp_flag", "-fiopenmp", "oneapi@=2020.8.0.0827")
|
|
supported_flag_test("cxx11_flag", "-std=c++11", "oneapi@=2020.8.0.0827")
|
|
supported_flag_test("cxx14_flag", "-std=c++14", "oneapi@=2020.8.0.0827")
|
|
supported_flag_test("c99_flag", "-std=c99", "oneapi@=2020.8.0.0827")
|
|
supported_flag_test("c11_flag", "-std=c1x", "oneapi@=2020.8.0.0827")
|
|
supported_flag_test("cc_pic_flag", "-fPIC", "oneapi@=2020.8.0.0827")
|
|
supported_flag_test("cxx_pic_flag", "-fPIC", "oneapi@=2020.8.0.0827")
|
|
supported_flag_test("f77_pic_flag", "-fPIC", "oneapi@=2020.8.0.0827")
|
|
supported_flag_test("fc_pic_flag", "-fPIC", "oneapi@=2020.8.0.0827")
|
|
supported_flag_test("stdcxx_libs", ("-cxxlib",), "oneapi@=2020.8.0.0827")
|
|
supported_flag_test(
|
|
"debug_flags", ["-debug", "-g", "-g0", "-g1", "-g2", "-g3"], "oneapi@=2020.8.0.0827"
|
|
)
|
|
supported_flag_test(
|
|
"opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os"], "oneapi@=2020.8.0.0827"
|
|
)
|
|
|
|
|
|
def test_nag_flags():
|
|
supported_flag_test("openmp_flag", "-openmp", "nag@=1.0")
|
|
supported_flag_test("cxx11_flag", "-std=c++11", "nag@=1.0")
|
|
supported_flag_test("cc_pic_flag", "-fPIC", "nag@=1.0")
|
|
supported_flag_test("cxx_pic_flag", "-fPIC", "nag@=1.0")
|
|
supported_flag_test("f77_pic_flag", "-PIC", "nag@=1.0")
|
|
supported_flag_test("fc_pic_flag", "-PIC", "nag@=1.0")
|
|
supported_flag_test("cc_rpath_arg", "-Wl,-rpath,", "nag@=1.0")
|
|
supported_flag_test("cxx_rpath_arg", "-Wl,-rpath,", "nag@=1.0")
|
|
supported_flag_test("f77_rpath_arg", "-Wl,-Wl,,-rpath,,", "nag@=1.0")
|
|
supported_flag_test("fc_rpath_arg", "-Wl,-Wl,,-rpath,,", "nag@=1.0")
|
|
supported_flag_test("linker_arg", "-Wl,-Wl,,", "nag@=1.0")
|
|
supported_flag_test("debug_flags", ["-g", "-gline", "-g90"], "nag@=1.0")
|
|
supported_flag_test("opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-O4"], "nag@=1.0")
|
|
|
|
|
|
def test_nvhpc_flags():
|
|
supported_flag_test("openmp_flag", "-mp", "nvhpc@=20.9")
|
|
supported_flag_test("cxx11_flag", "--c++11", "nvhpc@=20.9")
|
|
supported_flag_test("cxx14_flag", "--c++14", "nvhpc@=20.9")
|
|
supported_flag_test("cxx17_flag", "--c++17", "nvhpc@=20.9")
|
|
supported_flag_test("c99_flag", "-c99", "nvhpc@=20.9")
|
|
supported_flag_test("c11_flag", "-c11", "nvhpc@=20.9")
|
|
supported_flag_test("cc_pic_flag", "-fpic", "nvhpc@=20.9")
|
|
supported_flag_test("cxx_pic_flag", "-fpic", "nvhpc@=20.9")
|
|
supported_flag_test("f77_pic_flag", "-fpic", "nvhpc@=20.9")
|
|
supported_flag_test("fc_pic_flag", "-fpic", "nvhpc@=20.9")
|
|
supported_flag_test("debug_flags", ["-g", "-gopt"], "nvhpc@=20.9")
|
|
supported_flag_test("opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-O4"], "nvhpc@=20.9")
|
|
supported_flag_test("stdcxx_libs", ("-c++libs",), "nvhpc@=20.9")
|
|
|
|
|
|
def test_xl_flags():
|
|
supported_flag_test("openmp_flag", "-qsmp=omp", "xl@=1.0")
|
|
unsupported_flag_test("cxx11_flag", "xl@=13.0")
|
|
supported_flag_test("cxx11_flag", "-qlanglvl=extended0x", "xl@=13.1")
|
|
unsupported_flag_test("c99_flag", "xl@=10.0")
|
|
supported_flag_test("c99_flag", "-qlanglvl=extc99", "xl@=10.1")
|
|
supported_flag_test("c99_flag", "-std=gnu99", "xl@=13.1.1")
|
|
unsupported_flag_test("c11_flag", "xl@=12.0")
|
|
supported_flag_test("c11_flag", "-qlanglvl=extc1x", "xl@=12.1")
|
|
supported_flag_test("c11_flag", "-std=gnu11", "xl@=13.1.2")
|
|
supported_flag_test("cc_pic_flag", "-qpic", "xl@=1.0")
|
|
supported_flag_test("cxx_pic_flag", "-qpic", "xl@=1.0")
|
|
supported_flag_test("f77_pic_flag", "-qpic", "xl@=1.0")
|
|
supported_flag_test("fc_pic_flag", "-qpic", "xl@=1.0")
|
|
supported_flag_test("fflags", "-qzerosize", "xl@=1.0")
|
|
supported_flag_test("debug_flags", ["-g", "-g0", "-g1", "-g2", "-g8", "-g9"], "xl@=1.0")
|
|
supported_flag_test(
|
|
"opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-O4", "-O5", "-Ofast"], "xl@=1.0"
|
|
)
|
|
|
|
|
|
def test_xl_r_flags():
|
|
supported_flag_test("openmp_flag", "-qsmp=omp", "xl_r@=1.0")
|
|
unsupported_flag_test("cxx11_flag", "xl_r@=13.0")
|
|
supported_flag_test("cxx11_flag", "-qlanglvl=extended0x", "xl_r@=13.1")
|
|
unsupported_flag_test("c99_flag", "xl_r@=10.0")
|
|
supported_flag_test("c99_flag", "-qlanglvl=extc99", "xl_r@=10.1")
|
|
supported_flag_test("c99_flag", "-std=gnu99", "xl_r@=13.1.1")
|
|
unsupported_flag_test("c11_flag", "xl_r@=12.0")
|
|
supported_flag_test("c11_flag", "-qlanglvl=extc1x", "xl_r@=12.1")
|
|
supported_flag_test("c11_flag", "-std=gnu11", "xl_r@=13.1.2")
|
|
supported_flag_test("cc_pic_flag", "-qpic", "xl_r@=1.0")
|
|
supported_flag_test("cxx_pic_flag", "-qpic", "xl_r@=1.0")
|
|
supported_flag_test("f77_pic_flag", "-qpic", "xl_r@=1.0")
|
|
supported_flag_test("fc_pic_flag", "-qpic", "xl_r@=1.0")
|
|
supported_flag_test("fflags", "-qzerosize", "xl_r@=1.0")
|
|
supported_flag_test("debug_flags", ["-g", "-g0", "-g1", "-g2", "-g8", "-g9"], "xl@=1.0")
|
|
supported_flag_test(
|
|
"opt_flags", ["-O", "-O0", "-O1", "-O2", "-O3", "-O4", "-O5", "-Ofast"], "xl@=1.0"
|
|
)
|
|
|
|
|
|
# FIXME (compiler as nodes): revisit this test
|
|
# @pytest.mark.regression("14798,13733")
|
|
# def test_raising_if_compiler_target_is_over_specific(config):
|
|
# # Compiler entry with an overly specific target
|
|
# compilers = [
|
|
# {
|
|
# "compiler": {
|
|
# "spec": "gcc@9.0.1",
|
|
# "paths": {
|
|
# "cc": "/usr/bin/gcc-9",
|
|
# "cxx": "/usr/bin/g++-9",
|
|
# "f77": "/usr/bin/gfortran-9",
|
|
# "fc": "/usr/bin/gfortran-9",
|
|
# },
|
|
# "flags": {},
|
|
# "operating_system": "ubuntu18.04",
|
|
# "target": "haswell",
|
|
# "modules": [],
|
|
# "environment": {},
|
|
# "extra_rpaths": [],
|
|
# }
|
|
# }
|
|
# ]
|
|
# arch_spec = spack.spec.ArchSpec(("linux", "ubuntu18.04", "haswell"))
|
|
# with spack.config.override("compilers", compilers):
|
|
# cfg = spack.compilers.get_compiler_config(config)
|
|
# with pytest.raises(ValueError):
|
|
# spack.compilers.get_compilers(cfg, spack.spec.CompilerSpec("gcc@9.0.1"), arch_spec)
|
|
|
|
# FIXME (compiler as nodes): revisit this test
|
|
# @pytest.mark.regression("42679")
|
|
# def test_get_compilers(config):
|
|
# """Tests that we can select compilers whose versions differ only for a suffix."""
|
|
# common = {
|
|
# "flags": {},
|
|
# "operating_system": "ubuntu23.10",
|
|
# "target": "x86_64",
|
|
# "modules": [],
|
|
# "environment": {},
|
|
# "extra_rpaths": [],
|
|
# }
|
|
# with_suffix = {
|
|
# "spec": "gcc@13.2.0-suffix",
|
|
# "paths": {
|
|
# "cc": "/usr/bin/gcc-13.2.0-suffix",
|
|
# "cxx": "/usr/bin/g++-13.2.0-suffix",
|
|
# "f77": "/usr/bin/gfortran-13.2.0-suffix",
|
|
# "fc": "/usr/bin/gfortran-13.2.0-suffix",
|
|
# },
|
|
# **common,
|
|
# }
|
|
# without_suffix = {
|
|
# "spec": "gcc@13.2.0",
|
|
# "paths": {
|
|
# "cc": "/usr/bin/gcc-13.2.0",
|
|
# "cxx": "/usr/bin/g++-13.2.0",
|
|
# "f77": "/usr/bin/gfortran-13.2.0",
|
|
# "fc": "/usr/bin/gfortran-13.2.0",
|
|
# },
|
|
# **common,
|
|
# }
|
|
#
|
|
# compilers = [{"compiler": without_suffix}, {"compiler": with_suffix}]
|
|
#
|
|
# assert spack.compilers.get_compilers(
|
|
# compilers, cspec=spack.spec.CompilerSpec("gcc@=13.2.0-suffix")
|
|
# ) == [spack.compilers._compiler_from_config_entry(with_suffix)]
|
|
#
|
|
# assert spack.compilers.get_compilers(
|
|
# compilers, cspec=spack.spec.CompilerSpec("gcc@=13.2.0")
|
|
# ) == [spack.compilers._compiler_from_config_entry(without_suffix)]
|
|
|
|
|
|
@pytest.mark.enable_compiler_verification
|
|
def test_compiler_executable_verification_raises(tmpdir):
|
|
compiler = MockCompiler()
|
|
compiler.cc = "/this/path/does/not/exist"
|
|
|
|
with pytest.raises(spack.compiler.CompilerAccessError):
|
|
compiler.verify_executables()
|
|
|
|
|
|
@pytest.mark.enable_compiler_verification
|
|
def test_compiler_executable_verification_success(tmpdir):
|
|
def prepare_executable(name):
|
|
real = str(tmpdir.join("cc").ensure())
|
|
fs.set_executable(real)
|
|
setattr(compiler, name, real)
|
|
|
|
# setup mock compiler with real paths
|
|
compiler = MockCompiler()
|
|
for name in ("cc", "cxx", "f77", "fc"):
|
|
prepare_executable(name)
|
|
|
|
# testing that this doesn't raise an error because the paths exist and
|
|
# are executable
|
|
compiler.verify_executables()
|
|
|
|
# Test that null entries don't fail
|
|
compiler.cc = None
|
|
compiler.verify_executables()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"compilers_extra_attributes,expected_length",
|
|
[
|
|
# If we detect a C compiler we expect the result to be valid
|
|
({"c": "/usr/bin/clang-12", "cxx": "/usr/bin/clang-12"}, 1),
|
|
# If we detect only a C++ compiler we expect the result to be discarded
|
|
({"cxx": "/usr/bin/clang-12"}, 0),
|
|
],
|
|
)
|
|
def test_detection_requires_c_compiler(compilers_extra_attributes, expected_length):
|
|
"""Tests that compilers automatically added to the configuration have
|
|
at least a C compiler.
|
|
"""
|
|
packages_yaml = {
|
|
"llvm": {
|
|
"externals": [
|
|
{
|
|
"spec": "clang@12.0.0",
|
|
"prefix": "/usr",
|
|
"extra_attributes": {"compilers": compilers_extra_attributes},
|
|
}
|
|
]
|
|
}
|
|
}
|
|
result = spack.compilers.CompilerFactory.from_packages_yaml(packages_yaml)
|
|
assert len(result) == expected_length
|
|
|
|
|
|
def test_compiler_environment(working_env):
|
|
"""Test whether environment modifications from compilers are applied in compiler_environment"""
|
|
os.environ.pop("TEST", None)
|
|
compiler = Compiler(
|
|
"gcc@=13.2.0",
|
|
operating_system="ubuntu20.04",
|
|
target="x86_64",
|
|
paths=["/test/bin/gcc", "/test/bin/g++"],
|
|
environment={"set": {"TEST": "yes"}},
|
|
)
|
|
with compiler.compiler_environment():
|
|
assert os.environ["TEST"] == "yes"
|
|
|
|
|
|
class MockCompilerWithoutExecutables(MockCompiler):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._compile_dummy_c_source_count = 0
|
|
self._get_real_version_count = 0
|
|
|
|
def _compile_dummy_c_source(self) -> Optional[str]:
|
|
self._compile_dummy_c_source_count += 1
|
|
return "gcc helloworld.c -o helloworld"
|
|
|
|
def get_real_version(self) -> str:
|
|
self._get_real_version_count += 1
|
|
return "1.0.0"
|
|
|
|
|
|
def test_compiler_output_caching(tmp_path):
|
|
"""Test that compiler output is cached on the filesystem."""
|
|
# The first call should trigger the cache to updated.
|
|
a = MockCompilerWithoutExecutables()
|
|
cache = spack.compiler.FileCompilerCache(FileCache(str(tmp_path)))
|
|
assert cache.get(a).c_compiler_output == "gcc helloworld.c -o helloworld"
|
|
assert cache.get(a).real_version == "1.0.0"
|
|
assert a._compile_dummy_c_source_count == 1
|
|
assert a._get_real_version_count == 1
|
|
|
|
# The second call on an equivalent but distinct object should not trigger compiler calls.
|
|
b = MockCompilerWithoutExecutables()
|
|
cache = spack.compiler.FileCompilerCache(FileCache(str(tmp_path)))
|
|
assert cache.get(b).c_compiler_output == "gcc helloworld.c -o helloworld"
|
|
assert cache.get(b).real_version == "1.0.0"
|
|
assert b._compile_dummy_c_source_count == 0
|
|
assert b._get_real_version_count == 0
|
|
|
|
# Cache schema change should be handled gracefully.
|
|
with open(cache.cache.cache_path(cache.name), "w") as f:
|
|
for k in cache._data:
|
|
cache._data[k] = "corrupted entry"
|
|
f.write(json.dumps(cache._data))
|
|
|
|
c = MockCompilerWithoutExecutables()
|
|
cache = spack.compiler.FileCompilerCache(FileCache(str(tmp_path)))
|
|
assert cache.get(c).c_compiler_output == "gcc helloworld.c -o helloworld"
|
|
assert cache.get(c).real_version == "1.0.0"
|
|
|
|
# Cache corruption should be handled gracefully.
|
|
with open(cache.cache.cache_path(cache.name), "w") as f:
|
|
f.write("corrupted cache")
|
|
|
|
d = MockCompilerWithoutExecutables()
|
|
cache = spack.compiler.FileCompilerCache(FileCache(str(tmp_path)))
|
|
assert cache.get(d).c_compiler_output == "gcc helloworld.c -o helloworld"
|
|
assert cache.get(d).real_version == "1.0.0"
|