From 294e659ae895c45a8ada51ea5cc0db2e5a004e1d Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Wed, 18 Oct 2023 19:56:54 +0200 Subject: [PATCH] AutotoolsPackage / MakefilePackage: add gmake build dependency (#40380) --- .../docs/tables/system_prerequisites.csv | 1 - lib/spack/spack/build_systems/autotools.py | 1 + lib/spack/spack/build_systems/makefile.py | 8 +++-- lib/spack/spack/test/architecture.py | 28 ++++++--------- lib/spack/spack/test/cmd/ci.py | 21 +++++------ lib/spack/spack/test/installer.py | 14 ++++---- share/spack/qa/setup-env-test.fish | 36 +++++++++---------- share/spack/qa/setup-env-test.sh | 36 +++++++++---------- .../builder.test/packages/gmake/package.py | 18 ++++++++++ .../builtin.mock/packages/gmake/package.py | 3 ++ .../builtin.mock/packages/shell-a/package.py | 17 +++++++++ .../builtin.mock/packages/shell-b/package.py | 16 +++++++++ .../repos/builtin/packages/gmake/package.py | 20 +++++------ 13 files changed, 133 insertions(+), 86 deletions(-) create mode 100644 var/spack/repos/builder.test/packages/gmake/package.py create mode 100644 var/spack/repos/builtin.mock/packages/shell-a/package.py create mode 100644 var/spack/repos/builtin.mock/packages/shell-b/package.py diff --git a/lib/spack/docs/tables/system_prerequisites.csv b/lib/spack/docs/tables/system_prerequisites.csv index f275bcef5b..7a72078cdd 100644 --- a/lib/spack/docs/tables/system_prerequisites.csv +++ b/lib/spack/docs/tables/system_prerequisites.csv @@ -1,7 +1,6 @@ Name, Supported Versions, Notes, Requirement Reason Python, 3.6--3.12, , Interpreter for Spack C/C++ Compilers, , , Building software -make, , , Build software patch, , , Build software tar, , , Extract/create archives gzip, , , Compress/Decompress archives diff --git a/lib/spack/spack/build_systems/autotools.py b/lib/spack/spack/build_systems/autotools.py index e78b87bee4..760faf307b 100644 --- a/lib/spack/spack/build_systems/autotools.py +++ b/lib/spack/spack/build_systems/autotools.py @@ -46,6 +46,7 @@ class AutotoolsPackage(spack.package_base.PackageBase): depends_on("gnuconfig", type="build", when="target=ppc64le:") depends_on("gnuconfig", type="build", when="target=aarch64:") depends_on("gnuconfig", type="build", when="target=riscv64:") + depends_on("gmake", type="build") conflicts("platform=windows") def flags_to_build_system_args(self, flags): diff --git a/lib/spack/spack/build_systems/makefile.py b/lib/spack/spack/build_systems/makefile.py index feb6d37f24..25eec07095 100644 --- a/lib/spack/spack/build_systems/makefile.py +++ b/lib/spack/spack/build_systems/makefile.py @@ -9,7 +9,8 @@ import spack.builder import spack.package_base -from spack.directives import build_system, conflicts +from spack.directives import build_system, conflicts, depends_on +from spack.multimethod import when from ._checks import ( BaseBuilder, @@ -29,7 +30,10 @@ class MakefilePackage(spack.package_base.PackageBase): legacy_buildsystem = "makefile" build_system("makefile") - conflicts("platform=windows", when="build_system=makefile") + + with when("build_system=makefile"): + conflicts("platform=windows") + depends_on("gmake", type="build") @spack.builder.builder("makefile") diff --git a/lib/spack/spack/test/architecture.py b/lib/spack/spack/test/architecture.py index a5d7a0083d..7bea7a1d86 100644 --- a/lib/spack/spack/test/architecture.py +++ b/lib/spack/spack/test/architecture.py @@ -13,8 +13,8 @@ import spack.concretize import spack.operating_systems import spack.platforms -import spack.spec import spack.target +from spack.spec import ArchSpec, CompilerSpec, Spec @pytest.fixture(scope="module") @@ -64,7 +64,7 @@ def test_user_input_combination(config, target_str, os_str): the operating system match. """ spec_str = "libelf os={} target={}".format(os_str, target_str) - spec = spack.spec.Spec(spec_str) + spec = Spec(spec_str) assert spec.architecture.os == str(TEST_PLATFORM.operating_system(os_str)) assert spec.architecture.target == TEST_PLATFORM.target(target_str) @@ -114,7 +114,7 @@ def test_target_container_semantic(cpu_flag, target_name): ], ) def test_arch_spec_container_semantic(item, architecture_str): - architecture = spack.spec.ArchSpec(architecture_str) + architecture = ArchSpec(architecture_str) assert item in architecture @@ -141,24 +141,24 @@ def test_optimization_flags(compiler_spec, target_name, expected_flags, config): @pytest.mark.parametrize( "compiler,real_version,target_str,expected_flags", [ - (spack.spec.CompilerSpec("gcc@=9.2.0"), None, "haswell", "-march=haswell -mtune=haswell"), + (CompilerSpec("gcc@=9.2.0"), None, "haswell", "-march=haswell -mtune=haswell"), # Check that custom string versions are accepted ( - spack.spec.CompilerSpec("gcc@=10foo"), + CompilerSpec("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) ( - spack.spec.CompilerSpec("gcc@=4.4.0-special"), + CompilerSpec("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 - (spack.spec.CompilerSpec("apple-clang@=9.1.0"), None, "x86_64", "-march=x86-64"), + (CompilerSpec("apple-clang@=9.1.0"), None, "x86_64", "-march=x86-64"), ], ) def test_optimization_flags_with_custom_versions( @@ -180,8 +180,8 @@ def test_optimization_flags_with_custom_versions( ], ) def test_satisfy_strict_constraint_when_not_concrete(architecture_tuple, constraint_tuple): - architecture = spack.spec.ArchSpec(architecture_tuple) - constraint = spack.spec.ArchSpec(constraint_tuple) + architecture = ArchSpec(architecture_tuple) + constraint = ArchSpec(constraint_tuple) assert not architecture.satisfies(constraint) @@ -204,16 +204,10 @@ def test_satisfy_strict_constraint_when_not_concrete(architecture_tuple, constra 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_str = "a %%gcc@10 foobar=bar target=%s ^b target=%s" % ( - root_target_range, - dep_target_range, - ) - spec = spack.spec.Spec(spec_str) + 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() - - assert str(spec).count("arch=test-debian6-%s" % result) == 2 + assert spec.target == spec["b"].target == result @pytest.mark.parametrize( diff --git a/lib/spack/spack/test/cmd/ci.py b/lib/spack/spack/test/cmd/ci.py index a0de63517a..d02e1caa2d 100644 --- a/lib/spack/spack/test/cmd/ci.py +++ b/lib/spack/spack/test/cmd/ci.py @@ -1080,14 +1080,17 @@ def test_push_mirror_contents( ci.import_signing_key(_signing_key()) - spack_yaml_contents = """ + with tmpdir.as_cwd(): + with open("spack.yaml", "w") as f: + f.write( + f"""\ spack: definitions: - packages: [patchelf] specs: - $packages mirrors: - test-mirror: {0} + test-mirror: {mirror_url} ci: enable-artifacts-buildcache: True pipeline-gen: @@ -1107,15 +1110,8 @@ def test_push_mirror_contents( - nonbuildtag image: basicimage custom_attribute: custom! -""".format( - mirror_url - ) - - filename = str(tmpdir.join("spack.yaml")) - with open(filename, "w") as f: - f.write(spack_yaml_contents) - - with tmpdir.as_cwd(): +""" + ) env_cmd("create", "test", "./spack.yaml") with ev.read("test"): concrete_spec = Spec("patchelf").concretized() @@ -1126,7 +1122,8 @@ def test_push_mirror_contents( install_cmd("--add", "--keep-stage", json_path) - ci.push_mirror_contents(concrete_spec, mirror_url, True) + for s in concrete_spec.traverse(): + ci.push_mirror_contents(s, mirror_url, True) buildcache_path = os.path.join(mirror_dir.strpath, "build_cache") diff --git a/lib/spack/spack/test/installer.py b/lib/spack/spack/test/installer.py index 6b42e591eb..d28d3f44c3 100644 --- a/lib/spack/spack/test/installer.py +++ b/lib/spack/spack/test/installer.py @@ -719,13 +719,12 @@ def test_check_deps_status_external(install_mockery, monkeypatch): installer = create_installer(const_arg) request = installer.build_requests[0] - # Mock the known dependent, b, as external so assumed to be installed + # Mock the dependencies as external so assumed to be installed monkeypatch.setattr(spack.spec.Spec, "external", True) installer._check_deps_status(request) - # exotic architectures will add dependencies on gnuconfig, which we want to ignore - installed = [x for x in installer.installed if not x.startswith("gnuconfig")] - assert installed[0].startswith("b") + for dep in request.spec.traverse(root=False): + assert inst.package_id(dep.package) in installer.installed def test_check_deps_status_upstream(install_mockery, monkeypatch): @@ -733,13 +732,12 @@ def test_check_deps_status_upstream(install_mockery, monkeypatch): installer = create_installer(const_arg) request = installer.build_requests[0] - # Mock the known dependent, b, as installed upstream + # Mock the known dependencies as installed upstream monkeypatch.setattr(spack.spec.Spec, "installed_upstream", True) installer._check_deps_status(request) - # exotic architectures will add dependencies on gnuconfig, which we want to ignore - installed = [x for x in installer.installed if not x.startswith("gnuconfig")] - assert installed[0].startswith("b") + for dep in request.spec.traverse(root=False): + assert inst.package_id(dep.package) in installer.installed def test_add_bootstrap_compilers(install_mockery, monkeypatch): diff --git a/share/spack/qa/setup-env-test.fish b/share/spack/qa/setup-env-test.fish index 87158840b1..86563b4b08 100755 --- a/share/spack/qa/setup-env-test.fish +++ b/share/spack/qa/setup-env-test.fish @@ -285,7 +285,7 @@ spt_succeeds which spack # create a fake mock package install and store its location for later title "Setup" echo "Creating a mock package installation" -spack -m install --fake a +spack -m install --fake shell-a # create a test environment for testing environment commands echo "Creating a mock environment" @@ -300,7 +300,7 @@ function spt_cleanup -p %self title "Cleanup" echo "Removing test packages before exiting." - spack -m uninstall -yf b a + spack -m uninstall -yf shell-b shell-a echo echo "$__spt_success tests succeeded." @@ -322,7 +322,7 @@ spt_contains "usage: spack " spack help --all title 'Testing `spack cd`' spt_contains "usage: spack cd " spack cd -h spt_contains "usage: spack cd " spack cd --help -spt_contains "cd $b_install" spack cd -i b +spt_contains "cd $b_install" spack cd -i shell-b title 'Testing `spack module`' spt_contains "usage: spack module " spack -m module -h @@ -330,34 +330,34 @@ spt_contains "usage: spack module " spack -m module --help spt_contains "usage: spack module " spack -m module title 'Testing `spack load`' -set _b_loc (spack -m location -i b) +set _b_loc (spack -m location -i shell-b) set _b_bin $_b_loc"/bin" -set _a_loc (spack -m location -i a) +set _a_loc (spack -m location -i shell-a) set _a_bin $_a_loc"/bin" -spt_contains "set -gx PATH $_b_bin" spack -m load --only package --fish b -spt_succeeds spack -m load b -set LIST_CONTENT (spack -m load b; spack load --list) -spt_contains "b@" echo $LIST_CONTENT -spt_does_not_contain "a@" echo $LIST_CONTENT +spt_contains "set -gx PATH $_b_bin" spack -m load --only package --fish shell-b +spt_succeeds spack -m load shell-b +set LIST_CONTENT (spack -m load shell-b; spack load --list) +spt_contains "shell-b@" echo $LIST_CONTENT +spt_does_not_contain "shell-a@" echo $LIST_CONTENT # test a variable MacOS clears and one it doesn't for recursive loads -spt_contains "set -gx PATH $_a_bin:$_b_bin" spack -m load --fish a -spt_succeeds spack -m load --only dependencies a -spt_succeeds spack -m load --only package a +spt_contains "set -gx PATH $_a_bin:$_b_bin" spack -m load --fish shell-a +spt_succeeds spack -m load --only dependencies shell-a +spt_succeeds spack -m load --only package shell-a spt_fails spack -m load d spt_contains "usage: spack load " spack -m load -h spt_contains "usage: spack load " spack -m load -h d spt_contains "usage: spack load " spack -m load --help title 'Testing `spack unload`' -spack -m load b a # setup -# spt_contains "module unload $b_module" spack -m unload b -spt_succeeds spack -m unload b +spack -m load shell-b shell-a # setup +# spt_contains "module unload $b_module" spack -m unload shell-b +spt_succeeds spack -m unload shell-b spt_succeeds spack -m unload --all spack -m unload --all # cleanup spt_fails spack -m unload -l -# spt_contains "module unload -l --arg $b_module" spack -m unload -l --arg b -spt_fails spack -m unload d +# spt_contains "module unload -l --arg $b_module" spack -m unload -l --arg shell-b +spt_fails spack -m unload shell-d spt_contains "usage: spack unload " spack -m unload -h spt_contains "usage: spack unload " spack -m unload -h d spt_contains "usage: spack unload " spack -m unload --help diff --git a/share/spack/qa/setup-env-test.sh b/share/spack/qa/setup-env-test.sh index 94589e5bcb..58feca69ea 100755 --- a/share/spack/qa/setup-env-test.sh +++ b/share/spack/qa/setup-env-test.sh @@ -60,12 +60,12 @@ cd() { # Create a fake mock package install and store its location for later title "Setup" echo "Creating a mock package installation" -spack -m install --fake a -a_install=$(spack location -i a) -a_module=$(spack -m module tcl find a) +spack -m install --fake shell-a +a_install=$(spack location -i shell-a) +a_module=$(spack -m module tcl find shell-a) -b_install=$(spack location -i b) -b_module=$(spack -m module tcl find b) +b_install=$(spack location -i shell-b) +b_module=$(spack -m module tcl find shell-b) # Create a test environment for testing environment commands echo "Creating a mock environment" @@ -80,7 +80,7 @@ cleanup() { title "Cleanup" echo "Removing test packages before exiting." - spack -m uninstall -yf b a + spack -m uninstall -yf shell-b shell-a } # ----------------------------------------------------------------------- @@ -96,7 +96,7 @@ contains "usage: spack " spack help --all title 'Testing `spack cd`' contains "usage: spack cd " spack cd -h contains "usage: spack cd " spack cd --help -contains "cd $b_install" spack cd -i b +contains "cd $b_install" spack cd -i shell-b title 'Testing `spack module`' contains "usage: spack module " spack -m module -h @@ -104,25 +104,25 @@ contains "usage: spack module " spack -m module --help contains "usage: spack module " spack -m module title 'Testing `spack load`' -contains "export PATH=$(spack -m location -i b)/bin" spack -m load --only package --sh b -succeeds spack -m load b -LIST_CONTENT=`spack -m load b; spack load --list` -contains "b@" echo $LIST_CONTENT -does_not_contain "a@" echo $LIST_CONTENT +contains "export PATH=$(spack -m location -i shell-b)/bin" spack -m load --only package --sh shell-b +succeeds spack -m load shell-b +LIST_CONTENT=`spack -m load shell-b; spack load --list` +contains "shell-b@" echo $LIST_CONTENT +does_not_contain "shell-a@" echo $LIST_CONTENT fails spack -m load -l # test a variable MacOS clears and one it doesn't for recursive loads -contains "export PATH=$(spack -m location -i a)/bin" spack -m load --sh a -contains "export PATH=$(spack -m location -i b)/bin" spack -m load --sh b -succeeds spack -m load --only dependencies a -succeeds spack -m load --only package a +contains "export PATH=$(spack -m location -i shell-a)/bin" spack -m load --sh shell-a +contains "export PATH=$(spack -m location -i shell-b)/bin" spack -m load --sh shell-b +succeeds spack -m load --only dependencies shell-a +succeeds spack -m load --only package shell-a fails spack -m load d contains "usage: spack load " spack -m load -h contains "usage: spack load " spack -m load -h d contains "usage: spack load " spack -m load --help title 'Testing `spack unload`' -spack -m load b a # setup -succeeds spack -m unload b +spack -m load shell-b shell-a # setup +succeeds spack -m unload shell-b succeeds spack -m unload --all spack -m unload --all # cleanup fails spack -m unload -l diff --git a/var/spack/repos/builder.test/packages/gmake/package.py b/var/spack/repos/builder.test/packages/gmake/package.py new file mode 100644 index 0000000000..b3d5c50086 --- /dev/null +++ b/var/spack/repos/builder.test/packages/gmake/package.py @@ -0,0 +1,18 @@ +# Copyright 2013-2023 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) + +from spack.package import * + + +class Gmake(Package): + """Dummy GMake Package""" + + homepage = "https://www.gnu.org/software/make" + url = "https://ftpmirror.gnu.org/make/make-4.4.tar.gz" + + version("4.4", sha256="ce35865411f0490368a8fc383f29071de6690cbadc27704734978221f25e2bed") + + def do_stage(self): + mkdirp(self.stage.source_path) diff --git a/var/spack/repos/builtin.mock/packages/gmake/package.py b/var/spack/repos/builtin.mock/packages/gmake/package.py index aa5dd8452b..b3d5c50086 100644 --- a/var/spack/repos/builtin.mock/packages/gmake/package.py +++ b/var/spack/repos/builtin.mock/packages/gmake/package.py @@ -13,3 +13,6 @@ class Gmake(Package): url = "https://ftpmirror.gnu.org/make/make-4.4.tar.gz" version("4.4", sha256="ce35865411f0490368a8fc383f29071de6690cbadc27704734978221f25e2bed") + + def do_stage(self): + mkdirp(self.stage.source_path) diff --git a/var/spack/repos/builtin.mock/packages/shell-a/package.py b/var/spack/repos/builtin.mock/packages/shell-a/package.py new file mode 100644 index 0000000000..3ff34102bf --- /dev/null +++ b/var/spack/repos/builtin.mock/packages/shell-a/package.py @@ -0,0 +1,17 @@ +# Copyright 2013-2023 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) +from spack.package import * + + +class ShellA(Package): + """Simple package with one dependency for shell tests""" + + homepage = "http://www.example.com" + url = "http://www.example.com/shell-a-1.0.tar.gz" + + version("1.0", md5="0123456789abcdef0123456789abcdef") + version("2.0", md5="abcdef0123456789abcdef0123456789") + + depends_on("shell-b") diff --git a/var/spack/repos/builtin.mock/packages/shell-b/package.py b/var/spack/repos/builtin.mock/packages/shell-b/package.py new file mode 100644 index 0000000000..3db70f1218 --- /dev/null +++ b/var/spack/repos/builtin.mock/packages/shell-b/package.py @@ -0,0 +1,16 @@ +# Copyright 2013-2023 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) + +from spack.package import * + + +class ShellB(Package): + """Simple package with no dependencies for shell tests""" + + homepage = "http://www.example.com" + url = "http://www.example.com/shell-b-1.0.tar.gz" + + version("1.0", md5="0123456789abcdef0123456789abcdef") + version("0.9", md5="abcd456789abcdef0123456789abcdef") diff --git a/var/spack/repos/builtin/packages/gmake/package.py b/var/spack/repos/builtin/packages/gmake/package.py index 3f795ad637..0cfbccb80e 100644 --- a/var/spack/repos/builtin/packages/gmake/package.py +++ b/var/spack/repos/builtin/packages/gmake/package.py @@ -9,7 +9,7 @@ from spack.package import * -class Gmake(AutotoolsPackage, GNUMirrorPackage): +class Gmake(Package, GNUMirrorPackage): """GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files.""" @@ -64,17 +64,17 @@ def determine_version(cls, exe): return match.group(1) if match else None def configure_args(self): - args = [] - args.extend(self.with_or_without("guile")) - args.append("--disable-nls") - return args - - def build(self, spec, prefix): - with working_dir(self.build_directory): - Executable(os.path.join(self.stage.source_path, "build.sh"))() + return [ + "--with-guile" if self.spec.satisfies("+guile") else "--without-guile", + "--disable-nls", + ] def install(self, spec, prefix): - with working_dir(self.build_directory): + configure = Executable(join_path(self.stage.source_path, "configure")) + build_sh = Executable(join_path(self.stage.source_path, "build.sh")) + with working_dir(self.build_directory, create=True): + configure(f"--prefix={prefix}", *self.configure_args()) + build_sh() os.mkdir(prefix.bin) install("make", prefix.bin) os.symlink("make", prefix.bin.gmake)