From 2a874a481728d61cb40953c0b92d1a404b8bf1d5 Mon Sep 17 00:00:00 2001 From: Johan Dahlin Date: Sun, 23 Nov 2008 21:38:08 +0000 Subject: [PATCH] Add license headers, refactor into a class, avoid some duplication and do 2008-11-23 Johan Dahlin * giscanner/dumper.py: Add license headers, refactor into a class, avoid some duplication and do some extra pedantic checks. svn path=/trunk/; revision=962 --- ChangeLog | 6 ++ giscanner/dumper.py | 219 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 155 insertions(+), 70 deletions(-) diff --git a/ChangeLog b/ChangeLog index cf15744..55299ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,10 @@ 2008-11-23 Johan Dahlin + + * giscanner/dumper.py: Add license headers, + refactor into a class, avoid some duplication and do some + extra pedantic checks. + +2008-11-23 Johan Dahlin Make it compilable with -Werror on my system by adding a couple of prototypes and including headers. diff --git a/giscanner/dumper.py b/giscanner/dumper.py index c19f973..727bbca 100644 --- a/giscanner/dumper.py +++ b/giscanner/dumper.py @@ -1,3 +1,24 @@ +# -*- Mode: Python -*- +# GObject-Introspection - a framework for introspecting GObject libraries +# Copyright (C) 2008 Colin Walters +# 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. +# + import os import subprocess import tempfile @@ -8,19 +29,8 @@ from .glibtransformer import IntrospectionBinary # Compile a binary program which is then linked to a library # we want to introspect, in order to call its get_type functions. - -def mktmp(tmpdir, nsname, nsver, suffix): - name = '%s-%s%s' % (nsname, nsver, suffix) - return os.path.join(tmpdir, name) - - -def compile_introspection_binary(options): - tmpdir = tempfile.mkdtemp('', 'tmp-introspect') - nsname = options.namespace_name - nsver = options.namespace_version - c_path = mktmp(tmpdir, nsname, nsver, '.c') - f = open(c_path, 'w') - f.write('''#include +_PROGRAM_TEMPLATE = '''/* This file is generated, do not edit */ +#include #include #include @@ -50,64 +60,133 @@ main(int argc, char **argv) } return 0; } -''') - f.close() - - o_path = mktmp(tmpdir, nsname, nsver, '.o') - - cc = os.environ.get('CC', 'gcc') - ld = os.environ.get('LD', cc) - pkgconfig = os.environ.get('PKG_CONFIG', 'pkg-config') - uninst_srcdir = os.environ.get('UNINSTALLED_INTROSPECTION_SRCDIR') - uninst_builddir = os.environ.get('UNINSTALLED_INTROSPECTION_BUILDDIR') - - pkgs = ['gio-2.0 gthread-2.0'] - if not uninst_srcdir: - pkgs.append('gobject-introspection-1.0') - - cc_args = [cc] - if cc == 'gcc': - cc_args.append('-Wall') - output = subprocess.Popen([pkgconfig, '--cflags'] + pkgs, - stdout=subprocess.PIPE).communicate()[0] - if uninst_srcdir: - cc_args.append('-I' + os.path.join(uninst_srcdir, 'girepository')) - cc_args.extend(output.split()) - for include in options.cpp_includes: - cc_args.append('-I' + include) - cc_args.extend(['-c', '-o', o_path, c_path]) - subprocess.check_call(cc_args) - - bin_path = mktmp(tmpdir, nsname, nsver, '') - - ld_args = [ld, '-o', bin_path, o_path] - libtool_infection = not options.nolibtool - if not libtool_infection: +''' + + +class CompilerError(Exception): + pass + + +class LinkerError(Exception): + pass + + +class DumpCompiler(object): + + def __init__(self, options): + self._options = options + self._tmpdir = tempfile.mkdtemp('', 'tmp-introspect') + + self._compiler_cmd = os.environ.get('CC', 'gcc') + self._linker_cmd = os.environ.get('LD', self._compiler_cmd) + self._pkgconfig_cmd = os.environ.get('PKG_CONFIG', 'pkg-config') + + self._uninst_srcdir = os.environ.get( + 'UNINSTALLED_INTROSPECTION_SRCDIR') + self._packages = ['gio-2.0 gthread-2.0'] + if not self._uninst_srcdir: + self._packages.append('gobject-introspection-1.0') + + # Public API + + def run(self): + c_path = self._generate_tempfile('.c') + f = open(c_path, 'w') + f.write(_PROGRAM_TEMPLATE) + f.close() + + o_path = self._generate_tempfile('.o') + bin_path = self._generate_tempfile() + + try: + self._compile(o_path, c_path) + except CompilerError, e: + raise SystemExit('ERROR: ' + str(e)) + + try: + self._link(bin_path, o_path) + except LinkerError, e: + raise SystemExit('ERROR: ' + str(e)) + + os.unlink(c_path) + + return IntrospectionBinary([bin_path], self._tmpdir) + + # Private API + + def _generate_tempfile(self, suffix=''): + tmpl = '%s-%s%s' % (self._options.namespace_name, + self._options.namespace_version, suffix) + return os.path.join(self._tmpdir, tmpl) + + def _run_pkgconfig(self, flag): + proc = subprocess.Popen( + [self._pkgconfig_cmd, flag] + self._packages, + stdout=subprocess.PIPE) + return proc.communicate()[0].split() + + def _use_libtool_infection(self): + libtool_infection = not self._options.nolibtool + if not libtool_infection: + return False + try: subprocess.check_call(['libtool', '--version']) except subprocess.CalledProcessError, e: # If libtool's not installed, assume we don't need it - libtool_infection = False - if libtool_infection: - ld_args.insert(0, 'libtool') - ld_args.insert(1, '--mode=link') - output = subprocess.Popen([pkgconfig, '--libs'] + pkgs, - stdout=subprocess.PIPE).communicate()[0] - ld_args.extend(output.split()) - - # This hack is only for building gobject-introspection itself - if uninst_builddir: - path = os.path.join(uninst_builddir, 'girepository', - 'libgirepository.la') - ld_args.append(path) - # Search the current directory first - ld_args.append('-L.') - - # We only use the first library; assume others are "custom" libraries like - # from gir-repository. Right now those don't define new GTypes, so we - # don't need to introspect them. - ld_args.append('-l'+options.libraries[0]) - subprocess.check_call(ld_args) - - os.unlink(c_path) - return IntrospectionBinary([bin_path], tmpdir) + return False + + return True + + def _compile(self, output, *sources): + args = [self._compiler_cmd] + if self._compiler_cmd == 'gcc': + args.append('-Wall') + pkgconfig_flags = self._run_pkgconfig('--cflags') + if self._uninst_srcdir: + args.append('-I' + os.path.join(self._uninst_srcdir, + 'girepository')) + args.extend(pkgconfig_flags) + for include in self._options.cpp_includes: + args.append('-I' + include) + args.extend(['-c', '-o', output]) + for source in sources: + if not os.path.exists(source): + raise CompilerError( + "Could not find c source file: %s" % (source, )) + args.extend(list(sources)) + subprocess.check_call(args) + + def _link(self, output, *sources): + args = [] + if self._use_libtool_infection(): + args.extend(['libtool', '--mode=link']) + + args.extend([self._linker_cmd, '-o', output]) + args.extend(self._run_pkgconfig('--libs')) + for source in sources: + if not os.path.exists(source): + raise CompilerError( + "Could not find object file: %s" % (source, )) + args.extend(list(sources)) + + uninst_builddir = os.environ.get('UNINSTALLED_INTROSPECTION_BUILDDIR') + # This hack is only for building gobject-introspection itself + if uninst_builddir: + path = os.path.join(uninst_builddir, 'girepository', + 'libgirepository.la') + args.append(path) + + # Search the current directory first + args.append('-L.') + + # We only use the first library; assume others are "custom" libraries + # like from gir-repository. Right now those don't define new GTypes, + # so we don't need to introspect them. + args.append('-l' + self._options.libraries[0]) + subprocess.check_call(args) + + +def compile_introspection_binary(options): + dc = DumpCompiler(options) + return dc.run() -- 2.7.4