Add support for racket packages (#27564)

- Add variants for various common build flags, including support for both versions of the Racket VM environment.
- Prevent `-j` flags to `make`, which has been known to cause problems with Racket builds.
- Prefer the minimal release to improve install times. Bells and whistles carry their own runtime dependencies and should be installed via `raco`. An enterprising user may even create a `RacketPackage` class to make spack aware of `raco` installed packages.
- Match the official version numbering scheme.
This commit is contained in:
Thomas Dickerson
2022-04-04 04:32:25 -04:00
committed by GitHub
parent d61e54b4c7
commit ee505e6c69
13 changed files with 332 additions and 0 deletions

View File

@@ -51,6 +51,7 @@ on these ideas for each distinct build system that Spack supports:
build_systems/perlpackage
build_systems/pythonpackage
build_systems/rpackage
build_systems/racketpackage
build_systems/rubypackage
.. toctree::

View File

@@ -0,0 +1,46 @@
.. Copyright 2013-2021 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)
.. _racketpackage:
-------------
RacketPackage
-------------
Much like Python, Racket packages and modules have their own special build system.
To learn more about the specifics of Racket package system, please refer to the
`Racket Docs <https://docs.racket-lang.org/pkg/cmdline.html>`_.
^^^^^^
Phases
^^^^^^
The ``RacketPackage`` base class provides an ``install`` phase that
can be overridden, corresponding to the use of:
.. code-block:: console
$ raco pkg install
^^^^^^^
Caveats
^^^^^^^
In principle, ``raco`` supports a second, ``setup`` phase; however, we have not
implemented this separately, as in normal circumstances, ``install`` also handles
running ``setup`` automatically.
Unlike Python, Racket currently on supports two installation scopes for packages, user
or system, and keeps a registry of installed packages at each scope in its configuration files.
This means we can't simply compose a "``RACKET_PATH``" environment variable listing all of the
places packages are installed, and update this at will.
Unfortunately this means that all currently installed packages which extend Racket via ``raco pkg install``
are accessible whenever Racket is accessible.
Additionally, because Spack does not implement uninstall hooks, uninstalling a Spack ``rkt-`` package
will have no effect on the ``raco`` installed packages visible to your Racket installation.
Instead, you must manually run ``raco pkg remove`` to keep the two package managers in a mutually
consistent state.

View File

@@ -0,0 +1,70 @@
# Copyright 2013-2021 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 os
import llnl.util.tty as tty
from llnl.util.filesystem import working_dir
from spack.build_environment import SPACK_NO_PARALLEL_MAKE, determine_number_of_jobs
from spack.directives import extends
from spack.package import PackageBase
from spack.util.environment import env_flag
from spack.util.executable import Executable, ProcessError
class RacketPackage(PackageBase):
"""Specialized class for packages that are built using Racket's
`raco pkg install` and `raco setup` commands.
This class provides the following phases that can be overridden:
* install
* setup
"""
#: Package name, version, and extension on PyPI
maintainers = ['elfprince13']
# Default phases
phases = ['install']
# To be used in UI queries that require to know which
# build-system class we are using
build_system_class = 'RacketPackage'
extends('racket')
pkgs = False
subdirectory = None
name = None
parallel = True
@property
def homepage(self):
if self.pkgs:
return 'https://pkgs.racket-lang.org/package/{0}'.format(self.name)
@property
def build_directory(self):
ret = os.getcwd()
if self.subdirectory:
ret = os.path.join(ret, self.subdirectory)
return ret
def install(self, spec, prefix):
"""Install everything from build directory."""
raco = Executable("raco")
with working_dir(self.build_directory):
allow_parallel = self.parallel and (not env_flag(SPACK_NO_PARALLEL_MAKE))
args = ['pkg', 'install', '-t', 'dir', '-n', self.name, '--deps', 'fail',
'--ignore-implies', '--copy', '-i', '-j',
str(determine_number_of_jobs(allow_parallel)),
'--', os.getcwd()]
try:
raco(*args)
except ProcessError:
args.insert(-2, "--skip-installed")
raco(*args)
tty.warn(("Racket package {0} was already installed, uninstalling via "
"Spack may make someone unhappy!").format(self.name))

View File

@@ -258,6 +258,42 @@ def install(self, spec, prefix):
bazel()"""
class RacketPackageTemplate(PackageTemplate):
"""Provides approriate overrides for Racket extensions"""
base_class_name = 'RacketPackage'
url_line = """\
# FIXME: set the proper location from which to fetch your package
git = "git@github.com:example/example.git"
"""
dependencies = """\
# FIXME: Add dependencies if required. Only add the racket dependency
# if you need specific versions. A generic racket dependency is
# added implicity by the RacketPackage class.
# depends_on('racket@8.3:', type=('build', 'run'))"""
body_def = """\
# FIXME: specify the name of the package,
# as it should appear to ``raco pkg install``
name = '{0}'
# FIXME: set to true if published on pkgs.racket-lang.org
# pkgs = False
# FIXME: specify path to the root directory of the
# package, if not the base directory
# subdirectory = None
"""
def __init__(self, name, url, *args, **kwargs):
# If the user provided `--name rkt-scribble`, don't rename it rkt-rkt-scribble
if not name.startswith('rkt-'):
# Make it more obvious that we are renaming the package
tty.msg("Changing package name from {0} to rkt-{0}".format(name))
name = 'rkt-{0}'.format(name)
self.body_def = self.body_def.format(name[4:])
super(RacketPackageTemplate, self).__init__(name, url, *args, **kwargs)
class PythonPackageTemplate(PackageTemplate):
"""Provides appropriate overrides for python extensions"""
base_class_name = 'PythonPackage'
@@ -536,6 +572,7 @@ def __init__(self, name, *args, **kwargs):
'bazel': BazelPackageTemplate,
'python': PythonPackageTemplate,
'r': RPackageTemplate,
'racket': RacketPackageTemplate,
'perlmake': PerlmakePackageTemplate,
'perlbuild': PerlbuildPackageTemplate,
'octave': OctavePackageTemplate,

View File

@@ -38,6 +38,7 @@
from spack.build_systems.python import PythonPackage
from spack.build_systems.qmake import QMakePackage
from spack.build_systems.r import RPackage
from spack.build_systems.racket import RacketPackage
from spack.build_systems.rocm import ROCmPackage
from spack.build_systems.ruby import RubyPackage
from spack.build_systems.scons import SConsPackage