Closed JsBergbau closed 1 year ago
Hm, things are working fine for me with protoc 3.21.12. What version of protoc do you have installed?
Thanks for the fast reply.
3.12.4 is installed via sudoapt install protobuf-compiler
on Debian 11. Looks like I have to do a manual install as described here https://grpc.io/docs/protoc-installation/
Or where can I add the --experimental_allow_proto3_optional
option in the build script?
You know, our Dockerized Java build is using a Debian 10 image, and doesn't install protobuf-compiler. If you unset PROTOC
in your environment, will it use the version bundled with prost-build?
(This workaround won't work forever; newer versions of prost-build do not include a bundled protobuf-compiler, and we will eventually update to them.)
There is no PROTOC environment variable set. I had to install it via sudoapt install protobuf-compiler
, so it didn't seem to use the bundled version.
When uninstalling protobuf-compiler I get, as expected
thread 'main' panicked at 'Protobufs in src are valid: Custom { kind: NotFound, error: "failed to invoke protoc (hint: https://docs.rs/prost-build/#sourcing-protoc): No such file or directory (os error 2)" }', rust/protocol/build.rs:14:52
For better understanding: I'm only trying to compile libsignal for signal-cli as explained here https://github.com/AsamK/signal-cli/wiki/Provide-native-lib-for-libsignal
I am on armv6 (Raspberry PI Zero W) and I didn't find a prebuild library for armv6 so I try to compile myself. This had worked more than one year ago, but since some time I am not receiving messages any more probably because of the outdated library, so I am now trying to update it.
Obligatory "we don't officially support use outside of Signal's official clients", but then I'll note that libsignal is generally not perfectly compatible between releases (that's what the leading "0" in the version is supposed to indicate), and so compiling a newer version than what signal-cli expects will probably lead to crashes.
I think ultimately it is not a major goal of libsignal to remain compatible with older development tools than what the organization uses to build the Signal apps, and so installing protobuf from source is your best bet. Or cross-compiling from a newer system.
Installation from source is also not an easy task, since for protoc you need bazel to build and that makes also a lot of trouble, so: Can you give me a hint what has to be done to crosscompile libsignal? I mean I have crosscompiled before and signal-cli/libsignal are the cause that there is now a JDK17 available for Raspberry PI Zero (W) / armv6 https://github.com/raspberrypi/linux/issues/3306 So I just need some point where to start. Your help is really appreciated.
I found some general instructions for cross-compiling Rust for RasPi systems that look correct to me; the target name is libsignal-jni
, which you can see in build_jni.sh
.
I'm going to close this issue because I don't think there's any action for Signal to take, but I'll answer questions a bit longer too. Like I said, though, I strongly suspect you'll get to the end of this and then find out that it doesn't work the current version of signal-cli.
Obligatory "we don't officially support use outside of Signal's official clients", but then I'll note that libsignal is generally not perfectly compatible between releases (that's what the leading "0" in the version is supposed to indicate), and so compiling a newer version than what signal-cli expects will probably lead to crashes.
signal-cli defines exactly which version of libsignal is needed for the release, see https://github.com/AsamK/signal-cli/wiki/Provide-native-lib-for-libsignal#determine-the-required-libsignal-client-version So no problem with this.
So I've finally managed to compile and cross-compile libsignal and I want to share my experiences.
Without crosscompiling is the easiest way to
cd /usr/bin/
sudo bash
mv protoc protoc-bin
Then create file protoc
#!/bin/bash
/usr/bin/protoc-bin "$@" --experimental_allow_proto3_optional
This just invokes protoc with the desired --experimental_allow_proto3_optional
option. Stdin so piping is not working, have a look here of how to do it (just few lines more code) https://github.com/JsBergbau/nullmailer-Rewrite-Wrapper
Then chmod +x protoc
compiling now finally works.
Now for cross-compiling. This is a lot more complicated. The following steps may not be 100 % accurate but definitly helpful for others trying the same. Thanks for providing your link for crosscompiling Rust for RasPi systems. That helped me a lot. Since I've already compiled a crosscompiler for building JDK for Raspberry Pi Zero (W) I've used it https://github.com/JsBergbau/GCC-cross-compiler-for-Raspberry-PI-Zero-W
sudo apt-get install gcc-multilib libprotobuf-dev protobuf-compiler cmake clang
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add arm-unknown-linux-gnueabihf
wget https://github.com/JsBergbau/GCC-cross-compiler-for-Raspberry-PI-Zero-W/releases/download/cross-pi-gcc_gcc-10.1_glibc-2.28_binutils-2.31_Buster/cross-pi-gcc_gcc-10.1_glibc-2.28_binutils-2.31_Buster.tar.zst
tar xf cross-pi-gcc_gcc-10.1_glibc-2.28_binutils-2.31_Buster/cross-pi-gcc_gcc-10.1_glibc-2.28_binutils-2.31_Buster.tar.zst
sudo mv cross-pi-gcc /opt
The build_jni.sh has to be modified
if [ "$1" = 'desktop' ];
then
export PATH="/opt/cross-pi-gcc/bin:$PATH"
export CROSS_COMPILE=arm-linux-gnueabihf
export CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=/opt/cross-pi-gcc/bin/arm-linux-gnueabihf-gcc
export CC=/opt/cross-pi-gcc/bin/arm-linux-gnueabihf-gcc
echo_then_run cargo build -p libsignal-jni --release --target arm-unknown-linux-gnueabihf
copy_built_library target/release signal_jni "${DESKTOP_LIB_DIR}/"
elif [ "$1" = 'android' ];
I am not sure if these exports are really necessary, however they work.
Start building with ./build_jni.sh desktop
and libsignal_jni.so
will be successfully created and available in libsignal-client/target/arm-unknown-linux-gnueabihf/release/
The following error message is just for reference, so that other having trouble with crosscompiling rust will find their way here with the error message. The trick are the three environment variables
export CROSS_COMPILE=arm-linux-gnueabihf
export CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=/opt/cross-pi-gcc/bin/arm-linux-gnueabihf-gcc
export CC=/opt/cross-pi-gcc/bin/arm-linux-gnueabihf-gcc
Now the trickiest part. boring-sys fails to compile, because it tries to use the normal cc and c++.
Error message (note the username of the x86 build system is also pi
):
error: failed to run custom build command for `boring-sys v2.1.0 (https://github.com/signalapp/boring?branch=libsignal#bdf9d2ac)`
Caused by:
process didn't exit successfully: `/home/pi/libsignal-client/target/release/build/boring-sys-47d821133f93ac8a/build-script-build` (exit status: 101)
--- stdout
cargo:rerun-if-env-changed=BORING_BSSL_PATH
CMAKE_GENERATOR_arm-unknown-linux-gnueabihf = None
CMAKE_GENERATOR_arm_unknown_linux_gnueabihf = None
TARGET_CMAKE_GENERATOR = None
CMAKE_GENERATOR = None
CMAKE_PREFIX_PATH_arm-unknown-linux-gnueabihf = None
CMAKE_PREFIX_PATH_arm_unknown_linux_gnueabihf = None
TARGET_CMAKE_PREFIX_PATH = None
CMAKE_PREFIX_PATH = None
CMAKE_arm-unknown-linux-gnueabihf = None
CMAKE_arm_unknown_linux_gnueabihf = None
TARGET_CMAKE = None
CMAKE = None
running: "cmake" "/home/pi/.cargo/git/checkouts/boring-b37daebd62069023/bdf9d2a/boring-sys/deps/boringssl" "-DCMAKE_TOOLCHAIN_FILE=/home/pi/.cargo/git/checkouts/boring-b37daebd62069023/bdf9d2a/boring-sys/cmake/armv7-linux.cmake" "-DCMAKE_INSTALL_PREFIX=/home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/build/boring-sys-a9c215cff1764e8f/out" "-DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC -march=armv6 -marm -mfpu=vfp" "-DCMAKE_CXX_FLAGS= -ffunction-sections -fdata-sections -fPIC -march=armv6 -marm -mfpu=vfp" "-DCMAKE_ASM_FLAGS= -ffunction-sections -fdata-sections -fPIC -march=armv6 -marm -mfpu=vfp" "-DCMAKE_BUILD_TYPE=MinSizeRel"
-- The C compiler identification is GNU 10.2.1
-- The CXX compiler identification is GNU 10.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - failed
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc - broken
-- Configuring incomplete, errors occurred!
See also "/home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/build/boring-sys-a9c215cff1764e8f/out/build/CMakeFiles/CMakeOutput.log".
See also "/home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/build/boring-sys-a9c215cff1764e8f/out/build/CMakeFiles/CMakeError.log".
--- stderr
CMake Error at /usr/share/cmake-3.18/Modules/CMakeTestCCompiler.cmake:66 (message):
The C compiler
"/usr/bin/cc"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/build/boring-sys-a9c215cff1764e8f/out/build/CMakeFiles/CMakeTmp
Run Build Command(s):/usr/bin/gmake cmTC_c890f/fast && /usr/bin/gmake -f CMakeFiles/cmTC_c890f.dir/build.make CMakeFiles/cmTC_c890f.dir/build
gmake[1]: Verzeichnis „/home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/build/boring-sys-a9c215cff1764e8f/out/build/CMakeFiles/CMakeTmp“ wird betreten
Building C object CMakeFiles/cmTC_c890f.dir/testCCompiler.c.o
/usr/bin/cc -ffunction-sections -fdata-sections -fPIC -march=armv6 -marm -mfpu=vfp -o CMakeFiles/cmTC_c890f.dir/testCCompiler.c.o -c /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/build/boring-sys-a9c215cff1764e8f/out/build/CMakeFiles/CMakeTmp/testCCompiler.c
cc: error: unrecognized command-line option ‘-marm’; did you mean ‘-mabm’?
cc: error: unrecognized command-line option ‘-mfpu=vfp’
gmake[1]: *** [CMakeFiles/cmTC_c890f.dir/build.make:85: CMakeFiles/cmTC_c890f.dir/testCCompiler.c.o] Fehler 1
gmake[1]: Verzeichnis „/home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/build/boring-sys-a9c215cff1764e8f/out/build/CMakeFiles/CMakeTmp“ wird verlassen
gmake: *** [Makefile:140: cmTC_c890f/fast] Fehler 2
We have now to force the use of the crosscompiler: This step must be done after compiling fails with an error.
cd /usr/bin sudo mv cc cc.old sudo ln -s /opt/cross-pi-gcc/bin/arm-linux-gnueabihf-gcc cc sudo mv c++ c++.old sudo ln -s /opt/cross-pi-gcc/bin/arm-linux-gnueabihf-c++ c++
Re-Start building with ./build_jni.sh desktop
It will now finish compiling libsignal_jni.so
Now revert the systemchanges
cd /usr/bin sudo bash
mv cc cc.ln mv c++ cc++.ln mv cc.old cc mv c++.old c++
Clever solution for protoc
, heh.
You should be able to set CC=/opt/cross-pi-gcc/bin/arm-linux-gnueabihf-gcc
rather than using symlinks; you can see the Android build in build_jni.sh
doing something like this.
Thanks for the hint with CC=/opt/cross-pi-gcc/bin/arm-linux-gnueabihf-gcc
that is definitely a better solution. I didn't like the symlink solution neither, at least I was glad to get it compiled.
Still with the CC env variable set it seems it requires another addition, because now it fails with linking
Compiling libsignal-jni v0.23.1 (/home/pi/libsignal-client/rust/bridge/jni)
error: linking with `cc` failed: exit status: 1
[a lot of line with the args of cc omitted]
= note: /usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: /home/pi/libsignal-client/target/arm-unknown-linux-gnueabihf/release/deps/signal_jni.3la2dkqjlmz1h0v6.rcgu.o: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
error: could not compile `libsignal-jni` due to previous error
Ah, your CARGO_TARGET_ARM_LINUX_GNUEABIHF_LINKER
should be CARGO_TARGET_ARM_
UNKNOWN
_LINUX_GNUEABIHF_LINKER
Thank you very much. It works now and I've edited the post above.
Where did you find the name of the env variable CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER
?
I was searching for documentation but did only find here https://doc.rust-lang.org/cargo/reference/environment-variables.html
CARGO_TARGET_<triple>_LINKER — The linker to use, see [target.<triple>.linker](https://doc.rust-lang.org/cargo/reference/config.html#targettriplelinker). The triple must be [converted to uppercase and underscores](https://doc.rust-lang.org/cargo/reference/config.html#environment-variables).
and https://doc.rust-lang.org/cargo/reference/config.html#targettriplelinker
[target.<triple>.linker](https://doc.rust-lang.org/cargo/reference/config.html#targettriplelinker)
Type: string (program path)
Default: none
Environment: CARGO_TARGET_<triple>_LINKER
Specifies the linker which is passed to rustc (via [-C linker](https://doc.rust-lang.org/rustc/codegen-options/index.html#linker)) when the [<triple>](https://doc.rust-lang.org/cargo/appendix/glossary.html#target) is being compiled for. By default, the linker is not overridden.
To be exact this is no triple anymore, but a quadruple ;)
That's the correct documentation, yes. The "triple" comes from the Rust platform target name (from this big list), and yeah, it hasn't been a "triple" for a long time. (Coincidentally, there was just a thread on the Swift forums about this.)
Crosscompiling boring-sys is still an issue. The workaround with symlink is still needed. I've added the steps again https://github.com/signalapp/libsignal/issues/523#issuecomment-1562970981
When trying to build with
./build_jni.sh desktop
build process fails withusing commit a196fb8 but also the same problem with the commit from a few days ago.