diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py index 5028886a98..c8aa20e54d 100644 --- a/lib/spack/spack/build_environment.py +++ b/lib/spack/spack/build_environment.py @@ -789,7 +789,7 @@ def setup_package(pkg, dirty, context: Context = Context.BUILD): for mod in ["cray-mpich", "cray-libsci"]: module("unload", mod) - if target.module_name: + if target and target.module_name: load_module(target.module_name) load_external_modules(pkg) diff --git a/lib/spack/spack/compilers/__init__.py b/lib/spack/spack/compilers/__init__.py index 47ae91fffe..b5c4180033 100644 --- a/lib/spack/spack/compilers/__init__.py +++ b/lib/spack/spack/compilers/__init__.py @@ -112,16 +112,16 @@ def _to_dict(compiler): def get_compiler_config(scope=None, init_config=True): """Return the compiler configuration for the specified architecture.""" - config = spack.config.get("compilers", scope=scope) or [] + config = spack.config.CONFIG.get("compilers", scope=scope) or [] if config or not init_config: return config - merged_config = spack.config.get("compilers") + merged_config = spack.config.CONFIG.get("compilers") if merged_config: return config _init_compiler_config(scope=scope) - config = spack.config.get("compilers", scope=scope) + config = spack.config.CONFIG.get("compilers", scope=scope) return config diff --git a/lib/spack/spack/test/architecture.py b/lib/spack/spack/test/architecture.py index 7bea7a1d86..1a67850aaf 100644 --- a/lib/spack/spack/test/architecture.py +++ b/lib/spack/spack/test/architecture.py @@ -8,13 +8,16 @@ import pytest +import archspec.cpu + import llnl.util.filesystem as fs +import spack.compilers import spack.concretize import spack.operating_systems import spack.platforms import spack.target -from spack.spec import ArchSpec, CompilerSpec, Spec +from spack.spec import ArchSpec, Spec @pytest.fixture(scope="module") @@ -121,52 +124,60 @@ def test_arch_spec_container_semantic(item, architecture_str): @pytest.mark.parametrize( "compiler_spec,target_name,expected_flags", [ - # Check compilers with version numbers from a single toolchain + # Homogeneous compilers ("gcc@4.7.2", "ivybridge", "-march=core-avx-i -mtune=core-avx-i"), - # Check mixed toolchains - ("clang@8.0.0", "broadwell", ""), ("clang@3.5", "x86_64", "-march=x86-64 -mtune=generic"), - # Check Apple's Clang compilers ("apple-clang@9.1.0", "x86_64", "-march=x86-64"), + # Mixed toolchain + ("clang@8.0.0", "broadwell", ""), ], ) @pytest.mark.filterwarnings("ignore:microarchitecture specific") -def test_optimization_flags(compiler_spec, target_name, expected_flags, config): +def test_optimization_flags(compiler_spec, target_name, expected_flags, compiler_factory): target = spack.target.Target(target_name) - compiler = spack.compilers.compilers_for_spec(compiler_spec).pop() + compiler_dict = compiler_factory(spec=compiler_spec, operating_system="")["compiler"] + if compiler_spec == "clang@8.0.0": + compiler_dict["paths"] = { + "cc": "/path/to/clang-8", + "cxx": "/path/to/clang++-8", + "f77": "/path/to/gfortran-9", + "fc": "/path/to/gfortran-9", + } + compiler = spack.compilers.compiler_from_dict(compiler_dict) + opt_flags = target.optimization_flags(compiler) assert opt_flags == expected_flags @pytest.mark.parametrize( - "compiler,real_version,target_str,expected_flags", + "compiler_str,real_version,target_str,expected_flags", [ - (CompilerSpec("gcc@=9.2.0"), None, "haswell", "-march=haswell -mtune=haswell"), + ("gcc@=9.2.0", None, "haswell", "-march=haswell -mtune=haswell"), # Check that custom string versions are accepted - ( - CompilerSpec("gcc@=10foo"), - "9.2.0", - "icelake", - "-march=icelake-client -mtune=icelake-client", - ), + ("gcc@=10foo", "9.2.0", "icelake", "-march=icelake-client -mtune=icelake-client"), # Check that we run version detection (4.4.0 doesn't support icelake) - ( - CompilerSpec("gcc@=4.4.0-special"), - "9.2.0", - "icelake", - "-march=icelake-client -mtune=icelake-client", - ), + ("gcc@=4.4.0-special", "9.2.0", "icelake", "-march=icelake-client -mtune=icelake-client"), # Check that the special case for Apple's clang is treated correctly # i.e. it won't try to detect the version again - (CompilerSpec("apple-clang@=9.1.0"), None, "x86_64", "-march=x86-64"), + ("apple-clang@=9.1.0", None, "x86_64", "-march=x86-64"), ], ) def test_optimization_flags_with_custom_versions( - compiler, real_version, target_str, expected_flags, monkeypatch, config + compiler_str, + real_version, + target_str, + expected_flags, + monkeypatch, + mutable_config, + compiler_factory, ): target = spack.target.Target(target_str) + compiler_dict = compiler_factory(spec=compiler_str, operating_system="redhat6") + mutable_config.set("compilers", [compiler_dict]) if real_version: monkeypatch.setattr(spack.compiler.Compiler, "get_real_version", lambda x: real_version) + compiler = spack.compilers.compiler_from_dict(compiler_dict["compiler"]) + opt_flags = target.optimization_flags(compiler) assert opt_flags == expected_flags @@ -201,9 +212,10 @@ def test_satisfy_strict_constraint_when_not_concrete(architecture_tuple, constra ) @pytest.mark.usefixtures("mock_packages", "config") @pytest.mark.only_clingo("Fixing the parser broke this test for the original concretizer.") +@pytest.mark.skipif( + str(archspec.cpu.host().family) != "x86_64", reason="tests are for x86_64 uarch ranges" +) def test_concretize_target_ranges(root_target_range, dep_target_range, result, monkeypatch): - # Monkeypatch so that all concretization is done as if the machine is core2 - monkeypatch.setattr(spack.platforms.test.Test, "default", "core2") spec = Spec(f"a %gcc@10 foobar=bar target={root_target_range} ^b target={dep_target_range}") with spack.concretize.disable_compiler_existence_check(): spec.concretize() diff --git a/lib/spack/spack/test/bindist.py b/lib/spack/spack/test/bindist.py index b4ff265e59..ab44b1ef06 100644 --- a/lib/spack/spack/test/bindist.py +++ b/lib/spack/spack/test/bindist.py @@ -19,6 +19,8 @@ import py import pytest +import archspec.cpu + from llnl.util.filesystem import join_path, visit_directory_tree import spack.binary_distribution as bindist @@ -573,11 +575,20 @@ def test_update_sbang(tmpdir, test_mirror): uninstall_cmd("-y", "/%s" % new_spec.dag_hash()) -def test_install_legacy_buildcache_layout(install_mockery_mutable_config): +@pytest.mark.skipif( + str(archspec.cpu.host().family) != "x86_64", + reason="test data uses gcc 4.5.0 which does not support aarch64", +) +def test_install_legacy_buildcache_layout( + mutable_config, compiler_factory, install_mockery_mutable_config +): """Legacy buildcache layout involved a nested archive structure where the .spack file contained a repeated spec.json and another compressed archive file containing the install tree. This test makes sure we can still read that layout.""" + mutable_config.set( + "compilers", [compiler_factory(spec="gcc@4.5.0", operating_system="debian6")] + ) legacy_layout_dir = os.path.join(test_path, "data", "mirrors", "legacy_layout") mirror_url = "file://{0}".format(legacy_layout_dir) filename = ( diff --git a/lib/spack/spack/test/build_systems.py b/lib/spack/spack/test/build_systems.py index ccb7a08f6c..8342ecc6e8 100644 --- a/lib/spack/spack/test/build_systems.py +++ b/lib/spack/spack/test/build_systems.py @@ -9,6 +9,8 @@ import py.path import pytest +import archspec.cpu + import llnl.util.filesystem as fs import spack.build_systems.autotools @@ -209,6 +211,9 @@ def test_autotools_gnuconfig_replacement_disabled( assert "gnuconfig version of config.guess" not in f.read() @pytest.mark.disable_clean_stage_check + @pytest.mark.skipif( + str(archspec.cpu.host().family) != "x86_64", reason="test data is specific for x86_64" + ) def test_autotools_gnuconfig_replacement_no_gnuconfig(self, mutable_database, monkeypatch): """ Tests whether a useful error message is shown when patch_config_files is diff --git a/lib/spack/spack/test/cmd/compiler.py b/lib/spack/spack/test/cmd/compiler.py index 1cea72d3b2..a826c64866 100644 --- a/lib/spack/spack/test/cmd/compiler.py +++ b/lib/spack/spack/test/cmd/compiler.py @@ -111,10 +111,10 @@ def test_compiler_find_no_apple_gcc(no_compilers_yaml, working_env, mock_executa @pytest.mark.regression("37996") def test_compiler_remove(mutable_config, mock_packages): """Tests that we can remove a compiler from configuration.""" - assert spack.spec.CompilerSpec("gcc@=4.5.0") in spack.compilers.all_compiler_specs() - args = spack.util.pattern.Bunch(all=True, compiler_spec="gcc@4.5.0", add_paths=[], scope=None) + assert spack.spec.CompilerSpec("gcc@=4.8.0") in spack.compilers.all_compiler_specs() + args = spack.util.pattern.Bunch(all=True, compiler_spec="gcc@4.8.0", add_paths=[], scope=None) spack.cmd.compiler.compiler_remove(args) - assert spack.spec.CompilerSpec("gcc@=4.5.0") not in spack.compilers.all_compiler_specs() + assert spack.spec.CompilerSpec("gcc@=4.8.0") not in spack.compilers.all_compiler_specs() @pytest.mark.regression("37996") @@ -123,10 +123,10 @@ def test_removing_compilers_from_multiple_scopes(mutable_config, mock_packages): site_config = spack.config.get("compilers", scope="site") spack.config.set("compilers", site_config, scope="user") - assert spack.spec.CompilerSpec("gcc@=4.5.0") in spack.compilers.all_compiler_specs() - args = spack.util.pattern.Bunch(all=True, compiler_spec="gcc@4.5.0", add_paths=[], scope=None) + assert spack.spec.CompilerSpec("gcc@=4.8.0") in spack.compilers.all_compiler_specs() + args = spack.util.pattern.Bunch(all=True, compiler_spec="gcc@4.8.0", add_paths=[], scope=None) spack.cmd.compiler.compiler_remove(args) - assert spack.spec.CompilerSpec("gcc@=4.5.0") not in spack.compilers.all_compiler_specs() + assert spack.spec.CompilerSpec("gcc@=4.8.0") not in spack.compilers.all_compiler_specs() @pytest.mark.not_on_windows("Cannot execute bash script on Windows") diff --git a/lib/spack/spack/test/compilers/basics.py b/lib/spack/spack/test/compilers/basics.py index 537ebe593a..77fc1e97f0 100644 --- a/lib/spack/spack/test/compilers/basics.py +++ b/lib/spack/spack/test/compilers/basics.py @@ -62,10 +62,16 @@ def test_multiple_conflicting_compiler_definitions(mutable_config): assert cmp.f77 == "f77" -def test_get_compiler_duplicates(config): +def test_get_compiler_duplicates(mutable_config, compiler_factory): # In this case there is only one instance of the specified compiler in # the test configuration (so it is not actually a duplicate), but the # method behaves the same. + cnl_compiler = compiler_factory(spec="gcc@4.5.0", operating_system="CNL") + # CNL compiler has no target attribute, and this is essential to make detection pass + del cnl_compiler["compiler"]["target"] + mutable_config.set( + "compilers", [compiler_factory(spec="gcc@4.5.0", operating_system="SuSE11"), cnl_compiler] + ) cfg_file_to_duplicates = spack.compilers.get_compiler_duplicates( "gcc@4.5.0", spack.spec.ArchSpec("cray-CNL-xeon") ) @@ -75,13 +81,6 @@ def test_get_compiler_duplicates(config): assert len(duplicates) == 1 -def test_all_compilers(config): - all_compilers = spack.compilers.all_compilers() - filtered = [x for x in all_compilers if str(x.spec) == "clang@=3.3"] - filtered = [x for x in filtered if x.operating_system == "SuSE11"] - assert len(filtered) == 1 - - @pytest.mark.parametrize( "input_version,expected_version,expected_error", [(None, None, "Couldn't get version for compiler /usr/bin/gcc"), ("4.9", "4.9", None)], @@ -660,7 +659,25 @@ def test_xl_r_flags(): "compiler_spec,expected_result", [("gcc@4.7.2", False), ("clang@3.3", False), ("clang@8.0.0", True)], ) -def test_detecting_mixed_toolchains(compiler_spec, expected_result, config): +def test_detecting_mixed_toolchains( + compiler_spec, expected_result, mutable_config, compiler_factory +): + mixed_c = compiler_factory(spec="clang@8.0.0", operating_system="debian6") + mixed_c["compiler"]["paths"] = { + "cc": "/path/to/clang-8", + "cxx": "/path/to/clang++-8", + "f77": "/path/to/gfortran-9", + "fc": "/path/to/gfortran-9", + } + mutable_config.set( + "compilers", + [ + compiler_factory(spec="gcc@4.7.2", operating_system="debian6"), + compiler_factory(spec="clang@3.3", operating_system="debian6"), + mixed_c, + ], + ) + compiler = spack.compilers.compilers_for_spec(compiler_spec).pop() assert spack.compilers.is_mixed_toolchain(compiler) is expected_result diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index b8eb43d9a9..810a473cde 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -224,6 +224,20 @@ def change(self, changes=None): yield _changing_pkg +@pytest.fixture() +def clang12_with_flags(compiler_factory): + c = compiler_factory(spec="clang@12.2.0", operating_system="redhat6") + c["compiler"]["flags"] = {"cflags": "-O3", "cxxflags": "-O3"} + return c + + +@pytest.fixture() +def gcc11_with_flags(compiler_factory): + c = compiler_factory(spec="gcc@11.1.0", operating_system="redhat6") + c["compiler"]["flags"] = {"cflags": "-O0 -g", "cxxflags": "-O0 -g", "fflags": "-O0 -g"} + return c + + # This must use the mutable_config fixture because the test # adjusting_default_target_based_on_compiler uses the current_host fixture, # which changes the config. @@ -316,18 +330,35 @@ def test_provides_handles_multiple_providers_of_same_version(self): assert Spec("builtin.mock.multi-provider-mpi@1.10.0") in providers assert Spec("builtin.mock.multi-provider-mpi@1.8.8") in providers - def test_different_compilers_get_different_flags(self): + def test_different_compilers_get_different_flags( + self, mutable_config, clang12_with_flags, gcc11_with_flags + ): + """Tests that nodes get the flags of the associated compiler.""" + mutable_config.set("compilers", [clang12_with_flags, gcc11_with_flags]) client = Spec( "cmake-client %gcc@11.1.0 platform=test os=fe target=fe" - + " ^cmake %clang@12.2.0 platform=test os=fe target=fe" - ) - client.concretize() + " ^cmake %clang@12.2.0 platform=test os=fe target=fe" + ).concretized() cmake = client["cmake"] - assert set(client.compiler_flags["cflags"]) == set(["-O0", "-g"]) - assert set(cmake.compiler_flags["cflags"]) == set(["-O3"]) - assert set(client.compiler_flags["fflags"]) == set(["-O0", "-g"]) + assert set(client.compiler_flags["cflags"]) == {"-O0", "-g"} + assert set(cmake.compiler_flags["cflags"]) == {"-O3"} + assert set(client.compiler_flags["fflags"]) == {"-O0", "-g"} assert not set(cmake.compiler_flags["fflags"]) + @pytest.mark.regression("9908") + def test_spec_flags_maintain_order(self, mutable_config, gcc11_with_flags): + """Tests that Spack assembles flags in a consistent way (i.e. with the same ordering), + for successive concretizations. + """ + mutable_config.set("compilers", [gcc11_with_flags]) + spec_str = "libelf %gcc@11.1.0 os=redhat6" + for _ in range(3): + s = Spec(spec_str).concretized() + assert all( + s.compiler_flags[x] == ["-O0", "-g"] for x in ("cflags", "cxxflags", "fflags") + ) + + @pytest.mark.xfail(reason="Broken, needs to be fixed") def test_compiler_flags_from_compiler_and_dependent(self): client = Spec("cmake-client %clang@12.2.0 platform=test os=fe target=fe cflags==-g") client.concretize() @@ -335,7 +366,8 @@ def test_compiler_flags_from_compiler_and_dependent(self): for spec in [client, cmake]: assert spec.compiler_flags["cflags"] == ["-O3", "-g"] - def test_compiler_flags_differ_identical_compilers(self): + def test_compiler_flags_differ_identical_compilers(self, mutable_config, clang12_with_flags): + mutable_config.set("compilers", [clang12_with_flags]) # Correct arch to use test compiler that has flags spec = Spec("a %clang@12.2.0 platform=test os=fe target=fe") @@ -390,25 +422,20 @@ def test_compiler_inherited_upwards(self): for dep in spec.traverse(): assert "%clang" in dep - def test_architecture_inheritance(self): - """test_architecture_inheritance is likely to fail with an - UnavailableCompilerVersionError if the architecture is concretized - incorrectly. - """ - spec = Spec("cmake-client %gcc@11.1.0 os=fe ^ cmake") - spec.concretize() - assert spec["cmake"].architecture == spec.architecture - @pytest.mark.only_clingo("Fixing the parser broke this test for the original concretizer") - def test_architecture_deep_inheritance(self, mock_targets): + def test_architecture_deep_inheritance(self, mock_targets, compiler_factory): """Make sure that indirect dependencies receive architecture information from the root even when partial architecture information is provided by an intermediate dependency. """ - spec_str = "mpileaks %gcc@4.5.0 os=CNL target=nocona" " ^dyninst os=CNL ^callpath os=CNL" - spec = Spec(spec_str).concretized() - for s in spec.traverse(root=False): - assert s.architecture.target == spec.architecture.target + cnl_compiler = compiler_factory(spec="gcc@4.5.0", operating_system="CNL") + # CNL compiler has no target attribute, and this is essential to make detection pass + del cnl_compiler["compiler"]["target"] + with spack.config.override("compilers", [cnl_compiler]): + spec_str = "mpileaks %gcc@4.5.0 os=CNL target=nocona ^dyninst os=CNL ^callpath os=CNL" + spec = Spec(spec_str).concretized() + for s in spec.traverse(root=False): + assert s.architecture.target == spec.architecture.target def test_compiler_flags_from_user_are_grouped(self): spec = Spec('a%gcc cflags="-O -foo-flag foo-val" platform=test') @@ -843,9 +870,12 @@ def test_concretize_anonymous_dep(self, spec_str): ], ) @pytest.mark.only_clingo("Original concretizer cannot work around conflicts") - def test_compiler_conflicts_in_package_py(self, spec_str, expected_str): - s = Spec(spec_str).concretized() - assert s.satisfies(expected_str) + def test_compiler_conflicts_in_package_py( + self, spec_str, expected_str, clang12_with_flags, gcc11_with_flags + ): + with spack.config.override("compilers", [clang12_with_flags, gcc11_with_flags]): + s = Spec(spec_str).concretized() + assert s.satisfies(expected_str) @pytest.mark.parametrize( "spec_str,expected,unexpected", @@ -1135,16 +1165,18 @@ def test_activating_test_dependencies(self, spec_str, tests_arg, with_dep, witho @pytest.mark.regression("20019") @pytest.mark.only_clingo("Use case not supported by the original concretizer") - def test_compiler_match_is_preferred_to_newer_version(self): + def test_compiler_match_is_preferred_to_newer_version(self, compiler_factory): # This spec depends on openblas. Openblas has a conflict # that doesn't allow newer versions with gcc@4.4.0. Check # that an old version of openblas is selected, rather than # a different compiler for just that node. - spec_str = "simple-inheritance+openblas %gcc@10.1.0 os=redhat6" - s = Spec(spec_str).concretized() - - assert "openblas@0.2.15" in s - assert s["openblas"].satisfies("%gcc@10.1.0") + with spack.config.override( + "compilers", [compiler_factory(spec="gcc@10.1.0", operating_system="redhat6")] + ): + spec_str = "simple-inheritance+openblas %gcc@10.1.0 os=redhat6" + s = Spec(spec_str).concretized() + assert "openblas@0.2.15" in s + assert s["openblas"].satisfies("%gcc@10.1.0") @pytest.mark.regression("19981") def test_target_ranges_in_conflicts(self): @@ -1169,7 +1201,10 @@ def test_variant_not_default(self): @pytest.mark.regression("20055") @pytest.mark.only_clingo("Use case not supported by the original concretizer") - def test_custom_compiler_version(self): + def test_custom_compiler_version(self, mutable_config, compiler_factory): + mutable_config.set( + "compilers", [compiler_factory(spec="gcc@10foo", operating_system="redhat6")] + ) s = Spec("a %gcc@10foo os=redhat6").concretized() assert "%gcc@10foo" in s @@ -1369,11 +1404,16 @@ def test_external_with_non_default_variant_as_dependency(self): ("mpileaks%gcc@10.2.1 platform=test os=redhat6", "os=redhat6"), ], ) - def test_os_selection_when_multiple_choices_are_possible(self, spec_str, expected_os): - s = Spec(spec_str).concretized() - - for node in s.traverse(): - assert node.satisfies(expected_os) + def test_os_selection_when_multiple_choices_are_possible( + self, spec_str, expected_os, compiler_factory + ): + # GCC 10.2.1 is defined both for debian and for redhat + with spack.config.override( + "compilers", [compiler_factory(spec="gcc@10.2.1", operating_system="redhat6")] + ): + s = Spec(spec_str).concretized() + for node in s.traverse(): + assert node.satisfies(expected_os) @pytest.mark.regression("22718") @pytest.mark.parametrize( diff --git a/lib/spack/spack/test/concretize_preferences.py b/lib/spack/spack/test/concretize_preferences.py index 929ae0a9ec..295062faea 100644 --- a/lib/spack/spack/test/concretize_preferences.py +++ b/lib/spack/spack/test/concretize_preferences.py @@ -105,7 +105,7 @@ def test_preferred_variants_from_wildcard(self): @pytest.mark.parametrize( "compiler_str,spec_str", - [("gcc@=4.5.0", "mpileaks"), ("clang@=12.0.0", "mpileaks"), ("gcc@=4.5.0", "openmpi")], + [("gcc@=4.8.0", "mpileaks"), ("clang@=12.0.0", "mpileaks"), ("gcc@=4.8.0", "openmpi")], ) def test_preferred_compilers(self, compiler_str, spec_str): """Test preferred compilers are applied correctly""" diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py index 2a1cacf2fa..2bde1430fd 100644 --- a/lib/spack/spack/test/conftest.py +++ b/lib/spack/spack/test/conftest.py @@ -21,6 +21,7 @@ import py import pytest +import archspec.cpu import archspec.cpu.microarchitecture import archspec.cpu.schema @@ -708,7 +709,9 @@ def configuration_dir(tmpdir_factory, linux_os): t.write(content) compilers_yaml = test_config.join("compilers.yaml") - content = "".join(compilers_yaml.read()).format(linux_os) + content = "".join(compilers_yaml.read()).format( + linux_os=linux_os, target=str(archspec.cpu.host().family) + ) t = tmpdir.join("site", "compilers.yaml") t.write(content) yield tmpdir @@ -1952,3 +1955,48 @@ def pytest_runtest_setup(item): def disable_parallel_buildcache_push(monkeypatch): """Disable process pools in tests.""" monkeypatch.setattr(spack.cmd.buildcache, "_make_pool", spack.cmd.buildcache.NoPool) + + +def create_test_repo(tmpdir, pkg_name_content_tuples): + repo_path = str(tmpdir) + repo_yaml = tmpdir.join("repo.yaml") + with open(str(repo_yaml), "w") as f: + f.write( + """\ +repo: + namespace: testcfgrequirements +""" + ) + + packages_dir = tmpdir.join("packages") + for pkg_name, pkg_str in pkg_name_content_tuples: + pkg_dir = packages_dir.ensure(pkg_name, dir=True) + pkg_file = pkg_dir.join("package.py") + with open(str(pkg_file), "w") as f: + f.write(pkg_str) + + return spack.repo.Repo(repo_path) + + +@pytest.fixture() +def compiler_factory(): + """Factory for a compiler dict, taking a spec and an OS as arguments.""" + + def _factory(*, spec, operating_system): + return { + "compiler": { + "spec": spec, + "operating_system": operating_system, + "paths": {"cc": "/path/to/cc", "cxx": "/path/to/cxx", "f77": None, "fc": None}, + "modules": [], + "target": str(archspec.cpu.host().family), + } + } + + return _factory + + +@pytest.fixture() +def host_architecture_str(): + """Returns the broad architecture family (x86_64, aarch64, etc.)""" + return str(archspec.cpu.host().family) diff --git a/lib/spack/spack/test/data/config/compilers.yaml b/lib/spack/spack/test/data/config/compilers.yaml index 6f36c13b59..e8a709dc85 100644 --- a/lib/spack/spack/test/data/config/compilers.yaml +++ b/lib/spack/spack/test/data/config/compilers.yaml @@ -1,353 +1,41 @@ compilers: - compiler: - spec: clang@3.3 - operating_system: {0.name}{0.version} + spec: gcc@=4.8.0 + operating_system: {linux_os.name}{linux_os.version} + paths: + cc: /path/to/gcc + cxx: /path/to/g++ + f77: None + fc: None + modules: [] + target: {target} +- compiler: + spec: gcc@=4.8.0 + operating_system: redhat6 + paths: + cc: /path/to/gcc + cxx: /path/to/g++ + f77: None + fc: None + modules: [] + target: {target} +- compiler: + spec: clang@=12.0.0 + operating_system: {linux_os.name}{linux_os.version} paths: cc: /path/to/clang cxx: /path/to/clang++ f77: None fc: None - modules: 'None' - target: x86_64 + modules: [] + target: {target} - compiler: - spec: gcc@4.5.0 - operating_system: {0.name}{0.version} + spec: gcc@=10.2.1 + operating_system: {linux_os.name}{linux_os.version} paths: cc: /path/to/gcc cxx: /path/to/g++ f77: None fc: None - modules: 'None' - target: x86_64 -- compiler: - spec: gcc@4.5.0 - operating_system: redhat6 - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: None - fc: None - modules: 'None' - target: x86_64 -- compiler: - spec: clang@3.3 - operating_system: CNL - paths: - cc: /path/to/clang - cxx: /path/to/clang++ - f77: None - fc: None - modules: 'None' -- compiler: - spec: clang@3.3 - operating_system: SuSE11 - paths: - cc: /path/to/clang - cxx: /path/to/clang++ - f77: None - fc: None - modules: 'None' - target: x86_64 -- compiler: - spec: clang@3.3 - operating_system: yosemite - paths: - cc: /path/to/clang - cxx: /path/to/clang++ - f77: None - fc: None - modules: 'None' - target: x86_64 -- compiler: - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: /path/to/gfortran - fc: /path/to/gfortran - operating_system: CNL - spec: gcc@4.5.0 - modules: 'None' -- compiler: - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: /path/to/gfortran - fc: /path/to/gfortran - operating_system: SuSE11 - spec: gcc@4.5.0 - modules: 'None' - target: x86_64 -- compiler: - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: /path/to/gfortran - fc: /path/to/gfortran - operating_system: yosemite - spec: gcc@4.5.0 - modules: 'None' - target: x86_64 -- compiler: - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: /path/to/gfortran - fc: /path/to/gfortran - operating_system: elcapitan - spec: gcc@4.5.0 - modules: 'None' - target: x86_64 -- compiler: - spec: clang@3.3 - operating_system: elcapitan - paths: - cc: /path/to/clang - cxx: /path/to/clang++ - f77: None - fc: None - modules: 'None' - target: x86_64 -- compiler: - spec: gcc@4.7.2 - operating_system: redhat6 - paths: - cc: /path/to/gcc472 - cxx: /path/to/g++472 - f77: /path/to/gfortran472 - fc: /path/to/gfortran472 - flags: - cflags: -O0 -g - cxxflags: -O0 -g - fflags: -O0 -g - modules: 'None' - target: x86_64 -- compiler: - spec: gcc@4.4.0 - operating_system: redhat6 - paths: - cc: /path/to/gcc440 - cxx: /path/to/g++440 - f77: /path/to/gfortran440 - fc: /path/to/gfortran440 - modules: 'None' - target: x86_64 -- compiler: - spec: clang@3.5 - operating_system: redhat6 - paths: - cc: /path/to/clang35 - cxx: /path/to/clang++35 - f77: None - fc: None - flags: - cflags: -O3 - cxxflags: -O3 - modules: 'None' - target: x86_64 -- compiler: - spec: clang@8.0.0 - operating_system: redhat7 - paths: - cc: /path/to/clang-8 - cxx: /path/to/clang++-8 - f77: /path/to/gfortran-9 - fc: /path/to/gfortran-9 - flags: - cflags: -O3 - cxxflags: -O3 - modules: 'None' - target: x86_64 -- compiler: - spec: apple-clang@9.1.0 - operating_system: elcapitan - paths: - cc: /path/to/clang - cxx: /path/to/clang++ - f77: None - fc: None - modules: 'None' - target: x86_64 -- compiler: - spec: gcc@10foo - operating_system: redhat6 - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: /path/to/gfortran - fc: /path/to/gfortran - modules: 'None' - target: x86_64 -- compiler: - spec: gcc@4.4.0-special - operating_system: redhat6 - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: /path/to/gfortran - fc: /path/to/gfortran - modules: 'None' - target: x86_64 -- compiler: - spec: clang@12.0.0 - operating_system: {0.name}{0.version} - paths: - cc: /path/to/clang - cxx: /path/to/clang++ - f77: None - fc: None - modules: 'None' - target: aarch64 -- compiler: - spec: gcc@10.2.1 - operating_system: {0.name}{0.version} - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: None - fc: None - modules: 'None' - target: aarch64 -- compiler: - spec: clang@12.0.0 - operating_system: redhat6 - paths: - cc: /path/to/clang - cxx: /path/to/clang++ - f77: None - fc: None - modules: 'None' - target: aarch64 -- compiler: - spec: gcc@10.2.1 - operating_system: redhat6 - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: None - fc: None - modules: 'None' - target: aarch64 -- compiler: - spec: gcc@10.1.0 - operating_system: redhat6 - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: None - fc: None - modules: 'None' - target: aarch64 -- compiler: - spec: gcc@11.1.0 - operating_system: redhat6 - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: None - fc: None - flags: - cflags: -O0 -g - cxxflags: -O0 -g - fflags: -O0 -g - modules: 'None' - target: aarch64 -- compiler: - spec: clang@12.2.0 - operating_system: redhat6 - paths: - cc: /path/to/clang35 - cxx: /path/to/clang++35 - f77: None - fc: None - flags: - cflags: -O3 - cxxflags: -O3 - modules: 'None' - target: aarch64 -- compiler: - spec: gcc@10foo - operating_system: redhat6 - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: /path/to/gfortran - fc: /path/to/gfortran - modules: 'None' - target: aarch64 -- compiler: - spec: clang@12.0.0 - operating_system: {0.name}{0.version} - paths: - cc: /path/to/clang - cxx: /path/to/clang++ - f77: None - fc: None - modules: 'None' - target: x86_64 -- compiler: - spec: gcc@10.2.1 - operating_system: {0.name}{0.version} - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: None - fc: None - modules: 'None' - target: x86_64 -- compiler: - spec: clang@12.0.0 - operating_system: redhat6 - paths: - cc: /path/to/clang - cxx: /path/to/clang++ - f77: None - fc: None - modules: 'None' - target: x86_64 -- compiler: - spec: gcc@10.2.1 - operating_system: redhat6 - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: None - fc: None - modules: 'None' - target: x86_64 -- compiler: - spec: gcc@10.1.0 - operating_system: redhat6 - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: None - fc: None - modules: 'None' - target: x86_64 -- compiler: - spec: gcc@11.1.0 - operating_system: redhat6 - paths: - cc: /path/to/gcc - cxx: /path/to/g++ - f77: None - fc: None - flags: - cflags: -O0 -g - cxxflags: -O0 -g - fflags: -O0 -g - modules: 'None' - target: x86_64 -- compiler: - spec: clang@12.2.0 - operating_system: redhat6 - paths: - cc: /path/to/clang35 - cxx: /path/to/clang++35 - f77: None - fc: None - flags: - cflags: -O3 - cxxflags: -O3 - modules: 'None' - target: x86_64 + modules: [] + target: {target} diff --git a/lib/spack/spack/test/installer.py b/lib/spack/spack/test/installer.py index 2c3e47f307..13a36830cd 100644 --- a/lib/spack/spack/test/installer.py +++ b/lib/spack/spack/test/installer.py @@ -11,6 +11,8 @@ import py import pytest +import archspec.cpu + import llnl.util.filesystem as fs import llnl.util.lock as ulk import llnl.util.tty as tty @@ -528,6 +530,10 @@ def fake_package_list(compiler, architecture, pkgs): assert installer.build_pq[0][1].compiler +@pytest.mark.skipif( + str(archspec.cpu.host().family) != "x86_64", + reason="OneAPI compiler is not supported on other architectures", +) def test_bootstrapping_compilers_with_different_names_from_spec( install_mockery, mutable_config, mock_fetch, archspec_host_is_spack_test_host ): diff --git a/lib/spack/spack/test/modules/lmod.py b/lib/spack/spack/test/modules/lmod.py index acaae90f69..40bab66680 100644 --- a/lib/spack/spack/test/modules/lmod.py +++ b/lib/spack/spack/test/modules/lmod.py @@ -7,6 +7,8 @@ import pytest +import archspec.cpu + import spack.environment as ev import spack.main import spack.modules.lmod @@ -100,14 +102,19 @@ def test_file_layout(self, compiler, provider, factory, module_configuration): else: assert repetitions == 1 - def test_compilers_provided_different_name(self, factory, module_configuration): - module_configuration("complex_hierarchy") - module, spec = factory("intel-oneapi-compilers%clang@3.3") + def test_compilers_provided_different_name( + self, factory, module_configuration, compiler_factory + ): + with spack.config.override( + "compilers", [compiler_factory(spec="clang@3.3", operating_system="debian6")] + ): + module_configuration("complex_hierarchy") + module, spec = factory("intel-oneapi-compilers%clang@3.3") - provides = module.conf.provides + provides = module.conf.provides - assert "compiler" in provides - assert provides["compiler"] == spack.spec.CompilerSpec("oneapi@=3.0") + assert "compiler" in provides + assert provides["compiler"] == spack.spec.CompilerSpec("oneapi@=3.0") def test_simple_case(self, modulefile_content, module_configuration): """Tests the generation of a simple Lua module file.""" @@ -136,6 +143,9 @@ def test_autoload_all(self, modulefile_content, module_configuration): assert len([x for x in content if "depends_on(" in x]) == 5 + @pytest.mark.skipif( + str(archspec.cpu.host().family) != "x86_64", reason="test data is specific for x86_64" + ) def test_alter_environment(self, modulefile_content, module_configuration): """Tests modifications to run-time environment.""" @@ -207,6 +217,9 @@ def test_setenv_raw_value(self, modulefile_content, module_configuration): assert len([x for x in content if 'setenv("FOO", "{{name}}, {name}, {{}}, {}")' in x]) == 1 + @pytest.mark.skipif( + str(archspec.cpu.host().family) != "x86_64", reason="test data is specific for x86_64" + ) def test_help_message(self, modulefile_content, module_configuration): """Tests the generation of module help message.""" @@ -330,14 +343,16 @@ def test_override_template_in_package(self, modulefile_content, module_configura assert "Override successful!" in content - def test_override_template_in_modules_yaml(self, modulefile_content, module_configuration): + def test_override_template_in_modules_yaml( + self, modulefile_content, module_configuration, host_architecture_str + ): """Tests overriding a template from `modules.yaml`""" module_configuration("override_template") content = modulefile_content("override-module-templates") assert "Override even better!" in content - content = modulefile_content("mpileaks target=x86_64") + content = modulefile_content(f"mpileaks target={host_architecture_str}") assert "Override even better!" in content @pytest.mark.usefixtures("config") diff --git a/lib/spack/spack/test/modules/tcl.py b/lib/spack/spack/test/modules/tcl.py index f43f3d041e..ce939cd4d3 100644 --- a/lib/spack/spack/test/modules/tcl.py +++ b/lib/spack/spack/test/modules/tcl.py @@ -7,6 +7,8 @@ import pytest +import archspec.cpu + import spack.modules.common import spack.modules.tcl import spack.spec @@ -89,22 +91,29 @@ def test_autoload_all(self, modulefile_content, module_configuration): assert len([x for x in content if "depends-on " in x]) == 2 assert len([x for x in content if "module load " in x]) == 2 - def test_prerequisites_direct(self, modulefile_content, module_configuration): + def test_prerequisites_direct( + self, modulefile_content, module_configuration, host_architecture_str + ): """Tests asking direct dependencies as prerequisites.""" module_configuration("prerequisites_direct") - content = modulefile_content("mpileaks target=x86_64") + content = modulefile_content(f"mpileaks target={host_architecture_str}") assert len([x for x in content if "prereq" in x]) == 2 - def test_prerequisites_all(self, modulefile_content, module_configuration): + def test_prerequisites_all( + self, modulefile_content, module_configuration, host_architecture_str + ): """Tests asking all dependencies as prerequisites.""" module_configuration("prerequisites_all") - content = modulefile_content("mpileaks target=x86_64") + content = modulefile_content(f"mpileaks target={host_architecture_str}") assert len([x for x in content if "prereq" in x]) == 5 + @pytest.mark.skipif( + str(archspec.cpu.host().family) != "x86_64", reason="test data is specific for x86_64" + ) def test_alter_environment(self, modulefile_content, module_configuration): """Tests modifications to run-time environment.""" @@ -177,6 +186,9 @@ def test_setenv_raw_value(self, modulefile_content, module_configuration): assert len([x for x in content if "setenv FOO {{{name}}, {name}, {{}}, {}}" in x]) == 1 + @pytest.mark.skipif( + str(archspec.cpu.host().family) != "x86_64", reason="test data is specific for x86_64" + ) def test_help_message(self, modulefile_content, module_configuration): """Tests the generation of module help message.""" @@ -219,7 +231,7 @@ def test_help_message(self, modulefile_content, module_configuration): ) assert help_msg in "".join(content) - def test_exclude(self, modulefile_content, module_configuration): + def test_exclude(self, modulefile_content, module_configuration, host_architecture_str): """Tests excluding the generation of selected modules.""" module_configuration("exclude") @@ -231,9 +243,9 @@ def test_exclude(self, modulefile_content, module_configuration): # and IOError on Python 2 or common bases like EnvironmentError # which are not officially documented with pytest.raises(Exception): - modulefile_content("callpath target=x86_64") + modulefile_content(f"callpath target={host_architecture_str}") - content = modulefile_content("zmpi target=x86_64") + content = modulefile_content(f"zmpi target={host_architecture_str}") assert len([x for x in content if "module load " in x]) == 1 @@ -403,14 +415,16 @@ def test_override_template_in_package(self, modulefile_content, module_configura assert "Override successful!" in content - def test_override_template_in_modules_yaml(self, modulefile_content, module_configuration): + def test_override_template_in_modules_yaml( + self, modulefile_content, module_configuration, host_architecture_str + ): """Tests overriding a template from `modules.yaml`""" module_configuration("override_template") content = modulefile_content("override-module-templates") assert "Override even better!" in content - content = modulefile_content("mpileaks target=x86_64") + content = modulefile_content(f"mpileaks target={host_architecture_str}") assert "Override even better!" in content def test_extend_context(self, modulefile_content, module_configuration): diff --git a/lib/spack/spack/test/multimethod.py b/lib/spack/spack/test/multimethod.py index 76e06ab3a7..e3671c8730 100644 --- a/lib/spack/spack/test/multimethod.py +++ b/lib/spack/spack/test/multimethod.py @@ -69,9 +69,15 @@ def test_no_version_match(pkg_name): ("", "boolean_false_first", "True"), ], ) -def test_multimethod_calls(pkg_name, constraint_str, method_name, expected_result): - s = spack.spec.Spec(pkg_name + constraint_str).concretized() - msg = "Method {0} from {1} is giving a wrong result".format(method_name, s) +def test_multimethod_calls( + pkg_name, constraint_str, method_name, expected_result, compiler_factory +): + # Add apple-clang, as it is required by one of the tests + with spack.config.override( + "compilers", [compiler_factory(spec="apple-clang@9.1.0", operating_system="elcapitan")] + ): + s = spack.spec.Spec(pkg_name + constraint_str).concretized() + msg = f"Method {method_name} from {s} is giving a wrong result" assert getattr(s.package, method_name)() == expected_result, msg diff --git a/lib/spack/spack/test/spec_semantics.py b/lib/spack/spack/test/spec_semantics.py index 08caba1518..e0481c5967 100644 --- a/lib/spack/spack/test/spec_semantics.py +++ b/lib/spack/spack/test/spec_semantics.py @@ -734,18 +734,6 @@ def test_spec_formatting_escapes(self, default_mock_concretization): with pytest.raises(SpecFormatStringError): spec.format(fmt_str) - @pytest.mark.regression("9908") - def test_spec_flags_maintain_order(self): - # Spack was assembling flags in a manner that could result in - # different orderings for repeated concretizations of the same - # spec and config - spec_str = "libelf %gcc@11.1.0 os=redhat6" - for _ in range(3): - s = Spec(spec_str).concretized() - assert all( - s.compiler_flags[x] == ["-O0", "-g"] for x in ("cflags", "cxxflags", "fflags") - ) - def test_combination_of_wildcard_or_none(self): # Test that using 'none' and another value raises with pytest.raises(spack.variant.InvalidVariantValueCombinationError):