summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--giscanner/ccompiler.py133
-rw-r--r--giscanner/dumper.py188
2 files changed, 164 insertions, 157 deletions
diff --git a/giscanner/ccompiler.py b/giscanner/ccompiler.py
index f9105fe7..da56c60a 100644
--- a/giscanner/ccompiler.py
+++ b/giscanner/ccompiler.py
@@ -106,54 +106,76 @@ class CCompiler(object):
self._cflags_no_deprecation_warnings = "-Wno-deprecated-declarations"
- def get_internal_link_flags(self, args, libtool, libraries, libpaths):
+ def get_internal_link_flags(self, libtool, libraries, libpaths):
# An "internal" link is where the library to be introspected
# is being built in the current directory.
+ internal_link_args = []
# Search the current directory first
- # (This flag is not supported nor needed for Visual C++)
- if not self.check_is_msvc():
- args.append('-L.')
+ self.compiler.add_library_dir('.')
- # https://bugzilla.gnome.org/show_bug.cgi?id=625195
+ if self.check_is_msvc():
+ for library in libraries:
+ # MSVC Builds don't use libtool, so no .la libraries,
+ # so just add the library directly.
+ self.compiler.add_library(library)
+ for libpath in libpaths:
+ self.compiler.add_library_dir(libpath)
+
+ else:
if not libtool:
- args.append('-Wl,-rpath=.')
- args.append('-Wl,--no-as-needed')
+ # https://bugzilla.gnome.org/show_bug.cgi?id=625195
+ internal_link_args.append('-Wl,-rpath=.')
- for library in libraries:
- if self.check_is_msvc():
- args.append(library + '.lib')
- else:
+ # Ensure libraries are always linked as we are going to use ldd to work
+ # out their names later
+ internal_link_args.append('-Wl,--no-as-needed')
+
+ for library in libraries:
if library.endswith(".la"): # explicitly specified libtool library
- args.append(library)
+ self.compiler.add_library_dir('.libs')
+ if os.name != 'nt':
+ self.compiler.add_runtime_library_dir('.libs')
+ if (library.startswith('lib')):
+ self.compiler.add_library(library[len('lib'):library.rfind('.la')])
+ else:
+ self.compiler.add_library(library[:library.rfind('.la')])
else:
- args.append('-l' + library)
-
- for library_path in libpaths:
- # Not used/needed on Visual C++, and -Wl,-rpath options
- # will cause grief
- if not self.check_is_msvc():
- args.append('-L' + library_path)
- if os.path.isabs(library_path):
+ self.compiler.add_library(library)
+
+ for libpath in libpaths:
+ self.compiler.add_library_dir(libpath)
+
+ # Not used/needed on Windows, add_runtime_library_dir()
+ # will cause grief on Windows
+ if os.name != 'nt':
+ self.compiler.add_runtime_library_dir(libpath)
+ if os.path.isabs(libpath):
if libtool:
- args.append('-rpath')
- args.append(library_path)
+ internal_link_args.append('-rpath')
+ internal_link_args.append(libpath)
else:
- args.append('-Wl,-rpath=' + library_path)
+ internal_link_args.append('-Wl,-rpath=' + libpath)
+
+ return internal_link_args
- def get_external_link_flags(self, args, libraries):
+ def get_external_link_flags(self, 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.
+ external_link_args = []
+
for library in libraries:
- if self.check_is_msvc():
- args.append(library + '.lib')
- else:
- if library.endswith(".la"): # explicitly specified libtool library
- args.append(library)
+ if library.endswith(".la"): # explicitly specified libtool library
+ if (library.startswith('lib')):
+ self.compiler.add_library(library[len('lib'):library.rfind('.la')])
else:
- args.append('-l' + library)
+ self.compiler.add_library(library[:library.rfind('.la')])
+ else:
+ self.compiler.add_library(library)
+
+ return external_link_args
def preprocess(self, source, output, cpp_options):
extra_postargs = ['-C']
@@ -180,6 +202,57 @@ class CCompiler(object):
include_dirs=include_dirs,
extra_postargs=extra_postargs)
+ def compile(self, pkg_config_cflags, cpp_includes, source, init_sections, quiet):
+ extra_postargs = []
+ includes = []
+ cpp_options = None
+ source_str = ''.join(source)
+ tmpdir_idx = source_str.rfind(os.sep, 0, source_str.rfind(os.sep))
+ (include_paths, macros, extra_args) = \
+ self._set_cpp_options(pkg_config_cflags)
+
+ for include in cpp_includes:
+ includes.append(include)
+
+ # 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 init_sections:
+ extra_postargs.append('-Wall')
+ extra_postargs.append(self._cflags_no_deprecation_warnings)
+
+ includes.extend(include_paths)
+ extra_postargs.extend(extra_args)
+
+ return self.compiler.compile(sources=source,
+ macros=macros,
+ include_dirs=includes,
+ extra_postargs=extra_postargs,
+ output_dir=source_str[tmpdir_idx + 1:
+ source_str.rfind(os.sep)])
+
+ def link(self, output, objects, lib_args, libtool, quiet):
+ extra_preargs = []
+ extra_postargs = []
+ library_dirs = []
+ libraries = []
+ output_str = ''.join(output)
+ output_dir = output_str[:output_str.rfind(os.sep)]
+
+ if libtool:
+ if os.name == 'nt':
+ extra_postargs.append('-Wl,--export-all-symbols')
+ else:
+ extra_postargs.append('-export-dynamic')
+
+ for arg in lib_args:
+ extra_postargs.append(arg)
+
+ self.compiler.link(target_desc=self.compiler.EXECUTABLE,
+ objects=objects,
+ output_filename=output,
+ extra_preargs=extra_preargs,
+ extra_postargs=extra_postargs)
+
def resolve_windows_libs(self, libraries, options):
args = []
libsearch = []
diff --git a/giscanner/dumper.py b/giscanner/dumper.py
index 94231771..46aa8354 100644
--- a/giscanner/dumper.py
+++ b/giscanner/dumper.py
@@ -24,6 +24,7 @@ import sys
import subprocess
import shutil
import tempfile
+from distutils.errors import LinkError
from .gdumpparser import IntrospectionBinary
from . import utils
@@ -92,7 +93,6 @@ class DumpCompiler(object):
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
@@ -149,29 +149,23 @@ class DumpCompiler(object):
f.write("\n};\n")
f.close()
- # Microsoft compilers generate intermediate .obj files
- # during compilation, unlike .o files like GCC and others
- if self._compiler.check_is_msvc():
- o_path = self._generate_tempfile(tmpdir, '.obj')
- else:
- o_path = self._generate_tempfile(tmpdir, '.o')
-
- if os.name == 'nt':
- ext = '.exe'
+ o_path = self._generate_tempfile(tmpdir, self._compiler.compiler.obj_extension)
+ if self._compiler.compiler.exe_extension:
+ ext = self._compiler.compiler.exe_extension
else:
ext = ''
bin_path = self._generate_tempfile(tmpdir, ext)
try:
- self._compile(o_path, c_path)
+ introspection_obj = self._compile(o_path, c_path)
except CompilerError as e:
if not utils.have_debug_flag('save-temps'):
shutil.rmtree(tmpdir)
raise SystemExit('compilation of temporary binary failed:' + str(e))
try:
- self._link(bin_path, o_path)
+ self._link(introspection_obj, bin_path, o_path)
except LinkerError as e:
if not utils.have_debug_flag('save-temps'):
shutil.rmtree(tmpdir)
@@ -199,128 +193,68 @@ class DumpCompiler(object):
return proc.communicate()[0].split()
def _compile(self, output, *sources):
- # Not strictly speaking correct, but easier than parsing shell
- 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.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._compiler.check_is_msvc():
- args.append("-wd4996")
- else:
- args.append("-Wno-deprecated-declarations")
pkgconfig_flags = self._run_pkgconfig('--cflags')
- args.extend([utils.cflag_real_include_path(f) for f in pkgconfig_flags])
- cppflags = os.environ.get('CPPFLAGS', '')
- for cppflag in cppflags.split():
- args.append(cppflag)
- cflags = os.environ.get('CFLAGS', '')
- for cflag in cflags.split():
- args.append(cflag)
- for include in self._options.cpp_includes:
- args.append('-I' + include)
- # The Microsoft compiler uses different option flags for
- # compilation result output
- if self._compiler.check_is_msvc():
- args.extend(['-c', '-Fe' + output, '-Fo' + output])
- else:
- 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))
- if not self._options.quiet:
- print "g-ir-scanner: compile: %s" % (
- subprocess.list2cmdline(args), )
- sys.stdout.flush()
- try:
- subprocess.check_call(args)
- except subprocess.CalledProcessError as e:
- raise CompilerError(e)
- def _link(self, output, *sources):
- args = []
+ return self._compiler.compile(pkgconfig_flags,
+ self._options.cpp_includes,
+ sources,
+ self._options.init_sections,
+ self._options.quiet)
+
+ def _add_link_internal_args(self, libtool):
+ # An "internal" link is where the library to be introspected
+ # is being built in the current directory.
+ libs = []
+ libs.extend(self._compiler.get_internal_link_flags(libtool,
+ self._options.libraries,
+ self._options.library_paths))
+
+ libs.extend(self._run_pkgconfig('--libs'))
+
+ return libs
+
+ def _add_link_external_args(self):
+ # 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.
+ libs = []
+
+ libs.extend(self._run_pkgconfig('--libs'))
+
+ libs.extend(self._compiler.get_external_link_flags(self._options.libraries))
+ return libs
+
+ def _link(self, introspection_obj, output, *sources):
+ link_args = []
+
libtool = utils.get_libtool_command(self._options)
- if libtool:
- args.extend(libtool)
- args.append('--mode=link')
- args.append('--tag=CC')
- if self._options.quiet:
- args.append('--silent')
-
- 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._compiler.check_is_msvc():
- args.extend(['-Fe' + output])
- else:
- args.extend(['-o', output])
- if libtool:
- if os.name == 'nt':
- args.append('-Wl,--export-all-symbols')
- else:
- args.append('-export-dynamic')
-
- cppflags = os.environ.get('CPPFLAGS', '')
- for cppflag in cppflags.split():
- args.append(cppflag)
- cflags = os.environ.get('CFLAGS', '')
- for cflag in cflags.split():
- args.append(cflag)
- ldflags = os.environ.get('LDFLAGS', '')
- for ldflag in ldflags.split():
- args.append(ldflag)
-
- # Make sure to list the library to be introspected first since it's
- # likely to be uninstalled yet and we want the uninstalled RPATHs have
- # priority (or we might run with installed library that is older)
-
- for source in sources:
- if not os.path.exists(source):
- raise CompilerError(
- "Could not find object file: %s" % (source, ))
- args.extend(list(sources))
-
- pkg_config_libs = self._run_pkgconfig('--libs')
if not self._options.external_library:
- self._compiler.get_internal_link_flags(args,
- libtool,
- self._options.libraries,
- self._options.library_paths)
- args.extend(pkg_config_libs)
-
+ link_args.extend(self._add_link_internal_args(libtool))
else:
- 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" % (
- subprocess.list2cmdline(args), )
- sys.stdout.flush()
- msys = os.environ.get('MSYSTEM', None)
- if msys:
- shell = os.environ.get('SHELL', 'sh.exe')
- # Create a temporary script file that
- # runs the command we want
- tf, tf_name = tempfile.mkstemp()
- f = os.fdopen(tf, 'wb')
- shellcontents = ' '.join([x.replace('\\', '/') for x in args])
- fcontents = '#!/bin/sh\nunset PWD\n{}\n'.format(shellcontents)
- f.write(fcontents)
- f.close()
- shell = utils.which(shell)
- args = [shell, tf_name.replace('\\', '/')]
+ link_args.extend(self._add_link_external_args())
+
try:
- subprocess.check_call(args)
- except subprocess.CalledProcessError as e:
- raise LinkerError(e)
- finally:
- if msys:
- os.remove(tf_name)
+ self._compiler.link(output,
+ introspection_obj,
+ link_args,
+ libtool,
+ self._options.quiet)
+
+ # Ignore failing to embed the manifest files, when the manifest
+ # file does not exist, especially for MSVC 2010 and later builds.
+ # If we are on Visual C++ 2005/2008, where
+ # this embedding is required, the build will fail anyway, as
+ # the dumper program will likely fail to run, and this means
+ # something went wrong with the build.
+ except LinkError, e:
+ msg = str(e)
+
+ if msg[msg.rfind('mt.exe'):] == 'mt.exe\' failed with exit status 31':
+ sys.exc_clear()
+ pass
+ else:
+ raise LinkError(e)
def compile_introspection_binary(options, get_type_functions,