summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@src.gnome.org>2008-11-13 19:57:12 +0000
committerColin Walters <walters@src.gnome.org>2008-11-13 19:57:12 +0000
commitb76cca0eb5ea3363ef738b7c9b3d3e9eefea6b79 (patch)
treed11bbc4e4fcf7fbf927a2ac801f793dfcc9bbfed
parentb1b589ab793633352be375e18f0b3a821ae70afe (diff)
downloadgobject-introspection-b76cca0eb5ea3363ef738b7c9b3d3e9eefea6b79.tar.gz
Bug 558436 - avoid having scanner load app code
svn path=/trunk/; revision=912
-rw-r--r--ChangeLog20
-rw-r--r--docs/g-ir-scanner.115
-rw-r--r--gir/Makefile.am44
-rw-r--r--giscanner/Makefile.am2
-rw-r--r--giscanner/cgobject.py303
-rw-r--r--giscanner/glibtransformer.py335
-rw-r--r--giscanner/transformer.py19
-rw-r--r--tests/everything/Makefile.am11
-rw-r--r--tests/offsets/Makefile.am15
-rw-r--r--tests/scanner/Makefile.am60
-rw-r--r--tests/scanner/annotation-1.0-expected.gir2
-rw-r--r--tests/scanner/annotation-1.0-expected.tgir2
-rw-r--r--tests/scanner/annotation.c2
-rw-r--r--tests/scanner/annotation.h2
-rw-r--r--tests/scanner/foo-1.0-expected.gir2
-rw-r--r--tests/scanner/foo-1.0-expected.tgir2
-rwxr-xr-xtools/g-ir-scanner32
17 files changed, 290 insertions, 578 deletions
diff --git a/ChangeLog b/ChangeLog
index b35ce0a5..1682a289 100644
--- 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.
diff --git a/docs/g-ir-scanner.1 b/docs/g-ir-scanner.1
index 9148a359..315f678e 100644
--- a/docs/g-ir-scanner.1
+++ b/docs/g-ir-scanner.1
@@ -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.
diff --git a/gir/Makefile.am b/gir/Makefile.am
index 0e213912..6b48b313 100644
--- a/gir/Makefile.am
+++ b/gir/Makefile.am
@@ -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 \
diff --git a/giscanner/Makefile.am b/giscanner/Makefile.am
index c9d23e58..1d6942b4 100644
--- a/giscanner/Makefile.am
+++ b/giscanner/Makefile.am
@@ -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
index 308ebf49..00000000
--- a/giscanner/cgobject.py
+++ /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')
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index f97af9fa..a414078e 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -19,11 +19,12 @@
#
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 == []:
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index c512f7a4..fbf82ffd 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -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
diff --git a/tests/everything/Makefile.am b/tests/everything/Makefile.am
index 8f3eceb6..ec209d51 100644
--- a/tests/everything/Makefile.am
+++ b/tests/everything/Makefile.am
@@ -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) \
diff --git a/tests/offsets/Makefile.am b/tests/offsets/Makefile.am
index 57cfdfb7..2c3cae20 100644
--- a/tests/offsets/Makefile.am
+++ b/tests/offsets/Makefile.am
@@ -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 \
diff --git a/tests/scanner/Makefile.am b/tests/scanner/Makefile.am
index 9fba3b0f..ae42ccea 100644
--- a/tests/scanner/Makefile.am
+++ b/tests/scanner/Makefile.am
@@ -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; \
diff --git a/tests/scanner/annotation-1.0-expected.gir b/tests/scanner/annotation-1.0-expected.gir
index 4f080dc0..1a859b3c 100644
--- a/tests/scanner/annotation-1.0-expected.gir
+++ b/tests/scanner/annotation-1.0-expected.gir
@@ -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>
diff --git a/tests/scanner/annotation-1.0-expected.tgir b/tests/scanner/annotation-1.0-expected.tgir
index e6f3a18f..3a4067be 100644
--- a/tests/scanner/annotation-1.0-expected.tgir
+++ b/tests/scanner/annotation-1.0-expected.tgir
@@ -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>
diff --git a/tests/scanner/annotation.c b/tests/scanner/annotation.c
index bcfe55fa..ef521a23 100644
--- a/tests/scanner/annotation.c
+++ b/tests/scanner/annotation.c
@@ -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;
}
diff --git a/tests/scanner/annotation.h b/tests/scanner/annotation.h
index ea78786a..3eb9fcb8 100644
--- a/tests/scanner/annotation.h
+++ b/tests/scanner/annotation.h
@@ -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);
diff --git a/tests/scanner/foo-1.0-expected.gir b/tests/scanner/foo-1.0-expected.gir
index d55bc8dd..312db61e 100644
--- a/tests/scanner/foo-1.0-expected.gir
+++ b/tests/scanner/foo-1.0-expected.gir
@@ -157,7 +157,7 @@
<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">
diff --git a/tests/scanner/foo-1.0-expected.tgir b/tests/scanner/foo-1.0-expected.tgir
index d3e82e1a..5a457f89 100644
--- a/tests/scanner/foo-1.0-expected.tgir
+++ b/tests/scanner/foo-1.0-expected.tgir
@@ -101,7 +101,7 @@
<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">
diff --git a/tools/g-ir-scanner b/tools/g-ir-scanner
index 337f9b6e..0f460183 100755
--- a/tools/g-ir-scanner
+++ b/tools/g-ir-scanner
@@ -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()