Bug 558436 - avoid having scanner load app code
authorColin Walters <walters@src.gnome.org>
Thu, 13 Nov 2008 19:57:12 +0000 (19:57 +0000)
committerColin Walters <walters@src.gnome.org>
Thu, 13 Nov 2008 19:57:12 +0000 (19:57 +0000)
svn path=/trunk/; revision=912

17 files changed:
ChangeLog
docs/g-ir-scanner.1
gir/Makefile.am
giscanner/Makefile.am
giscanner/cgobject.py [deleted file]
giscanner/glibtransformer.py
giscanner/transformer.py
tests/everything/Makefile.am
tests/offsets/Makefile.am
tests/scanner/Makefile.am
tests/scanner/annotation-1.0-expected.gir
tests/scanner/annotation-1.0-expected.tgir
tests/scanner/annotation.c
tests/scanner/annotation.h
tests/scanner/foo-1.0-expected.gir
tests/scanner/foo-1.0-expected.tgir
tools/g-ir-scanner

index b35ce0a..1682a28 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2008-11-13  Colin Walters  <walters@verbum.org>
 
+       Bug 558436 - avoid having scanner load app code
+
+       * giscanner/cgobject.py: Delete; we no longer load shared
+       libraries directly.
+       * giscanner/dumper.py: Support for linking a library to
+       a stub binary for introspection.
+       * giscanner/glibtransformer.py: Rewrite to use gdump XML
+       from invocation of child binary.
+       * giscanner/transformer.py: Fix up to use fully qualified
+       name in parse tree.  Make parse_ctype public so we can use
+       it inside glibtransformer.
+       * tests/scanner/barapp.c: New test, using --program arg
+       for g-ir-scanner.
+       * tests/*: Update to use common.mk for invoking scanner.
+       * tools/g-ir-scanner: Add options --program, --program-arg,
+       and --no-libtool.
+       * docs/g-ir-scanner.1: Update.
+
+2008-11-13  Colin Walters  <walters@verbum.org>
+
        * configure.ac: Depend on Gio, we use it in gdump.c.
        * girepository/gdump.c: Code to dump GType data to XML.
        * girepository/girepository.c: Add option group for dumping.
index 9148a35..315f678 100644 (file)
@@ -43,14 +43,27 @@ Include this directory when searching for a library.
 This option can be specified multiple times to include more than one
 directory to look for libraries in.
 .TP
-.B \-n, ---namspace=NAME
+.B \-n, ---namespace=NAME
 The namespace name. This name should be capitalized, eg the first letter
 should be upper case. Examples: Gtk, Clutter, WebKit.
 .TP
+.B \---no-libtool
+Disable usage of libtool for compiling stub introspection binary.  Use this
+if your build system does not require libtool.
+.TP
 .B ---nsversion=VERSION
 The namespace version. For instance 1.0. This is usually the platform version,
 eg 2.0 for Gtk+, not 2.12.7.
 .TP
+.B \-p, ---program=PROGRAM
+Specifies a binary that will be introspected. This means that the
+*_get_type() functions in it will be called for GObject data types.
+The binary must be modified to take a --introspect= option, and
+to pass the argument to this function to g_irepository_dump.
+.TP
+.B \---program-arg=ARG
+Additional argument to pass to program for introspection.
+.TP
 .B \, ---strip-prefix=PREFIX
 If this option is specified a prefix will be stripped from all functions.
 If not specified, the lower case version of the namespace will be used.
index 0e21391..6b48b31 100644 (file)
@@ -1,11 +1,8 @@
+include $(top_srcdir)/common.mk
+
 BUILT_SOURCES =
 EXTRA_DIST = 
 
-G_IR_SCANNER = $(top_srcdir)/tools/g-ir-scanner
-G_IR_SCANNER_PYTHONPATH = $(top_builddir):$(top_srcdir):$$PYTHONPATH
-G_IR_SCANNER_FILES = $(top_srcdir)/giscanner/*.py \
-       $(top_builddir)/giscanner/libgiscanner.la
-
 # glib
 GLIB_INCLUDEDIR=`pkg-config --variable=includedir glib-2.0`/glib-2.0
 GLIB_LIBDIR=`pkg-config --variable=libdir glib-2.0`
@@ -16,10 +13,9 @@ else
 GLIB_LIBRARY=glib-2.0
 endif
 
-GLib-2.0.gir: $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) glib-2.0.c
-       PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
-           -v --namespace GLib --nsversion=2.0 \
-           --add-include-path=. \
+GLib-2.0.gir: $(SCANNER_BIN) $(SCANNER_LIBS) Makefile glib-2.0.c
+       $(SCANNER) \
+           --namespace GLib --nsversion=2.0 \
            --noclosure \
            --output $@ \
            --strip-prefix=g \
@@ -32,7 +28,7 @@ GLib-2.0.gir: $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) glib-2.0.c
            $(GLIB_LIBDIR)/glib-2.0/include/glibconfig.h \
            $(srcdir)/glib-2.0.c \
            $(GLIB_INCLUDEDIR)/glib/*.h
-       PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
+       $(SCANNER) $(SCANNER_ARGS) \
            --xpath-assertions=$(srcdir)/GLib-2.0.xpath GLib-2.0.gir
 BUILT_SOURCES += GLib-2.0.gir
 EXTRA_DIST += glib-2.0.c GLib-2.0.xpath
@@ -47,10 +43,9 @@ else
 GOBJECT_LIBRARY=gobject-2.0
 endif
 
-GObject-2.0.gir: GLib-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES)
-       PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
-           -v --namespace GObject --nsversion=2.0 \
-           --add-include-path=. \
+GObject-2.0.gir: GLib-2.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+       $(SCANNER) \
+           --namespace GObject --nsversion=2.0 \
            --noclosure \
            --output $@ \
            --strip-prefix=g \
@@ -73,9 +68,9 @@ else
 GMODULE_LIBRARY=gmodule-2.0
 endif
 
-GModule-2.0.gir: GLib-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES)
-       PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
-           -v --namespace GModule --nsversion=2.0 \
+GModule-2.0.gir: GLib-2.0.gir $(SCANNER_BIN) $(SCANNER_LIBS)
+       $(SCANNER) \
+           --namespace GModule --nsversion=2.0 \
            --add-include-path=. \
            --noclosure \
            --output $@ \
@@ -98,9 +93,9 @@ else
 GIO_LIBRARY=gio-2.0
 endif
 
-Gio-2.0.gir: GObject-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) $(srcdir)/gio-2.0.c
-       PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
-           -v --namespace Gio --nsversion=2.0 \
+Gio-2.0.gir: GObject-2.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile $(srcdir)/gio-2.0.c
+       $(SCANNER) \
+           --namespace Gio --nsversion=2.0 \
            --add-include-path=. \
            --noclosure \
            --output $@ \
@@ -122,15 +117,14 @@ GIREPOSITORY_FILES = \
        $(top_srcdir)/girepository/girepository.c \
        $(top_srcdir)/girepository/girepository.h
 
-GIRepository-2.0.gir: GObject-2.0.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) $(GIREPOSITORY_FILES)
-       PYTHONPATH=$(G_IR_SCANNER_PYTHONPATH) $(G_IR_SCANNER) \
-           -v --namespace GIRepository --nsversion=1.0\
-           --add-include-path=. \
+GIRepository-2.0.gir: GObject-2.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) $(GIREPOSITORY_FILES)
+       $(SCANNER) \
+           --namespace GIRepository --nsversion=1.0\
            --noclosure \
            --output $@ \
            --strip-prefix=g \
             --include=GObject-2.0 \
-           --library=$(top_builddir)/girepository/libgirepository.la \
+           --library=girepository \
            -I$(srcdir)/girepository \
             --pkg glib-2.0 \
             --pkg gobject-2.0 \
index c9d23e5..1d6942b 100644 (file)
@@ -37,8 +37,8 @@ pkgpyexec_PYTHON =            \
        __init__.py             \
        ast.py                  \
        cachestore.py           \
-       cgobject.py             \
        config.py               \
+       dumper.py               \
        girparser.py            \
        girwriter.py            \
        glibast.py              \
diff --git a/giscanner/cgobject.py b/giscanner/cgobject.py
deleted file mode 100644 (file)
index 308ebf4..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-# -*- Mode: Python -*-
-# GObject-Introspection - a framework for introspecting GObject libraries
-# Copyright (C) 2008  Johan Dahlin
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-
-# Poor mans GObject python bindings
-# Incidentally portable beyond CPython, due to usage of ctypes
-# Why not PyGObject?
-# - 1) Avoid PyGObject dependency
-# - 2) Low-level binding
-# - 3) Implementation independent
-# - 4) Usage lower in the stack
-#
-# based on defsgen.py (C) 2006 John Finlay
-#
-
-import os
-import ctypes
-from ctypes.util import find_library
-
-
-# Constants
-
-# from gobject/gtype.h
-
-
-def _make_fundamental(x):
-    G_TYPE_FUNDAMENTAL_SHIFT = 2
-    return x << G_TYPE_FUNDAMENTAL_SHIFT
-
-
-TYPE_INVALID = _make_fundamental(0)
-TYPE_NONE = _make_fundamental(1)
-TYPE_INTERFACE = _make_fundamental(2)
-TYPE_CHAR = _make_fundamental(3)
-TYPE_UCHAR = _make_fundamental(4)
-TYPE_BOOLEAN = _make_fundamental(5)
-TYPE_INT = _make_fundamental(6)
-TYPE_UINT = _make_fundamental(7)
-TYPE_LONG = _make_fundamental(8)
-TYPE_ULONG = _make_fundamental(9)
-TYPE_INT64 = _make_fundamental(10)
-TYPE_UINT64 = _make_fundamental(11)
-TYPE_ENUM = _make_fundamental(12)
-TYPE_FLAGS = _make_fundamental(13)
-TYPE_FLOAT = _make_fundamental(14)
-TYPE_DOUBLE = _make_fundamental(15)
-TYPE_STRING = _make_fundamental(16)
-TYPE_POINTER = _make_fundamental(17)
-TYPE_BOXED = _make_fundamental(18)
-TYPE_PARAM = _make_fundamental(19)
-TYPE_OBJECT = _make_fundamental(20)
-
-# Typedefs
-
-# FIXME - this is wrong on win64, where long == 32 but size_t == 64
-GType = ctypes.c_ulong
-
-TYPE_FLAG_ABSTRACT = 1 << 4
-
-# Structs
-
-
-class GTypeClass(ctypes.Structure):
-    _fields_ = [('g_type', GType)]
-
-
-class GTypeInstance(ctypes.Structure):
-    _fields_ = [('g_class', ctypes.POINTER(GTypeClass))]
-
-
-class GEnumValue(ctypes.Structure):
-    _fields_ = [('value', ctypes.c_int),
-                ('value_name', ctypes.c_char_p),
-                ('value_nick', ctypes.c_char_p)]
-
-
-class GFlagsValue(ctypes.Structure):
-    _fields_ = [('value', ctypes.c_uint),
-                ('value_name', ctypes.c_char_p),
-                ('value_nick', ctypes.c_char_p)]
-
-
-class GEnumClass(ctypes.Structure):
-    _fields_ = [('g_type_class', GTypeClass),
-                ('minimum', ctypes.c_int),
-                ('maximum', ctypes.c_int),
-                ('n_values', ctypes.c_uint),
-                ('values', ctypes.POINTER(GEnumValue))]
-
-    def get_values(self):
-        for i in range(self.n_values):
-            yield self.values[i]
-
-
-class GFlagsClass(ctypes.Structure):
-    _fields_ = [('g_type_class', GTypeClass),
-               ('mask', ctypes.c_uint),
-               ('n_values', ctypes.c_uint),
-               ('values', ctypes.POINTER(GFlagsValue))]
-
-    def get_values(self):
-        for i in range(self.n_values):
-            yield self.values[i]
-
-
-class GTypeInterface(ctypes.Structure):
-    _fields_ = [('g_type', GType),
-                ('g_instance_type', GType)]
-
-
-class GParamSpec(ctypes.Structure):
-    _fields_ = [('g_type_instance', GTypeInstance),
-                ('name', ctypes.c_char_p),
-                ('flags', ctypes.c_uint),
-                ('value_type', GType),
-                ('owner_type', GType)]
-
-
-class GSignalInfo(ctypes.Structure):
-    _fields_ = [('signal_id', ctypes.c_uint),
-                ('signal_name', ctypes.c_char_p),
-                ('itype', GType),
-                ('signal_flags', ctypes.c_uint),
-                ('return_type', GType),
-                ('n_params', ctypes.c_uint),
-                ('param_types', ctypes.POINTER(GType))]
-
-    def get_params(self):
-        for i in range(self.n_params):
-            yield self.param_types[i]
-
-
-if os.name == 'nt':
-    _library_path = find_library('libgobject-2.0-0')
-else:
-    _library_path = find_library('gobject-2.0')
-if not _library_path:
-    raise ImportError("Could not find gobject-2.0 library")
-_gobj = ctypes.CDLL(_library_path, ctypes.RTLD_GLOBAL)
-_gobj.g_type_init()
-
-# We need to initialize threads just in case part of the library
-# wants to use gthreads; libsoup seems to use g_once for its
-# type init functions.
-if os.name == 'nt':
-    _threads_library_path = find_library('libgthread-2.0-0')
-else:
-    _threads_library_path = find_library('gthread-2.0')
-if not _threads_library_path:
-    raise ImportError("Could not find gthread-2.0 library")
-_gthreads = ctypes.CDLL(_threads_library_path, ctypes.RTLD_GLOBAL)
-_gthreads.g_thread_init.argtypes = [ctypes.c_void_p]
-_gthreads.g_thread_init(None)
-
-# Functions
-
-
-def _gwrap(fname, ret, *argtypes):
-
-    def _deco(f):
-        f._cfunc = getattr(_gobj, fname)
-        f._cfunc.restype = ret
-        f._cfunc.argtypes = argtypes
-        return f
-    return _deco
-
-
-@_gwrap('g_object_new', ctypes.c_void_p, GType)
-def object_new(type_id):
-    return _gobj.g_object_new(type_id, None)
-
-
-# Workaround this error:
-#   GLib-GObject-CRITICAL **: g_param_spec_pool_list:
-#   assertion `pool != NULL' failed
-# which happens when trying to introspect an interface before instantiating
-# a GObject.
-
-object_new(TYPE_OBJECT)
-_gobj.g_initially_unowned_get_type()
-
-
-@_gwrap('g_type_name', ctypes.c_char_p, GType)
-def type_name(type_id):
-    return _gobj.g_type_name(type_id)
-
-
-@_gwrap('g_type_from_name', GType, ctypes.c_char_p)
-def type_from_name(name):
-    return _gobj.g_type_from_name(name)
-
-
-@_gwrap('g_type_fundamental', GType, GType)
-def type_fundamental(type_id):
-    return _gobj.g_type_fundamental(type_id)
-
-
-@_gwrap('g_type_test_flags', ctypes.c_int, GType, ctypes.c_int)
-def type_test_flags(type_id, flag):
-    return _gobj.g_type_test_flags(type_id, flag)
-
-
-def type_is_abstract(type_id):
-    return type_test_flags(type_id, TYPE_FLAG_ABSTRACT) != 0
-
-
-@_gwrap('g_type_parent', GType, GType)
-def type_parent(type_id):
-    return _gobj.g_type_parent(type_id)
-
-
-@_gwrap('g_type_class_ref', ctypes.POINTER(GTypeClass), GType)
-def type_class_ref(type_id):
-    fundamental_type = type_fundamental(type_id)
-    if fundamental_type == TYPE_INVALID:
-        return None
-    if fundamental_type == TYPE_ENUM:
-        typeclass = GEnumClass
-    elif fundamental_type == TYPE_FLAGS:
-        typeclass = GFlagsClass
-    else:
-        raise NotImplementedError(fundamental_type)
-    ptr = _gobj.g_type_class_ref(type_id)
-    return ctypes.cast(ptr, ctypes.POINTER(typeclass)).contents
-
-
-@_gwrap('g_object_class_list_properties',
-       ctypes.POINTER(ctypes.POINTER(GParamSpec)),
-       ctypes.POINTER(GTypeClass), ctypes.POINTER(ctypes.c_uint))
-def object_class_list_properties(type_id):
-    klass = _gobj.g_type_class_ref(type_id)
-    n = ctypes.c_uint()
-    pspecs = _gobj.g_object_class_list_properties(klass, ctypes.byref(n))
-    for i in range(n.value):
-        yield ctypes.cast(pspecs[i], ctypes.POINTER(GParamSpec)).contents
-
-
-@_gwrap('g_type_default_interface_ref', ctypes.c_void_p, GType)
-def type_default_interface_ref(type_id):
-    return _gobj.g_type_default_interface_ref(type_id)
-
-
-@_gwrap('g_object_interface_list_properties',
-       ctypes.POINTER(ctypes.POINTER(GParamSpec)),
-       ctypes.c_void_p, ctypes.POINTER(ctypes.c_uint))
-def object_interface_list_properties(type_id):
-    iface = type_default_interface_ref(type_id)
-    n = ctypes.c_uint()
-    pspecs = _gobj.g_object_interface_list_properties(iface, ctypes.byref(n))
-    for i in range(n.value):
-        yield ctypes.cast(pspecs[i], ctypes.POINTER(GParamSpec)).contents
-
-
-@_gwrap('g_type_interfaces', ctypes.POINTER(GType), GType,
-       ctypes.POINTER(ctypes.c_uint))
-def type_interfaces(type_id):
-    n = ctypes.c_uint()
-    type_ids = _gobj.g_type_interfaces(type_id, ctypes.byref(n))
-    for i in range(n.value):
-        yield type_ids[i]
-
-
-@_gwrap('g_type_interface_prerequisites', ctypes.POINTER(GType), GType,
-       ctypes.POINTER(ctypes.c_uint))
-def type_interface_prerequisites(type_id):
-    n = ctypes.c_uint()
-    type_ids = _gobj.g_type_interface_prerequisites(type_id, ctypes.byref(n))
-    for i in range(n.value):
-        yield type_ids[i]
-
-
-@_gwrap('g_signal_query', None, ctypes.c_uint, ctypes.POINTER(GSignalInfo))
-def signal_query(sigid, qptr):
-    _gobj.g_signal_query(sigid, qptr)
-
-
-@_gwrap('g_signal_list_ids', ctypes.POINTER(ctypes.c_uint),
-       GType, ctypes.POINTER(ctypes.c_uint))
-def signal_list(type_id):
-    n = ctypes.c_uint()
-    signal_ids = _gobj.g_signal_list_ids(type_id, ctypes.byref(n))
-    for i in range(n.value):
-        info = GSignalInfo()
-        signal_query(signal_ids[i], ctypes.byref(info))
-        yield info
-
-TYPE_GTYPE = type_from_name('GType')
index f97af9f..a414078 100644 (file)
 #
 
 import os
+import sys
 import re
-import ctypes
-from ctypes.util import find_library
+import tempfile
+import shutil
+import subprocess
 
-from . import cgobject
 from .ast import (Callback, Constant, Enum, Function, Member, Namespace,
                   Parameter, Property, Return, Struct, Type, Alias,
                   Union, Field, type_name_from_ctype,
@@ -32,10 +33,20 @@ from .transformer import Names
 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
                       GLibInterface, GLibObject, GLibSignal, GLibBoxedStruct,
                       GLibBoxedUnion, GLibBoxedOther, type_names)
-from .utils import extract_libtool, to_underscores, to_underscores_noprefix
+from .utils import to_underscores, to_underscores_noprefix
 
 default_array_types['guchar*'] = TYPE_UINT8
 
+# GParamFlags
+G_PARAM_READABLE = 1 << 0
+G_PARAM_WRITABLE = 1 << 1
+G_PARAM_CONSTRUCT = 1 << 2
+G_PARAM_CONSTRUCT_ONLY = 1 << 3
+G_PARAM_LAX_VALIDATION = 1 << 4
+G_PARAM_STATIC_NAME = 1 << 5
+G_PARAM_STATIC_NICK = 1 << 6
+G_PARAM_STATIC_BLURB = 1 << 7
+
 SYMBOL_BLACKLIST = [
     # These ones break GError conventions
     'g_simple_async_result_new_from_error',
@@ -49,6 +60,16 @@ SYMBOL_BLACKLIST_RE = [re.compile(x) for x in \
                            [r'\w+_marshal_[A-Z]+__', ]]
 
 
+class IntrospectionBinary(object):
+
+    def __init__(self, args, tmpdir=None):
+        self.args = args
+        if tmpdir is None:
+            self.tmpdir = tempfile.mkdtemp('', 'tmp-introspect')
+        else:
+            self.tmpdir = tmpdir
+
+
 class Unresolved(object):
 
     def __init__(self, target):
@@ -68,7 +89,9 @@ class GLibTransformer(object):
         self._namespace_name = None
         self._names = Names()
         self._uscore_type_names = {}
-        self._libraries = []
+        self._binary = None
+        self._get_type_functions = []
+        self._gtype_data = {}
         self._failed_types = {}
         self._boxed_types = {}
         self._private_internal_types = {}
@@ -77,23 +100,8 @@ class GLibTransformer(object):
 
     # Public API
 
-    def add_library(self, libname):
-        # For testing mainly.
-        libtool_libname = 'lib' + libname + '.la'
-        if os.path.exists(libname):
-            found_libname = os.path.abspath(libname)
-        elif os.path.exists(libtool_libname):
-            found_libname = extract_libtool(libtool_libname)
-        else:
-            found_libname = find_library(libname)
-
-        if libname.endswith('.la'):
-            found_libname = extract_libtool(libname)
-            libname = os.path.basename(found_libname)
-        if not found_libname:
-            raise ValueError("Failed to find library: %r" % (libname, ))
-        self._libraries.append(ctypes.cdll.LoadLibrary(found_libname))
-        return libname
+    def set_introspection_binary(self, binary):
+        self._binary = binary
 
     def _print_statistics(self):
         nodes = list(self._names.names.itervalues())
@@ -120,6 +128,11 @@ class GLibTransformer(object):
         if namespace.name == 'GObject':
             del self._names.aliases['Type']
 
+        # Get all the GObject data by passing our list of get_type
+        # functions to the compiled binary
+
+        self._execute_binary()
+
         # Introspection is done from within parsing
 
         # Second pass: pair boxed structures
@@ -169,6 +182,16 @@ class GLibTransformer(object):
             return node[1]
         return None
 
+    def _lookup_node(self, name):
+        if name in type_names:
+            return None
+        node = self._get_attribute(name)
+        if node is None:
+            node = self._transformer.get_names().names.get(name)
+            if node:
+                return node[1]
+        return node
+
     def _register_internal_type(self, type_name, node):
         self._names.type_names[type_name] = (None, node)
         uscored = to_underscores(type_name).lower()
@@ -183,16 +206,6 @@ class GLibTransformer(object):
 
     # Helper functions
 
-    def _type_from_gtype(self, type_id):
-        ctype = cgobject.type_name(type_id)
-        type_name = type_name_from_ctype(ctype)
-        type_name = type_name.replace('*', '')
-        type_name = self._resolve_type_name(type_name)
-
-        type = Type(type_name, ctype)
-        type._gtype = type_id
-        return type
-
     def _resolve_gtypename(self, gtype_name):
         try:
             return self._transformer.gtypename_to_giname(gtype_name,
@@ -200,21 +213,45 @@ class GLibTransformer(object):
         except KeyError, e:
             return Unresolved(gtype_name)
 
+    def _execute_binary(self):
+        in_path = os.path.join(self._binary.tmpdir, 'types.txt')
+        f = open(in_path, 'w')
+        for func in self._get_type_functions:
+            f.write(func)
+            f.write('\n')
+        f.close()
+        out_path = os.path.join(self._binary.tmpdir, 'dump.xml')
+
+        introspect_arg = '--introspect-dump=%s,%s' % (in_path, out_path)
+        args = self._binary.args
+        args.append(introspect_arg)
+        # Invoke the binary, having written our get_type functions to types.txt
+        print args
+        subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr)
+        self._read_introspect_dump(out_path)
+
+        # Clean up temporaries
+        shutil.rmtree(self._binary.tmpdir)
+
+    def _read_introspect_dump(self, xmlpath):
+        from xml.etree.cElementTree import parse
+        tree = parse(xmlpath)
+        root = tree.getroot()
+        for child in root:
+            self._gtype_data[child.attrib['name']] = child
+        for child in root:
+            self._introspect_type(child)
+
     def _create_gobject(self, node):
         type_name = 'G' + node.name
         if type_name == 'GObject':
             parent_gitype = None
             symbol = 'intern'
-        else:
-            type_id = cgobject.type_from_name(type_name)
-            parent_type_name = cgobject.type_name(
-                cgobject.type_parent(type_id))
+        elif type_name == 'GInitiallyUnowned':
+            parent_type_name = 'GObject'
             parent_gitype = self._resolve_gtypename(parent_type_name)
-            symbol = to_underscores(type_name).lower() + '_get_type'
+            symbol = 'g_initially_unowned_get_type'
         node = GLibObject(node.name, parent_gitype, type_name, symbol, True)
-        type_id = cgobject.TYPE_OBJECT
-        self._introspect_properties(node, type_id)
-        self._introspect_signals(node, type_id)
         self._add_attribute(node)
         self._register_internal_type(type_name, node)
 
@@ -281,26 +318,7 @@ class GLibTransformer(object):
                    ", not GObject.Type") % (func.retval.type.name, )
             return False
 
-        if not self._libraries:
-            print "Warning: No libraries loaded, cannot call %s" % (symbol, )
-            return False
-
-        for library in self._libraries:
-            try:
-                func = getattr(library, symbol)
-                break
-            except AttributeError:
-                continue
-        else:
-            print 'Warning: could not find symbol: %s' % symbol
-            name = symbol.replace('_get_type', '')
-            self._failed_types[name] = True
-            return False
-
-        func.restype = cgobject.GType
-        func.argtypes = []
-        type_id = func()
-        self._introspect_type(type_id, symbol)
+        self._get_type_functions.append(symbol)
         return True
 
     def _name_is_internal_gtype(self, giname):
@@ -491,65 +509,51 @@ class GLibTransformer(object):
 
     # Introspection
 
-    def _introspect_type(self, type_id, symbol):
-        fundamental_type_id = cgobject.type_fundamental(type_id)
-        if (fundamental_type_id == cgobject.TYPE_ENUM or
-            fundamental_type_id == cgobject.TYPE_FLAGS):
-            self._introspect_enum(fundamental_type_id, type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_OBJECT:
-            self._introspect_object(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_INTERFACE:
-            self._introspect_interface(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_BOXED:
-            self._introspect_boxed(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_BOXED:
-            self._introspect_boxed(type_id, symbol)
-        elif fundamental_type_id == cgobject.TYPE_POINTER:
-            # FIXME: Should we do something about these?
-            #        GHashTable, GValue and a few other fundamentals are
-            #        covered here
-            return
+    def _introspect_type(self, xmlnode):
+        if xmlnode.tag in ('enum', 'flags'):
+            self._introspect_enum(xmlnode)
+        elif xmlnode.tag == 'class':
+            self._introspect_object(xmlnode)
+        elif xmlnode.tag == 'interface':
+            self._introspect_interface(xmlnode)
+        elif xmlnode.tag == 'boxed':
+            self._introspect_boxed(xmlnode)
         else:
-            print 'unhandled GType: %s(%d)' % (cgobject.type_name(type_id),
-                                               type_id)
-
-    def _introspect_enum(self, ftype_id, type_id, symbol):
-        type_class = cgobject.type_class_ref(type_id)
-        if type_class is None:
-            return
+            raise ValueError("Unhandled introspection XML tag %s", xmlnode.tag)
 
+    def _introspect_enum(self, node):
         members = []
-        for enum_value in type_class.get_values():
-            members.append(GLibEnumMember(enum_value.value_nick,
-                                          enum_value.value,
-                                          enum_value.value_name,
-                                          enum_value.value_nick))
-
-        klass = (GLibFlags if ftype_id == cgobject.TYPE_FLAGS else GLibEnum)
-        type_name = cgobject.type_name(type_id)
+        for member in node.findall('member'):
+            members.append(GLibEnumMember(member.attrib['nick'],
+                                          member.attrib['value'],
+                                          member.attrib['name'],
+                                          member.attrib['nick']))
+
+        klass = (GLibFlags if node.tag == 'flags' else GLibEnum)
+        type_name = node.attrib['name']
         enum_name = self._transformer.remove_prefix(type_name)
-        node = klass(enum_name, type_name, members, symbol)
+        node = klass(enum_name, type_name, members, node.attrib['get-type'])
         self._add_attribute(node, replace=True)
         self._register_internal_type(type_name, node)
 
-    def _introspect_object(self, type_id, symbol):
-        type_name = cgobject.type_name(type_id)
+    def _introspect_object(self, xmlnode):
+        type_name = xmlnode.attrib['name']
         # We handle this specially above; in 2.16 and below there
         # was no g_object_get_type, for later versions we need
         # to skip it
         if type_name == 'GObject':
             return
-        parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
+        parent_type_name = xmlnode.attrib['parent']
         parent_gitype = self._resolve_gtypename(parent_type_name)
-        is_abstract = cgobject.type_is_abstract(type_id)
+        is_abstract = not not xmlnode.attrib.get('abstract', False)
         node = GLibObject(
             self._transformer.remove_prefix(type_name),
             parent_gitype,
             type_name,
-            symbol, is_abstract)
-        self._introspect_properties(node, type_id)
-        self._introspect_signals(node, type_id)
-        self._introspect_implemented_interfaces(node, type_id)
+            xmlnode.attrib['get-type'], is_abstract)
+        self._introspect_properties(node, xmlnode)
+        self._introspect_signals(node, xmlnode)
+        self._introspect_implemented_interfaces(node, xmlnode)
 
         # add struct fields
         struct = self._get_attribute(node.name)
@@ -564,84 +568,69 @@ class GLibTransformer(object):
         self._add_attribute(node, replace=True)
         self._register_internal_type(type_name, node)
 
-    def _introspect_interface(self, type_id, symbol):
-        type_name = cgobject.type_name(type_id)
-        parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
-        if parent_type_name == 'GInterface':
-            parent_gitype = None
-        else:
-            parent_gitype = self._resolve_gtypename(parent_type_name)
+    def _introspect_interface(self, xmlnode):
+        type_name = xmlnode.attrib['name']
         node = GLibInterface(
             self._transformer.remove_prefix(type_name),
-            parent_gitype,
-            type_name, symbol)
-        self._introspect_properties(node, type_id)
-        self._introspect_signals(node, type_id)
+            None,
+            type_name, xmlnode.attrib['get-type'])
+        self._introspect_properties(node, xmlnode)
+        self._introspect_signals(node, xmlnode)
         # GtkFileChooserEmbed is an example of a private interface, we
         # just filter them out
-        if symbol.startswith('_'):
+        if xmlnode.attrib['get-type'].startswith('_'):
             print "NOTICE: Marking %s as internal type" % (type_name, )
             self._private_internal_types[type_name] = node
         else:
             self._add_attribute(node, replace=True)
             self._register_internal_type(type_name, node)
 
-    def _introspect_boxed(self, type_id, symbol):
-        type_name = cgobject.type_name(type_id)
+    def _introspect_boxed(self, xmlnode):
+        type_name = xmlnode.attrib['name']
         # This one doesn't go in the main namespace; we associate it with
         # the struct or union
-        node = GLibBoxed(type_name, symbol)
+        node = GLibBoxed(type_name, xmlnode.attrib['get-type'])
         self._boxed_types[node.type_name] = node
         self._register_internal_type(type_name, node)
 
-    def _introspect_implemented_interfaces(self, node, type_id):
-        fundamental_type_id = cgobject.type_fundamental(type_id)
-        if fundamental_type_id != cgobject.TYPE_OBJECT:
-            raise AssertionError
-        interfaces = cgobject.type_interfaces(type_id)
+    def _introspect_implemented_interfaces(self, node, xmlnode):
         gt_interfaces = []
-        for interface_typeid in interfaces:
-            iname = cgobject.type_name(interface_typeid)
-            gitype = self._resolve_gtypename(iname)
+        for interface in xmlnode.findall('implements'):
+            gitype = self._resolve_gtypename(interface.attrib['name'])
             gt_interfaces.append(gitype)
         node.interfaces = gt_interfaces
 
-    def _introspect_properties(self, node, type_id):
-        fundamental_type_id = cgobject.type_fundamental(type_id)
-        if fundamental_type_id == cgobject.TYPE_OBJECT:
-            pspecs = cgobject.object_class_list_properties(type_id)
-        elif fundamental_type_id == cgobject.TYPE_INTERFACE:
-            pspecs = cgobject.object_interface_list_properties(type_id)
-        else:
-            raise AssertionError
-
-        for pspec in pspecs:
-            if pspec.owner_type != type_id:
-                continue
-            ctype = cgobject.type_name(pspec.value_type)
-            readable = (pspec.flags & 1) != 0
-            writable = (pspec.flags & 2) != 0
-            construct = (pspec.flags & 4) != 0
-            construct_only = (pspec.flags & 8) != 0
+    def _introspect_properties(self, node, xmlnode):
+        for pspec in xmlnode.findall('property'):
+            ctype = pspec.attrib['type']
+            flags = int(pspec.attrib['flags'])
+            readable = (flags & G_PARAM_READABLE) != 0
+            writable = (flags & G_PARAM_WRITABLE) != 0
+            construct = (flags & G_PARAM_CONSTRUCT) != 0
+            construct_only = (flags & G_PARAM_CONSTRUCT_ONLY) != 0
             node.properties.append(Property(
-                pspec.name,
+                pspec.attrib['name'],
                 type_name_from_ctype(ctype),
                 readable, writable, construct, construct_only,
                 ctype,
                 ))
 
-    def _introspect_signals(self, node, type_id):
-        for signal_info in cgobject.signal_list(type_id):
-            rtype = self._type_from_gtype(signal_info.return_type)
-            return_ = Return(rtype)
-            signal = GLibSignal(signal_info.signal_name, return_)
-            for i, parameter in enumerate(signal_info.get_params()):
+    def _introspect_signals(self, node, xmlnode):
+        for signal_info in xmlnode.findall('signal'):
+            rctype = signal_info.attrib['return']
+            rtype = Type(self._transformer.parse_ctype(rctype), rctype)
+            return_ = Return(rtype, signal_info.attrib['return'])
+            return_.transfer = 'full'
+            signal = GLibSignal(signal_info.attrib['name'], return_)
+            for i, parameter in enumerate(signal_info.findall('param')):
                 if i == 0:
                     name = 'object'
                 else:
                     name = 'p%s' % (i-1, )
-                ptype = self._type_from_gtype(parameter)
+                pctype = parameter.attrib['type']
+                ptype = Type(self._transformer.parse_ctype(pctype), pctype)
                 param = Parameter(name, ptype)
+                param.transfer = 'none'
                 signal.parameters.append(param)
             node.signals.append(signal)
 
@@ -651,7 +640,6 @@ class GLibTransformer(object):
         # Workaround glib bug #548689, to be included in 2.18.0
         if type_name == "GParam":
             type_name = "GObject.ParamSpec"
-
         res = self._transformer.resolve_type_name_full
         try:
             return res(type_name, ctype, self._names)
@@ -659,6 +647,9 @@ class GLibTransformer(object):
             return self._transformer.resolve_type_name(type_name, ctype)
 
     def _resolve_param_type(self, ptype, **kwargs):
+        # Workaround glib bug #548689, to be included in 2.18.0
+        if ptype.name == "GParam":
+            ptype.name = "GObject.ParamSpec"
         return self._transformer.resolve_param_type_full(ptype,
                                                          self._names,
                                                          **kwargs)
@@ -783,43 +774,23 @@ class GLibTransformer(object):
         prop.type = self._resolve_param_type(prop.type, allow_invalid=False)
 
     def _adjust_transfer(self, param):
-        # Do GLib/GObject-specific type transformations here
-
-        transfer = None
-        is_object = None
-        if hasattr(param.type, '_gtype'):
-            ftype = cgobject.type_fundamental(param.type._gtype)
-            assert ftype != cgobject.TYPE_INVALID, param.type._gtype
+        if not (param.transfer is None or param.transfer_inferred):
+            return
 
-            is_object = ftype in [cgobject.TYPE_OBJECT,
-                                  cgobject.TYPE_INTERFACE]
+        # Do GLib/GObject-specific type transformations here
+        node = self._lookup_node(param.type.name)
+        if node is None:
+            return
 
-            if ftype in [cgobject.TYPE_OBJECT,
-                         cgobject.TYPE_INTERFACE,
-                         cgobject.TYPE_STRING,
-                         cgobject.TYPE_BOXED,
-                         cgobject.TYPE_PARAM]:
+        if isinstance(param, Parameter):
+            if param.direction != PARAM_DIRECTION_IN:
                 transfer = 'full'
             else:
-                # if type is a cgobject.TYPE_POINTER we could require direction
-                # and transfer-ownership annotations
                 transfer = 'none'
-
-        if is_object is None:
-            is_object = (param.type.name == 'GObject.Object' or
-                         (self._namespace_name == 'GObject' and
-                          param.type.name == 'Object'))
-
-        # Default to full transfer for GObjects
-        if isinstance(param, Parameter):
-            is_out = (param.direction != PARAM_DIRECTION_IN)
         else:
-            is_out = True
-        if param.transfer is None or param.transfer_inferred:
-            if is_out and is_object:
-                param.transfer = 'full'
-            elif transfer is not None:
-                param.transfer = transfer
+            transfer = 'full'
+
+        param.transfer = transfer
 
     def _adjust_throws(self, func):
         if func.parameters == []:
index c512f7a..fbf82ff 100644 (file)
@@ -142,7 +142,8 @@ class Transformer(object):
                 self._names.aliases[node.name] = (nsname, node)
             elif isinstance(node, (GLibBoxed, Interface, Class)):
                 self._names.type_names[node.type_name] = (nsname, node)
-            self._names.names[node.name] = (nsname, node)
+            giname = '%s.%s' % (nsname, node.name)
+            self._names.names[giname] = (nsname, node)
             if hasattr(node, 'ctype'):
                 self._names.ctypes[node.ctype] = (nsname, node)
             elif hasattr(node, 'symbol'):
@@ -370,7 +371,7 @@ class Transformer(object):
                 "symbol %r of type %s" % (symbol.ident, ctype_name(ctype)))
         return node
 
-    def _parse_ctype(self, ctype):
+    def parse_ctype(self, ctype):
         # First look up the ctype including any pointers;
         # a few type names like 'char*' have their own aliases
         # and we need pointer information for those.
@@ -398,29 +399,29 @@ class Transformer(object):
         if ctype in self._list_ctypes:
             param = options.get('element-type')
             if param:
-                contained_type = self._parse_ctype(param[0])
+                contained_type = self.parse_ctype(param[0])
             else:
                 contained_type = None
-            derefed_name = self._parse_ctype(ctype)
+            derefed_name = self.parse_ctype(ctype)
             rettype = List(derefed_name,
                            ctype,
                            contained_type)
         elif ctype in self._map_ctypes:
             param = options.get('element-type')
             if param:
-                key_type = self._parse_ctype(param[0])
-                value_type = self._parse_ctype(param[1])
+                key_type = self.parse_ctype(param[0])
+                value_type = self.parse_ctype(param[1])
             else:
                 key_type = None
                 value_type = None
-            derefed_name = self._parse_ctype(ctype)
+            derefed_name = self.parse_ctype(ctype)
             rettype = Map(derefed_name,
                           ctype,
                           key_type, value_type)
         elif (ctype in default_array_types) or ('array' in options):
             derefed_name = ctype[:-1] if ctype[-1] == '*' else ctype
             rettype = Array(ctype,
-                            self._parse_ctype(derefed_name))
+                            self.parse_ctype(derefed_name))
             array_opts = dict([opt.split('=')
                                for opt in options.get('array', [])])
             if 'length' in array_opts:
@@ -429,7 +430,7 @@ class Transformer(object):
                 rettype.size = array_opts['fixed-size']
                 rettype.zeroterminated = False
         else:
-            derefed_name = self._parse_ctype(ctype)
+            derefed_name = self.parse_ctype(ctype)
             rettype = Type(derefed_name, ctype)
 
         # Deduce direction for some types passed by reference that
index 8f3eceb..ec209d5 100644 (file)
@@ -1,3 +1,5 @@
+include $(top_srcdir)/common.mk
+
 LT_CURRENT = 1
 LT_REVISION = 0
 LT_AGE = 0
@@ -23,18 +25,13 @@ AM_LDFLAGS += -no-undefined
 endif
 
 GIRS =
-SCANNER = $(top_srcdir)/tools/g-ir-scanner
-SCANNER_PYTHONPATH = $(top_builddir):$(top_srcdir):$$PYTHONPATH
-SCANNER_LIBS = $(top_srcdir)/giscanner/*.py \
-              $(top_builddir)/giscanner/libgiscanner.la
 TYPELIBS = $(GIRS:.gir=.typelib)
 TXMLS = $(GIRS:.gir=.gir.txml)
 CLEANFILES = $(TYPELIBS) $(TXMLS) $(GIRS)
 BUILT_SOURCES = $(TYPELIBS) $(TXMLS) $(GIRS)
 
-Everything-$(TYPELIB_VERSION).gir: libgirepository-everything.la gitesttypes.c gitesttypes.h $(SCANNER) $(SCANNER_LIBS)
-       PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-       --add-include-path=$(top_builddir)/gir \
+Everything-$(TYPELIB_VERSION).gir: libgirepository-everything.la gitesttypes.c gitesttypes.h $(SCANNER_BIN) $(SCANNER_LIBS)
+       $(CHECK_DEBUG) $(SCANNER) \
        --include=GObject-2.0 \
        --library=girepository-everything \
        --namespace=Everything --nsversion=$(TYPELIB_VERSION) \
index 57cfdfb..2c3cae2 100644 (file)
@@ -1,3 +1,5 @@
+include $(top_srcdir)/common.mk
+
 BUILT_SOURCES =
 CLEANFILES =
 EXTRA_DIST =
@@ -5,12 +7,6 @@ EXTRA_DIST =
 check_LTLIBRARIES =
 check_PROGRAMS =
 
-SCANNER = $(top_srcdir)/tools/g-ir-scanner
-SCANNER_PYTHONPATH = $(top_builddir):$(top_srcdir):$$PYTHONPATH
-SCANNER_LIBS = \
-       $(top_srcdir)/giscanner/*.py \
-       $(top_builddir)/giscanner/libgiscanner.la
-
 ############################################################
 
 check_LTLIBRARIES += liboffsets.la
@@ -20,11 +16,10 @@ liboffsets_la_SOURCES = \
        offsets.c
 liboffsets_la_CPPFLAGS = $(GIREPO_CFLAGS)
 # dummy rpath to get built dynamically (huh?)
-liboffsets_la_LDFLAGS = -module -avoid-version -rpath $(libdir)
+liboffsets_la_LDFLAGS = -avoid-version -rpath $(libdir)
 
-offsets-1.0.gir: liboffsets.la offsets.h $(SCANNER) $(SCANNER_LIBS) Makefile
-       PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-       --add-include-path=$(top_builddir)/gir --add-include-path=. \
+offsets-1.0.gir: liboffsets.la offsets.h $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+       $(CHECK_DEBUG) $(SCANNER) \
        --library=offsets \
        --namespace=offsets \
        --nsversion=1.0 \
index 9fba3b0..ae42cce 100644 (file)
@@ -1,3 +1,5 @@
+include $(top_srcdir)/common.mk
+
 # We need to build a shared library, which can be dlopened
 # it does not work with noinst_LTLIBRARIES
 testlib_LTLIBRARIES = \
@@ -9,9 +11,10 @@ testlib_LTLIBRARIES = \
 testlibdir = $(prefix)/unused
 install-testlibLTLIBRARIES: # prevent it from being installed
 
-AM_CFLAGS = $(GOBJECT_CFLAGS)
-AM_LDFLAGS = -module -avoid-version
-LIBS = $(GOBJECT_LIBS)
+AM_CPPFLAGS = -I$(top_srcdir)/girepository
+AM_CFLAGS = $(GOBJECT_CFLAGS) $(GTHREAD_CFLAGS)
+AM_LDFLAGS = -avoid-version
+LIBS = $(GOBJECT_LIBS) $(GTHREAD_LIBS)
 
 libannotation_la_SOURCES = $(srcdir)/annotation.c $(srcdir)/annotation.h
 libdrawable_la_SOURCES = $(srcdir)/drawable.c $(srcdir)/drawable.h
@@ -25,11 +28,6 @@ endif
 
 # .gir --[scanner]-> .typelib --[generate]-> .tgir
 GIRS =
-SCANNER = $(top_srcdir)/tools/g-ir-scanner
-SCANNER_PYTHONPATH = $(top_builddir):$(top_srcdir):$$PYTHONPATH
-SCANNER_LIBS = \
-       $(top_srcdir)/giscanner/*.py \
-       $(top_builddir)/giscanner/libgiscanner.la
 TYPELIBS = $(GIRS:.gir=.typelib)
 CHECKGIRS = $(GIRS:.gir=.gir.check)
 EXPECTEDGIRS = $(GIRS:.gir=-expected.gir)
@@ -40,9 +38,8 @@ CLEANFILES = $(TYPELIBS)  $(GIRS) $(TGIRS)
 BUILT_SOURCES = $(TYPELIBS) $(GIRS)
 EXTRA_DIST = $(EXPECTEDGIRS) $(EXPECTEDTGIRS)
 
-annotation-1.0.gir: libannotation.la annotation.c annotation.h utility-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
-       PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-       --add-include-path=$(top_builddir)/gir --add-include-path=. \
+annotation-1.0.gir: libannotation.la annotation.c annotation.h utility-1.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+        $(CHECK_DEBUG) $(SCANNER) \
        --include=GObject-2.0 \
        --include=utility-1.0 \
        --library=annotation \
@@ -53,9 +50,8 @@ annotation-1.0.gir: libannotation.la annotation.c annotation.h utility-1.0.gir $
         --output $@
 GIRS += annotation-1.0.gir
 
-drawable-1.0.gir: libdrawable.la drawable.c drawable.h utility-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
-       PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-       --add-include-path=$(top_builddir)/gir --add-include-path=. \
+drawable-1.0.gir: libdrawable.la drawable.c drawable.h utility-1.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+       $(CHECK_DEBUG) $(SCANNER) \
        --include=GObject-2.0 \
        --include=utility-1.0 \
        --library=drawable \
@@ -66,15 +62,14 @@ drawable-1.0.gir: libdrawable.la drawable.c drawable.h utility-1.0.gir $(SCANNER
         --output $@
 GIRS += drawable-1.0.gir
 
-drawable-injected-1.0.gir: drawable-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
-       PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
+drawable-injected-1.0.gir: drawable-1.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+       $(CHECK_DEBUG) $(SCANNER) -v \
         --inject drawable-1.0.gir $(srcdir)/DrawableAdditions.xml $@
 GIRS += drawable-injected-1.0.gir
 EXTRA_DIST += DrawableAdditions.xml
 
-foo-1.0.gir: libfoo.la foo.c foo.h utility-1.0.gir $(SCANNER) $(SCANNER_LIBS) Makefile
-       PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-       --add-include-path=$(top_builddir)/gir --add-include-path=. \
+foo-1.0.gir: libfoo.la foo.c foo.h utility-1.0.gir $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+       $(CHECK_DEBUG) $(SCANNER) \
        --include=GObject-2.0 \
        --include=utility-1.0 \
        --library=foo \
@@ -85,9 +80,8 @@ foo-1.0.gir: libfoo.la foo.c foo.h utility-1.0.gir $(SCANNER) $(SCANNER_LIBS) Ma
         --output $@
 GIRS += foo-1.0.gir
 
-utility-1.0.gir: libutility.la utility.h $(SCANNER) $(SCANNER_LIBS) Makefile
-       PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-       --add-include-path=$(top_builddir)/gir --add-include-path=. \
+utility-1.0.gir: libutility.la utility.h $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+       $(CHECK_DEBUG) $(SCANNER) \
        --include=GObject-2.0 \
        --library=utility \
        --namespace=utility \
@@ -98,9 +92,8 @@ utility-1.0.gir: libutility.la utility.h $(SCANNER) $(SCANNER_LIBS) Makefile
 GIRS += utility-1.0.gir
 
 # This one tests different --namespace and --strip-prefix
-GtkFrob-1.0.gir: libgtkfrob.la gtkfrob.h $(SCANNER) $(SCANNER_LIBS) Makefile
-       PYTHONPATH=$(SCANNER_PYTHONPATH) $(CHECK_DEBUG) $(SCANNER) -v \
-       --add-include-path=$(top_builddir)/gir --add-include-path=. \
+GtkFrob-1.0.gir: libgtkfrob.la gtkfrob.h $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+       $(CHECK_DEBUG) $(SCANNER) \
        --include=GObject-2.0 \
        --library=gtkfrob \
        --namespace=GtkFrob \
@@ -111,6 +104,23 @@ GtkFrob-1.0.gir: libgtkfrob.la gtkfrob.h $(SCANNER) $(SCANNER_LIBS) Makefile
        --output $@
 GIRS += GtkFrob-1.0.gir
 
+bin_PROGRAMS = barapp
+
+barapp_SOURCES = barapp.c barapp.h
+barapp_LDADD = $(top_builddir)/girepository/libgirepository.la
+barapp_LDFLAGS = -export-dynamic
+BarApp-1.0.gir: barapp $(SCANNER_BIN) $(SCANNER_LIBS) Makefile
+       $(SCANNER) \
+       --include=GObject-2.0 \
+       --program=./barapp \
+       --namespace=BarApp \
+       --strip-prefix=Bar \
+       --nsversion=1.0 \
+       --pkg gobject-2.0 \
+       $(barapp_SOURCES) \
+       --output $@
+GIRS += BarApp-1.0.gir
+
 pre-check:
        @if test "$(top_builddir)" != "$(top_srcdir)"; then \
           cp -f $(top_srcdir)/giscanner/*.py $(top_builddir)/giscanner; \
index 4f080dc..1a859b3 100644 (file)
@@ -62,7 +62,7 @@
           <type name="GObject.Object" c:type="GObject*"/>
         </return-value>
         <parameters>
-          <parameter name="somearg" transfer-ownership="full" allow-none="1">
+          <parameter name="somearg" transfer-ownership="none" allow-none="1">
             <type name="utf8" c:type="gchar*"/>
           </parameter>
         </parameters>
index e6f3a18..3a4067b 100644 (file)
@@ -60,7 +60,7 @@
           <type name="GObject.Object"/>
         </return-value>
         <parameters>
-          <parameter name="somearg" transfer-ownership="full" allow-none="1">
+          <parameter name="somearg" transfer-ownership="none" allow-none="1">
             <type name="utf8"/>
           </parameter>
         </parameters>
index bcfe55f..ef521a2 100644 (file)
@@ -247,7 +247,7 @@ annotation_object_compute_sum_n(AnnotationObject *object,
  * @somearg: (allow-none):
  **/
 GObject*
-annotation_object_allow_none (AnnotationObject *object, gchar *somearg)
+annotation_object_allow_none (AnnotationObject *object, const gchar *somearg)
 {
   return NULL;
 }
index ea78786..3eb9fcb 100644 (file)
@@ -39,7 +39,7 @@ gint     annotation_object_out          (AnnotationObject *object,
                                         int              *outarg);
 GObject* annotation_object_create_object(AnnotationObject *object);
 GObject* annotation_object_allow_none   (AnnotationObject *object,
-                                        gchar            *somearg);
+                                        const gchar      *somearg);
 GObject* annotation_object_notrans      (AnnotationObject *object);
 gint     annotation_object_inout        (AnnotationObject *object,
                                         int              *inoutarg);
index d55bc8d..312db61 100644 (file)
           <type name="utf8" c:type="gchararray"/>
         </return-value>
         <parameters>
-          <parameter name="object" transfer-ownership="full">
+          <parameter name="object" transfer-ownership="none">
             <type name="GObject.Object" c:type="GObject"/>
           </parameter>
           <parameter name="p0" transfer-ownership="none">
index d3e82e1..5a457f8 100644 (file)
           <type name="utf8"/>
         </return-value>
         <parameters>
-          <parameter name="object" transfer-ownership="full">
+          <parameter name="object" transfer-ownership="none">
             <type name="GObject.Object"/>
           </parameter>
           <parameter name="p0" transfer-ownership="none">
index 337f9b6..0f46018 100755 (executable)
@@ -43,12 +43,12 @@ sys.path.insert(0, path)
 
 from giscanner.ast import Include
 from giscanner.cachestore import CacheStore
-from giscanner.glibtransformer import GLibTransformer
+from giscanner.dumper import compile_introspection_binary
+from giscanner.glibtransformer import GLibTransformer, IntrospectionBinary
 from giscanner.minixpath import myxpath, xpath_assert
 from giscanner.sourcescanner import SourceScanner
 from giscanner.transformer import Transformer
 
-
 def _get_option_parser():
     parser = optparse.OptionParser('%prog [options] sources')
     parser.add_option("", "--format",
@@ -58,9 +58,18 @@ def _get_option_parser():
     parser.add_option("-i", "--include",
                       action="append", dest="includes", default=[],
                       help="include types for other gidls")
-    parser.add_option("--add-include-path",
+    parser.add_option("", "--add-include-path",
                       action="append", dest="include_paths", default=[],
                       help="include paths for other GIR files")
+    parser.add_option("", "--program",
+                      action="store", dest="program", default=None,
+                      help="program to execute")
+    parser.add_option("", "--program-arg",
+                      action="append", dest="program_args", default=[],
+                      help="extra arguments to program")
+    parser.add_option("", "--no-libtool",
+                      action="store_true", dest="nolibtool", default=False,
+                      help="use libtool")
     parser.add_option("-l", "--library",
                       action="append", dest="libraries", default=[],
                       help="libraries of this unit")
@@ -209,8 +218,9 @@ def main(args):
     else:
         _error("Unknown format: %s" % (options.format, ))
 
-    if not options.libraries:
-        _error("Must specify --library at least one primary library")
+    if not (options.libraries or options.program):
+        _error("Must specify --program or --library")
+    libraries = options.libraries
 
     for package in options.packages:
         output = subprocess.Popen(['pkg-config', '--cflags', package],
@@ -285,13 +295,17 @@ def main(args):
         include_obj = Include.from_string(include)
         transformer.register_include(include_obj)
 
+    if options.program:
+        args=[options.program]
+        args.extend(options.program_args)
+        binary = IntrospectionBinary(args)
+    else:
+        binary = compile_introspection_binary(options)
+
     # Transform the C AST nodes into higher level
     # GLib/GObject nodes
     glibtransformer = GLibTransformer(transformer, noclosure=options.noclosure)
-    libraries = []
-    if options.libraries:
-        for library in options.libraries:
-            libraries.append(glibtransformer.add_library(library))
+    glibtransformer.set_introspection_binary(binary)
 
     namespace = glibtransformer.parse()