matrix-org / olm

An implementation of the Double Ratchet cryptographic ratchet in C++/C
https://gitlab.matrix.org/matrix-org/olm
63 stars 9 forks source link

python binding cannot be cross-compiled #16

Open uhoreg opened 5 years ago

uhoreg commented 5 years ago

Received this report from Nathan O.:

Update, seem cffi causes issues when cross-compiling for a different arch, as it wants to use host's LD instead of target's even though I am telling it to use target's

jonnius commented 4 years ago

I am failing to cross-compile pantalaimon, due to an issue with cross-compiling python-olm. Is this the same or should I open a new issue?

poljar commented 4 years ago

This seems to be a peculiarity of CFFI, other people seem to have solved this by installing the target CFFI besides the host one.

Trying to do this myself I experienced the same isssue

DEVELOP=1 CC=aarch64-linux-gnu-gcc CFLAGS="-march=armv8-a" python olm_build.py
mkdir -p include/olm
aarch64-linux-gnu-gcc -E -I dummy -I ../include ../include/olm/olm.h -o include/olm/olm.h
echo 'void *memset(void *s, int c, size_t n);' >> include/olm/olm.h
aarch64-linux-gnu-gcc -E -I dummy -I ../include ../include/olm/pk.h -o include/olm/pk.h
aarch64-linux-gnu-gcc -E -I dummy -I ../include ../include/olm/sas.h -o include/olm/sas.h
generating ./_libolm.c
the current directory is '/home/poljar/werk/misc/olm/python'
running build_ext
building '_libolm' extension
aarch64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -fno-semantic-interposition -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -march=armv8-a -fPIC -I/usr/include/python3.8 -c _libolm.c -o ./_libolm.o -I../include
gcc -pthread -shared -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -fno-semantic-interposition -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -march=armv8-a ./_libolm.o -L/usr/lib -lolm -o ./_libolm.cpython-38-x86_64-linux-gnu.so -L../build -Wl,-rpath=../build
/usr/bin/ld: ./_libolm.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: ./_libolm.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: ./_libolm.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: ./_libolm.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: ./_libolm.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: ./_libolm.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: ./_libolm.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: ./_libolm.o: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status

We can see that it first invokes the correct gcc with aarch64-linux-gnu-gcc, it compiles the module fine but the linking step uses the default host gcc.

It also leaves a bunch of -march flags setting the arch to x86_64

The build creates a single C file that needs to be compiled so running the compile and link step manually is another valid workaround.

To compile i ran this:

$ aarch64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -mtune=generic -O3 -pipe -fno-plt -fno-semantic-interposition -mtune=generic -O3 -pipe -fno-plt -mtune=generic -O3 -pipe -fno-plt -march=armv8-a -fPIC -I/usr/include/python3.8 -c _libolm.c -o ./_libolm.o -I../include

This picks up the cross compiled libolm from the ../build dir.

Linking it worked with

$ aarch64-linux-gnu-gcc -pthread -shared -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -fno-semantic-interposition -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -march=armv8-a ./_libolm.o -L/usr/lib -lolm -o ./_libolm.cpython-38-aarch64-linux-gnu.so -L../build -Wl,-rpath=../build

The resulting file

$ file _libolm.cpython-38-aarch64-linux-gnu.so 
_libolm.cpython-38-aarch64-linux-gnu.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]=2880cebb2fe27ffd56e449303f98061615944cda, with debug_info, not stripped
jonnius commented 4 years ago

Thanks for the useful hints. My issue was not with the linker but rather the cross-compiling itself.

What I am trying to do is to simply compile it via python3.7 -m pip install -t $TARGET_DIR python-olm (the ultimate goal is to build pantalaimon via python3.7 -m pip install -t $TARGET_DIR pantalaimon) in a cross-compiling-prepared docker container (provided by Clickable), which results in:

   Running setup.py install for python-olm: finished with status 'error'
    ERROR: Command errored out with exit status 1:
     command: /usr/bin/python3.7 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-2bi8y70r/python-olm/setup.py'"'"'; __file__='"'"'/tmp/pip-install-2bi8y70r/python-olm/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-r6bgi257/install-record.txt --single-version-externally-managed --home /tmp/pip-target-rka1p523 --compile --install-headers /tmp/pip-target-rka1p523/include/python/python-olm
         cwd: /tmp/pip-install-2bi8y70r/python-olm/
    Complete output (23 lines):
    WARNING: The wheel package is not available.
    WARNING: The wheel package is not available.
    make: *** No rule to make target '../include/olm/olm.h', needed by 'include/olm/olm.h'.  Stop.
    running install
    running build
    running build_py
    creating build
    creating build/lib.linux-x86_64-3.7
    creating build/lib.linux-x86_64-3.7/olm
    copying olm/_finalize.py -> build/lib.linux-x86_64-3.7/olm
    copying olm/_compat.py -> build/lib.linux-x86_64-3.7/olm
    copying olm/account.py -> build/lib.linux-x86_64-3.7/olm
    copying olm/pk.py -> build/lib.linux-x86_64-3.7/olm
    copying olm/__init__.py -> build/lib.linux-x86_64-3.7/olm
    copying olm/session.py -> build/lib.linux-x86_64-3.7/olm
    copying olm/group_session.py -> build/lib.linux-x86_64-3.7/olm
    copying olm/sas.py -> build/lib.linux-x86_64-3.7/olm
    copying olm/__version__.py -> build/lib.linux-x86_64-3.7/olm
    copying olm/utility.py -> build/lib.linux-x86_64-3.7/olm
    running build_ext
    generating cffi module 'build/temp.linux-x86_64-3.7/_libolm.c'
    creating build/temp.linux-x86_64-3.7
    error: don't know how to compile C/C++ code on platform 'posix' with 'aarch64-linux-gnu-gcc' compiler

I set the compiler to aarch64-linux-gnu-gcc in ~/.pydistutils.cfg.

Any chance I can get along with this approach or do I need to setup a build script that downloads python-olm sources and builds it as you suggested above?

poljar commented 4 years ago

Not sure if pydistutils is supposed to work, did you try with overriding CC and CFLAGS, perhaps it just works™ if you have the target CFFI installed.

jonnius commented 4 years ago

I finally got it cross-compiled within the Clickable docker image building olm as a shared library and overriding some env vars like:

"CC": "${ARCH_TRIPLET}-gcc",
"CFLAGS": "-I${OLM_DIR}/include -I${OLM_DIR}/include",
"LDFLAGS": "-L${OLM_DIR}/lib/${ARCH_TRIPLET} -shared",
"LDSHARED": "${ARCH_TRIPLET}-gcc",
"LD": "${ARCH_TRIPLET}-gcc"

Thanks for your help!