summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChun-wei Fan <fanchunwei@src.gnome.org>2020-01-15 15:32:38 +0800
committerChun-wei Fan <fanchunwei@src.gnome.org>2020-01-16 12:20:06 +0800
commitd14923f6c52e4747658c1b58766103fe6c207b40 (patch)
treea44a7b228d408c592f3ba7e647ca90a035a8d339
parentad937bca10be979cc468b8da0d31f40f86ce0851 (diff)
downloadgobject-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.
-rw-r--r--giscanner/dumper.py4
-rw-r--r--giscanner/pkgconfig.py9
-rw-r--r--giscanner/sourcescanner.py5
-rw-r--r--giscanner/utils.py36
-rwxr-xr-xtools/g-ir-tool-template.in4
5 files changed, 57 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()
diff --git a/tools/g-ir-tool-template.in b/tools/g-ir-tool-template.in
index 8462f88a..c4a10a28 100755
--- a/tools/g-ir-tool-template.in
+++ b/tools/g-ir-tool-template.in
@@ -96,5 +96,9 @@ if not os.path.isfile(os.path.join(pylibdir, 'giscanner', '_giscanner' + py_mod_
sys.path.insert(0, pylibdir)
+from giscanner.utils import dll_dirs
+dll_dirs = dll_dirs()
+dll_dirs.add_dll_dirs(['gio-2.0'])
+
from giscanner.@TOOL_MODULE@ import @TOOL_FUNCTION@
sys.exit(@TOOL_FUNCTION@(sys.argv))