summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--giscanner/ccompiler.py136
-rw-r--r--giscanner/dumper.py55
2 files changed, 113 insertions, 78 deletions
diff --git a/giscanner/ccompiler.py b/giscanner/ccompiler.py
index 2db535cb..884fc2cc 100644
--- a/giscanner/ccompiler.py
+++ b/giscanner/ccompiler.py
@@ -21,6 +21,13 @@
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
@@ -30,51 +37,85 @@ class CCompiler(object):
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):
+ def __init__(self,
+ environ=os.environ,
+ osname=os.name,
+ compiler_name=None):
+
+ if osname == 'nt':
+ # The compiler used here on Windows may well not be
+ # the same compiler that was used to build Python,
+ # as the official Python binaries are built with
+ # Visual Studio
+ if compiler_name is None:
+ if environ.get('MSYSTEM') == 'MINGW32' or environ.get('MSYSTEM') == 'MINGW64':
+ compiler_name = 'mingw32'
+ else:
+ compiler_name = distutils.ccompiler.get_default_compiler()
+ if compiler_name != 'msvc' and \
+ compiler_name != 'mingw32':
+ raise SystemExit('Specified Compiler \'%s\' is unsupported.' % compiler_name)
+ else:
+ # XXX: Is it common practice to use a non-Unix compiler
+ # class instance on non-Windows on platforms g-i supports?
+ compiler_name = distutils.ccompiler.get_default_compiler()
+
+ # Now, create the distutils ccompiler instance based on the info we have.
+ self.compiler = distutils.ccompiler.new_compiler(compiler=compiler_name)
+ customize_compiler(self.compiler)
+
+ # customize_compiler from distutils only does customization
+ # for 'unix' compiler type. Also, avoid linking to msvcrxx.dll
+ # for MinGW builds as the dumper binary does not link to the
+ # Python DLL, but link to msvcrt.dll if necessary.
+ if isinstance(self.compiler, Mingw32CCompiler):
+ if self.compiler.dll_libraries != ['msvcrt']:
+ self.compiler.dll_libraries = []
+ if self.compiler.preprocessor is None:
+ self.compiler.preprocessor = self.compiler.compiler + ['-E']
+
+ if self.check_is_msvc():
+ # We trick distutils to believe that we are (always) using a
+ # compiler supplied by a Windows SDK, so that we avoid launching
+ # a new build environment to detect the compiler that is used to
+ # build Python itself, which is not desirable, so that we use the
+ # compiler commands (and env) as-is.
+ os.environ['DISTUTILS_USE_SDK'] = '1'
+ if 'MSSdk' not in os.environ:
+ if 'WindowsSDKDir' in os.environ:
+ os.environ['MSSdk'] = os.environ.get('WindowsSDKDir')
+ elif os.environ.get('VCInstallDir'):
+ os.environ['MSSdk'] = os.environ.get('VCInstallDir')
+
+ self.compiler_cmd = 'cl.exe'
+
+ self._cflags_no_deprecation_warnings = "-wd4996"
+ else:
+ if (isinstance(self.compiler, Mingw32CCompiler)):
+ self.compiler_cmd = self.compiler.compiler[0]
+ else:
+ self.compiler_cmd = ''.join(self.compiler.executables['compiler'])
+
+ self._cflags_no_deprecation_warnings = "-Wno-deprecated-declarations"
+
+ def get_internal_link_flags(self, args, libtool, libraries, libpaths):
# 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 == '':
+ if not self.check_is_msvc():
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:
+ # https://bugzilla.gnome.org/show_bug.cgi?id=625195
+ if not libtool:
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')
+ 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 self.check_is_msvc():
+ args.append(library + '.lib')
+ else:
if library.endswith(".la"): # explicitly specified libtool library
args.append(library)
else:
@@ -83,7 +124,7 @@ class CCompiler(object):
for library_path in libpaths:
# Not used/needed on Visual C++, and -Wl,-rpath options
# will cause grief
- if pkgconfig_msvc_flags == '':
+ if not self.check_is_msvc():
args.append('-L' + library_path)
if os.path.isabs(library_path):
if libtool:
@@ -92,15 +133,15 @@ class CCompiler(object):
else:
args.append('-Wl,-rpath=' + library_path)
- def get_external_link_flags(self, args, libraries, pkgconfig_msvc_flags):
+ def get_external_link_flags(self, args, libraries):
# 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 self.check_is_msvc():
+ args.append(library + '.lib')
+ else:
if library.endswith(".la"): # explicitly specified libtool library
args.append(library)
else:
@@ -108,15 +149,13 @@ class CCompiler(object):
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:
+ if self.check_is_msvc():
# 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(';')
@@ -128,7 +167,6 @@ class CCompiler(object):
# When we are not using Visual C++ (i.e. we are using GCC)...
else:
- is_msvc = False
libtool = utils.get_libtool_command(options)
if libtool:
args.append(utils.which(os.environ.get('SHELL', 'sh.exe')))
@@ -136,7 +174,7 @@ class CCompiler(object):
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'],
+ proc = subprocess.Popen([self.compiler_cmd, '-print-search-dirs'],
stdout=subprocess.PIPE)
o, e = proc.communicate()
for line in o.splitlines():
@@ -168,7 +206,7 @@ class CCompiler(object):
stdout=subprocess.PIPE)
o, e = proc.communicate()
for line in o.splitlines():
- if is_msvc:
+ if self.check_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
@@ -194,3 +232,9 @@ class CCompiler(object):
"ERROR: can't resolve libraries to shared libraries: " +
", ".join(not_resolved))
return shlibs
+
+ def check_is_msvc(self):
+ if isinstance(self.compiler, MSVCCompiler):
+ return True
+ else:
+ return False
diff --git a/giscanner/dumper.py b/giscanner/dumper.py
index 45a09fc8..94231771 100644
--- a/giscanner/dumper.py
+++ b/giscanner/dumper.py
@@ -78,25 +78,21 @@ class LinkerError(Exception):
class DumpCompiler(object):
+ _compiler = None
+
def __init__(self, options, get_type_functions, error_quark_functions):
self._options = options
self._get_type_functions = get_type_functions
self._error_quark_functions = error_quark_functions
- self._compiler_cmd = os.environ.get('CC', 'cc')
- self._linker_cmd = os.environ.get('CC', self._compiler_cmd)
+ # Acquire the compiler (and linker) commands via the CCompiler class in ccompiler.py
+ self._compiler = CCompiler()
+
self._pkgconfig_cmd = os.environ.get('PKG_CONFIG', 'pkg-config')
- self._pkgconfig_msvc_flags = ''
- # Enable the --msvc-syntax pkg-config flag when
- # the Microsoft compiler is used
- # (This is the other way to check whether Visual C++ is used subsequently)
- args = self._compiler_cmd.split()
- if 'cl.exe' in args or 'cl' in args:
- self._pkgconfig_msvc_flags = '--msvc-syntax'
- self._uninst_srcdir = os.environ.get(
- 'UNINSTALLED_INTROSPECTION_SRCDIR')
+ self._uninst_srcdir = os.environ.get('UNINSTALLED_INTROSPECTION_SRCDIR')
self._packages = ['gio-2.0 gmodule-2.0']
self._packages.extend(options.packages)
+ self._linker_cmd = os.environ.get('CC', 'cc')
# Public API
@@ -155,7 +151,7 @@ class DumpCompiler(object):
# Microsoft compilers generate intermediate .obj files
# during compilation, unlike .o files like GCC and others
- if self._pkgconfig_msvc_flags:
+ if self._compiler.check_is_msvc():
o_path = self._generate_tempfile(tmpdir, '.obj')
else:
o_path = self._generate_tempfile(tmpdir, '.o')
@@ -193,8 +189,8 @@ class DumpCompiler(object):
def _run_pkgconfig(self, flag):
# Enable the --msvc-syntax pkg-config flag when
# the Microsoft compiler is used
- if self._pkgconfig_msvc_flags:
- cmd = [self._pkgconfig_cmd, self._pkgconfig_msvc_flags, flag]
+ if self._compiler.check_is_msvc():
+ cmd = [self._pkgconfig_cmd, '--msvc-syntax', flag]
else:
cmd = [self._pkgconfig_cmd, flag]
proc = subprocess.Popen(
@@ -204,14 +200,14 @@ class DumpCompiler(object):
def _compile(self, output, *sources):
# Not strictly speaking correct, but easier than parsing shell
- args = self._compiler_cmd.split()
+ args = self._compiler.compiler_cmd.split()
# Do not add -Wall when using init code as we do not include any
# header of the library being introspected
- if self._compiler_cmd == 'gcc' and not self._options.init_sections:
+ if self._compiler.compiler_cmd == 'gcc' and not self._options.init_sections:
args.append('-Wall')
# The Microsoft compiler uses different option flags for
# silencing warnings on deprecated function usage
- if self._pkgconfig_msvc_flags:
+ if self._compiler.check_is_msvc():
args.append("-wd4996")
else:
args.append("-Wno-deprecated-declarations")
@@ -227,7 +223,7 @@ class DumpCompiler(object):
args.append('-I' + include)
# The Microsoft compiler uses different option flags for
# compilation result output
- if self._pkgconfig_msvc_flags:
+ if self._compiler.check_is_msvc():
args.extend(['-c', '-Fe' + output, '-Fo' + output])
else:
args.extend(['-c', '-o', output])
@@ -258,7 +254,7 @@ class DumpCompiler(object):
args.extend(self._linker_cmd.split())
# We can use -o for the Microsoft compiler/linker,
# but it is considered deprecated usage with that
- if self._pkgconfig_msvc_flags:
+ if self._compiler.check_is_msvc():
args.extend(['-Fe' + output])
else:
args.extend(['-o', output])
@@ -288,23 +284,18 @@ class DumpCompiler(object):
"Could not find object file: %s" % (source, ))
args.extend(list(sources))
- cc = CCompiler()
+ pkg_config_libs = self._run_pkgconfig('--libs')
if not self._options.external_library:
- 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'))
+ self._compiler.get_internal_link_flags(args,
+ libtool,
+ self._options.libraries,
+ self._options.library_paths)
+ args.extend(pkg_config_libs)
else:
- args.extend(self._run_pkgconfig('--libs'))
- cc.get_external_link_flags(args,
- self._options.libraries,
- self._pkgconfig_msvc_flags)
+ args.extend(pkg_config_libs)
+ self._compiler.get_external_link_flags(args, self._options.libraries)
if not self._options.quiet:
print "g-ir-scanner: link: %s" % (