CargoPackage: add new build system for Cargo packages (#41192)

Co-authored-by: Tom Scogland <scogland1@llnl.gov>
This commit is contained in:
Alec Scott 2023-11-27 13:15:16 -07:00 committed by GitHub
parent fbec91e491
commit c482534c1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 153 additions and 26 deletions

View File

@ -0,0 +1,89 @@
# 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)
import inspect
import llnl.util.filesystem as fs
import spack.builder
import spack.package_base
from spack.directives import build_system, depends_on
from spack.multimethod import when
from ._checks import BaseBuilder, execute_install_time_tests
class CargoPackage(spack.package_base.PackageBase):
"""Specialized class for packages built using a Makefiles."""
#: This attribute is used in UI queries that need to know the build
#: system base class
build_system_class = "CargoPackage"
build_system("cargo")
with when("build_system=cargo"):
depends_on("rust", type="build")
@spack.builder.builder("cargo")
class CargoBuilder(BaseBuilder):
"""The Cargo builder encodes the most common way of building software with
a rust Cargo.toml file. It has two phases that can be overridden, if need be:
1. :py:meth:`~.CargoBuilder.build`
2. :py:meth:`~.CargoBuilder.install`
For a finer tuning you may override:
+-----------------------------------------------+----------------------+
| **Method** | **Purpose** |
+===============================================+======================+
| :py:meth:`~.CargoBuilder.build_args` | Specify arguments |
| | to ``cargo install`` |
+-----------------------------------------------+----------------------+
| :py:meth:`~.CargoBuilder.check_args` | Specify arguments |
| | to ``cargo test`` |
+-----------------------------------------------+----------------------+
"""
phases = ("build", "install")
#: Callback names for install-time test
install_time_test_callbacks = ["check"]
@property
def build_directory(self):
"""Return the directory containing the main Cargo.toml."""
return self.pkg.stage.source_path
@property
def build_args(self):
"""Arguments for ``cargo build``."""
return []
@property
def check_args(self):
"""Argument for ``cargo test`` during check phase"""
return []
def build(self, pkg, spec, prefix):
"""Runs ``cargo install`` in the source directory"""
with fs.working_dir(self.build_directory):
inspect.getmodule(pkg).cargo(
"install", "--root", "out", "--path", ".", *self.build_args
)
def install(self, pkg, spec, prefix):
"""Copy build files into package prefix."""
with fs.working_dir(self.build_directory):
fs.install_tree("out", prefix)
spack.builder.run_after("install")(execute_install_time_tests)
def check(self):
"""Run "cargo test"."""
with fs.working_dir(self.build_directory):
inspect.getmodule(self.pkg).cargo("test", *self.check_args)

View File

@ -172,6 +172,14 @@ def configure_args(self):
return args"""
class CargoPackageTemplate(PackageTemplate):
"""Provides appropriate overrides for cargo-based packages"""
base_class_name = "CargoPackage"
body_def = ""
class CMakePackageTemplate(PackageTemplate):
"""Provides appropriate overrides for CMake-based packages"""
@ -575,28 +583,29 @@ def __init__(self, name, *args, **kwargs):
templates = {
"autotools": AutotoolsPackageTemplate,
"autoreconf": AutoreconfPackageTemplate,
"cmake": CMakePackageTemplate,
"bundle": BundlePackageTemplate,
"qmake": QMakePackageTemplate,
"maven": MavenPackageTemplate,
"scons": SconsPackageTemplate,
"waf": WafPackageTemplate,
"autotools": AutotoolsPackageTemplate,
"bazel": BazelPackageTemplate,
"bundle": BundlePackageTemplate,
"cargo": CargoPackageTemplate,
"cmake": CMakePackageTemplate,
"generic": PackageTemplate,
"intel": IntelPackageTemplate,
"lua": LuaPackageTemplate,
"makefile": MakefilePackageTemplate,
"maven": MavenPackageTemplate,
"meson": MesonPackageTemplate,
"octave": OctavePackageTemplate,
"perlbuild": PerlbuildPackageTemplate,
"perlmake": PerlmakePackageTemplate,
"python": PythonPackageTemplate,
"qmake": QMakePackageTemplate,
"r": RPackageTemplate,
"racket": RacketPackageTemplate,
"perlmake": PerlmakePackageTemplate,
"perlbuild": PerlbuildPackageTemplate,
"octave": OctavePackageTemplate,
"ruby": RubyPackageTemplate,
"makefile": MakefilePackageTemplate,
"intel": IntelPackageTemplate,
"meson": MesonPackageTemplate,
"lua": LuaPackageTemplate,
"scons": SconsPackageTemplate,
"sip": SIPPackageTemplate,
"generic": PackageTemplate,
"waf": WafPackageTemplate,
}
@ -679,6 +688,7 @@ def __call__(self, stage, url):
clues = [
(r"/CMakeLists\.txt$", "cmake"),
(r"/NAMESPACE$", "r"),
(r"/Cargo\.toml$", "cargo"),
(r"/configure$", "autotools"),
(r"/configure\.(in|ac)$", "autoreconf"),
(r"/Makefile\.am$", "autoreconf"),

View File

@ -37,6 +37,7 @@
cmake_cache_path,
cmake_cache_string,
)
from spack.build_systems.cargo import CargoPackage
from spack.build_systems.cmake import CMakePackage, generator
from spack.build_systems.cuda import CudaPackage
from spack.build_systems.generic import Package

View File

@ -1261,7 +1261,7 @@ complete -c spack -n '__fish_spack_using_command create' -l keep-stage -f -a kee
complete -c spack -n '__fish_spack_using_command create' -l keep-stage -d 'don\'t clean up staging area when command completes'
complete -c spack -n '__fish_spack_using_command create' -s n -l name -r -f -a name
complete -c spack -n '__fish_spack_using_command create' -s n -l name -r -d 'name of the package to create'
complete -c spack -n '__fish_spack_using_command create' -s t -l template -r -f -a 'autoreconf autotools bazel bundle cmake generic intel lua makefile maven meson octave perlbuild perlmake python qmake r racket ruby scons sip waf'
complete -c spack -n '__fish_spack_using_command create' -s t -l template -r -f -a 'autoreconf autotools bazel bundle cargo cmake generic intel lua makefile maven meson octave perlbuild perlmake python qmake r racket ruby scons sip waf'
complete -c spack -n '__fish_spack_using_command create' -s t -l template -r -d 'build system template to use'
complete -c spack -n '__fish_spack_using_command create' -s r -l repo -r -f -a repo
complete -c spack -n '__fish_spack_using_command create' -s r -l repo -r -d 'path to a repository where the package should be created'

View File

@ -6,17 +6,22 @@
from spack.package import *
class Exa(Package):
"""exa is a replacement for ls written in Rust."""
class Exa(CargoPackage):
"""DEPRECATED: The exa upstream is no longer maintained, see the eza package for a
replacement.
exa is a replacement for ls written in Rust."""
homepage = "https://the.exa.website"
url = "https://github.com/ogham/exa/archive/v0.9.0.tar.gz"
version("0.10.1", sha256="ff0fa0bfc4edef8bdbbb3cabe6fdbd5481a71abbbcc2159f402dea515353ae7c")
version("0.9.0", sha256="96e743ffac0512a278de9ca3277183536ee8b691a46ff200ec27e28108fef783")
depends_on("rust")
def install(self, spec, prefix):
cargo = which("cargo")
cargo("install", "--root", prefix, "--path", ".")
version(
"0.10.1",
sha256="ff0fa0bfc4edef8bdbbb3cabe6fdbd5481a71abbbcc2159f402dea515353ae7c",
deprecated=True,
)
version(
"0.9.0",
sha256="96e743ffac0512a278de9ca3277183536ee8b691a46ff200ec27e28108fef783",
deprecated=True,
)

View File

@ -0,0 +1,19 @@
# 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 Eza(CargoPackage):
"""A modern, maintained replacement for ls."""
homepage = "https://github.com/eza-community/eza"
url = "https://github.com/eza-community/eza/archive/refs/tags/v0.15.3.tar.gz"
maintainers("trws")
license("MIT")
version("0.15.3", sha256="09093e565913104acb7a8eba974f8067c95566b6fbedf31138c9923a8cfde42f")

View File

@ -89,6 +89,9 @@ def determine_version(csl, exe):
match = re.match(r"rustc (\S+)", output)
return match.group(1) if match else None
def setup_dependent_package(self, module, dependent_spec):
module.cargo = Executable(os.path.join(self.spec.prefix.bin, "cargo"))
def setup_build_environment(self, env):
# Manually inject the path of ar for build.
ar = which("ar", required=True)