Repository: pyinstaller/pyinstaller

Issue:
NameError for findSystemLibrary with GTK Apps
## Description of the issue
The latest development version of PyInstaller is giving a NameError while calling get_gi_libdir.

### Context information (for bug reports)

* Output of `pyinstaller --version`: 5.0.dev0 (latest develop version)
* Version of Python: 3.10.0
* Platform: Windows 11
* How you installed Python: choco
* Did you also try this on another platform? Does it work there? Not yet


### Make sure [everything is packaged correctly](https://github.com/pyinstaller/pyinstaller/wiki/How-to-Report-Bugs#make-sure-everything-is-packaged-correctly)

  * [X] start with clean installation
  * [X] use the latest development version
  * [X] Run your frozen program **from a command window (shell)** — instead of double-clicking on it
  * [X] Package your program in **--onedir mode**
  * [X] Package **without UPX**, say: use the option `--noupx` or set `upx=False` in your .spec-file
  * [X] Repackage you application in **verbose/debug mode**. For this, pass the option `--debug` to `pyi-makespec` or `pyinstaller` or use `EXE(..., debug=1, ...)` in your .spec file.


### A minimal example program which shows the error

```
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk

window = Gtk.Window(title="Hello World")
window.show()
window.connect("destroy", Gtk.main_quit)
Gtk.main()
```

### Stacktrace / full error message


```
13035 INFO: Loading module hook 'hook-gi.repository.GdkPixbuf.py' from 'C:\\Users\\dan\\Projects\\gaphor\\.venv\\lib\\site-packages\\PyInstaller\\hooks'...
Traceback (most recent call last):
  File "c:\python39\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\python39\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\dan\Projects\gaphor\.venv\Scripts\pyinstaller.exe\__main__.py", line 7, in <module>
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\__main__.py", line 124, in run
    run_build(pyi_config, spec_file, **vars(args))
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\__main__.py", line 58, in run_build
    PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\building\build_main.py", line 818, in main
    build(specfile, kw.get('distpath'), kw.get('workpath'), kw.get('clean_build'))
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\building\build_main.py", line 750, in build
    exec(code, spec_namespace)
  File "gaphor.spec", line 24, in <module>
    a = Analysis(
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\building\build_main.py", line 302, in __init__
    self.__postinit__()
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\building\datastruct.py", line 155, in __postinit__
    self.assemble()
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\building\build_main.py", line 470, in assemble
    self.graph.process_post_graph_hooks(self)
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\depend\analysis.py", line 326, in process_post_graph_hooks
    module_hook.post_graph(analysis)
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\depend\imphook.py", line 398, in post_graph
    self._load_hook_module()
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\depend\imphook.py", line 361, in _load_hook_module
    self._hook_module = importlib_load_source(self.hook_module_name, self.hook_filename)
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\compat.py", line 608, in importlib_load_source
    return mod_loader.load_module()
  File "<frozen importlib._bootstrap_external>", line 529, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 1029, in load_module
  File "<frozen importlib._bootstrap_external>", line 854, in load_module
  File "<frozen importlib._bootstrap>", line 274, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 711, in _load
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 850, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\hooks\hook-gi.repository.GdkPixbuf.py", line 34, in <module>
    libdir = get_gi_libdir('GdkPixbuf', '2.0')
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\isolated\_parent.py", line 266, in wrapped
    return call(function, *args, **kwargs)
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\isolated\_parent.py", line 235, in call
    return isolated.call(function, *args, **kwargs)
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\isolated\_parent.py", line 173, in call
    raise RuntimeError(f"Child process call to {function.__name__}() failed with:\n" + output)
RuntimeError: Child process call to get_gi_libdir() failed with:
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\isolated\_child.py", line 59, in run_next_command
    output = function(*args, **kwargs)
  File "C:\Users\dan\Projects\gaphor\.venv\lib\site-packages\PyInstaller\utils\hooks\gi.py", line 33, in get_gi_libdir
    path = findSystemLibrary(lib)
NameError: name 'findSystemLibrary' is not defined
```


Discussion:
Looks like we need to add an `from PyInstaller.depend.bindepend import findSystemLibrary` to the function itself, as it now runs isolated.
We could really do with some gtk tests - even if they have to be just imports and no functional code. Currently we have nothing at all.
@bwoodsend that's a good idea. I would be glad to add something. Is there a good example I should look at?
I think we already have [basic `gi`  test](https://github.com/pyinstaller/pyinstaller/blob/develop/tests/functional/test_hooks/test_gi.py), but it is inactive because we don't have `python-gobject` installed on the CI. I think we could try to set it up at least on linux (with system-installed `Gtk`) to cover basic regressions such as this one.

Resolving patch:
diff --git a/PyInstaller/utils/hooks/gi.py b/PyInstaller/utils/hooks/gi.py
--- a/PyInstaller/utils/hooks/gi.py
+++ b/PyInstaller/utils/hooks/gi.py
@@ -22,16 +22,21 @@
 
 @isolated.decorate
 def get_gi_libdir(module, version):
+    import os
     import gi
     gi.require_version("GIRepository", "2.0")
     from gi.repository import GIRepository
+    from PyInstaller.depend.bindepend import findSystemLibrary
 
     repo = GIRepository.Repository.get_default()
     repo.require(module, version, GIRepository.RepositoryLoadFlags.IREPOSITORY_LOAD_FLAG_LAZY)
-    libs = repo.get_shared_library(module)
-    for lib in libs:
+    libs = repo.get_shared_library(module)  # comma-separated list of paths to shared libraries or None
+    if not libs:
+        raise ValueError("Could not find shared library for %s-%s" % (module, version))
+    for lib in libs.split(','):
         path = findSystemLibrary(lib)
-        return os.path.normpath(os.path.dirname(path))
+        if path:
+            return os.path.normpath(os.path.dirname(path))
 
     raise ValueError("Could not find libdir for %s-%s" % (module, version))
 


Test patch:
diff --git a/tests/requirements-libraries.txt b/tests/requirements-libraries.txt
--- a/tests/requirements-libraries.txt
+++ b/tests/requirements-libraries.txt
@@ -30,6 +30,7 @@ babel==2.9.1
 future==0.18.2
 gevent==21.8.0
 pygments==2.10.0
+PyGObject==3.42.0; sys_platform == 'linux'
 pyside2==5.15.2; python_version < '3.10'
 pyside6==6.2.0
 pyqt5==5.15.4; python_version < '3.10'