Merge pull request #1171 from adamjstewart/features/octave
Allow spack create to automatically detect octave build system
This commit is contained in:
		| @@ -42,7 +42,8 @@ def setup_parser(subparser): | ||||
|         '--keep-stage', action='store_true', dest='keep_stage', | ||||
|         help="Don't clean up staging area when command completes.") | ||||
|     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): | ||||
| @@ -59,10 +60,10 @@ def get_checksums(versions, urls, **kwargs): | ||||
|             with Stage(url, keep=keep_stage) as stage: | ||||
|                 stage.fetch() | ||||
|                 if i == 0 and first_stage_function: | ||||
|                     first_stage_function(stage) | ||||
|                     first_stage_function(stage, url) | ||||
|  | ||||
|                 hashes.append((version, | ||||
|                                spack.util.crypto.checksum(hashlib.md5, stage.archive_file))) | ||||
|                 hashes.append((version, spack.util.crypto.checksum( | ||||
|                     hashlib.md5, stage.archive_file))) | ||||
|                 i += 1 | ||||
|         except FailedDownloadError as e: | ||||
|             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 args.versions: | ||||
|         versions = {} | ||||
|         for v in args.versions: | ||||
|             v = ver(v) | ||||
|             if not isinstance(v, Version): | ||||
|         for version in args.versions: | ||||
|             version = ver(version) | ||||
|             if not isinstance(version, Version): | ||||
|                 tty.die("Cannot generate checksums for version lists or " + | ||||
|                         "version ranges.  Use unambiguous versions.") | ||||
|             versions[v] = pkg.url_for_version(v) | ||||
|             versions[version] = pkg.url_for_version(version) | ||||
|     else: | ||||
|         versions = pkg.fetch_remote_versions() | ||||
|         if not versions: | ||||
| @@ -111,5 +112,7 @@ def checksum(parser, args): | ||||
|     if not version_hashes: | ||||
|         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) | ||||
|   | ||||
| @@ -103,6 +103,64 @@ def install(self, spec, prefix): | ||||
| ${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): | ||||
|     """Adds a version() call to the package for each version found.""" | ||||
| @@ -133,60 +191,17 @@ def setup_parser(subparser): | ||||
|     setup_parser.subparser = subparser | ||||
|  | ||||
|  | ||||
| class ConfigureGuesser(object): | ||||
|     def __call__(self, stage): | ||||
|         """Try to guess the type of build system used by the project. | ||||
|         Set any necessary build dependencies or extensions. | ||||
|         Set the appropriate default installation instructions.""" | ||||
| class BuildSystemGuesser(object): | ||||
|     def __call__(self, stage, url): | ||||
|         """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.""" | ||||
|  | ||||
|         # Build dependencies and extensions | ||||
|         dependenciesDict = { | ||||
|             'autotools': "# depends_on('foo')", | ||||
|             'cmake':     "depends_on('cmake', type='build')", | ||||
|             'scons':     "depends_on('scons', type='build')", | ||||
|             'python':    "extends('python', type=nolink)", | ||||
|             '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')""" | ||||
|         } | ||||
|         # Most octave extensions are hosted on Octave-Forge: | ||||
|         #     http://octave.sourceforge.net/index.html | ||||
|         # They all have the same base URL. | ||||
|         if 'downloads.sourceforge.net/octave/' in url: | ||||
|             self.build_system = 'octave' | ||||
|             return | ||||
|  | ||||
|         # 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 | ||||
| @@ -224,12 +239,6 @@ def __call__(self, stage): | ||||
|  | ||||
|         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): | ||||
|     # 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) | ||||
|     versions, urls = fetch_tarballs(url, name, version) | ||||
|  | ||||
|     # Try to guess what configure system is used. | ||||
|     guesser = ConfigureGuesser() | ||||
|     # Try to guess what build system is used. | ||||
|     guesser = BuildSystemGuesser() | ||||
|     ver_hash_tuples = spack.cmd.checksum.get_checksums( | ||||
|         versions, urls, | ||||
|         first_stage_function=guesser, | ||||
| @@ -344,13 +353,13 @@ def create(parser, args): | ||||
|     if not ver_hash_tuples: | ||||
|         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': | ||||
|         name = 'py-%s' % name | ||||
|  | ||||
|     # Prepend 'r-' to R package names, by convention. | ||||
|         name = 'py-{0}'.format(name) | ||||
|     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. | ||||
|     pkg_path = repo.filename_for_package_name(name) | ||||
| @@ -367,8 +376,8 @@ def create(parser, args): | ||||
|                 class_name=mod_to_class(name), | ||||
|                 url=url, | ||||
|                 versions=make_version_calls(ver_hash_tuples), | ||||
|                 dependencies=guesser.dependencies, | ||||
|                 install=guesser.install)) | ||||
|                 dependencies=dependencies_dict[guesser.build_system], | ||||
|                 install=install_dict[guesser.build_system])) | ||||
|  | ||||
|     # If everything checks out, go ahead and edit. | ||||
|     spack.editor(pkg_path) | ||||
|   | ||||
| @@ -32,15 +32,16 @@ | ||||
| from spack.test.tally_plugin import Tally | ||||
| """Names of tests to be included in Spack's test suite""" | ||||
|  | ||||
| test_names = ['architecture', 'versions', 'url_parse', 'url_substitution', 'packages', 'stage', | ||||
|               'spec_syntax', 'spec_semantics', 'spec_dag', 'concretize', | ||||
|               'multimethod', 'install', 'package_sanity', 'config', | ||||
|               'directory_layout', 'pattern', 'python_version', 'git_fetch', | ||||
|               'svn_fetch', 'hg_fetch', 'mirror', 'modules', 'url_extrapolate', | ||||
|               'cc', 'link_tree', 'spec_yaml', 'optional_deps', | ||||
|               'make_executable', 'configure_guess', 'lock', 'database', | ||||
|               'namespace_trie', 'yaml', 'sbang', 'environment', 'cmd.find', | ||||
|               'cmd.uninstall', 'cmd.test_install', 'cmd.test_compiler_cmd'] | ||||
| test_names = [ | ||||
|     'architecture', 'versions', 'url_parse', 'url_substitution', 'packages', | ||||
|     'stage', 'spec_syntax', 'spec_semantics', 'spec_dag', 'concretize', | ||||
|     'multimethod', 'install', 'package_sanity', 'config', 'directory_layout', | ||||
|     'pattern', 'python_version', 'git_fetch', 'svn_fetch', 'hg_fetch', | ||||
|     'mirror', 'modules', 'url_extrapolate', 'cc', 'link_tree', 'spec_yaml', | ||||
|     'optional_deps', 'make_executable', 'build_system_guess', 'lock', | ||||
|     'database', 'namespace_trie', 'yaml', 'sbang', 'environment', 'cmd.find', | ||||
|     'cmd.uninstall', 'cmd.test_install', 'cmd.test_compiler_cmd' | ||||
| ] | ||||
|  | ||||
|  | ||||
| def list_tests(): | ||||
|   | ||||
| @@ -28,14 +28,14 @@ | ||||
| import unittest | ||||
| 
 | ||||
| from llnl.util.filesystem import * | ||||
| from spack.cmd.create import ConfigureGuesser | ||||
| from spack.cmd.create import BuildSystemGuesser | ||||
| from spack.stage import Stage | ||||
| from spack.test.mock_packages_test import * | ||||
| from spack.util.executable import which | ||||
| 
 | ||||
| 
 | ||||
| class InstallTest(unittest.TestCase): | ||||
|     """Tests the configure guesser in spack create""" | ||||
|     """Tests the build system guesser in spack create""" | ||||
| 
 | ||||
|     def setUp(self): | ||||
|         self.tar = which('tar') | ||||
| @@ -44,12 +44,10 @@ def setUp(self): | ||||
|         os.chdir(self.tmpdir) | ||||
|         self.stage = None | ||||
| 
 | ||||
| 
 | ||||
|     def tearDown(self): | ||||
|         shutil.rmtree(self.tmpdir, ignore_errors=True) | ||||
|         os.chdir(self.orig_dir) | ||||
| 
 | ||||
| 
 | ||||
|     def check_archive(self, filename, system): | ||||
|         mkdirp('archive') | ||||
|         touch(join_path('archive', filename)) | ||||
| @@ -60,24 +58,24 @@ def check_archive(self, filename, system): | ||||
|         with Stage(url) as stage: | ||||
|             stage.fetch() | ||||
| 
 | ||||
|             guesser = ConfigureGuesser() | ||||
|             guesser(stage) | ||||
|             guesser = BuildSystemGuesser() | ||||
|             guesser(stage, url) | ||||
|             self.assertEqual(system, guesser.build_system) | ||||
| 
 | ||||
| 
 | ||||
|     def test_python(self): | ||||
|         self.check_archive('setup.py', 'python') | ||||
| 
 | ||||
| 
 | ||||
|     def test_autotools(self): | ||||
|         self.check_archive('configure', 'autotools') | ||||
| 
 | ||||
| 
 | ||||
|     def test_cmake(self): | ||||
|         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): | ||||
|         self.check_archive('foobar', 'unknown') | ||||
| 
 | ||||
| 
 | ||||
		Reference in New Issue
	
	Block a user
	 Todd Gamblin
					Todd Gamblin