Compiling Crypto++ for armhf for cross compiling - c++

I want to cross compile the library crypto++ for deployment on a beaglebone running Debian. My host PC runs Ubuntu 14.04 LTS in a 64-bit configuration.
I face the following problem when I invoke the make command from eclipse
arm-linux-gnueabihf-g++-4.8 -L/usr/include/cryptopp -o "GCMwithAES" ./main.o -lcryptopp
/usr/lib/../lib/libcryptopp.so: file not recognized: File format not recognized
My guess is that since the compiler is configured for armhf, it cannot recognize the library that was compiled for amd64.
I have successfully cross compiled and run standard (ie no external libraries) programs from my host PC to my target device.
Solutions that I have tried
Used libcrypto++ packages with the architecture specified as armhf as done in multiarch. The armhf libraries get installed ( as per apt) but I am unable to include and link my code with them.
Manually try to compile the library as per the instruction given on this wiki. However, I always run into errors whenever I try to compile the library.
How do I install the libcryptopp libraries of the armhf architecture on my x64 based PC so I can cross compile? or is there any other way to resolve this issue.
Edit
As suggested in the answer below I tried out the method suggested. I slightly modified the script setenv-embed.sh since I had gcc-4.8 instead of gcc-4.7. The results of running the script are
CPP: /usr/bin/arm-linux-gnueabihf-cpp
CXX: /usr/bin/arm-linux-gnueabihf-g++
AR: /usr/bin/arm-linux-gnueabihf-ar
LD: /usr/bin/arm-linux-gnueabihf-ld
RANLIB: /usr/bin/arm-linux-gnueabihf-gcc-ranlib-4.8
ARM_EMBEDDED_TOOLCHAIN: /usr/bin
ARM_EMBEDDED_CXX_HEADERS: /usr/arm-linux-gnueabihf/include/c++/4.8.2
ARM_EMBEDDED_FLAGS: -march=armv7-a mfloat-abi=hard -mfpu=neon -I/usr/arm-linux-gnueabihf/include/c++/4.8.2 -I/usr/arm-linux-gnueabihf/include/c++/4.8.2/arm-linux-gnueabihf
ARM_EMBEDDED_SYSROOT: /usr/arm-linux-gnueabihf
I build the library using the make command and run into the following error
/usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/../../../../arm-linux-gnueabihf/bin/‌​ld: cannot find /usr/arm-linux-gnueabihf/lib/libc.so.6 inside /usr/arm-linux-gnueabihf
/usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/../../../../arm-linux-gnueabihf/bin/‌​ld: cannot find /usr/arm-linux-gnueabihf/lib/libc_nonshared.a inside /usr/arm-linux-gnueabihf
/usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/../../../../arm-linux-gnueabihf/bin/‌​ld: cannot find /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3 inside /usr/arm-linux-gnueabihf
But when I open the location /usr/arm-linux-gnueabihf/lib I can find all the three error files mentioned above ie libc.so.6, libc_nonshared.a and ld-linux-armhf.so.3
As per the suggestions of #jww, I'm shifting this to a new question since I'm having trouble linking. My results here are left for completeness.

How do I install the libcryptopp libraries of the armhf architecture on my x64 based PC so I can cross compile? or is there any other way to resolve this issue.
Checkout ARM Embedded (Command Line) on the Crypto++ wiki.
Note: that wiki page is a bit dated. You can now use GNUmakefile-cross. I have not updated the page to reflect recent changes like GNUmakefile-cross.
GNUmakefile-cross is a special purpose built for cross-compiling on Android, iOS, Windows Phone, ARM Embedded, and bare metal (I doubt anyone would do the later, but I tested it as a platform). You will still need to run the setenv-embedded.sh script.
To fetch the latest sources from GitHub:
git clone https://github.com/weidai11/cryptopp.git cryptopp-armhf
The GitHub sources are quite active at the moment. We are preparing for a Crypto++ 5.6.3 release. 5.6.3 will include
GNUmakefile-cross.
The complete instructions will look something like (assuming you have the tools installed):
git clone https://github.com/weidai11/cryptopp.git cryptopp-armhf
cd cryptopp-armhf
# Note the leading dot!!!
. ./setenv-embedded.sh
# The command above must execute successfully
# It cannot display a message like "**CXX is not valid**"
# Build it
make -f GNUmakefile-cross static dynamic cryptest.exe
# Check it
$ find . -name cryptest.exe
./cryptest.exe
$ /usr/bin/arm-linux-gnueabi-readelf -h ./cryptest.exe | grep -i 'class\|machine'
Class: ELF32
Machine:
Because the GitHub sources are quite active at the moment, I've already added all the other files from Crypto++-Mobile.zip and Setenv-embedded.sh.zip to the official Crypto++ sources. You only need to get setenv-embedded.sh out of the Setenv-embedded.sh.zip.

In addition to jww's answer, I wanted to add some further notes. (These notes are relevant for version 5.6.3 released 20-Nov-2015.)
It may be necessary to edit the config.h file to change some options. See Config.h on the Crypto++ wiki. In particular:
CRYPTOPP_NO_UNALIGNED_DATA_ACCESS may need to be defined so that the code operates properly on systems that can't do unaligned data read/writes (e.g. ARM).
CRYPTOPP_INIT_PRIORITY and CRYPTOPP_USER_PRIORITY may need to be defined. See Static Initialization Order Fiasco - Crypto++ Wiki for details.
CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562 may need to be defined or undefined, depending on whether the project using it is using older API features or not.
After building the library, it is very much worth running the test program cryptest.exe v on the target system, to check if the library has been built okay for that system. For example, by doing this, I discovered that the library doesn't work properly on the ARM-based BeagleBone Black unless I define CRYPTOPP_NO_UNALIGNED_DATA_ACCESS in config.h (it freezes indefinitely on the test step Testing MessageDigest algorithm SHA-384.).

Related

Compile a library in a way that it's shippable

I've a question regarding compilation of a dependency (namely poppler). Poppler is a dependency of my app which is an electron app.
It's working fine on windows (because npm package node-poppler ships the poppler windows build). But on a mac / linux I have to install poppler dependencies by myself (e.g. via homebrew) and then also everything works well.
Now I want to ship the app including poppler and therefore I've started to compile poppler by myself. This is working particularly and all dependencies that it needs I've added via homebrew and finally the build is running and it compiles successfully after long try and error.
But my problem now is, hat if I remove all homebrew dependencies after I've compiled poppler it stops working because there are "links ? (dont know the exact term)" to these dependencies.
e.g.
cmd: './extlib/darwin/poppler/poppler-gitlab/cmake-build-release/utils/pdfinfo -v',
stdout: '',
stderr: 'dyld[93398]: Library not loaded: /usr/local/opt/fontconfig/lib/libfontconfig.1.dylib\n' +
' Referenced from: <0062B574-27F1-35D4-BEF8-81E2F2B5EEDB> /Users/bernhard´/Coding/Sides/backend/extlib/darwin/poppler/poppler-gitlab/cmake-build-release/libpoppler.126.0.0.dylib\n' +
" Reason: tried: '/usr/local/opt/fontconfig/lib/libfontconfig.1.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/opt/fontconfig/lib/libfontconfig.1.dylib' (no such file), '/usr/local/opt/fontconfig/lib/libfontconfig.1.dylib' (no such file), '/usr/local/lib/libfontconfig.1.dylib' (no such file), '/usr/lib/libfontconfig.1.dylib' (no such file, not in dyld cache)\n"
After a lot of reading I've found out that it might be possible to compile it static (even unsure if I'm using the right term here).
I'd like to know what I neet to do, that I can ship the app and what's required, to build poppler in a way that is has no dependencies anymore or has it's dependencies in a place that I have control over and can ship it with my app.
Actually I'm building using following CMAKE options:
-G Ninja -DCMAKE_BUILD_TYPE=Release -DC_MAKE_PROGRAM=/Applications/CLion.app/Contents/bin/ninja/mac/ninja -DCMAKE_FIND_FRAMEWORK=LAST -DCMAKE_VERBOSE_MAKEFILE=ON -DPOPPLER_QT5=OFF -DPOPPLER_ENABLE_CMS=none -DPOPPLER_ENABLE_SPLASH=OFF -DPOPPLER_ENABLE_UTILS=OFF -DPOPPLER_ENABLE_GLIB=OFF -DPOPPLER_ENABLE_CPP=OFF -DPOPPLER_ENABLE_XPDF_HEADERS=OFF -DPOPPLER_ENABLE_ZLIB=OFF -DPOPPLER_ENABLE_LIBCURL=OFF -DPOPPLER_ENABLE_LIBSYSTEMD=OFF -DPOPPLER_ENABLE_OPENJPEG=OFF -DPOPPLER_ENABLE_TIFF=OFF
Thanks for any help and sorry for maybe misusing terms as I'm mostly a frontend dev.
You have to compile your program with an RPATH option for your shipped libraries. The reason why you can't run it without those deleted dependencies is simple. (Regarding RPATH check out the ld man pages.)
Your application seems to be linking against the same version of the dependency as the one in your homebrew directory. Thus this shared object is compatible with your executable.
Your linker is only configured to look for the shared objects within certain directories. Thus when you delete the directory, your linker doesn't know where to find these shared objects anymore (because they do not exist).
On linux distributions you could run your application for example with: LD_LIBRARY_PATH=./path_to_your/library/ && ./your_executable. And it would suddenly work.
RPATH solves this by telling the linker where to look for the linked dependencies.
I would like to give you a general warning here. This is not the way to go when it comes to shipping your executable (and especially libraries) on different distros. It's better to make a package, using the available -dev packages for the given distribution. - Because otherwise you are slowly introducing dependency hell for the developers who wish to use it!
To answer your question regarding static linking: You will increase the size of your executable, so keep that in your mind if you wish to take this path instead

Library errors after upgrading gcc versions. Unable to figure out what part of my code depends on libgmp

I'm upgrading a project from gcc 4.3 to 12.1 (a major jump) on Centos 7 & 6 - both 64 bit. As part of that I'm having trouble with what I suspect is an indirect dependency on a very old version of libgmp.
The submodule I'm compiling does not require any external libraries, however while running make I get the error:
gcc_12.1.0_path/cc1plus: error while loading shared libraries: libgmp.so.3: cannot open shared object file: No such file or directory
Google search does not turn out anything useful, issues that turn up are different than my case, my ld_library_path vars, lib paths are set correctly. libgmp v 3 is not available on my machine, and ideally I do not wish to install it, instead figure out where the dependency is and try upgrade it to use a more recent version of libgmp.
Even more confusing is, libgmp3 is not supported by centos 7 (or gcc 12). I'm not sure what part of compilation is dependent on this library, or how that part was successfully compiling with gcc 4 on centos 6.
The command for compilation is
g++_path -g -Wno-deprecated -D_DEBUG -fPIC -m64 -DLIN64BIT -I multiple_include_paths -o object_path -c source_file no -L inclusions
I wish to know two things:
In this case, what information should I provide to seek help?
Is there any tool for 2nd level or further (indirect) dependency
analysis? Would a c++ package manager help with such cases?
Is it possible to use libgmp v 3 built on another platform and copied to my lib path to resolve this (I do not have immediate access to such a machine or lib hence cannot check immediately)
Are there any suspects based on just the message and command?

How to use ported library in NaCl module?

I want to use openssl library in my NaCl module. Luckily it is ported already as in https://code.google.com/p/naclports/. However, its kind of pity but I don't know how to add the library to the toolchain. I did as instructed in the Readme file:
...nacl_sdk/pepper_33/naclports/src$ python build_tools/naclports.py install openssl
Already installed 'openssl' [x86_64/newlib]
And then I tried to compile this simple C code, and the compiler complaint some errors which are because of linking problem with openssl/evp.h.
This is my Makefile: link. Please let me know how to make it run.
NaCl actually consists of several different toolchains. naclports will build and install a given library to just one of them at time. The libraries and headers get installed directly into the toolchain so there is no need to -L or -I on the command line.
In this case you have built and installed the x86_64 newlib version of openssl. This means that you should be able to build the x86_64 newlib version of your app (add TOOLCHAIN=newlib NACL_ARCH=x86_64 to your make call).
To build all the other versions of openssh you can use the "make_all.sh" script at the top level of naclports (e.g. ./make_all.sh openssl).
Build naclports. Look in naclports/README.rst for instructions.

How to use Qt app on tiny210 device?

I want to use a Qt app on a tiny210 device.
I installed Qt ( qt-everywhere-opensource-src.4.8.5 ) downloaded from here. I managed to compile a simple application for use on tiny210. The problem is that now when I try to run the app on the device, I get the following errors:
libc.so.6: version 'GLIBC_2.15' not found (required by libQtCore.so.4)
libc.so.6: version 'GLIBC_2.15' not found (required by libQtNetwork.so.4)
There is a libc.so.6 in /lib/ on the target device, but it is version 2.11.
I should mention that before getting those errors I also got errors for not having libQtCore.so.4, libQtNetwork.so.4 and libQtGui.so.4. I fixed those errors just by copying the compiled libraries from my host PC to the device.
First question is: Would there have been a better way to provide the needed libraries, or copying them is fine?
Second question is: How can I get over the errors mentioned above?
EDIT : I've read something about building it static, but I am not sure how, and what are the downsides of this.
EDIT2 : I managed to get over the above errors thanks to artless noise's answer, but now I get: error loading shared libraries: libQtGui.so.4: cannot open shared object file: No such file or directory.
The issue is the cross-compiler (apt-get install gcc-arm-linux-gnueabi) is ARM based and this cross compiler has a newer glibc than on the ARM device. You can copy the libc from the cross compiler directory to your ARM device. I suggest testing with LD_LIBRARY_PATH, before updating the main libraries. Use ls /var/lib/dpkg/info/*arm-linux*.list to see most packages related to the ARM compiler. You can use grep to figure out where the libraries are (or fancier things like apt-file, etc).
Crosstool-ng has a populate script, but I dont see it in the Ubuntu packages; it is perfect for your issue. If it is present on your Debian version, I would use it.
The glibc 2.15 is backwards compatible with the glibc 2.11 which is currently on your system. Issues may arise if the compiler was configured with different options (different ABI); however if this is the case, you will have many issues with your built Qt besides the library. In this case, you need to find a better compiler which fits your root filesystem.
So to be clear, on the target
mkdir /lib/staging
cp libc.so-2.15 /lib/staging
cd /lib/staging
ln -s libc.so-2.15 libc.so
LD_LIBRARY_PATH=/lib/staging ls # test the library
You may have to copy additional libraries, such as pthread, resolv, rt, crypt, etc. The files are probably in a directory like sysroot/lib. You can copy the whole directory to the /lib/staging to test it. If the above ls functions, then the compilers should be ABI compatible. If you have a crash or not an executable, then the compiler and rootfs may not be compatible.
Would there have been a better way to provide the needed libraries, or copying them is fine?
Copying may be fine as per above. If it is not fine, then either the compiler or the root filesystem must be updated.
How can I get over the errors mentioned above?
Try the above method. As well, you maybe able to leave your root filesystem alone. Set-up a shadow directory and use chroot to run the Qt application with the copied files as another solution. To test this, make a very simple program and put it along the compiler libraries in a test directory, say /lib/staging as above. Then the test code can be run like,
$ LD_LIBRARY_PATH=/lib/staging ./hello_world
If this doesn't work, your compiler and the ARM file system/OS are not compatible. No library magic will help.
I've read something about building it static, but I am not sure how, and what are the downsides of this.
See Linux static linking is dead. I understand this seems like a solution. However, if the compiler is wrong, this won't help. The calling convention between OS, libraries and what registers are saved by the OS will be implicit in the compiled code. You may have to rebuild Qt with -softfp, etc.

How to install the program depending on libstdc++ library

My program is written in C++, using GCC on Ubuntu 9.10 64 bit. If depends on /usr/lib64/libstdc++.so.6 which actually points to /usr/lib64/libstdc++.so.6.0.13. Now I copy this program to virgin Ubuntu 7.04 system and try to run it. It doesn't run, as expected. Then I add to the program directory the following files:
libstdc++.so.6.0.13
libstdc++.so.6 (links to libstdc++.so.6.0.13)
Execute command:
LD_LIBRARY_PATH=. ./myprogram
Now everything is OK. The question: how can I write installation script for such program? myprogram file itself should be placed to /usr/local/bin. What can I do with dependencies? For example, on destination computer, /usr/lib64/libstdc++.so.6 link points to /usr/lib64/libstdc++.so.6.0.8. What can I do with this?
Note: the program is closed-source, I cannot provide source code and makefile.
If you're working on Ubuntu, making a .deb (Debian Package) seems to way to go. Here is a link to get you started.
Your package will state it depends on some other packages (typically the packages that includes libstdc++.so.6.0.13 - i guess the package name is something like libstdc++) and dependencies will be installed when you install your own package using dpkg -i <yourpackage>.deb.
Afterwards, you'll be able to uninstall it using dpkg -r <yourpackage>.
Anyway, never ship such standards files with your own archive. Dependencies exists for this exact purpose.
Hope it helps.
The real problem is that you try to install a binary that use newer versions os common libraries that the ones available on Ubuntu 9.10. The best option should be to make a specific target for the old Ubuntu 7.10 an compile it with the old libraries (that's a backport).
Then you should make two (or more) .deb packages, one for Ubuntu 9.10 and one for Ubuntu 7.10.
Another possibility is to continue doing what you are doing now : set LD_LIBRARY_PATH to point to the desired version of libstdc++ and other necessary libraries. You just set this environment variable in a launcher shell script. In you script you check if the new libraries are available or not and you set your LB_LIBRARY_PATH (say to /usr/local/lib/myprogram/) only if needed. But as others poster pointed out : that's a very bad practice. Anyway, never try to put these provided libraries at their standard place in Ubuntu 9.10, you would risk broking the target system and causing update problems for users or your program if these libraries are officially backported someday.
But if you choose to include your own set of system libraries there is still another way to go than the above one: just link these libraries statically. If a program is the only user of a library as it will probably be in the above scenario you'll lose all advantages of using a shared dynamic library, then why bother with using it at all ? And with stacically linked libraries you won't have to install them.