spack create : now creates packages that are derived from AutotoolsPackage and CMakePackage

This commit is contained in:
alalazo 2016-10-21 22:12:21 +02:00
parent 2251428f0a
commit 04821c7be8
2 changed files with 161 additions and 102 deletions

View File

@ -22,25 +22,24 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import string from __future__ import print_function
import os import os
import re import re
import string
from ordereddict_backport import OrderedDict
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.filesystem import mkdirp
import spack import spack
import spack.cmd import spack.cmd
import spack.cmd.checksum import spack.cmd.checksum
import spack.url import spack.url
import spack.util.web import spack.util.web
from spack.spec import Spec from llnl.util.filesystem import mkdirp
from spack.util.naming import * from ordereddict_backport import OrderedDict
from spack.repository import Repo, RepoError from spack.repository import Repo, RepoError
from spack.spec import Spec
from spack.util.executable import which from spack.util.executable import which
from spack.util.naming import *
description = "Create a new package file from an archive URL" description = "Create a new package file from an archive URL"
@ -87,7 +86,7 @@
from spack import * from spack import *
class ${class_name}(Package): class ${class_name}(${base_class_name}):
""\"FIXME: Put a proper description of your package here.""\" ""\"FIXME: Put a proper description of your package here.""\"
# FIXME: Add a proper url for your package's homepage here. # FIXME: Add a proper url for your package's homepage here.
@ -98,109 +97,158 @@ class ${class_name}(Package):
${dependencies} ${dependencies}
def install(self, spec, prefix): ${body}
${install}
""") """)
# Build dependencies and extensions
dependencies_dict = { class DefaultGuess(object):
'autotools': """\
base_class_name = 'Package'
dependencies = """\
# FIXME: Add dependencies if required. # FIXME: Add dependencies if required.
# depends_on('foo')""", # depends_on('foo')"""
'cmake': """\ body = """\
def install(self, spec, prefix):
# FIXME: Unknown build system
make()
make('install')"""
def __init__(self, name, url, version_hash_tuples):
self.name = name
self.class_name = mod_to_class(name)
self.url = url
self.version_hash_tuples = version_hash_tuples
@property
def versions(self):
"""Adds a version() call to the package for each version found."""
max_len = max(len(str(v)) for v, h in self.version_hash_tuples)
format = " version(%%-%ds, '%%s')" % (max_len + 2)
return '\n'.join(format % ("'%s'" % v, h) for v, h in self.version_hash_tuples)
class AutotoolsGuess(DefaultGuess):
base_class_name = 'AutotoolsPackage'
dependencies = """\
# FIXME: Add dependencies if required.
# depends_on('m4', type='build')
# depends_on('autoconf', type='build')
# depends_on('automake', type='build')
# depends_on('libtool', type='build')
# depends_on('foo')"""
body = """\
def configure_args(self):
# FIXME : Add arguments other than --prefix
# FIXME : If not needed delete the function
args = []
return args"""
class CMakeGuess(DefaultGuess):
base_class_name = 'CMakePackage'
dependencies = """\
# FIXME: Add additional dependencies if required. # FIXME: Add additional dependencies if required.
depends_on('cmake', type='build')""", depends_on('cmake', type='build')"""
'scons': """\ body = """\
def cmake_args(self):
# FIXME : Add arguments other than
# FIXME : CMAKE_INSTALL_PREFIX and CMAKE_BUILD_TYPE
# FIXME : If not needed delete the function
args = []
return args"""
class SconsGuess(DefaultGuess):
dependencies = """\
# FIXME: Add additional dependencies if required. # FIXME: Add additional dependencies if required.
depends_on('scons', type='build')""", depends_on('scons', type='build')"""
'bazel': """\ body = """\
def install(self, spec, prefix):
# FIXME: Add logic to build and install here.
scons('prefix={0}'.format(prefix))
scons('install')"""
class BazelGuess(DefaultGuess):
dependencies = """\
# FIXME: Add additional dependencies if required. # FIXME: Add additional dependencies if required.
depends_on('bazel', type='build')""", depends_on('bazel', type='build')"""
'python': """\ body = """\
def install(self, spec, prefix):
# FIXME: Add logic to build and install here.
bazel()"""
class PythonGuess(DefaultGuess):
dependencies = """\
extends('python') extends('python')
# FIXME: Add additional dependencies if required. # FIXME: Add additional dependencies if required.
# depends_on('py-setuptools', type='build') # depends_on('py-setuptools', type='build')
# depends_on('py-foo', type=nolink)""", # depends_on('py-foo', type=nolink)"""
'R': """\ body = """\
def install(self, spec, prefix):
# FIXME: Add logic to build and install here.
setup_py('install', '--prefix={0}'.format(prefix))"""
def __init__(self, name, *args):
name = 'py-{0}'.format(name)
super(PythonGuess, self).__init__(name, *args)
class RGuess(DefaultGuess):
dependencies = """\
extends('R') extends('R')
# FIXME: Add additional dependencies if required. # FIXME: Add additional dependencies if required.
# depends_on('r-foo', type=nolink)""", # depends_on('r-foo', type=nolink)"""
'octave': """\ body = """\
def install(self, spec, prefix):
# FIXME: Add logic to build and install here.
R('CMD', 'INSTALL', '--library={0}'.format(self.module.r_lib_dir),
self.stage.source_path)"""
def __init__(self, name, *args):
name = 'r-{0}'.format(name)
super(RGuess, self).__init__(name, *args)
class OctaveGuess(DefaultGuess):
dependencies = """\
extends('octave') extends('octave')
# FIXME: Add additional dependencies if required. # FIXME: Add additional dependencies if required.
# depends_on('octave-foo', type=nolink)""", # depends_on('octave-foo', type=nolink)"""
'unknown': """\ body = """\
# FIXME: Add dependencies if required. def install(self, spec, prefix):
# 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')""",
'bazel': """\
# FIXME: Add logic to build and install here.
bazel()""",
'python': """\
# FIXME: Add logic to build and install here.
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. # FIXME: Add logic to build and install here.
octave('--quiet', '--norc', octave('--quiet', '--norc',
'--built-in-docstrings-file=/dev/null', '--built-in-docstrings-file=/dev/null',
'--texi-macros-file=/dev/null', '--texi-macros-file=/dev/null',
'--eval', 'pkg prefix {0}; pkg install {1}'.format( '--eval', 'pkg prefix {0}; pkg install {1}'.format(
prefix, self.stage.archive_file))""", prefix, self.stage.archive_file))"""
'unknown': """\ def __init__(self, name, *args):
# FIXME: Unknown build system name = 'octave-{0}'.format(name)
make() super(OctaveGuess, self).__init__(name, *args)
make('install')"""
}
def make_version_calls(ver_hash_tuples):
"""Adds a version() call to the package for each version found."""
max_len = max(len(str(v)) for v, h in ver_hash_tuples)
format = " version(%%-%ds, '%%s')" % (max_len + 2)
return '\n'.join(format % ("'%s'" % v, h) for v, h in ver_hash_tuples)
def setup_parser(subparser): def setup_parser(subparser):
@ -227,6 +275,16 @@ def setup_parser(subparser):
class BuildSystemGuesser(object): class BuildSystemGuesser(object):
_choiches = {
'autotools': AutotoolsGuess,
'cmake': CMakeGuess,
'scons': SconsGuess,
'bazel': BazelGuess,
'python': PythonGuess,
'R': RGuess,
'octave': OctaveGuess
}
def __call__(self, stage, url): def __call__(self, stage, url):
"""Try to guess the type of build system used by a project based on """Try to guess the type of build system used by a project based on
the contents of its archive or the URL it was downloaded from.""" the contents of its archive or the URL it was downloaded from."""
@ -275,6 +333,10 @@ def __call__(self, stage, url):
self.build_system = build_system self.build_system = build_system
def make_guess(self, name, url, ver_hash_tuples):
cls = self._choiches.get(self.build_system, DefaultGuess)
return cls(name, url, ver_hash_tuples)
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
@ -348,7 +410,7 @@ def fetch_tarballs(url, name, version):
tty.msg("Found %s versions of %s:" % (len(versions), name), tty.msg("Found %s versions of %s:" % (len(versions), name),
*spack.cmd.elide_list( *spack.cmd.elide_list(
["%-10s%s" % (v, u) for v, u in versions.iteritems()])) ["%-10s%s" % (v, u) for v, u in versions.iteritems()]))
print print('')
archives_to_fetch = tty.get_number( archives_to_fetch = tty.get_number(
"Include how many checksums in the package file?", "Include how many checksums in the package file?",
default=5, abort='q') default=5, abort='q')
@ -389,16 +451,10 @@ 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)
# Add prefix to package name if it is an extension. guess = guesser.make_guess(name, url, ver_hash_tuples)
if guesser.build_system == 'python':
name = 'py-{0}'.format(name)
if guesser.build_system == 'R':
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(guess.name)
if os.path.exists(pkg_path) and not args.force: if os.path.exists(pkg_path) and not args.force:
tty.die("%s already exists." % pkg_path) tty.die("%s already exists." % pkg_path)
else: else:
@ -408,12 +464,15 @@ def create(parser, args):
with open(pkg_path, "w") as pkg_file: with open(pkg_path, "w") as pkg_file:
pkg_file.write( pkg_file.write(
package_template.substitute( package_template.substitute(
name=name, name=guess.name,
class_name=mod_to_class(name), class_name=guess.class_name,
url=url, base_class_name=guess.base_class_name,
versions=make_version_calls(ver_hash_tuples), url=guess.url,
dependencies=dependencies_dict[guesser.build_system], versions=guess.versions,
install=install_dict[guesser.build_system])) dependencies=guess.dependencies,
body=guess.body
)
)
# If everything checks out, go ahead and edit. # If everything checks out, go ahead and edit.
spack.editor(pkg_path) spack.editor(pkg_path)

View File

@ -1686,10 +1686,10 @@ def wdir(self):
return self.stage.source_path return self.stage.source_path
def build_args(self): def build_args(self):
return list() return []
def install_args(self): def install_args(self):
return list() return []
def edit(self, spec, prefix): def edit(self, spec, prefix):
raise NotImplementedError('\'edit\' function not implemented') raise NotImplementedError('\'edit\' function not implemented')
@ -1721,7 +1721,7 @@ def is_configure_or_die(self):
'configure script not found in {0}'.format(os.getcwd())) 'configure script not found in {0}'.format(os.getcwd()))
def configure_args(self): def configure_args(self):
return list() return []
def configure(self, spec, prefix): def configure(self, spec, prefix):
options = ['--prefix={0}'.format(prefix)] + self.configure_args() options = ['--prefix={0}'.format(prefix)] + self.configure_args()
@ -1761,7 +1761,7 @@ def _std_args(pkg):
args = ['-DCMAKE_INSTALL_PREFIX:PATH={0}'.format(pkg.prefix), args = ['-DCMAKE_INSTALL_PREFIX:PATH={0}'.format(pkg.prefix),
'-DCMAKE_BUILD_TYPE:STRING={0}'.format(build_type), '-DCMAKE_BUILD_TYPE:STRING={0}'.format(build_type),
'-DCMAKE_VERBOSE_MAKEFILE=ON'] '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON']
if platform.mac_ver()[0]: if platform.mac_ver()[0]:
args.append('-DCMAKE_FIND_FRAMEWORK:STRING=LAST') args.append('-DCMAKE_FIND_FRAMEWORK:STRING=LAST')