Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r2643:96df07b3e9ba Date: 2016-02-19 16:22 +0100 http://bitbucket.org/cffi/cffi/changeset/96df07b3e9ba/
Log: A dump of my experiences with rpaths and $ORIGIN messes diff --git a/doc/source/embedding.rst b/doc/source/embedding.rst --- a/doc/source/embedding.rst +++ b/doc/source/embedding.rst @@ -76,7 +76,10 @@ library. It is a file with the extension ``.dll`` on Windows, ``.dylib`` on Mac OS/X, or ``.so`` on other platforms. As usual, it is produced by generating some intermediate ``.c`` code and then -calling the regular platform-specific C compiler. +calling the regular platform-specific C compiler. See below__ for +some pointers to C-level issues with using the probuced library. + +.. __: `Issues about using the .so`_ Here are some details about the methods used above: @@ -231,6 +234,79 @@ than 1.5. CFFI 1.5 or newer must be installed in the running Python. +Issues about using the .so +-------------------------- + +This paragraph describes issues that are not necessarily specific to +CFFI. It assumes that you have obtained the ``.so/.dylib/.dll`` file as +described above, but that you have troubles using it. (In summary: it +is a mess. This is my own experience, slowly built by using Google and +by listening to reports from various platforms. Please report any +inaccuracies in this paragraph or better ways to do things.) + +* The file produced by CFFI should follow this naming pattern: + ``libmy_plugin.so`` on Linux, ``libmy_plugin.dylib`` on Mac, or + ``my_plugin.dll`` on Windows (no ``lib`` prefix on Windows). + +* First note that this file does not contain the Python interpreter + nor the standard library of Python. You still need it to be + somewhere. There are ways to compact it to a smaller number of files, + but this is outside the scope of CFFI (please report if you used some + of these ways successfully so that I can add some links here). + +* In what we'll call the "main program", the ``.so`` can be either + used dynamically (e.g. by calling ``dlopen()`` or ``LoadLibrary()`` + inside the main program), or at compile-time (e.g. by compiling it + with ``gcc -lmy_plugin``). The former case is always used if you're + building a plugin for a program, and the program itself doesn't need + to be recompiled. The latter case is for making a CFFI library that + is more tightly integrated inside the main program. + +* In the case of compile-time usage: you can add the gcc + option ``-Lsome/path/`` before ``-lmy_plugin`` to describe where the + ``libmy_plugin.so`` is. On some platforms, notably Linux, ``gcc`` + will complain if it can find ``libmy_plugin.so`` but not + ``libpython27.so`` or ``libpypy-c.so``. To fix it, you need to call + ``LD_LIBRARY_PATH=/some/path/to/libpypy gcc``. + +* When actually executing the main program, it needs to find the + ``libmy_plugin.so`` but also ``libpython27.so`` or ``libpypy-c.so``. + For PyPy, unpack a PyPy distribution and you get a full directory + structure with ``libpypy-c.so`` inside a ``bin`` subdirectory, or on + Windows ``pypy-c.dll`` inside the top directory; you must not move + this file around, but just point to it. One way to point to it is by + running the main program with some environment variable: + ``LD_LIBRARY_PATH=/some/path/to/libpypy`` on Linux, + ``DYLD_LIBRARY_PATH=/some/path/to/libpypy`` on OS/X. + +* You can avoid the ``LD_LIBRARY_PATH`` issue if you compile + ``libmy_plugin.so`` with the path hard-coded inside in the first + place. On Linux, this is done by ``gcc -Wl,-rpath=/some/path``. You + would put this option in ``ffi.set_source("my_plugin", ..., + extra_link_args=['-Wl,-rpath=/some/path/to/libpypy'])``. The path can + start with ``$ORIGIN`` to mean "the directory where + ``libmy_plugin.so`` is". You can then specify a path relative to that + place, like ``extra_link_args=['-Wl,-rpath=$ORIGIN/../venv/bin']``. + Use ``ldd libmy_plugin.so`` to look at what path is currently compiled + in after the expansion of ``$ORIGIN``.) + + After this, you don't need ``LD_LIBRARY_PATH`` any more to locate + ``libpython27.so`` or ``libpypy-c.so`` at runtime. In theory it + should also cover the call to ``gcc`` for the main program. I wasn't + able to make ``gcc`` happy without ``LD_LIBRARY_PATH`` on Linux if + the rpath starts with ``$ORIGIN``, though. + +* The same rpath trick might be used to let the main program find + ``libmy_plugin.so`` in the first place without ``LD_LIBRARY_PATH``. + (This doesn't apply if the main program uses ``dlopen()`` to load it + as a dynamic plugin.) You'd make the main program with ``gcc + -Wl,-rpath=/path/to/libmyplugin``, possibly with ``$ORIGIN``. The + ``$`` in ``$ORIGIN`` causes various shell problems on its own: if + using a common shell you need to say ``gcc + -Wl,-rpath=\$ORIGIN/../venv/bin``. From a Makefile, you need to say + something like ``gcc -Wl,-rpath=\$$ORIGIN/../venv/bin``. + + Using multiple CFFI-made DLLs ----------------------------- _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit