Add new files from last commit
[gnome.gobject-introspection] / giscanner / dumper.py
1 import os
2 import subprocess
3 import tempfile
4
5 from .glibtransformer import IntrospectionBinary
6
7 # bugzilla.gnome.org/558436
8 # Compile a binary program which is then linked to a library
9 # we want to introspect, in order to call its get_type functions.
10
11
12 def mktmp(tmpdir, nsname, nsver, suffix):
13     name = '%s-%s%s' % (nsname, nsver, suffix)
14     return os.path.join(tmpdir, name)
15
16
17 def compile_introspection_binary(options):
18     tmpdir = tempfile.mkdtemp('', 'tmp-introspect')
19     nsname = options.namespace_name
20     nsver = options.namespace_version
21     c_path = mktmp(tmpdir, nsname, nsver, '.c')
22     f = open(c_path, 'w')
23     f.write('''#include <glib.h>
24 #include <girepository.h>
25 #include <string.h>
26
27 static GOptionEntry entries[] =
28 {
29   { NULL }
30 };
31
32 int
33 main(int argc, char **argv)
34 {
35   GOptionContext *context;
36   GError *error = NULL;
37
38   g_type_init ();
39   g_thread_init (NULL);
40
41   context = g_option_context_new ("");
42   g_option_context_add_main_entries (context, entries, "girepository");
43   g_option_context_add_group (context, g_irepository_get_option_group ());
44   if (!g_option_context_parse (context, &argc, &argv, &error))
45     {
46       g_printerr ("introspect failed (%d,%d): %s\\n",
47                   error->domain, error->code,
48                   error->message);
49       return 1;
50     }
51   return 0;
52 }
53 ''')
54     f.close()
55
56     o_path = mktmp(tmpdir, nsname, nsver, '.o')
57
58     cc = os.environ.get('CC', 'gcc')
59     ld = os.environ.get('LD', cc)
60     pkgconfig = os.environ.get('PKG_CONFIG', 'pkg-config')
61     uninst_srcdir = os.environ.get('UNINSTALLED_INTROSPECTION_SRCDIR')
62     uninst_builddir = os.environ.get('UNINSTALLED_INTROSPECTION_BUILDDIR')
63
64     pkgs = ['gio-2.0 gthread-2.0']
65     if not uninst_srcdir:
66         pkgs.append('gobject-introspection-1.0')
67
68     cc_args = [cc]
69     if cc == 'gcc':
70         cc_args.append('-Wall')
71     output = subprocess.Popen([pkgconfig, '--cflags'] + pkgs,
72                               stdout=subprocess.PIPE).communicate()[0]
73     if uninst_srcdir:
74         cc_args.append('-I' + os.path.join(uninst_srcdir, 'girepository'))
75     cc_args.extend(output.split())
76     for include in options.cpp_includes:
77         cc_args.append('-I' + include)
78     cc_args.extend(['-c', '-o', o_path, c_path])
79     print "%r" % (cc_args, )
80     subprocess.check_call(cc_args)
81
82     bin_path = mktmp(tmpdir, nsname, nsver, '')
83
84     ld_args = [ld, '-o', bin_path, o_path]
85     libtool_infection = not options.nolibtool
86     if not libtool_infection:
87         try:
88             subprocess.check_call(['libtool', '--version'])
89         except subprocess.CalledProcessError, e:
90             # If libtool's not installed, assume we don't need it
91             libtool_infection = False
92     if libtool_infection:
93         ld_args.insert(0, 'libtool')
94         ld_args.insert(1, '--mode=link')
95     output = subprocess.Popen([pkgconfig, '--libs'] + pkgs,
96                               stdout=subprocess.PIPE).communicate()[0]
97     ld_args.extend(output.split())
98
99     # This hack is only for building gobject-introspection itself
100     if uninst_builddir:
101         path = os.path.join(uninst_builddir, 'girepository',
102                             'libgirepository.la')
103         ld_args.append(path)
104     # Search the current directory first
105     ld_args.append('-L.')
106
107     # We only use the first library; assume others are "custom" libraries like
108     # from gir-repository.  Right now those don't define new GTypes, so we
109     # don't need to introspect them.
110     ld_args.append('-l'+options.libraries[0])
111     print "%r" % (ld_args, )
112     subprocess.check_call(ld_args)
113
114     os.unlink(c_path)
115     return IntrospectionBinary([bin_path], tmpdir)