From ec3bcb29fb938ac3d0ea70c1b739a76970613403 Mon Sep 17 00:00:00 2001 From: Owen W. Taylor Date: Mon, 16 Feb 2009 21:52:52 +0000 Subject: Bug 572075 - Make the scanner work with static and convenience libraries We need to reference the get_type() functions we are going to dlsym or otherwise the linker may not include them in the introspection binary. giscanner/dumper.py: Accept a list of _get_type() functions and write an array referencing them into the introspection binary. giscanner/glibtransformer.py: Break parsing into too stages - the stage where we compute the _get_type() functions and the stage where we invoke the introspection binary. tools/g-ir-scanner: Pass _get_type() functions from the scanner when creating the introspection binary. http://bugzilla.gnome.org/show_bug.cgi?id=572075 --- diff --git a/giscanner/dumper.py b/giscanner/dumper.py index 6b78568..e487c12 100644 --- a/giscanner/dumper.py +++ b/giscanner/dumper.py @@ -73,8 +73,9 @@ class LinkerError(Exception): class DumpCompiler(object): - def __init__(self, options): + def __init__(self, options, get_type_functions): self._options = options + self._get_type_functions = get_type_functions self._tmpdir = tempfile.mkdtemp('', 'tmp-introspect') self._compiler_cmd = os.environ.get('CC', 'gcc') @@ -93,6 +94,22 @@ class DumpCompiler(object): c_path = self._generate_tempfile('.c') f = open(c_path, 'w') f.write(_PROGRAM_TEMPLATE) + + # We need to reference our get_type functions to make sure they are + # pulled in at the linking stage if the library is a static library + # rather than a shared library. + for func in self._get_type_functions: + f.write("extern GType " + func + "(void);\n") + f.write("GType (*GI_GET_TYPE_FUNCS_[])(void) = {\n") + first = True + for func in self._get_type_functions: + if first: + first = False + else: + f.write(",\n") + f.write(" " + func) + f.write("\n};\n") + f.close() o_path = self._generate_tempfile('.o') @@ -208,6 +225,6 @@ class DumpCompiler(object): subprocess.check_call(args) -def compile_introspection_binary(options): - dc = DumpCompiler(options) +def compile_introspection_binary(options, get_type_functions): + dc = DumpCompiler(options, get_type_functions) return dc.run() diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py index f05ce65..c39ce64 100644 --- a/giscanner/glibtransformer.py +++ b/giscanner/glibtransformer.py @@ -99,9 +99,6 @@ class GLibTransformer(object): # Public API - def set_introspection_binary(self, binary): - self._binary = binary - def _print_statistics(self): nodes = list(self._names.names.itervalues()) @@ -114,9 +111,16 @@ class GLibTransformer(object): print " %d nodes; %d objects, %d interfaces, %d enums" \ % (len(nodes), objectcount, ifacecount, enumcount) - def parse(self): + def init_parse(self): + """Do parsing steps that don't involve the introspection binary + + This does enough work that get_type_functions() can be called. + + """ + namespace = self._transformer.parse() self._namespace_name = namespace.name + self._namespace_version = namespace.version # First pass: parsing for node in namespace.nodes: @@ -127,6 +131,15 @@ class GLibTransformer(object): if namespace.name == 'GObject': del self._names.aliases['Type'] + def get_get_type_functions(self): + return self._get_type_functions + + def set_introspection_binary(self, binary): + self._binary = binary + + def parse(self): + """Do remaining parsing steps requiring introspection binary""" + # Get all the GObject data by passing our list of get_type # functions to the compiled binary @@ -158,7 +171,7 @@ class GLibTransformer(object): self._validate(nodes) # Create a new namespace with what we found - namespace = Namespace(namespace.name, namespace.version) + namespace = Namespace(self._namespace_name, self._namespace_version) namespace.nodes = map(lambda x: x[1], self._names.aliases.itervalues()) for (ns, x) in self._names.names.itervalues(): namespace.nodes.append(x) diff --git a/tools/g-ir-scanner b/tools/g-ir-scanner index 0cf54ce..f53f7fc 100755 --- a/tools/g-ir-scanner +++ b/tools/g-ir-scanner @@ -316,17 +316,23 @@ def main(args): # Transform the C symbols into AST nodes transformer.set_source_ast(ss) + # Transform the C AST nodes into higher level + # GLib/GObject nodes + glibtransformer = GLibTransformer(transformer, + noclosure=options.noclosure) + + # Do enough parsing that we have the get_type() functions to reference + # when creating the introspection binary + glibtransformer.init_parse() + if options.program: args=[options.program] args.extend(options.program_args) binary = IntrospectionBinary(args) else: - binary = compile_introspection_binary(options) + binary = compile_introspection_binary(options, + glibtransformer.get_get_type_functions()) - # Transform the C AST nodes into higher level - # GLib/GObject nodes - glibtransformer = GLibTransformer(transformer, - noclosure=options.noclosure) glibtransformer.set_introspection_binary(binary) namespace = glibtransformer.parse() -- cgit v0.9.1