diff options
author | Chun-wei Fan <fanchunwei@src.gnome.org> | 2020-01-15 15:32:38 +0800 |
---|---|---|
committer | Chun-wei Fan <fanchunwei@src.gnome.org> | 2020-01-16 12:20:06 +0800 |
commit | d14923f6c52e4747658c1b58766103fe6c207b40 (patch) | |
tree | a44a7b228d408c592f3ba7e647ca90a035a8d339 /giscanner | |
parent | ad937bca10be979cc468b8da0d31f40f86ce0851 (diff) | |
download | gobject-introspection-d14923f6c52e4747658c1b58766103fe6c207b40.tar.gz |
Windows: Fix building and running on Python 3.8+
Python 3.8.x and later changed the way how dependent DLLs can be found for a
given Python module that depends on the presence of external, non-system DLLs,
for more fine-grained DLLs searching and loading, as well as for security
purposes, which required the use of os.add_dll_directory().
Thus, the scripts in scanner/ must be updated such that:
-We are able to find and load the GObject and GLib DLLs, at least, on
initialization, via the use of 'pkg-config --variable bindir', as we already
depend on the GLib DLLs. Note that since the gobject-2.0.pc file does not
have a 'bindir' entry, we use gio-2.0.pc instead to discover the bindir of the
GObject and GLib DLLs. Likewise, we use the same technique for pkg-config
files that are dependent upon when using g-ir-scanner (or friends) on items
that are higher up in the stack.
-We are able to find any other DLLs (e.g. non-GNOME DLLs such as ZLib) that
are dependent but are not found in the path(s) given by 'pkg-config --variable
bindir' with the envvar GI_EXTRA_BASE_DLL_DIRS, as needed. Note that
GI_EXTRA_BASE_DLL_DIRS can be multiple paths, and that the results from
'pkg-config --variable bindir' takes precendence, in a LIFO manner.
Diffstat (limited to 'giscanner')
-rw-r--r-- | giscanner/dumper.py | 4 | ||||
-rw-r--r-- | giscanner/pkgconfig.py | 9 | ||||
-rw-r--r-- | giscanner/sourcescanner.py | 5 | ||||
-rw-r--r-- | giscanner/utils.py | 36 |
4 files changed, 53 insertions, 1 deletions
diff --git a/giscanner/dumper.py b/giscanner/dumper.py index 61942faf..0c10a780 100644 --- a/giscanner/dumper.py +++ b/giscanner/dumper.py @@ -252,6 +252,9 @@ class DumpCompiler(object): for ldflag in shlex.split(os.environ.get('LDFLAGS', '')): args.append(ldflag) + dll_dirs = utils.dll_dirs() + dll_dirs.add_dll_dirs(self._packages) + if not self._options.quiet: print("g-ir-scanner: link: %s" % ( subprocess.list2cmdline(args), )) @@ -278,6 +281,7 @@ class DumpCompiler(object): finally: if msys: os.remove(tf_name) + dll_dirs.cleanup_dll_dirs() def compile_introspection_binary(options, get_type_functions, diff --git a/giscanner/pkgconfig.py b/giscanner/pkgconfig.py index 6f0b2d57..66822378 100644 --- a/giscanner/pkgconfig.py +++ b/giscanner/pkgconfig.py @@ -56,3 +56,12 @@ def libs(packages, msvc_syntax=False, ignore_errors=True, command=None): flags.extend(packages) out = check_output(flags, ignore_errors, command) return shlex.split(out) + + +def bindir(packages, ignore_errors=True, command=None): + flags = [] + flags.append('--variable') + flags.append('bindir') + flags.extend(packages) + out = check_output(flags, ignore_errors, command) + return shlex.split(out) diff --git a/giscanner/sourcescanner.py b/giscanner/sourcescanner.py index 1632e1cb..e50f40aa 100644 --- a/giscanner/sourcescanner.py +++ b/giscanner/sourcescanner.py @@ -24,13 +24,16 @@ import tempfile from .libtoolimporter import LibtoolImporter from .message import Position from .ccompiler import CCompiler -from .utils import have_debug_flag +from .utils import have_debug_flag, dll_dirs with LibtoolImporter(None, None): + dlldirs = dll_dirs() + dlldirs.add_dll_dirs(['gio-2.0']) if 'UNINSTALLED_INTROSPECTION_SRCDIR' in os.environ: from _giscanner import SourceScanner as CSourceScanner else: from giscanner._giscanner import SourceScanner as CSourceScanner + dlldirs.cleanup_dll_dirs() HEADER_EXTS = ['.h', '.hpp', '.hxx'] SOURCE_EXTS = ['.c', '.cpp', '.cc', '.cxx'] diff --git a/giscanner/utils.py b/giscanner/utils.py index 25160c3e..e8c246dd 100644 --- a/giscanner/utils.py +++ b/giscanner/utils.py @@ -24,6 +24,7 @@ import subprocess import platform import shutil import time +import giscanner.pkgconfig _debugflags = None @@ -282,3 +283,38 @@ def rmtree(*args, **kwargs): continue else: return + + +# Mainly used for builds against Python 3.8.x and later on Windows where we need to be +# more explicit on where dependent DLLs are located, via the use of +# os.add_dll_directory(). So, we make use of the envvar GI_EXTRA_BASE_DLL_DIRS and the +# newly-added bindir() method of our pkgconfig module to acquire the paths where dependent +# DLLs could be found. +class dll_dirs(): + _cached_dll_dirs = None + _cached_added_dll_dirs = None + + def __init__(self): + if os.name == 'nt' and hasattr(os, 'add_dll_directory'): + self._cached_dll_dirs = [] + self._cached_added_dll_dirs = [] + + def add_dll_dirs(self, pkgs): + if os.name == 'nt' and hasattr(os, 'add_dll_directory'): + if 'GI_EXTRA_BASE_DLL_DIRS' in os.environ: + for path in os.environ.get('GI_EXTRA_BASE_DLL_DIRS').split(os.pathsep): + if path not in self._cached_dll_dirs: + self._cached_dll_dirs.append(path) + self._cached_added_dll_dirs.append(os.add_dll_directory(path)) + + for path in giscanner.pkgconfig.bindir(pkgs): + if path not in self._cached_dll_dirs: + self._cached_dll_dirs.append(path) + self._cached_added_dll_dirs.append(os.add_dll_directory(path)) + + def cleanup_dll_dirs(self): + if self._cached_added_dll_dirs is not None: + for added_dll_dir in self._cached_added_dll_dirs: + added_dll_dir.close() + if self._cached_dll_dirs is not None: + self._cached_dll_dirs.clear() |