summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile-giscanner.am1
-rw-r--r--giscanner/ccompiler.py202
-rw-r--r--giscanner/dumper.py87
-rw-r--r--giscanner/shlibs.py89
4 files changed, 222 insertions, 157 deletions
diff --git a/Makefile-giscanner.am b/Makefile-giscanner.am
index bccd8151..c2273cd6 100644
--- a/Makefile-giscanner.am
+++ b/Makefile-giscanner.am
@@ -31,6 +31,7 @@ pkgpyexec_PYTHON = \
giscanner/annotationparser.py \
giscanner/ast.py \
giscanner/cachestore.py \
+ giscanner/ccompiler.py \
giscanner/codegen.py \
giscanner/docmain.py \
giscanner/docwriter.py \
diff --git a/giscanner/ccompiler.py b/giscanner/ccompiler.py
new file mode 100644
index 00000000..63110a22
--- /dev/null
+++ b/giscanner/ccompiler.py
@@ -0,0 +1,202 @@
+# -*- Mode: Python -*-
+# GObject-Introspection - a framework for introspecting GObject libraries
+# Copyright (C) 2014 Chun-wei Fan
+#
+# 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 sys
+import distutils
+
+from distutils.msvccompiler import MSVCCompiler
+from distutils.cygwinccompiler import Mingw32CCompiler
+from distutils.sysconfig import customize_compiler
+
+from . import utils
+
+
+class CCompiler(object):
+
+ compiler_cmd = ''
+ compiler = None
+ _cflags_no_deprecation_warnings = ''
+
+ def __init__(self, compiler_name=None):
+ pass
+
+ def get_internal_link_flags(self,
+ args,
+ libtool,
+ libraries,
+ libpaths,
+ pkgconfig_msvc_flags,
+ ns,
+ ns_version):
+ # An "internal" link is where the library to be introspected
+ # is being built in the current directory.
+
+ # Search the current directory first
+ # (This flag is not supported nor needed for Visual C++)
+ if pkgconfig_msvc_flags == '':
+ args.append('-L.')
+
+ # https://bugzilla.gnome.org/show_bug.cgi?id=625195
+ if not libtool:
+ # We don't have -Wl,-rpath for Visual C++, and that's
+ # going to cause a problem. Instead, link to internal
+ # libraries by deducing the .lib file name using
+ # the namespace name and version
+ if pkgconfig_msvc_flags:
+ if ns_version:
+ args.append(str.lower(ns) +
+ '-' +
+ ns_version + '.lib')
+ else:
+ args.append(str.lower(ns) + '.lib')
+ else:
+ args.append('-Wl,-rpath=.')
+
+ # Ensure libraries are always linked as we are going to use ldd to work
+ # out their names later
+ if not libtool and pkgconfig_msvc_flags == '':
+ args.append('-Wl,--no-as-needed')
+
+ for library in libraries:
+ # Visual C++: We have the needed .lib files now, and we need to link
+ # to .lib files, not the .dll as the --library option specifies the
+ # .dll(s) the .gir file refers to
+ if pkgconfig_msvc_flags == '':
+ if library.endswith(".la"): # explicitly specified libtool library
+ args.append(library)
+ else:
+ args.append('-l' + library)
+
+ for library_path in libpaths:
+ # Not used/needed on Visual C++, and -Wl,-rpath options
+ # will cause grief
+ if pkgconfig_msvc_flags == '':
+ args.append('-L' + library_path)
+ if os.path.isabs(library_path):
+ if libtool:
+ args.append('-rpath')
+ args.append(library_path)
+ else:
+ args.append('-Wl,-rpath=' + library_path)
+
+ def get_external_link_flags(self, args, libraries, pkgconfig_msvc_flags):
+ # An "external" link is where the library to be introspected
+ # is installed on the system; this case is used for the scanning
+ # of GLib in gobject-introspection itself.
+
+ for library in libraries:
+ # The --library option on Windows pass in the .dll file(s) the
+ # .gir files refer to, so don't link to them on Visual C++
+ if pkgconfig_msvc_flags == '':
+ if library.endswith(".la"): # explicitly specified libtool library
+ args.append(library)
+ else:
+ args.append('-l' + library)
+
+ def resolve_windows_libs(self, libraries, options):
+ args = []
+ compiler_cmd = os.environ.get('CC', 'cc')
+ libsearch = []
+
+ # When we are using Visual C++...
+ if 'cl.exe' in compiler_cmd or 'cl' in compiler_cmd:
+ # The search path of the .lib's on Visual C++
+ # is dependent on the LIB environmental variable,
+ # so just query for that
+ is_msvc = True
+ libpath = os.environ.get('LIB')
+ libsearch = libpath.split(';')
+
+ # Use the dumpbin utility that's included in
+ # every Visual C++ installation to find out which
+ # DLL the library gets linked to
+ args.append('dumpbin.exe')
+ args.append('-symbols')
+
+ # When we are not using Visual C++ (i.e. we are using GCC)...
+ else:
+ is_msvc = False
+ libtool = get_libtool_command(options)
+ if libtool:
+ args.append(which(os.environ.get('SHELL', 'sh.exe')))
+ args.extend(libtool)
+ args.append('--mode=execute')
+ # FIXME: it could have prefix (i686-w64-mingw32-dlltool.exe)
+ args.extend(['dlltool.exe', '--identify'])
+ proc = subprocess.Popen([compiler_cmd, '-print-search-dirs'],
+ stdout=subprocess.PIPE)
+ o, e = proc.communicate()
+ for line in o.splitlines():
+ if line.startswith('libraries: '):
+ libsearch = line[len('libraries: '):].split(';')
+
+ shlibs = []
+ not_resolved = []
+ for lib in libraries:
+ found = False
+ candidates = [
+ 'lib%s.dll.a' % lib,
+ 'lib%s.a' % lib,
+ '%s.dll.a' % lib,
+ '%s.a' % lib,
+ '%s.lib' % lib,
+ ]
+ for l in libsearch:
+ if found:
+ break
+ if l.startswith('='):
+ l = l[1:]
+ for c in candidates:
+ if found:
+ break
+ implib = os.path.join(l, c)
+ if os.path.exists(implib):
+ proc = subprocess.Popen(args + [implib],
+ stdout=subprocess.PIPE)
+ o, e = proc.communicate()
+ for line in o.splitlines():
+ if is_msvc:
+ # On Visual Studio, dumpbin -symbols something.lib gives the
+ # filename of DLL without the '.dll' extension that something.lib
+ # links to, in the line that contains
+ # __IMPORT_DESCRIPTOR_<dll_filename_that_something.lib_links_to>
+
+ if '__IMPORT_DESCRIPTOR_' in line:
+ line_tokens = line.split()
+ for item in line_tokens:
+ if item.startswith('__IMPORT_DESCRIPTOR_'):
+ shlibs.append(item[20:] + '.dll')
+ found = True
+ break
+ if found:
+ break
+ else:
+ shlibs.append(line)
+ found = True
+ break
+ if not found:
+ not_resolved.append(lib)
+ if len(not_resolved) > 0:
+ raise SystemExit(
+ "ERROR: can't resolve libraries to shared libraries: " +
+ ", ".join(not_resolved))
+ return shlibs
diff --git a/giscanner/dumper.py b/giscanner/dumper.py
index ce119619..45a09fc8 100644
--- a/giscanner/dumper.py
+++ b/giscanner/dumper.py
@@ -27,6 +27,7 @@ import tempfile
from .gdumpparser import IntrospectionBinary
from . import utils
+from .ccompiler import CCompiler
# bugzilla.gnome.org/558436
# Compile a binary program which is then linked to a library
@@ -287,10 +288,23 @@ class DumpCompiler(object):
"Could not find object file: %s" % (source, ))
args.extend(list(sources))
+ cc = CCompiler()
+
if not self._options.external_library:
- self._add_link_internal_args(args, libtool)
+ cc.get_internal_link_flags(args,
+ libtool,
+ self._options.libraries,
+ self._options.library_paths,
+ self._pkgconfig_msvc_flags,
+ self._options.namespace_name,
+ self._options.namespace_version)
+ args.extend(self._run_pkgconfig('--libs'))
+
else:
- self._add_link_external_args(args)
+ args.extend(self._run_pkgconfig('--libs'))
+ cc.get_external_link_flags(args,
+ self._options.libraries,
+ self._pkgconfig_msvc_flags)
if not self._options.quiet:
print "g-ir-scanner: link: %s" % (
@@ -317,75 +331,6 @@ class DumpCompiler(object):
if msys:
os.remove(tf_name)
- def _add_link_internal_args(self, args, libtool):
- # An "internal" link is where the library to be introspected
- # is being built in the current directory.
-
- # Search the current directory first
- # (This flag is not supported nor needed for Visual C++)
- if self._pkgconfig_msvc_flags == '':
- args.append('-L.')
-
- # https://bugzilla.gnome.org/show_bug.cgi?id=625195
- if not libtool:
- # We don't have -Wl,-rpath for Visual C++, and that's
- # going to cause a problem. Instead, link to internal
- # libraries by deducing the .lib file name using
- # the namespace name and version
- if self._pkgconfig_msvc_flags:
- if self._options.namespace_version:
- args.append(str.lower(self._options.namespace_name) +
- '-' +
- self._options.namespace_version + '.lib')
- else:
- args.append(str.lower(self._options.namespace_name) + '.lib')
- else:
- args.append('-Wl,-rpath=.')
-
- # Ensure libraries are always linked as we are going to use ldd to work
- # out their names later
- if not libtool and self._pkgconfig_msvc_flags == '':
- args.append('-Wl,--no-as-needed')
-
- for library in self._options.libraries:
- # Visual C++: We have the needed .lib files now, and we need to link
- # to .lib files, not the .dll as the --library option specifies the
- # .dll(s) the .gir file refers to
- if self._pkgconfig_msvc_flags == '':
- if library.endswith(".la"): # explicitly specified libtool library
- args.append(library)
- else:
- args.append('-l' + library)
-
- for library_path in self._options.library_paths:
- # Not used/needed on Visual C++, and -Wl,-rpath options
- # will cause grief
- if self._pkgconfig_msvc_flags == '':
- args.append('-L' + library_path)
- if os.path.isabs(library_path):
- if libtool:
- args.append('-rpath')
- args.append(library_path)
- else:
- args.append('-Wl,-rpath=' + library_path)
-
- args.extend(self._run_pkgconfig('--libs'))
-
- def _add_link_external_args(self, args):
- # An "external" link is where the library to be introspected
- # is installed on the system; this case is used for the scanning
- # of GLib in gobject-introspection itself.
-
- args.extend(self._run_pkgconfig('--libs'))
- for library in self._options.libraries:
- # The --library option on Windows pass in the .dll file(s) the
- # .gir files refer to, so don't link to them on Visual C++
- if self._pkgconfig_msvc_flags == '':
- if library.endswith(".la"): # explicitly specified libtool library
- args.append(library)
- else:
- args.append('-l' + library)
-
def compile_introspection_binary(options, get_type_functions,
error_quark_functions):
diff --git a/giscanner/shlibs.py b/giscanner/shlibs.py
index ec974fa4..1ad75ee6 100644
--- a/giscanner/shlibs.py
+++ b/giscanner/shlibs.py
@@ -25,6 +25,7 @@ import re
import subprocess
from .utils import get_libtool_command, extract_libtool_shlib, which
+from .ccompiler import CCompiler
# For .la files, the situation is easy.
@@ -89,92 +90,8 @@ def _resolve_non_libtool(options, binary, libraries):
binary.args[0] = old_argdir
if os.name == 'nt':
- args = []
- compiler_cmd = os.environ.get('CC', 'cc')
- libsearch = []
-
- # When we are using Visual C++...
- if 'cl.exe' in compiler_cmd or 'cl' in compiler_cmd:
- # The search path of the .lib's on Visual C++
- # is dependent on the LIB environmental variable,
- # so just query for that
- is_msvc = True
- libpath = os.environ.get('LIB')
- libsearch = libpath.split(';')
-
- # Use the dumpbin utility that's included in
- # every Visual C++ installation to find out which
- # DLL the library gets linked to
- args.append('dumpbin.exe')
- args.append('-symbols')
-
- # When we are not using Visual C++ (i.e. we are using GCC)...
- else:
- is_msvc = False
- libtool = get_libtool_command(options)
- if libtool:
- args.append(which(os.environ.get('SHELL', 'sh.exe')))
- args.extend(libtool)
- args.append('--mode=execute')
- # FIXME: it could have prefix (i686-w64-mingw32-dlltool.exe)
- args.extend(['dlltool.exe', '--identify'])
- proc = subprocess.Popen([compiler_cmd, '-print-search-dirs'],
- stdout=subprocess.PIPE)
- o, e = proc.communicate()
- for line in o.splitlines():
- if line.startswith('libraries: '):
- libsearch = line[len('libraries: '):].split(';')
-
- shlibs = []
- not_resolved = []
- for lib in libraries:
- found = False
- candidates = [
- 'lib%s.dll.a' % lib,
- 'lib%s.a' % lib,
- '%s.dll.a' % lib,
- '%s.a' % lib,
- '%s.lib' % lib,
- ]
- for l in libsearch:
- if found:
- break
- if l.startswith('='):
- l = l[1:]
- for c in candidates:
- if found:
- break
- implib = os.path.join(l, c)
- if os.path.exists(implib):
- proc = subprocess.Popen(args + [implib],
- stdout=subprocess.PIPE)
- o, e = proc.communicate()
- for line in o.splitlines():
- if is_msvc:
- # On Visual Studio, dumpbin -symbols something.lib gives the
- # filename of DLL without the '.dll' extension that something.lib
- # links to, in the line that contains
- # __IMPORT_DESCRIPTOR_<dll_filename_that_something.lib_links_to>
-
- if '__IMPORT_DESCRIPTOR_' in line:
- line_tokens = line.split()
- for item in line_tokens:
- if item.startswith('__IMPORT_DESCRIPTOR_'):
- shlibs.append(item[20:] + '.dll')
- found = True
- break
- if found:
- break
- else:
- shlibs.append(line)
- found = True
- break
- if not found:
- not_resolved.append(lib)
- if len(not_resolved) > 0:
- raise SystemExit(
- "ERROR: can't resolve libraries to shared libraries: " +
- ", ".join(not_resolved))
+ cc = CCompiler()
+ shlibs = cc.resolve_windows_libs(libraries, options)
else:
args = []