Commit 0638f9f1 authored by Chun-wei Fan's avatar Chun-wei Fan
Browse files

giscanner/ccompiler.py: Initiate Distutils Compiler Instance

This updates the __init__ constructor method of CCompiler so that distutils
can be used, with some environment or user-supplied options to create the
compiler instance that is appropriate with the platform that the giscanner
scripts are being run on, and sets some specific environment for the
compilers as necessary.  This also adds a check_is_msvc() method that will
progressively replace calls in the other giscanner scripts that attempt to
check for CC=cl (or so), where a part of which is done in this patch.  This
is done for dumper.py as well as it needs to be updated in this patch to
use the updated ccompiler.py which uses distutils to initiate the compiler
instance.

Also, as we have been using the --library option on Windows to pass in the
library (not DLL) to deduce the correct DLL to link to in the introspection
files for some time, we no longer need to make a copy of the library (.lib)
to introspect that matches the <namespace>-<namespace_version>.lib
convention, but use the libraries that were passed in with --library
directly, so that we can link the dumper program during the introspection
build.

Please note that this also partially reverts commit c9cfa2b5 as the
distutils items are clearly needed for these to work.

https://bugzilla.gnome.org/show_bug.cgi?id=728313
parent af054fef
......@@ -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
......@@ -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" % (
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment