summaryrefslogtreecommitdiff
path: root/giscanner
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2018-02-15 00:00:00 +0000
committerChristoph Reiter <reiter.christoph@gmail.com>2018-07-28 19:00:55 +0200
commitb80fff2e5a8f327c3128378c12c290dd8e4f7c01 (patch)
treebdf8e8dd62436a99513e35645245e4641a93245f /giscanner
parent8bf05589bba98a13dacce1312075af9f04145b82 (diff)
downloadgobject-introspection-b80fff2e5a8f327c3128378c12c290dd8e4f7c01.tar.gz
Factor out pkg-config functionality to a separate module.
Functional changes: * Consistently check that return code from pkg-config is zero. * Use shell word splitting rules to process pkg-config output to match behaviour obtained by running `cc program.cc $(pkg-config --cflags ...)`. Fixes issue #171 . * Use user preferred encoding to process output from pkg-config on Python 3. Python 2 behaviour defaults to using ascii encoding as before. edit creiter: still ignore pkg-config errors by default for now as we depend on it when glib is a subproject.
Diffstat (limited to 'giscanner')
-rw-r--r--giscanner/dumper.py24
-rw-r--r--giscanner/meson.build1
-rw-r--r--giscanner/pkgconfig.py58
-rw-r--r--[-rwxr-xr-x]giscanner/scannermain.py23
4 files changed, 73 insertions, 33 deletions
diff --git a/giscanner/dumper.py b/giscanner/dumper.py
index bb97bc81..494c7ff7 100644
--- a/giscanner/dumper.py
+++ b/giscanner/dumper.py
@@ -32,7 +32,7 @@ import tempfile
from distutils.errors import LinkError
from .gdumpparser import IntrospectionBinary
-from . import utils
+from . import pkgconfig, utils
from .ccompiler import CCompiler
# bugzilla.gnome.org/558436
@@ -94,9 +94,8 @@ class DumpCompiler(object):
# 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._uninst_srcdir = os.environ.get('UNINSTALLED_INTROSPECTION_SRCDIR')
- self._packages = ['gio-2.0 gmodule-2.0']
+ self._packages = ['gio-2.0', 'gmodule-2.0']
self._packages.extend(options.packages)
if self._compiler.check_is_msvc():
self._linker_cmd = ['link.exe']
@@ -189,21 +188,9 @@ class DumpCompiler(object):
self._options.namespace_version, suffix)
return os.path.join(tmpdir, tmpl)
- def _run_pkgconfig(self, flag):
- # Enable the --msvc-syntax pkg-config flag when
- # the Microsoft compiler is used
- if self._compiler.check_is_msvc():
- cmd = [self._pkgconfig_cmd, '--msvc-syntax', flag]
- else:
- cmd = [self._pkgconfig_cmd, flag]
- proc = subprocess.Popen(
- cmd + self._packages,
- stdout=subprocess.PIPE)
- out, err = proc.communicate()
- return out.decode('ascii').split()
-
def _compile(self, *sources):
- cflags = self._run_pkgconfig('--cflags')
+ cflags = pkgconfig.cflags(self._packages,
+ msvc_syntax=self._compiler.check_is_msvc())
cflags.extend(self._options.cflags)
return self._compiler.compile(cflags,
self._options.cpp_includes,
@@ -255,7 +242,8 @@ class DumpCompiler(object):
args.extend(sources)
- pkg_config_libs = self._run_pkgconfig('--libs')
+ pkg_config_libs = pkgconfig.libs(self._packages,
+ msvc_syntax=self._compiler.check_is_msvc())
if not self._options.external_library:
self._compiler.get_internal_link_flags(args,
diff --git a/giscanner/meson.build b/giscanner/meson.build
index b4ec3796..7b4b0d9d 100644
--- a/giscanner/meson.build
+++ b/giscanner/meson.build
@@ -17,6 +17,7 @@ giscanner_files = [
'maintransformer.py',
'message.py',
'msvccompiler.py',
+ 'pkgconfig.py',
'shlibs.py',
'scannermain.py',
'sectionparser.py',
diff --git a/giscanner/pkgconfig.py b/giscanner/pkgconfig.py
new file mode 100644
index 00000000..6f0b2d57
--- /dev/null
+++ b/giscanner/pkgconfig.py
@@ -0,0 +1,58 @@
+# GObject-Introspection - a framework for introspecting GObject libraries
+#
+# 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 shlex
+import subprocess
+
+
+class PkgConfigError(Exception):
+ pass
+
+
+def check_output(flags, ignore_errors, command=None):
+ if command is None:
+ command = [os.environ.get('PKG_CONFIG', 'pkg-config')]
+ argv = command[:]
+ argv.extend(flags)
+ try:
+ return subprocess.check_output(argv, universal_newlines=True, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ output = e.output or ''
+ if ignore_errors:
+ print(output)
+ return ''
+ raise PkgConfigError('pkg-config: %s\n%s' % (e, output))
+ except OSError as e:
+ raise PkgConfigError('pkg-config: error executing command %s: %s' % (argv, e))
+
+
+def cflags(packages, msvc_syntax=False, ignore_errors=True, command=None):
+ flags = ['--msvc-syntax'] if msvc_syntax else []
+ flags.append('--cflags')
+ flags.extend(packages)
+ out = check_output(flags, ignore_errors, command)
+ return shlex.split(out)
+
+
+def libs(packages, msvc_syntax=False, ignore_errors=True, command=None):
+ flags = ['--msvc-syntax'] if msvc_syntax else []
+ flags.append('--libs')
+ flags.extend(packages)
+ out = check_output(flags, ignore_errors, command)
+ return shlex.split(out)
diff --git a/giscanner/scannermain.py b/giscanner/scannermain.py
index 2f1d9095..e0af993a 100755..100644
--- a/giscanner/scannermain.py
+++ b/giscanner/scannermain.py
@@ -37,7 +37,7 @@ import platform
import shlex
import giscanner
-from giscanner import message
+from giscanner import message, pkgconfig
from giscanner.annotationparser import GtkDocCommentBlockParser
from giscanner.ast import Include, Namespace
from giscanner.dumper import compile_introspection_binary
@@ -288,7 +288,7 @@ def test_codegen(optstring,
def process_options(output, allowed_flags):
- for option in output.split():
+ for option in output:
for flag in allowed_flags:
if not option.startswith(flag):
continue
@@ -297,19 +297,11 @@ def process_options(output, allowed_flags):
def process_packages(options, packages):
- args = [os.environ.get('PKG_CONFIG', 'pkg-config'), '--cflags']
- args.extend(packages)
- output = subprocess.Popen(args,
- stdout=subprocess.PIPE).communicate()[0]
- if output is None:
- # the error output should have already appeared on our stderr,
- # so we just exit
- return 1
- output = output.decode('ascii')
+ flags = pkgconfig.cflags(packages)
# Some pkg-config files on Windows have options we don't understand,
# so we explicitly filter to only the ones we need.
options_whitelist = ['-I', '-D', '-U', '-l', '-L']
- filtered_output = list(process_options(output, options_whitelist))
+ filtered_output = list(process_options(flags, options_whitelist))
parser = _get_option_parser()
pkg_options, unused = parser.parse_args(filtered_output)
options.cpp_includes.extend([os.path.realpath(f) for f in pkg_options.cpp_includes])
@@ -539,9 +531,10 @@ def scanner_main(args):
packages = set(options.packages)
packages.update(transformer.get_pkgconfig_packages())
if packages:
- exit_code = process_packages(options, packages)
- if exit_code:
- return exit_code
+ try:
+ process_packages(options, packages)
+ except pkgconfig.PkgConfigError as e:
+ _error(str(e))
ss = create_source_scanner(options, args)