For development statically link dcc-rs

This links the python bindings statically to libdeltachat.a if the
DCC_RS_DEV environment variable is set to the project's root.  This is
a little simpler then requiring the manual CFLAGS and LD_LIBRARY_PATH
tweaking.

It also adds a script to easily invoke the integration tests locally
without forgetting steps.
This commit is contained in:
Floris Bruynooghe
2019-06-10 17:17:34 +02:00
parent af8d056206
commit 5090b4d24b
7 changed files with 88 additions and 45 deletions

6
.gitignore vendored
View File

@@ -11,3 +11,9 @@ include
.dc-history.txt .dc-history.txt
*.db *.db
*.db-blobs *.db-blobs
python/.eggs
python/.tox
*.egg-info
__pycache__
python/src/deltachat/capi*.so

View File

@@ -1,13 +1,12 @@
#!/bin/bash #!/bin/bash
# #
# Build the Delta Chat C/Rust library # Build the Delta Chat C/Rust library typically run in a docker
# typically run in a docker container that contains all library deps # container that contains all library deps but should also work
# but should also work outside if you have the dependencies installed # outside if you have the dependencies installed on your system.
# on your system.
set -e -x set -e -x
# perform clean build of core and install # Perform clean build of core and install.
export TOXWORKDIR=.docker-tox export TOXWORKDIR=.docker-tox
# install core lib # install core lib
@@ -16,12 +15,11 @@ export PATH=/root/.cargo/bin:$PATH
cargo build --release -p deltachat_ffi cargo build --release -p deltachat_ffi
# cargo test --all --all-features # cargo test --all --all-features
# make sure subsequent compiler invocations find header and libraries # Statically link against libdeltachat.a.
export CFLAGS=-I`pwd`/deltachat-ffi export DCC_RS_DEV=$(pwd)
export LD_LIBRARY_PATH=`pwd`/target/release
# configure access to a base python and # Configure access to a base python and to several python interpreters
# to several python interpreters needed by tox below # needed by tox below.
export PATH=$PATH:/opt/python/cp35-cp35m/bin export PATH=$PATH:/opt/python/cp35-cp35m/bin
export PYTHONDONTWRITEBYTECODE=1 export PYTHONDONTWRITEBYTECODE=1
pushd /bin pushd /bin

View File

@@ -50,18 +50,14 @@ to core deltachat library::
cd deltachat-core-rust cd deltachat-core-rust
cargo build -p deltachat_ffi --release cargo build -p deltachat_ffi --release
This will result in a ``libdeltachat.so`` and ``deltachat.h`` file This will result in a ``libdeltachat.so`` and ``libdeltachat.a`` files
in the ``deltachat_ffi`` directory. These files are needed for in the ``target/release`` directory. These files are needed for
creating the python bindings for deltachat:: creating the python bindings for deltachat::
cd python cd python
CFLAGS=I`pwd`/../deltachat-ffi pip install -e . DCC_RS_DEV=`pwd`/.. pip install -e .
You then need to set the load-dynamic-library path in your shell:: Now test if the bindings find the correct library::
export LD_LIBRARY_PATH=`pwd`/../target/release
so that importing the bindings finds the correct library::
python -c 'import deltachat ; print(deltachat.__version__)' python -c 'import deltachat ; print(deltachat.__version__)'
@@ -73,6 +69,14 @@ This should print your deltachat bindings version.
that'd be much appreciated! please then get that'd be much appreciated! please then get
`in contact with us <https://delta.chat/en/contribute>`_. `in contact with us <https://delta.chat/en/contribute>`_.
Using a system-installed deltachat-core-rust
--------------------------------------------
When calling ``pip`` without specifying the ``DCC_RS_DEV`` environment
variable cffi will try to use a ``deltachat.h`` from a system location
like ``/usr/local/include`` and will try to dynamically link against a
``libdeltachat.so`` in a similar location (e.g. ``/usr/local/lib``).
Code examples Code examples
============= =============
@@ -83,13 +87,10 @@ You may look at `examples <https://py.delta.chat/examples.html>`_.
Running tests Running tests
============= =============
Get a checkout of the `deltachat-core github repository`_ and type:: Get a checkout of the `deltachat-core-rust github repository`_ and type::
cd python
export CFLAGS=I`pwd`/../deltachat-ffi
export LD_LIBRARY_PATH=`pwd`/../target/release
pip install tox pip install tox
tox ./run-integration-tests.sh
If you want to run functional tests with real If you want to run functional tests with real
e-mail test accounts, generate a "liveconfig" file where each e-mail test accounts, generate a "liveconfig" file where each
@@ -103,12 +104,14 @@ The "keyword=value" style allows to specify any
`deltachat account config setting <https://c.delta.chat/classdc__context__t.html#aff3b894f6cfca46cab5248fdffdf083d>`_ so you can also specify smtp or imap servers, ports, ssl modes etc. `deltachat account config setting <https://c.delta.chat/classdc__context__t.html#aff3b894f6cfca46cab5248fdffdf083d>`_ so you can also specify smtp or imap servers, ports, ssl modes etc.
Typically DC's automatic configuration allows to not specify these settings. Typically DC's automatic configuration allows to not specify these settings.
You can now run tests with this ``liveconfig`` file:: The ``run-integration-tests.sh`` script will automatically use
``python/liveconfig`` if it exists, to manually run tests with this
``liveconfig`` file use::
tox -- --liveconfig liveconfig tox -- --liveconfig liveconfig
.. _`deltachat-core github repository`: https://github.com/deltachat/deltachat-core-rust .. _`deltachat-core-rust github repository`: https://github.com/deltachat/deltachat-core-rust
.. _`deltachat-core`: https://github.com/deltachat/deltachat-core-rust .. _`deltachat-core`: https://github.com/deltachat/deltachat-core-rust

View File

@@ -2,7 +2,7 @@ from deltachat import capi, const
from deltachat.capi import ffi from deltachat.capi import ffi
from deltachat.account import Account # noqa from deltachat.account import Account # noqa
__version__ = "0.10.0dev1" __version__ = "0.10.0.dev2"
_DC_CALLBACK_MAP = {} _DC_CALLBACK_MAP = {}

View File

@@ -1,17 +1,21 @@
import distutils.ccompiler import distutils.ccompiler
import distutils.log
import distutils.sysconfig import distutils.sysconfig
import tempfile import tempfile
import os import os
import cffi import cffi
# XXX hack out the header and library dirs
# relying on CFLAGS and LD_LIBRARY_PATH being set properly is not good
# (but we also don't want to rely on global installs of headers and libs)
HEADERDIR = os.environ["CFLAGS"].split("-I", 1)[1]
LIBDIR = os.environ["LD_LIBRARY_PATH"]
def ffibuilder(): def ffibuilder():
projdir = os.environ.get('DCC_RS_DEV')
if projdir:
libs = []
objs = [os.path.join(projdir, 'target', 'release', 'libdeltachat.a')]
incs = [os.path.join(projdir, 'deltachat-ffi')]
else:
libs = ['deltachat']
objs = []
incs = []
builder = cffi.FFI() builder = cffi.FFI()
builder.set_source( builder.set_source(
'deltachat.capi', 'deltachat.capi',
@@ -35,9 +39,9 @@ def ffibuilder():
return result; return result;
} }
""", """,
libraries=['deltachat'], include_dirs=incs,
include_dirs=[HEADERDIR], libraries=libs,
library_dirs=[LIBDIR], extra_objects=objs,
) )
builder.cdef(""" builder.cdef("""
typedef int... time_t; typedef int... time_t;
@@ -45,6 +49,7 @@ def ffibuilder():
extern const char * dupstring_helper(const char* string); extern const char * dupstring_helper(const char* string);
extern int dc_get_event_signature_types(int); extern int dc_get_event_signature_types(int);
""") """)
distutils.log.set_verbosity(distutils.log.INFO)
cc = distutils.ccompiler.new_compiler(force=True) cc = distutils.ccompiler.new_compiler(force=True)
distutils.sysconfig.customize_compiler(cc) distutils.sysconfig.customize_compiler(cc)
with tempfile.NamedTemporaryFile(mode='w', suffix='.h') as src_fp: with tempfile.NamedTemporaryFile(mode='w', suffix='.h') as src_fp:
@@ -53,7 +58,7 @@ def ffibuilder():
with tempfile.NamedTemporaryFile(mode='r') as dst_fp: with tempfile.NamedTemporaryFile(mode='r') as dst_fp:
cc.preprocess(source=src_fp.name, cc.preprocess(source=src_fp.name,
output_file=dst_fp.name, output_file=dst_fp.name,
include_dirs=[HEADERDIR], include_dirs=incs,
macros=[('PY_CFFI', '1')]) macros=[('PY_CFFI', '1')])
builder.cdef(dst_fp.read()) builder.cdef(dst_fp.read())
builder.cdef(""" builder.cdef("""

View File

@@ -10,15 +10,17 @@ envlist =
commands = commands =
pytest -rsXx {posargs:tests} pytest -rsXx {posargs:tests}
pip wheel . -w {toxworkdir}/wheelhouse pip wheel . -w {toxworkdir}/wheelhouse
passenv = passenv =
TRAVIS TRAVIS
LD_LIBRARY_PATH DCC_RS_DEV
CFLAGS
deps = deps =
pytest pytest
pytest-faulthandler pytest-faulthandler
pdbpp pdbpp
cffi
requests
attrs
six
[testenv:auditwheels] [testenv:auditwheels]
skipsdist = True skipsdist = True

29
run-integration-tests.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/bash
# Small helper to easily run integration tests locally for development
# purposes. Any arguments are passed straight to tox. E.g. to run
# only one environment run with:
#
# ./run-integration-tests.sh -e py35
#
# To also run with `pytest -x` use:
#
# ./run-integration-tests.sh -e py35 -- -x
cargo build -p deltachat_ffi --release
# CFLAGS=-I`pwd`/deltachat-ffi
# LD_LIBRARY_PATH=`pwd`/target/release
# export CFLAGS
# export LD_LIBRARY_PATH
export DCC_RS_DEV=$(pwd)
pushd python
toxargs="$@"
if [ -e liveconfig ]; then
toxargs="--liveconfig liveconfig $@"
fi
tox $toxargs
ret=$?
popd
exit $ret