[jhbuild] enhance <systemmodule> to support path dependencies (GNOME bug 671042)



commit 03d8f544daf65c5196da88a6627f917371582f2c
Author: Craig Keogh <cskeogh adam com au>
Date:   Fri Jun 22 14:33:41 2012 +0930

    enhance <systemmodule> to support path dependencies (GNOME bug 671042)
    
    Can now add a program as a system dependency. For example, ruby:
      <systemmodule id="ruby" >
        <branch repo="system" version="1.8"/>
        <systemdependencies>
          <dep type="path" name="ruby"/>
        </systemdependencies>
      </systemmodule>
    
    Can now add include files as a system dependency. For example, ppp:
      <systemmodule id="ppp" >
        <branch repo="system" version="2.4"/>
        <systemdependencies>
          <dep type="c_include" name="pppd/pppd.h"/>
        </systemdependencies>
      </systemmodule>
    
    Version is not checked, but required as version is shown in the help
    message.

 jhbuild/modtypes/__init__.py   |   35 ++++++++++++++++---
 jhbuild/modtypes/linux.py      |    2 +-
 jhbuild/modtypes/tarball.py    |    3 +-
 jhbuild/moduleset.py           |   19 ++++++++--
 jhbuild/utils/systeminstall.py |   72 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 120 insertions(+), 11 deletions(-)
---
diff --git a/jhbuild/modtypes/__init__.py b/jhbuild/modtypes/__init__.py
index 9197f8f..2b89c11 100644
--- a/jhbuild/modtypes/__init__.py
+++ b/jhbuild/modtypes/__init__.py
@@ -66,6 +66,7 @@ def get_dependencies(node):
     dependencies = []
     after = []
     suggests = []
+    systemdependencies = []
 
     def add_to_list(list, childnode):
         for dep in childnode.childNodes:
@@ -76,6 +77,25 @@ def get_dependencies(node):
                             node.getAttribute('id'))
                 list.append(package)
 
+    def add_to_system_dependencies(lst, childnode):
+        for dep in childnode.childNodes:
+            if dep.nodeType == dep.ELEMENT_NODE and dep.nodeName == 'dep':
+                typ = dep.getAttribute('type')
+                if not type:
+                    raise FatalError(_('%(node)s node for %(module)s module is'
+                                       ' missing %(attribute)s attribute') % \
+                                     {'node_name'   : 'dep',
+                                      'module_name' : node.getAttribute('id'),
+                                      'attribute'   : 'type'})
+                name = dep.getAttribute('name')
+                if not type:
+                    raise FatalError(_('%(node)s node for %(module)s module is'
+                                       ' missing %(attribute)s attribute') % \
+                                     {'node_name'   : 'dep',
+                                      'module_name' : node.getAttribute('id'),
+                                      'attribute'   : 'name'})
+                lst.append((typ, name))
+
     for childnode in node.childNodes:
         if childnode.nodeType != childnode.ELEMENT_NODE: continue
         if childnode.nodeName == 'dependencies':
@@ -84,8 +104,10 @@ def get_dependencies(node):
             add_to_list(suggests, childnode)
         elif childnode.nodeName == 'after':
             add_to_list(after, childnode)
+        elif childnode.nodeName == 'systemdependencies':
+            add_to_system_dependencies(systemdependencies, childnode)
 
-    return dependencies, after, suggests
+    return dependencies, after, suggests, systemdependencies
 
 def get_node_content(node):
     node.normalize()
@@ -145,12 +167,14 @@ class Package:
     type = 'base'
     PHASE_START = 'start'
     PHASE_DONE  = 'done'
-    def __init__(self, name, branch=None, dependencies = [], after = [], suggests = [], pkg_config=None):
+    def __init__(self, name, branch=None, dependencies = [], after = [],
+                  suggests = [], systemdependencies = [], pkg_config=None):
         self.name = name
         self.branch = branch
         self.dependencies = dependencies
         self.after = after
         self.suggests = suggests
+        self.systemdependencies = systemdependencies
         self.pkg_config = pkg_config
         self.tags = []
         self.moduleset_name = None
@@ -438,7 +462,7 @@ them into the prefix."""
         name = node.getAttribute('id')
         instance = cls(name)
         instance.branch = get_branch(node, repositories, default_repo, config)
-        instance.dependencies, instance.after, instance.suggests = get_dependencies(node)
+        instance.dependencies, instance.after, instance.suggests, instance.systemdependencies = get_dependencies(node)
         instance.supports_parallel_build = (node.getAttribute('supports-parallel-builds') != 'no')
         instance.config = config
         pkg_config = find_first_child_node_content(node, 'pkg-config')
@@ -500,8 +524,9 @@ class MetaModule(Package):
 
 def parse_metamodule(node, config, url, repos, default_repo):
     id = node.getAttribute('id')
-    dependencies, after, suggests = get_dependencies(node)
-    return MetaModule(id, dependencies=dependencies, after=after, suggests=suggests)
+    dependencies, after, suggests, systemdependencies = get_dependencies(node)
+    return MetaModule(id, dependencies=dependencies, after=after,
+                      suggests=suggests, systemdependencies=systemdependencies)
 register_module_type('metamodule', parse_metamodule)
 
 
diff --git a/jhbuild/modtypes/linux.py b/jhbuild/modtypes/linux.py
index 6372c42..7c34763 100644
--- a/jhbuild/modtypes/linux.py
+++ b/jhbuild/modtypes/linux.py
@@ -276,7 +276,7 @@ def parse_linux(node, config, uri, repositories, default_repo):
         makeargs = node.getAttribute('makeargs')
         makeargs = makeargs.replace('${prefix}', config.prefix)
 
-    dependencies, after, suggests = get_dependencies(node)
+    dependencies, after, suggests = get_dependencies(node)[0:2]
     branch = get_branch(node, repositories, default_repo, config)
     kconfigs = get_kconfigs(node, repositories, default_repo)
 
diff --git a/jhbuild/modtypes/tarball.py b/jhbuild/modtypes/tarball.py
index e5d65b4..8097a94 100644
--- a/jhbuild/modtypes/tarball.py
+++ b/jhbuild/modtypes/tarball.py
@@ -85,7 +85,7 @@ def parse_tarball(node, config, uri, repositories, default_repo):
     # for tarballs, don't ever pass --enable-maintainer-mode
     autogenargs = autogenargs.replace('--enable-maintainer-mode', '')
 
-    dependencies, after, suggests = get_dependencies(node)
+    dependencies, after, suggests, systemdependencies = get_dependencies(node)
 
     from autotools import AutogenModule
     from jhbuild.versioncontrol.tarball import TarballBranch, TarballRepository
@@ -106,6 +106,7 @@ def parse_tarball(node, config, uri, repositories, default_repo):
     instance.dependencies = dependencies
     instance.after = after
     instance.suggests = suggests
+    instance.systemdependencies = systemdependencies
     instance.pkg_config = find_first_child_node_content(node, 'pkg-config')
     instance.config = config
 
diff --git a/jhbuild/moduleset.py b/jhbuild/moduleset.py
index 019c8d5..a0b5259 100644
--- a/jhbuild/moduleset.py
+++ b/jhbuild/moduleset.py
@@ -191,13 +191,24 @@ class ModuleSet:
         # pkgconfig -> (required_version, installed_verison)
         module_state = {}
         for module in modules:
-            if module.pkg_config is None:
-                continue
             if (isinstance(module.branch, TarballBranch)
                 or isinstance(module, SystemModule)):
-                # Strip off the .pc
-                module_pkg = module.pkg_config[:-3]
                 required_version = module.branch.version
+                if module.pkg_config is None:
+                    module_pkg = module.name
+                else: # Strip off the .pc
+                    module_pkg = module.pkg_config[:-3]
+
+                if module.systemdependencies:
+                    if not systeminstall.systemdependencies_met \
+                               (module.name, module.systemdependencies,
+                                self.config):
+                        module_state[module_pkg] = (module, required_version,
+                                                    None, False,
+                                                    isinstance(module,
+                                                               SystemModule))
+                if module.pkg_config is None:
+                    continue
                 if not module_pkg in installed_pkgconfig:
                     module_state[module_pkg] = (module, required_version, None, False, isinstance(module, SystemModule))
                 else:
diff --git a/jhbuild/utils/systeminstall.py b/jhbuild/utils/systeminstall.py
index 4718dea..5de6c12 100755
--- a/jhbuild/utils/systeminstall.py
+++ b/jhbuild/utils/systeminstall.py
@@ -20,6 +20,7 @@
 import os
 import sys 
 import logging
+import shlex
 import subprocess
 import pipes
 from StringIO import StringIO
@@ -49,6 +50,77 @@ def get_installed_pkgconfigs(config):
         pkgversions[pkg] = stdout.strip()
     return pkgversions
 
+def systemdependencies_met(module_name, sysdeps, config):
+    '''Returns True of the system dependencies are met for module_name'''
+    def get_c_include_search_paths(config):
+        '''returns a list of C include paths (-I) from the environment and the
+        user's config'''
+        def extract_path_from_cflags(args):
+            '''extract the C include paths (-I) from a list of arguments (args)
+            Returns a list of paths'''
+            itr = iter(args.split())
+            paths = []
+            if os.name == 'nt':
+                # shlex.split doesn't handle sep '\' on Windows
+                import string
+                shell_split = string.split
+            else:
+                shell_split = shlex.split
+            try:
+                while True:
+                    arg = itr.next()
+                    if arg.strip() == '-I':
+                        # extract paths handling quotes and multiple paths
+                        paths += shell_split(itr.next())[0].split(os.pathsep)
+                    elif arg.startswith('-I'):
+                        paths += shell_split(arg[2:])[0].split(os.pathsep)
+            except StopIteration:
+                pass
+            return paths
+        # search /usr/include by default
+        paths = [ os.path.join(os.sep, 'usr', 'include')]
+        paths += extract_path_from_cflags(os.environ.get('CPPFLAGS', ''))
+        # check include paths incorrectly configured in CFLAGS, CXXFLAGS
+        paths += extract_path_from_cflags(os.environ.get('CFLAGS', ''))
+        paths += extract_path_from_cflags(os.environ.get('CXXFLAGS', ''))
+        # check include paths incorrectly configured in makeargs
+        paths += extract_path_from_cflags(config.makeargs)
+        paths += extract_path_from_cflags(config.module_autogenargs.get
+                                             (module_name, ''))
+        paths += extract_path_from_cflags(config.module_makeargs.get
+                                             (module_name, ''))
+        paths = list(set(paths)) # remove duplicates
+        return paths
+
+    c_include_search_paths = None
+    for dep_type, value in sysdeps:
+        if dep_type.lower() == 'path':
+            if os.path.split(value)[0]:
+                if not os.path.isfile(value) and not os.access(value, os.X_OK):
+                    return False
+            else:
+                found = False
+                for path in os.environ.get('PATH', '').split(os.pathsep):
+                    filename = os.path.join(path, value)
+                    if (os.path.isfile(filename) and
+                        os.access(filename, os.X_OK)):
+                        found = True
+                        break
+                if not found:
+                    return False
+        elif dep_type.lower() == 'c_include':
+            if c_include_search_paths is None:
+                c_include_search_paths = get_c_include_search_paths(config)
+            found = False
+            for path in c_include_search_paths:
+                filename = os.path.join(path, value)
+                if os.path.isfile(filename):
+                    found = True
+                    break
+            if not found:
+                return False
+    return True
+
 class SystemInstall(object):
     def __init__(self):
         if cmds.has_command('pkexec'):



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]