Skip to content

Commit

Permalink
Merge pull request #352 from kyrofa/backport/autotools_support_instal…
Browse files Browse the repository at this point in the history
…l_via_prefix

Backport to 1.x: Autotools plugin: Support installing via prefix.
  • Loading branch information
Kyle Fazzari committed Mar 1, 2016
2 parents 34f96cb + b9feb1c commit c5986c2
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 7 deletions.
34 changes: 31 additions & 3 deletions snapcraft/plugins/autotools.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright (C) 2015 Canonical Ltd
# Copyright (C) 2015, 2016 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
Expand Down Expand Up @@ -32,6 +32,10 @@
(list of strings)
configure flags to pass to the build such as those shown by running
'./configure --help'
- install-via:
(enum, 'destdir' or 'prefix')
Whether to install via DESTDIR or by using --prefix (default is
'destdir')
"""

import os
Expand All @@ -55,6 +59,11 @@ def schema(cls):
'default': [],
}

schema['properties']['install-via'] = {
'enum': ['destdir', 'prefix'],
'default': 'destdir',
}

return schema

def __init__(self, name, options):
Expand All @@ -67,6 +76,14 @@ def __init__(self, name, options):
'make',
])

if options.install_via == 'destdir':
self.install_via_destdir = True
elif options.install_via == 'prefix':
self.install_via_destdir = False
else:
raise RuntimeError('Unsupported installation method: "{}"'.format(
options.install_via))

def build(self):
super().build()
if not os.path.exists(os.path.join(self.builddir, "configure")):
Expand All @@ -82,6 +99,17 @@ def build(self):
self.run(['env', 'NOCONFIGURE=1', './autogen.sh'])
else:
self.run(['autoreconf', '-i'])
self.run(['./configure', '--prefix='] + self.options.configflags)

configure_command = ['./configure']
make_install_command = ['make', 'install']

if self.install_via_destdir:
# Use an empty prefix since we'll install via DESTDIR
configure_command.append('--prefix=')
make_install_command.append('DESTDIR=' + self.installdir)
else:
configure_command.append('--prefix=' + self.installdir)

self.run(configure_command + self.options.configflags)
self.run(['make'])
self.run(['make', 'install', 'DESTDIR=' + self.installdir])
self.run(make_install_command)
93 changes: 89 additions & 4 deletions snapcraft/tests/test_plugin_autotools.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def setUp(self):

class Options:
configflags = []
install_via = 'destdir'

self.options = Options()

Expand All @@ -40,10 +41,14 @@ class Options:
def test_schema(self):
schema = autotools.AutotoolsPlugin.schema()

# Verify the presence of all properties
properties = schema['properties']
self.assertTrue('configflags' in properties,
'Expected "configflags" to be included in properties')
self.assertTrue('install-via' in properties,
'Expected "install-via" to be included in properties')

# Check configflags property
configflags = properties['configflags']
for item in ['type', 'minitems', 'uniqueItems', 'items', 'default']:
self.assertTrue(item in configflags,
Expand Down Expand Up @@ -78,8 +83,31 @@ def test_schema(self):
'"string", but it was "{}"'
.format(configflags_items_type))

@mock.patch.object(autotools.AutotoolsPlugin, 'run')
def test_build_configure(self, run_mock):
# Check install-via property
installvia = properties['install-via']
self.assertTrue('enum' in installvia,
'Expected "enum" to be included in "install-via"')
self.assertTrue('default' in installvia,
'Expected "default" to be included in "install-via"')

installvia_enum = installvia['enum']
# Using sets for order independence in the comparison
self.assertEqual(set(['destdir', 'prefix']), set(installvia_enum))

installvia_default = installvia['default']
self.assertEqual(installvia_default, 'destdir',
'Expected "install-via" "default" to be "destdir", '
'but it was "{}"'.format(installvia_default))

def test_install_via_invalid_enum(self):
self.options.install_via = 'invalid'
with self.assertRaises(RuntimeError) as raised:
autotools.AutotoolsPlugin('test-part', self.options)

self.assertEqual(str(raised.exception),
'Unsupported installation method: "invalid"')

def build_with_configure(self):
plugin = autotools.AutotoolsPlugin('test-part', self.options)
os.makedirs(plugin.sourcedir)

Expand All @@ -90,6 +118,12 @@ def test_build_configure(self, run_mock):

plugin.build()

return plugin

@mock.patch.object(autotools.AutotoolsPlugin, 'run')
def test_build_configure_with_destdir(self, run_mock):
plugin = self.build_with_configure()

self.assertEqual(3, run_mock.call_count)
run_mock.assert_has_calls([
mock.call(['./configure', '--prefix=']),
Expand All @@ -99,7 +133,19 @@ def test_build_configure(self, run_mock):
])

@mock.patch.object(autotools.AutotoolsPlugin, 'run')
def test_build_autogen(self, run_mock):
def test_build_configure_with_prefix(self, run_mock):
self.options.install_via = 'prefix'
plugin = self.build_with_configure()

self.assertEqual(3, run_mock.call_count)
run_mock.assert_has_calls([
mock.call(['./configure', '--prefix={}'.format(
plugin.installdir)]),
mock.call(['make']),
mock.call(['make', 'install'])
])

def build_with_autogen(self):
plugin = autotools.AutotoolsPlugin('test-part', self.options)
os.makedirs(plugin.sourcedir)

Expand All @@ -110,6 +156,12 @@ def test_build_autogen(self, run_mock):

plugin.build()

return plugin

@mock.patch.object(autotools.AutotoolsPlugin, 'run')
def test_build_autogen_with_destdir(self, run_mock):
plugin = self.build_with_autogen()

self.assertEqual(4, run_mock.call_count)
run_mock.assert_has_calls([
mock.call(['env', 'NOCONFIGURE=1', './autogen.sh']),
Expand All @@ -120,14 +172,33 @@ def test_build_autogen(self, run_mock):
])

@mock.patch.object(autotools.AutotoolsPlugin, 'run')
def test_build_autoreconf(self, run_mock):
def test_build_autogen_with_prefix(self, run_mock):
self.options.install_via = 'prefix'
plugin = self.build_with_autogen()

self.assertEqual(4, run_mock.call_count)
run_mock.assert_has_calls([
mock.call(['env', 'NOCONFIGURE=1', './autogen.sh']),
mock.call(['./configure', '--prefix={}'.format(
plugin.installdir)]),
mock.call(['make']),
mock.call(['make', 'install'])
])

def build_with_autoreconf(self):
plugin = autotools.AutotoolsPlugin('test-part', self.options)
os.makedirs(plugin.sourcedir)

# No configure or autogen.sh.

plugin.build()

return plugin

@mock.patch.object(autotools.AutotoolsPlugin, 'run')
def test_build_autoreconf_with_destdir(self, run_mock):
plugin = self.build_with_autoreconf()

self.assertEqual(4, run_mock.call_count)
run_mock.assert_has_calls([
mock.call(['autoreconf', '-i']),
Expand All @@ -137,6 +208,20 @@ def test_build_autoreconf(self, run_mock):
'DESTDIR={}'.format(plugin.installdir)])
])

@mock.patch.object(autotools.AutotoolsPlugin, 'run')
def test_build_autoreconf_with_prefix(self, run_mock):
self.options.install_via = 'prefix'
plugin = self.build_with_autoreconf()

self.assertEqual(4, run_mock.call_count)
run_mock.assert_has_calls([
mock.call(['autoreconf', '-i']),
mock.call(['./configure', '--prefix={}'.format(
plugin.installdir)]),
mock.call(['make']),
mock.call(['make', 'install'])
])

@mock.patch('sys.stdout')
def test_build_nonexecutable_autogen(self, stdout_mock):
plugin = autotools.AutotoolsPlugin('test-part', self.options)
Expand Down

0 comments on commit c5986c2

Please sign in to comment.