Repository: pyinstaller/pyinstaller

Issue:
Linux: Shared Library Files from LD_LIBRARY_PATH Not Found Without Version Suffix
## Description of the issue
If a shared library on Linux doesn't have a version suffix and is in a location set by `LD_LIBRARY_PATH`, it isn't being packaged as a binary.

For example:
- Not packaged: `/root/jhbuild/install/lib/libadwaita-1.so.0`
- Packaged: `/root/jhbuild/install/lib/libgobject-2.0.so.0.7400.1`

I think this is caused by an incorrect regex in the `_library_matcher` function in the `bindepend` module. I will submit a PR to fix it.

### Context information (for bug reports)

* Output of `pyinstaller --version`: ```5.6.2+ge83c6029.mod```
* Version of Python: 3.11.0
* Platform: Ubuntu 18.04 via Docker
* How you installed Python: Deadsnakes PPA Repo
* Did you also try this on another platform? Does it work there? Yes, works on Windows, and macOS. Works in Linux using default library locations.

* follow *all* the instructions in our "If Things Go Wrong" Guide
  (https://github.com/pyinstaller/pyinstaller/wiki/If-Things-Go-Wrong) and

### 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', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Adw, Gtk

def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    btn = Gtk.Button(label='Hello, World!')
    btn.connect('clicked', lambda x: win.close())
    win.set_child(btn)
    win.present()

app = Adw.Application(application_id='com.example.GtkApplication')
app.connect('activate', on_activate)

app.run(None)
```
GTK4 and libadwaita were built from source and exist in `/root/jhbuild/install/lib`
`LD_LIBRARY_PATH="/root/jhbuild/install/lib:/root/jhbuild/install/local/lib"`

Docker image is located at ghcr.io/gaphor/gaphor-appimage:latest

### Stacktrace / full error message

```
Failed to load shared library 'libadwaita-1.so.0' referenced by the typelib: libadwaita-1.so.0: cannot open shared object file: No such file or directory
```

Please also see <https://github.com/pyinstaller/pyinstaller/wiki/How-to-Report-Bugs>
for more about what would use to solve the issue.



Discussion:
Can you try running the following snippet:

```python
from PyInstaller.utils.hooks.gi import GiModuleInfo
info = GiModuleInfo('Adw', '1')
print(info.collect_typelib_data())
```

On my Fedora system with RPM-installed Gtk4/libadwaita, I get:
```
([('/lib64/libadwaita-1.so.0', '.')], [('/usr/lib64/girepository-1.0/Adw-1.typelib', 'gi_typelibs')], ['gi.repository.Gtk', 'gi.repository.Gio'])
```

Nevermind, I tested with the docker image you provided, and it does indeed look like the problem is the regex, as you pointed out. The correct result on my Fedora system likely comes from a fallback code path...
```
>>> from PyInstaller.utils.hooks.gi import GiModuleInfo
>>> info = GiModuleInfo('Adw', '1')
>>> print(info.collect_typelib_data())
([], [('/root/jhbuild/install/lib/girepository-1.0/Adw-1.typelib', 'gi_typelibs')], ['gi.repository.Gtk', 'gi.repository.Gio'])
```

That's how I debugged the issues. Binaries are empty, I'll submit a PR with the fix.
OK, thanks!
Hmm, perhaps the most straightforward way to fix this problem would be to simply have `_which_library` check whether `name` == `_path` before even trying to use matcher.

The whole matcher business seems to me that different parts of codebase are trying to use the `findLibrary` / `findSystemLibrary` with different name semantics. `git blame` for that part explicitly mentions `findLibrary('libc')` and equivalents (i.e., calls without any suffix at all). On the other hand, from the GI hook utils, we call this with fully-suffixed library name...

Resolving patch:
diff --git a/PyInstaller/building/splash.py b/PyInstaller/building/splash.py
--- a/PyInstaller/building/splash.py
+++ b/PyInstaller/building/splash.py
@@ -448,7 +448,7 @@ def generate_script(self):
         if self.minify_script:
             # Remove any documentation, empty lines and unnecessary spaces
             script = '\n'.join(
-                line for line in map(lambda l: l.strip(), script.splitlines())
+                line for line in map(lambda line: line.strip(), script.splitlines())
                 if not line.startswith('#')  # documentation
                 and line  # empty lines
             )
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
@@ -11,6 +11,7 @@
 import os
 import re
 
+from PyInstaller.depend.utils import _resolveCtypesImports
 from PyInstaller.utils.hooks import collect_submodules, collect_system_data_files, get_hook_config
 from PyInstaller import isolated
 from PyInstaller import log as logging
@@ -112,11 +113,10 @@ def collect_typelib_data(self):
             raise ValueError(f"Module {self.name} {self.version} is unavailable!")
 
         # Find shared libraries
-        for lib in self.sharedlibs:
-            lib_path = findSystemLibrary(lib)
-            if lib_path:
-                logger.debug('Collecting shared library %s at %s', lib, lib_path)
-                binaries.append((lib_path, '.'))
+        resolved_libs = _resolveCtypesImports(self.sharedlibs)
+        for resolved_lib in resolved_libs:
+            logger.debug("Collecting shared library %s at %s", resolved_lib[0], resolved_lib[1])
+            binaries.append((resolved_lib[1], "."))
 
         # Find and collect .typelib file. Run it through the `gir_library_path_fix` to fix the library path, if
         # necessary.


Test patch: