TL;DR: sudo strip --remove-section=.note.ABI-tag $(realpath /usr/lib/libQt5Core.so.5)
Ref: https://github.com/Microsoft/WSL/issues/3023

Why I had this issue

I am doing a homework that uses matplotlib.pyplot. When I import this package, I get the following error:

>> import matplotlib.pyplot as plt
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/site-packages/matplotlib/pyplot.py", line 115, in <module>
    _backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup()
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/__init__.py", line 62, in pylab_setup
    [backend_name], 0)
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/backend_qt5agg.py", line 15, in <module>
    from .backend_qt5 import (
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/backend_qt5.py", line 19, in <module>
    import matplotlib.backends.qt_editor.figureoptions as figureoptions
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/qt_editor/figureoptions.py", line 20, in <module>
    import matplotlib.backends.qt_editor.formlayout as formlayout
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/qt_editor/formlayout.py", line 54, in <module>
    from matplotlib.backends.qt_compat import QtGui, QtWidgets, QtCore
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/qt_compat.py", line 158, in <module>
    raise ImportError("Failed to import any qt binding")
ImportError: Failed to import any qt binding

After STFW, I found this post that suggest I can get more precise error message by importing PyQt5 first. (Later I found that simply import pyplot twice has the same effect). Now the error message becomes:

>>> import matplotlib.pyplot as plt
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/site-packages/matplotlib/pyplot.py", line 115, in <module>
    _backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup()
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/__init__.py", line 62, in pylab_setup
    [backend_name], 0)
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/backend_qt5agg.py", line 15, in <module>
    from .backend_qt5 import (
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/backend_qt5.py", line 19, in <module>
    import matplotlib.backends.qt_editor.figureoptions as figureoptions
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/qt_editor/figureoptions.py", line 20, in <module>
    import matplotlib.backends.qt_editor.formlayout as formlayout
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/qt_editor/formlayout.py", line 54, in <module>
    from matplotlib.backends.qt_compat import QtGui, QtWidgets, QtCore
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/qt_compat.py", line 135, in <module>
    _setup_pyqt5()
  File "/usr/lib/python3.7/site-packages/matplotlib/backends/qt_compat.py", line 69, in _setup_pyqt5
    from PyQt5 import QtCore, QtGui, QtWidgets
ImportError: libQt5Core.so.5: cannot open shared object file: No such file or directory

Ok, so let find where is libQt5Core.so.5. A simple ls showed that /usr/lib/libQt5Core.so.5 does exist. So why is python ignoring it? Let’s try directly import PyQt5.QtCore:

>>> import PyQt5.QtCore
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: libQt5Core.so.5: cannot open shared object file: No such file or directory

So the problem is with PyQt5 (or Qt) itself, not pyplot’s fault. So what does import PyQt5.QtCore do?

~$ python
Python 3.7.0 (default, Sep 15 2018, 19:13:07)
[GCC 8.2.1 20180831] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import PyQt5
>>> PyQt5.__file__
'/usr/lib/python3.7/site-packages/PyQt5/__init__.py'
>>>
~$ ll /usr/lib/python3.7/site-packages/PyQt5/QtCore*
-rw-r--r-- 1 root root  378865 Jul 19 03:27 /usr/lib/python3.7/site-packages/PyQt5/QtCore.pyi
-rwxr-xr-x 1 root root 3006848 Jul 19 03:27 /usr/lib/python3.7/site-packages/PyQt5/QtCore.so*

So PyQt5.QtCore is just a shared object. Let’s ldd it :/

~$ ldd /usr/lib/python3.7/site-packages/PyQt5/QtCore.so
        linux-vdso.so.1 (0x00007fffcf2a0000)
        libQt5Core.so.5 => not found
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fa852a06000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007fa852842000)
        libm.so.6 => /usr/lib/libm.so.6 (0x00007fa8526b0000)
        /usr/lib64/ld-linux-x86-64.so.2 (0x00007fa853092000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fa852696000)
~$ LD_PRELOAD=/usr/lib/libQt5Core.so.5.11.2 ldd /usr/lib/python3.7/site-packages/PyQt5/QtCore.so
ERROR: ld.so: object '/usr/lib/libQt5Core.so.5.11.2' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object '/usr/lib/libQt5Core.so.5.11.2' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
        linux-vdso.so.1 (0x00007fffd8a2a000)
        libQt5Core.so.5 => not found
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f4725e96000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007f4725cd2000)
        libm.so.6 => /usr/lib/libm.so.6 (0x00007f4725b40000)
        /usr/lib64/ld-linux-x86-64.so.2 (0x00007f4726526000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f4725b26000)

How can libQt5Core.so.5 not found? Why even LD_PRELOAD cannot load it? I think there might be something wrong with the ldconfig cache, so let’s see it:

~$ ldconfig -p | grep Qt5Core
        libQt5Core.so.5 (libc6,x86-64, OS ABI: Linux 3.17.0) => /usr/lib/libQt5Core.so.5
        libQt5Core.so (libc6,x86-64, OS ABI: Linux 3.17.0) => /usr/lib/libQt5Core.so

Yes, ldconfig knows this so. But wait, what is the OS ABI: Linux 3.17.0 mean? I haven’t seen it with other so’s in the output of ldconfig. File this so gives:

~$ file /usr/lib/libQt5Core.so.5.11.2
/usr/lib/libQt5Core.so.5.11.2: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=544bad9528cefc82c20e31eb3eac7eaf8079681b, for GNU/Linux 3.17.0, stripped

Oh, for GNU/Linux 3.17.0. This makes sense. We know that Windows is faking itself as linux 4.4.0. So is it rejecting this so due to wrong metainfo?

After some more search I found this issue, which finally guided me to the core issue. WSL is not loading so with .note.ABI-tag section, which other so’s don’t have. This core issue also gives a solution: simply strip this section. Now everything works as expected.

发表评论