Skip to content

Commit

Permalink
feat(docs): Add troubleshooting guide for CairoSVG crash
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilkrzyskow committed Feb 28, 2024
1 parent 6e486ce commit 8e65ac4
Showing 1 changed file with 183 additions and 0 deletions.
183 changes: 183 additions & 0 deletions docs/plugins/requirements/image-processing.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,189 @@ The following environments come with a preinstalled version of [Cairo Graphics]:
[Docker image]: https://hub.docker.com/r/squidfunk/mkdocs-material/
[GitHub Actions]: ../../publishing-your-site.md#with-github-actions

#### Troubleshooting { id="cairosvg-troubleshooting" }

After following the installation guide above it may happen that you still
get the following error:

```bash
no library called "cairo-2" was found
no library called "cairo" was found
no library called "libcairo-2" was found
cannot load library 'libcairo.so.2': error 0x7e. Additionally, ctypes.util.find_library() did not manage to locate a library called 'libcairo.so.2'
cannot load library 'libcairo.2.dylib': error 0x7e. Additionally, ctypes.util.find_library() did not manage to locate a library called 'libcairo.2.dylib'
cannot load library 'libcairo-2.dll': error 0x7e. Additionally, ctypes.util.find_library() did not manage to locate a library called 'libcairo-2.dll'
```

This means that the [`cairosvg`][PyPi CairoSVG] package was installed,
but the underlying [`cairocffi`][PyPi CairoCFFI] dependency couldn't
[find][cffi-dopen] the installed library. Depending on the operating system
the library lookup process is different:

!!! tip
Before proceeding remember to fully restart any open Terminal windows, and
their parent hosts like IDEs to reload any environmental variables, which
were altered during the installation process. This might be the quick fix.

=== ":material-apple: macOS"

On macOS the library lookup checks inside paths defined in [dyld].
Additionally each library `name` is [checked][find-library-macOS] in three
variants with the `libname.dylib`, `name.dylib` and `name.framework/name`
format.

[Homebrew] should set every needed variable to point at the installed
library, but if that didn't happen, you can use the debug script below
to maybe find the issue.

A [known workaround][cffi-issue] is to add the homebrew lib path
directly before running MkDocs:

```bash
export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib
```

??? tip "Python Debug macOS Script"

You can run the code below as a `debug.py` script or directly in
the interpreter.

```py
import os
from ctypes.macholib import dyld
from itertools import chain

library_names = ("cairo-2", "cairo", "libcairo-2")
filenames = ("libcairo.so.2", "libcairo.2.dylib", "libcairo-2.dll")
found_path = ""
names = []

for name in library_names:
names += [
'lib%s.dylib' % name,
'%s.dylib' % name,
'%s.framework/%s' % (name, name)
]

for name in names:
for path in dyld.dyld_image_suffix_search(
chain(
dyld.dyld_override_search(name),
dyld.dyld_executable_path_search(name),
dyld.dyld_default_search(name)
)
):
print(path)
if os.path.isfile(path):
found_path = path
break
try:
if dyld._dyld_shared_cache_contains_path(path):
found_path = path
break
except NotImplementedError:
pass
if found_path:
filenames = (found_path, ) + filenames
break
else:
found_path = "not found"

print(f"The path is {found_path}")
print("List of files that FFI will try to load:")
for filename in filenames:
print("-", filename)
```

=== ":fontawesome-brands-windows: Windows"

On Windows the library lookup checks inside the paths defined in the
environmental `PATH` variable. Additionally each library `name` is checked
in [two variants][find-library-Windows] with the `name` and `name.dll` format.

The default installation path of [GTK runtime] is:

```powershell
C:\Program Files\GTK3-Runtime Win64
```

and the libraries are in the `lib` directory. Use the debug script
below to check if the path is included. If it isn't then:

1. Press ++windows+r++
2. Run the `SystemPropertiesAdvanced` applet
3. Select "Environmental Variables" at the bottom
4. Add the whole path to the `lib` directory to your `PATH` variable.
5. Fully restart any open Terminal windows and parent hosts like IDEs to
reload the `PATH` inside them.

??? tip "Python Debug Windows Script"

You can run the code below as a `debug.py` script or directly in
the interpreter.

```py
import os

library_names = ("cairo-2.dll", "cairo.dll", "libcairo-2.dll")
filenames = ("libcairo.so.2", "libcairo.2.dylib", "libcairo-2.dll")
found_path = ""

for name in library_names:
for path in os.environ['PATH'].split(os.pathsep):
resolved_path = os.path.join(path, name)
print(resolved_path)
if os.path.exists(resolved_path):
filenames = (resolved_path, ) + filenames
found_path = resolved_path
break
if found_path:
break
else:
found_path = "not found"

print(f"The path is {found_path}")
print("List of files that FFI will try to load:")
for filename in filenames:
print("-", filename)
```

=== ":material-linux: Linux"

On Linux the library lookup [differs greatly][find-library-Linux] and
is dependant from the installed distribution. For example Python could
run a specific system shell command to find out which libraries are
available for a given C compiler.

The below Python script will show, which function is being run to find
installed libraries. You can check the source to find out what specific
commands are run on your system during execution.

??? tip "Python Debug Linux Script"

You can run the code below as a `debug.py` script or directly in
the interpreter.

```py
import inspect
from ctypes.util import find_library

print("find_library script:")
print(inspect.getsourcefile(find_library))
print("\nfind_library function:")
print(inspect.getsource(find_library))
```

[PyPi CairoSVG]: https://pypi.org/project/CairoSVG
[PyPi CairoCFFI]: https://pypi.org/project/CairoCFFI
[dyld]: https://www.unix.com/man-page/OSX/1/dyld/
[cffi-issue]: https://github.com/squidfunk/mkdocs-material/issues/5121
[cffi-dopen]: https://github.com/Kozea/cairocffi/blob/f1984d644bbc462ef0ec33b97782cf05733d7b53/cairocffi/__init__.py#L24-L49
[find-library-macOS]: https://github.com/python/cpython/blob/4d58a1d8fb27048c11bcbda3da1bebf78f979335/Lib/ctypes/util.py#L70-L81
[find-library-Windows]: https://github.com/python/cpython/blob/4d58a1d8fb27048c11bcbda3da1bebf78f979335/Lib/ctypes/util.py#L59-L67
[find-library-Linux]: https://github.com/python/cpython/blob/4d58a1d8fb27048c11bcbda3da1bebf78f979335/Lib/ctypes/util.py#L92


### pngquant

[pngquant] is an excellent library for lossy PNG compression, and a direct
Expand Down

0 comments on commit 8e65ac4

Please sign in to comment.