Merge pull request #1171 from adamjstewart/features/octave
Allow spack create to automatically detect octave build system
This commit is contained in:
commit
653f25d676
@ -42,7 +42,8 @@ def setup_parser(subparser):
|
|||||||
'--keep-stage', action='store_true', dest='keep_stage',
|
'--keep-stage', action='store_true', dest='keep_stage',
|
||||||
help="Don't clean up staging area when command completes.")
|
help="Don't clean up staging area when command completes.")
|
||||||
subparser.add_argument(
|
subparser.add_argument(
|
||||||
'versions', nargs=argparse.REMAINDER, help='Versions to generate checksums for')
|
'versions', nargs=argparse.REMAINDER,
|
||||||
|
help='Versions to generate checksums for')
|
||||||
|
|
||||||
|
|
||||||
def get_checksums(versions, urls, **kwargs):
|
def get_checksums(versions, urls, **kwargs):
|
||||||
@ -59,10 +60,10 @@ def get_checksums(versions, urls, **kwargs):
|
|||||||
with Stage(url, keep=keep_stage) as stage:
|
with Stage(url, keep=keep_stage) as stage:
|
||||||
stage.fetch()
|
stage.fetch()
|
||||||
if i == 0 and first_stage_function:
|
if i == 0 and first_stage_function:
|
||||||
first_stage_function(stage)
|
first_stage_function(stage, url)
|
||||||
|
|
||||||
hashes.append((version,
|
hashes.append((version, spack.util.crypto.checksum(
|
||||||
spack.util.crypto.checksum(hashlib.md5, stage.archive_file)))
|
hashlib.md5, stage.archive_file)))
|
||||||
i += 1
|
i += 1
|
||||||
except FailedDownloadError as e:
|
except FailedDownloadError as e:
|
||||||
tty.msg("Failed to fetch %s" % url)
|
tty.msg("Failed to fetch %s" % url)
|
||||||
@ -79,12 +80,12 @@ def checksum(parser, args):
|
|||||||
# If the user asked for specific versions, use those.
|
# If the user asked for specific versions, use those.
|
||||||
if args.versions:
|
if args.versions:
|
||||||
versions = {}
|
versions = {}
|
||||||
for v in args.versions:
|
for version in args.versions:
|
||||||
v = ver(v)
|
version = ver(version)
|
||||||
if not isinstance(v, Version):
|
if not isinstance(version, Version):
|
||||||
tty.die("Cannot generate checksums for version lists or " +
|
tty.die("Cannot generate checksums for version lists or " +
|
||||||
"version ranges. Use unambiguous versions.")
|
"version ranges. Use unambiguous versions.")
|
||||||
versions[v] = pkg.url_for_version(v)
|
versions[version] = pkg.url_for_version(version)
|
||||||
else:
|
else:
|
||||||
versions = pkg.fetch_remote_versions()
|
versions = pkg.fetch_remote_versions()
|
||||||
if not versions:
|
if not versions:
|
||||||
@ -111,5 +112,7 @@ def checksum(parser, args):
|
|||||||
if not version_hashes:
|
if not version_hashes:
|
||||||
tty.die("Could not fetch any versions for %s" % pkg.name)
|
tty.die("Could not fetch any versions for %s" % pkg.name)
|
||||||
|
|
||||||
version_lines = [" version('%s', '%s')" % (v, h) for v, h in version_hashes]
|
version_lines = [
|
||||||
|
" version('%s', '%s')" % (v, h) for v, h in version_hashes
|
||||||
|
]
|
||||||
tty.msg("Checksummed new versions of %s:" % pkg.name, *version_lines)
|
tty.msg("Checksummed new versions of %s:" % pkg.name, *version_lines)
|
||||||
|
@ -103,6 +103,64 @@ def install(self, spec, prefix):
|
|||||||
${install}
|
${install}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
# Build dependencies and extensions
|
||||||
|
dependencies_dict = {
|
||||||
|
'autotools': "# depends_on('foo')",
|
||||||
|
'cmake': "depends_on('cmake')",
|
||||||
|
'scons': "depends_on('scons')",
|
||||||
|
'python': "extends('python')",
|
||||||
|
'R': "extends('R')",
|
||||||
|
'octave': "extends('octave')",
|
||||||
|
'unknown': "# depends_on('foo')"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default installation instructions
|
||||||
|
install_dict = {
|
||||||
|
'autotools': """\
|
||||||
|
# FIXME: Modify the configure line to suit your build system here.
|
||||||
|
configure('--prefix={0}'.format(prefix))
|
||||||
|
|
||||||
|
# FIXME: Add logic to build and install here.
|
||||||
|
make()
|
||||||
|
make('install')""",
|
||||||
|
|
||||||
|
'cmake': """\
|
||||||
|
with working_dir('spack-build', create=True):
|
||||||
|
# FIXME: Modify the cmake line to suit your build system here.
|
||||||
|
cmake('..', *std_cmake_args)
|
||||||
|
|
||||||
|
# FIXME: Add logic to build and install here.
|
||||||
|
make()
|
||||||
|
make('install')""",
|
||||||
|
|
||||||
|
'scons': """\
|
||||||
|
# FIXME: Add logic to build and install here.
|
||||||
|
scons('prefix={0}'.format(prefix))
|
||||||
|
scons('install')""",
|
||||||
|
|
||||||
|
'python': """\
|
||||||
|
# FIXME: Add logic to build and install here.
|
||||||
|
python('setup.py', 'install', '--prefix={0}'.format(prefix))""",
|
||||||
|
|
||||||
|
'R': """\
|
||||||
|
# FIXME: Add logic to build and install here.
|
||||||
|
R('CMD', 'INSTALL', '--library={0}'.format(self.module.r_lib_dir),
|
||||||
|
self.stage.source_path)""",
|
||||||
|
|
||||||
|
'octave': """\
|
||||||
|
# FIXME: Add logic to build and install here.
|
||||||
|
octave('--quiet', '--norc',
|
||||||
|
'--built-in-docstrings-file=/dev/null',
|
||||||
|
'--texi-macros-file=/dev/null',
|
||||||
|
'--eval', 'pkg prefix {0}; pkg install {1}'.format(
|
||||||
|
prefix, self.stage.archive_file))""",
|
||||||
|
|
||||||
|
'unknown': """\
|
||||||
|
# FIXME: Unknown build system
|
||||||
|
make()
|
||||||
|
make('install')"""
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def make_version_calls(ver_hash_tuples):
|
def make_version_calls(ver_hash_tuples):
|
||||||
"""Adds a version() call to the package for each version found."""
|
"""Adds a version() call to the package for each version found."""
|
||||||
@ -133,60 +191,17 @@ def setup_parser(subparser):
|
|||||||
setup_parser.subparser = subparser
|
setup_parser.subparser = subparser
|
||||||
|
|
||||||
|
|
||||||
class ConfigureGuesser(object):
|
class BuildSystemGuesser(object):
|
||||||
def __call__(self, stage):
|
def __call__(self, stage, url):
|
||||||
"""Try to guess the type of build system used by the project.
|
"""Try to guess the type of build system used by a project based on
|
||||||
Set any necessary build dependencies or extensions.
|
the contents of its archive or the URL it was downloaded from."""
|
||||||
Set the appropriate default installation instructions."""
|
|
||||||
|
|
||||||
# Build dependencies and extensions
|
# Most octave extensions are hosted on Octave-Forge:
|
||||||
dependenciesDict = {
|
# http://octave.sourceforge.net/index.html
|
||||||
'autotools': "# depends_on('foo')",
|
# They all have the same base URL.
|
||||||
'cmake': "depends_on('cmake', type='build')",
|
if 'downloads.sourceforge.net/octave/' in url:
|
||||||
'scons': "depends_on('scons', type='build')",
|
self.build_system = 'octave'
|
||||||
'python': "extends('python', type=nolink)",
|
return
|
||||||
'R': "extends('R')",
|
|
||||||
'unknown': "# depends_on('foo')"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Default installation instructions
|
|
||||||
installDict = {
|
|
||||||
'autotools': """\
|
|
||||||
# FIXME: Modify the configure line to suit your build system here.
|
|
||||||
configure('--prefix={0}'.format(prefix))
|
|
||||||
|
|
||||||
# FIXME: Add logic to build and install here.
|
|
||||||
make()
|
|
||||||
make('install')""",
|
|
||||||
|
|
||||||
'cmake': """\
|
|
||||||
with working_dir('spack-build', create=True):
|
|
||||||
# FIXME: Modify the cmake line to suit your build system here.
|
|
||||||
cmake('..', *std_cmake_args)
|
|
||||||
|
|
||||||
# FIXME: Add logic to build and install here.
|
|
||||||
make()
|
|
||||||
make('install')""",
|
|
||||||
|
|
||||||
'scons': """\
|
|
||||||
# FIXME: Add logic to build and install here.
|
|
||||||
scons('prefix={0}'.format(prefix))
|
|
||||||
scons('install')""",
|
|
||||||
|
|
||||||
'python': """\
|
|
||||||
# FIXME: Add logic to build and install here.
|
|
||||||
python('setup.py', 'install', '--prefix={0}'.format(prefix))""",
|
|
||||||
|
|
||||||
'R': """\
|
|
||||||
# FIXME: Add logic to build and install here.
|
|
||||||
R('CMD', 'INSTALL', '--library={0}'.format(self.module.r_lib_dir),
|
|
||||||
self.stage.source_path)""",
|
|
||||||
|
|
||||||
'unknown': """\
|
|
||||||
# FIXME: Unknown build system
|
|
||||||
make()
|
|
||||||
make('install')"""
|
|
||||||
}
|
|
||||||
|
|
||||||
# A list of clues that give us an idea of the build system a package
|
# A list of clues that give us an idea of the build system a package
|
||||||
# uses. If the regular expression matches a file contained in the
|
# uses. If the regular expression matches a file contained in the
|
||||||
@ -224,12 +239,6 @@ def __call__(self, stage):
|
|||||||
|
|
||||||
self.build_system = build_system
|
self.build_system = build_system
|
||||||
|
|
||||||
# Set any necessary build dependencies or extensions.
|
|
||||||
self.dependencies = dependenciesDict[build_system]
|
|
||||||
|
|
||||||
# Set the appropriate default installation instructions
|
|
||||||
self.install = installDict[build_system]
|
|
||||||
|
|
||||||
|
|
||||||
def guess_name_and_version(url, args):
|
def guess_name_and_version(url, args):
|
||||||
# Try to deduce name and version of the new package from the URL
|
# Try to deduce name and version of the new package from the URL
|
||||||
@ -334,8 +343,8 @@ def create(parser, args):
|
|||||||
# Fetch tarballs (prompting user if necessary)
|
# Fetch tarballs (prompting user if necessary)
|
||||||
versions, urls = fetch_tarballs(url, name, version)
|
versions, urls = fetch_tarballs(url, name, version)
|
||||||
|
|
||||||
# Try to guess what configure system is used.
|
# Try to guess what build system is used.
|
||||||
guesser = ConfigureGuesser()
|
guesser = BuildSystemGuesser()
|
||||||
ver_hash_tuples = spack.cmd.checksum.get_checksums(
|
ver_hash_tuples = spack.cmd.checksum.get_checksums(
|
||||||
versions, urls,
|
versions, urls,
|
||||||
first_stage_function=guesser,
|
first_stage_function=guesser,
|
||||||
@ -344,13 +353,13 @@ def create(parser, args):
|
|||||||
if not ver_hash_tuples:
|
if not ver_hash_tuples:
|
||||||
tty.die("Could not fetch any tarballs for %s" % name)
|
tty.die("Could not fetch any tarballs for %s" % name)
|
||||||
|
|
||||||
# Prepend 'py-' to python package names, by convention.
|
# Add prefix to package name if it is an extension.
|
||||||
if guesser.build_system == 'python':
|
if guesser.build_system == 'python':
|
||||||
name = 'py-%s' % name
|
name = 'py-{0}'.format(name)
|
||||||
|
|
||||||
# Prepend 'r-' to R package names, by convention.
|
|
||||||
if guesser.build_system == 'R':
|
if guesser.build_system == 'R':
|
||||||
name = 'r-%s' % name
|
name = 'r-{0}'.format(name)
|
||||||
|
if guesser.build_system == 'octave':
|
||||||
|
name = 'octave-{0}'.format(name)
|
||||||
|
|
||||||
# Create a directory for the new package.
|
# Create a directory for the new package.
|
||||||
pkg_path = repo.filename_for_package_name(name)
|
pkg_path = repo.filename_for_package_name(name)
|
||||||
@ -367,8 +376,8 @@ def create(parser, args):
|
|||||||
class_name=mod_to_class(name),
|
class_name=mod_to_class(name),
|
||||||
url=url,
|
url=url,
|
||||||
versions=make_version_calls(ver_hash_tuples),
|
versions=make_version_calls(ver_hash_tuples),
|
||||||
dependencies=guesser.dependencies,
|
dependencies=dependencies_dict[guesser.build_system],
|
||||||
install=guesser.install))
|
install=install_dict[guesser.build_system]))
|
||||||
|
|
||||||
# If everything checks out, go ahead and edit.
|
# If everything checks out, go ahead and edit.
|
||||||
spack.editor(pkg_path)
|
spack.editor(pkg_path)
|
||||||
|
@ -32,15 +32,16 @@
|
|||||||
from spack.test.tally_plugin import Tally
|
from spack.test.tally_plugin import Tally
|
||||||
"""Names of tests to be included in Spack's test suite"""
|
"""Names of tests to be included in Spack's test suite"""
|
||||||
|
|
||||||
test_names = ['architecture', 'versions', 'url_parse', 'url_substitution', 'packages', 'stage',
|
test_names = [
|
||||||
'spec_syntax', 'spec_semantics', 'spec_dag', 'concretize',
|
'architecture', 'versions', 'url_parse', 'url_substitution', 'packages',
|
||||||
'multimethod', 'install', 'package_sanity', 'config',
|
'stage', 'spec_syntax', 'spec_semantics', 'spec_dag', 'concretize',
|
||||||
'directory_layout', 'pattern', 'python_version', 'git_fetch',
|
'multimethod', 'install', 'package_sanity', 'config', 'directory_layout',
|
||||||
'svn_fetch', 'hg_fetch', 'mirror', 'modules', 'url_extrapolate',
|
'pattern', 'python_version', 'git_fetch', 'svn_fetch', 'hg_fetch',
|
||||||
'cc', 'link_tree', 'spec_yaml', 'optional_deps',
|
'mirror', 'modules', 'url_extrapolate', 'cc', 'link_tree', 'spec_yaml',
|
||||||
'make_executable', 'configure_guess', 'lock', 'database',
|
'optional_deps', 'make_executable', 'build_system_guess', 'lock',
|
||||||
'namespace_trie', 'yaml', 'sbang', 'environment', 'cmd.find',
|
'database', 'namespace_trie', 'yaml', 'sbang', 'environment', 'cmd.find',
|
||||||
'cmd.uninstall', 'cmd.test_install', 'cmd.test_compiler_cmd']
|
'cmd.uninstall', 'cmd.test_install', 'cmd.test_compiler_cmd'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def list_tests():
|
def list_tests():
|
||||||
|
@ -28,14 +28,14 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from llnl.util.filesystem import *
|
from llnl.util.filesystem import *
|
||||||
from spack.cmd.create import ConfigureGuesser
|
from spack.cmd.create import BuildSystemGuesser
|
||||||
from spack.stage import Stage
|
from spack.stage import Stage
|
||||||
from spack.test.mock_packages_test import *
|
from spack.test.mock_packages_test import *
|
||||||
from spack.util.executable import which
|
from spack.util.executable import which
|
||||||
|
|
||||||
|
|
||||||
class InstallTest(unittest.TestCase):
|
class InstallTest(unittest.TestCase):
|
||||||
"""Tests the configure guesser in spack create"""
|
"""Tests the build system guesser in spack create"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.tar = which('tar')
|
self.tar = which('tar')
|
||||||
@ -44,12 +44,10 @@ def setUp(self):
|
|||||||
os.chdir(self.tmpdir)
|
os.chdir(self.tmpdir)
|
||||||
self.stage = None
|
self.stage = None
|
||||||
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
shutil.rmtree(self.tmpdir, ignore_errors=True)
|
shutil.rmtree(self.tmpdir, ignore_errors=True)
|
||||||
os.chdir(self.orig_dir)
|
os.chdir(self.orig_dir)
|
||||||
|
|
||||||
|
|
||||||
def check_archive(self, filename, system):
|
def check_archive(self, filename, system):
|
||||||
mkdirp('archive')
|
mkdirp('archive')
|
||||||
touch(join_path('archive', filename))
|
touch(join_path('archive', filename))
|
||||||
@ -60,24 +58,24 @@ def check_archive(self, filename, system):
|
|||||||
with Stage(url) as stage:
|
with Stage(url) as stage:
|
||||||
stage.fetch()
|
stage.fetch()
|
||||||
|
|
||||||
guesser = ConfigureGuesser()
|
guesser = BuildSystemGuesser()
|
||||||
guesser(stage)
|
guesser(stage, url)
|
||||||
self.assertEqual(system, guesser.build_system)
|
self.assertEqual(system, guesser.build_system)
|
||||||
|
|
||||||
|
|
||||||
def test_python(self):
|
|
||||||
self.check_archive('setup.py', 'python')
|
|
||||||
|
|
||||||
|
|
||||||
def test_autotools(self):
|
def test_autotools(self):
|
||||||
self.check_archive('configure', 'autotools')
|
self.check_archive('configure', 'autotools')
|
||||||
|
|
||||||
|
|
||||||
def test_cmake(self):
|
def test_cmake(self):
|
||||||
self.check_archive('CMakeLists.txt', 'cmake')
|
self.check_archive('CMakeLists.txt', 'cmake')
|
||||||
|
|
||||||
|
def test_scons(self):
|
||||||
|
self.check_archive('SConstruct', 'scons')
|
||||||
|
|
||||||
|
def test_python(self):
|
||||||
|
self.check_archive('setup.py', 'python')
|
||||||
|
|
||||||
|
def test_R(self):
|
||||||
|
self.check_archive('NAMESPACE', 'R')
|
||||||
|
|
||||||
def test_unknown(self):
|
def test_unknown(self):
|
||||||
self.check_archive('foobar', 'unknown')
|
self.check_archive('foobar', 'unknown')
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user