diff options
-rw-r--r-- | README | 32 | ||||
-rwxr-xr-x | morphlib/app.py | 5 | ||||
-rw-r--r-- | morphlib/builder2.py | 18 | ||||
-rw-r--r-- | morphlib/buildsystem.py | 14 | ||||
-rw-r--r-- | morphlib/morph2.py | 8 | ||||
-rw-r--r-- | morphlib/morph2_tests.py | 16 | ||||
-rw-r--r-- | morphlib/util.py | 17 |
7 files changed, 102 insertions, 8 deletions
@@ -80,15 +80,44 @@ For chunks, use the following fields: `*-commands` fields; only `autotools` is currently known; the commands that the build system specifies can be overridden; optional + +* `pre-configure-commands`: a list of shell commands to run at + the configuration phase of a build, before the list in `configure-commands`; + optional * `configure-commands`: a list of shell commands to run at the configuraiton phase of a build; optional +* `post-configure-commands`: a list of shell commands to run at + the configuration phase of a build, after the list in `configure-commands`; + optional + +* `pre-build-commands`: a list of shell commands to run at + the build phase of a build, before the list in `build-commands`; + optional * `build-commands`: a list of shell commands to run to build (compile) the project; optional +* `post-build-commands`: a list of shell commands to run at + the build phase of a build, after the list in `build-commands`; + optional + +* `pre-test-commands`: a list of shell commands to run at + the test phase of a build, before the list in `test-commands`; + optional * `test-commands`: a list of shell commands to run unit tests and other non-interactive tests on the built but un-installed project; optional +* `post-test-commands`: a list of shell commands to run at + the test phase of a build, after the list in `test-commands`; + optional + +* `pre-install-commands`: a list of shell commands to run at + the install phase of a build, before the list in `install-commands`; + optional * `install-commands`: a list of shell commands to install the built project; the install should go into the directory named in the `DESTDIR` environment variable, not the actual system; optional +* `post-install-commands`: a list of shell commands to run at + the install phase of a build, after the list in `install-commands`; + optional + * `max-jobs`: a string to be given to `make` as the argument to the `-j` option to specify the maximum number of parallel jobs; the only sensible value is `"1"` (including the quotes), to prevent parallel jobs to run @@ -96,6 +125,7 @@ For chunks, use the following fields: since the other phases are often not safe when run in parallel; `morph` picks a default value based on the number of CPUs on the host system; optional + * `chunks`: a key/value map of lists of regular expressions; the key is the name of a binary chunk, the regexps match the pathnames that will be @@ -332,7 +362,7 @@ uses the strata that were build in stage 2. Legalese -------- -Copyright (C) 2011, 2012 Codethink Limited +Copyright (C) 2011-2013 Codethink Limited This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/morphlib/app.py b/morphlib/app.py index 21e18e32..87710ee5 100755 --- a/morphlib/app.py +++ b/morphlib/app.py @@ -395,8 +395,9 @@ class Morph(cliapp.Application): chatty=True) # Log the environment. - for name in kwargs['env']: - logging.debug('environment: %s=%s' % (name, kwargs['env'][name])) + prev = getattr(self, 'prev_env', {}) + morphlib.util.log_dict_diff(kwargs['env'], prev) + self.prev_env = kwargs['env'] # run the command line return cliapp.Application.runcmd(self, argv, *args, **kwargs) diff --git a/morphlib/builder2.py b/morphlib/builder2.py index 82a95820..73745d66 100644 --- a/morphlib/builder2.py +++ b/morphlib/builder2.py @@ -377,10 +377,20 @@ class ChunkBuilder(BuilderBase): relative_destdir = self.staging_area.relative(destdir) self.build_env.env['DESTDIR'] = relative_destdir - steps = [('configure', False), - ('build', True), - ('test', False), - ('install', False)] + steps = [ + ('pre-configure', False), + ('configure', False), + ('post-configure', False), + ('pre-build', True), + ('build', True), + ('post-build', True), + ('pre-test', False), + ('test', False), + ('post-test', False), + ('pre-install', False), + ('install', False), + ('post-install', False), + ] for step, in_parallel in steps: with self.build_watch(step): key = '%s-commands' % step diff --git a/morphlib/buildsystem.py b/morphlib/buildsystem.py index 6287063a..a6645eb2 100644 --- a/morphlib/buildsystem.py +++ b/morphlib/buildsystem.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012 Codethink Limited +# Copyright (C) 2012-2013 Codethink Limited # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -32,10 +32,18 @@ class BuildSystem(object): ''' def __init__(self): + self.pre_configure_commands = [] self.configure_commands = [] + self.post_configure_commands = [] + self.pre_build_commands = [] self.build_commands = [] + self.post_build_commands = [] + self.pre_test_commands = [] self.test_commands = [] + self.post_test_commands = [] + self.pre_install_commands = [] self.install_commands = [] + self.post_install_commands = [] def __getitem__(self, key): key = '_'.join(key.split('-')) @@ -82,6 +90,7 @@ class DummyBuildSystem(BuildSystem): name = 'dummy' def __init__(self): + BuildSystem.__init__(self) self.configure_commands = ['echo dummy configure'] self.build_commands = ['echo dummy build'] self.test_commands = ['echo dummy test'] @@ -98,6 +107,7 @@ class AutotoolsBuildSystem(BuildSystem): name = 'autotools' def __init__(self): + BuildSystem.__init__(self) self.configure_commands = [ 'export NOCONFIGURE=1; ' + 'if [ -e autogen ]; then ./autogen; ' + @@ -134,6 +144,7 @@ class PythonDistutilsBuildSystem(BuildSystem): name = 'python-distutils' def __init__(self): + BuildSystem.__init__(self) self.configure_commands = [ ] self.build_commands = [ @@ -160,6 +171,7 @@ class CPANBuildSystem(BuildSystem): name = 'cpan' def __init__(self): + BuildSystem.__init__(self) self.configure_commands = [ 'perl Makefile.PL INSTALLDIRS=perl ' 'INSTALLARCHLIB="$PREFIX/lib/perl" ' diff --git a/morphlib/morph2.py b/morphlib/morph2.py index ee58ecdc..3cdf49a9 100644 --- a/morphlib/morph2.py +++ b/morphlib/morph2.py @@ -32,10 +32,18 @@ class Morphology(object): static_defaults = { 'chunk': [ ('description', ''), + ('pre-configure-commands', None), ('configure-commands', None), + ('post-configure-commands', None), + ('pre-build-commands', None), ('build-commands', None), + ('post-build-commands', None), + ('pre-test-commands', None), ('test-commands', None), + ('post-test-commands', None), + ('pre-install-commands', None), ('install-commands', None), + ('post-install-commands', None), ('devices', None), ('chunks', []), ('max-jobs', None), diff --git a/morphlib/morph2_tests.py b/morphlib/morph2_tests.py index d2973d5c..49be9c8c 100644 --- a/morphlib/morph2_tests.py +++ b/morphlib/morph2_tests.py @@ -37,10 +37,18 @@ class MorphologyTests(unittest.TestCase): self.assertEqual(m['name'], 'foo') self.assertEqual(m['kind'], 'chunk') self.assertEqual(m['build-system'], 'manual') + self.assertEqual(m['pre-configure-commands'], None) self.assertEqual(m['configure-commands'], None) + self.assertEqual(m['post-configure-commands'], None) + self.assertEqual(m['pre-build-commands'], None) self.assertEqual(m['build-commands'], None) + self.assertEqual(m['post-build-commands'], None) + self.assertEqual(m['pre-test-commands'], None) self.assertEqual(m['test-commands'], None) + self.assertEqual(m['post-test-commands'], None) + self.assertEqual(m['pre-install-commands'], None) self.assertEqual(m['install-commands'], None) + self.assertEqual(m['post-install-commands'], None) self.assertEqual(m['max-jobs'], None) self.assertEqual(m['chunks'], []) @@ -55,10 +63,18 @@ class MorphologyTests(unittest.TestCase): self.assertEqual(m['name'], 'foo') self.assertEqual(m['kind'], 'chunk') self.assertEqual(m['build-system'], 'manual') + self.assertEqual(m['pre-configure-commands'], None) self.assertEqual(m['configure-commands'], None) + self.assertEqual(m['post-configure-commands'], None) + self.assertEqual(m['pre-build-commands'], None) self.assertEqual(m['build-commands'], None) + self.assertEqual(m['post-build-commands'], None) + self.assertEqual(m['pre-test-commands'], None) self.assertEqual(m['test-commands'], None) + self.assertEqual(m['post-test-commands'], None) + self.assertEqual(m['pre-install-commands'], None) self.assertEqual(m['install-commands'], None) + self.assertEqual(m['post-install-commands'], None) self.assertEqual(m['max-jobs'], None) self.assertEqual(m['chunks'], []) diff --git a/morphlib/util.py b/morphlib/util.py index c832a141..b4e06092 100644 --- a/morphlib/util.py +++ b/morphlib/util.py @@ -16,6 +16,7 @@ import re import morphlib +import logging '''Utility functions for morph.''' @@ -170,6 +171,22 @@ def new_repo_caches(app): # pragma: no cover return lrc, rrc +def log_dict_diff(cur, pre): # pragma: no cover + '''Log the differences between two dicts to debug log''' + dictA = cur + dictB = pre + for key in dictA.keys(): + if key not in dictB: + logging.debug("New environment: %s = %s" % (key, dictA[key])) + elif dictA[key] != dictB[key]: + logging.debug( + "Environment changed: %(key)s = %(valA)s to %(key)s = %(valB)s" + % {"key": key, "valA": dictA[key], "valB": dictB[key]}) + for key in dictB.keys(): + if key not in dictA: + logging.debug("Environment removed: %s = %s" % (key, dictB[key])) + + # This acquired from rdiff-backup which is GPLv2+ and a patch from 2011 # which has not yet been merged, combined with a tad of tidying from us. def copyfileobj(inputfp, outputfp, blocksize=1024*1024): # pragma: no cover |