summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--attoconf/_version.py4
-rw-r--r--attoconf/classy.py12
-rw-r--r--attoconf/lib/pkg_config.py97
3 files changed, 110 insertions, 3 deletions
diff --git a/attoconf/_version.py b/attoconf/_version.py
index 791d3d9..d4930e4 100644
--- a/attoconf/_version.py
+++ b/attoconf/_version.py
@@ -7,11 +7,11 @@ major = 0
# Incremented for releases with compatible API additions.
# This is the number that is usually incremented.
-minor = 9
+minor = 10
# Incremented if there is a bugfix release.
# Might not be contiguous.
-patch = 1
+patch = 0
# Reserved for distributors and forks.
# Contains arbitrary text, but no parentheses or newlines.
diff --git a/attoconf/classy.py b/attoconf/classy.py
index 98d54aa..ba06fcc 100644
--- a/attoconf/classy.py
+++ b/attoconf/classy.py
@@ -1,4 +1,4 @@
-# Copyright 2013-2014 Ben Longbons <b.r.longbons@gmail.com>
+# Copyright 2013-2015 Ben Longbons <b.r.longbons@gmail.com>
#
# This file is part of attoconf.
#
@@ -35,6 +35,12 @@ class PolymorphicSlotMergerMetaclass(type):
assert dct['__slots__'] == ()
return type.__new__(meta, name, bases, dct)
+ # TODO: remove *args for 1.0
+ def __call__(cls, *args, **kwargs):
+ instance = type.__call__(cls, *args, **kwargs)
+ instance._do_jiggle()
+ return instance
+
# TODO: remove this for 1.0
def add_slots(cls):
@@ -50,7 +56,11 @@ class ClassyProject(Project):
def __init__(self, srcdir):
super(ClassyProject, self).__init__(srcdir)
+ # TODO: remove this for 1.0
def jiggle(self):
+ pass
+
+ def _do_jiggle(self):
self.order.append(None)
self.general()
self.order.append(None)
diff --git a/attoconf/lib/pkg_config.py b/attoconf/lib/pkg_config.py
new file mode 100644
index 0000000..00bfba8
--- /dev/null
+++ b/attoconf/lib/pkg_config.py
@@ -0,0 +1,97 @@
+# Copyright 2015 Ben Longbons <b.r.longbons@gmail.com>
+#
+# This file is part of attoconf.
+#
+# attoconf is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# attoconf is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with attoconf. If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import print_function, division, absolute_import
+
+import os
+import sys
+
+from ..classy import ClassyProject
+from ..types import enum, ShellList
+
+from .c import do_exec, TestError, C, Cxx
+
+
+yesno = enum('yes', 'no')
+
+def run_pkg_config(build, *args):
+ PKG_CONFIG = build.vars['PKG_CONFIG']
+ status, output = do_exec(build, PKG_CONFIG + list(args))
+ if status:
+ raise TestError(output)
+ return output.strip()
+
+def check_pkg_config(build, PKG_CONFIG):
+ version = run_pkg_config(build, '--version')
+ print('Found pkg-config: %s' % version)
+
+def package_check(build, package, **var):
+ assert len(var) == 1
+ _package, enabled = var.popitem()
+ enabled = enabled == 'yes'
+ modversion = run_pkg_config(build, '--modversion', package)
+ print("Found dependency '%s': %s" % (package, modversion))
+ cppflags = run_pkg_config(build, '--cflags-only-I', package)
+ cflags = run_pkg_config(build, '--cflags-only-other', package)
+ ldflags = run_pkg_config(build, '--libs-only-L', '--libs-only-other', package)
+ libs = run_pkg_config(build, '--libs-only-l', package)
+
+ build.vars['CPPFLAGS'] += cppflags
+ if 'CFLAGS' in build.vars:
+ build.vars['CFLAGS'] += cflags
+ if 'CXXFLAGS' in build.vars:
+ build.vars['CXXFLAGS'] += cflags
+ build.vars['LDFLAGS'] += ldflags
+ build.vars['LIBS'] += libs
+
+class PkgConfig(ClassyProject):
+ ''' Fill CFLAGS etc by pkg-config for dependencies.
+ '''
+ __slots__ = ()
+ _merge_slots_ = ('required_packages', 'optional_packages')
+
+ def __init__(self, required_packages, optional_packages, **kwargs):
+ assert isinstance(self, (C, Cxx))
+ super(PkgConfig, self).__init__(**kwargs)
+ self.required_packages = required_packages
+ self.optional_packages = optional_packages
+
+ def vars(self):
+ super(PkgConfig, self).vars()
+ self.add_option('PKG_CONFIG', init=['pkg-config'],
+ type=ShellList, check=check_pkg_config,
+ help='Tool to find dependencies', hidden=False)
+
+ def packages(self):
+ super(PkgConfig, self).packages()
+ for package in self.required_packages:
+ self._pkg_config_add_package(package, True)
+ for package in self.optional_packages:
+ self._pkg_config_add_package(package, False)
+
+ def _pkg_config_add_package(self, package, hidden):
+ positive = '--with-' + package
+ negative = '--without-' + package
+ #check = package_required_check if hidden else package_optional_check
+ check = lambda build, **kwargs: package_check(build, package, **kwargs)
+ level = 'required' if hidden else 'optional'
+ help = "Build with %s dependency '%s'" % (level, package)
+ self.add_option(positive, type=yesno, hidden=hidden, init='yes', check=check, help=help)
+ # TODO: instead reveal one of the aliases and hide the main
+ # this requires messing with help slightly
+ self.add_alias(positive, [positive + '=yes'], help=None, hidden=True)
+ self.add_alias(negative, [positive + '=no'], help=None, hidden=True)