Dynamically linking SQLCipher on OS X with C++ - c++

I originally wanted to compile SQLCipher statically since it seems like it is easier to link up, but I have been unsuccessful at that. The only place I can find that discusses compiling SQLCipher on OS X is this blog post, but even he was not able to get the static compiling to work.
I was able to get the dynamic compiling working for the SQLCipher and I am able to use the sqlcipher command line program as mentioned in the blog, but now I want to use sqlcipher in a compiled C++ program. I have never dealt directly with dynamic compiling in the command line so I am a bit lost.
It looks like it produces a libtool file libsqlcipher.la so I am wondering how I should import it in C++ #include "libsqlcipher.h"? Looking around at tutorials for libtool they mostly mention how to compile it but I have not found any simple examples of how to link it.
I attempted something like this based on what I saw but I got a couple of errors:
libtool g++ -o test EncryptDatabases.cpp sqlcipher/libsqlcipher.la
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't open file: g++ (No such file or directory)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: EncryptDatabases.cpp is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: sqlcipher/libsqlcipher.la is not an object file (not allowed in a library)

Not an answer yes, but too long for a comment.
As far as I remember first libtool should be explicitly told to compile source file into a "library object":
libtool --mode=compile g++ -c EncryptDatabases.cpp -o EncryptDatabases.lo
then it should link the binary:
libtool --mode=link g++ -o test EncryptDatabases.lo sqlcipher/libsqlcipher.la
See the docs

Related

C++ Executable cannot find library at runtime, even though it's in /usr/lib (On Linux)

I'm creating a game in c++ with the Panda3D framework on Ubuntu. All of the Panda3D shared libraries are in /usr/lib/panda3d and all of the headers are in /usr/include/panda3d. I'm compiling with SCons, but I've tried it with gcc and it's the same, so here are the commands:
g++ -o src/main.o -c -fPIC -O2 -std=gnu++11 -I/usr/include/python2.7 -I/usr/include/panda3d -Iinclude src/main.cpp
g++ -o Test src/main.o -L/usr/lib/panda3d -lp3framework -lpanda -lpandafx -lpandaexpress -lpandabullet -lp3dtoolconfig -lp3dtool -lp3direct -lpthread
And here is the error I get when I run the executable:
./Test: error while loading shared libraries: libp3framework.so.1.11: cannot open shared object file: No such file or directory
There isn't much in the code, just initializing a Panda3D window, so I doubt that's the culprit.
As I said before, the libraries are in /usr/lib/panda3d, I've checked about a million times now and it's driving me crazy. I can't think of a single reason why I would get this error. Any help is appreciated :)
Edit:
I was looking through my files and there's a panda3d.conf file in /etc/ld.so.conf.d with one line: /usr/local/lib/x86_64-linux-gnu/panda3d. Does this have anything to do with it?
Edit #2:
I used the path in the above edit as the library path and got the same results, unfortunately.
I can't think of a single reason why I would get this error.
The reason is very simple: the dynamic loader hasn't been told to look in /usr/lib/panda3d for shared libraries, and so doesn't.
You can run your program with:
LD_DEBUG=files,libs ./Test
and observe which directories the loader is searching.
panda3d.conf ... with one line: /usr/local/lib/x86_64-linux-gnu/panda3d
That is the wrong directory (or at least not the one where your libraries are).
One way to fix this is to correct the above path to /usr/lib/panda3d and run sudo ldconfig.
Another way is to add -Wl,-rpath=/usr/lib/panda3d to your link line.

Compiling an external library on Linux

Good Day Everyone,
N.B - This problem has been solved - I have provided my own solution in the answer section however the solution provided by Jonathan is much shorter. Nevertheless, this was the following question I originally posted:
I am basically trying to compile a serial library (for UART communication) on Linux however I am not really sure how to correctly compile (I have mentioned what I have done so far below), any suggestions would be highly valuable. I am using the serialib library - which is composed of 2 main files (serialib.h and serialib.cpp) , you may directly view the source code of these files here (scroll all the way to the bottom and view the files in new tabs): http://serialib.free.fr/html/classserialib.html
I transferred these files (serialib.h and serialib.cpp) to my BeagleBone Black micro-controller which is running Debian (Wheezy) , g++/gcc (Debian 4.6.3-14) 4.6.3. I wrote my own program (uart.cpp is my file name) to access the functions provided by this library, this is what I wrote:
#include <iostream>
#include "serialib.h"
#ifdef __linux__
#define DEVICE_PORT "/dev/ttyO1"
#endif
int main()
{
serialib LS;
return 0;
}
So as you can see I am trying to access the 'seriallib' class. serialib.h, serialib.cpp and uart.cpp are all in the home directory. I also manually added the iostream library in serialib.cpp as I did not see it being declared in the original source code.
Now I am really unsure of how to compile such external libraries but so far I tried the following steps:
g++ -c -Wall -Werror -fPIC serialib.c to convert to PIC which gives the following error:
distcc[3142] (dcc_parse_hosts) Warning: /home/debian/.distcc/zeroconf/hosts contained no hosts; can't distribute work
distcc[3142] (dcc_zeroconf_add_hosts) CRITICAL! failed to parse host file.
distcc[3142] (dcc_build_somewhere) Warning: failed to distribute, running locally instead
g++ serialib.cpp -L /home/debian/serialib.h which gives the following error:
/usr/lib/gcc/arm-linux-gnueabihf/4.6/../../../arm-linux-gnueabihf/crt1.o: In function _start':
(.text+0x30): undefined reference tomain'
collect2: ld returned 1 exit status
distcc[3210] ERROR: compile serialib.cpp on localhost failed
As of now I am still finding out how to compile this and if I manage to work this out then I'll post my solution here too. Once again any suggestion will be highly valuable. Thank you all :) .
g++ -c -Wall -Werror -fPIC serialib.c to convert to PIC which gives the following error:
The "error" is not an error, it's a warning, telling you that your distcc setup is broken, but that it compiled locally.
That command doesn't "convert to PIC", it compiles the file serialib.c and produces a compiled object file, serialib.o
g++ serialib.cpp -L /home/debian/serialib.h
This is just nonsense. It tries to build a program from serialib.cpp and use the directory /home/debian/serialib.h (which isn't a directory!) to find libraries.
You don't need to "compile a library" you can just compile both the source files and link them together into a program. Either:
g++ -c serialib.cpp
g++ -c uart.cpp
g++ serialib.o uart.o -o uart
Or all in one command:
g++ serialib.cpp uart.cpp -o uart
You should read An Introduction to GCC to understand the commands, not just enter bogus commands without understanding them.
I have found a solution to this problem, hope this helps for all the future readers with similar problems. I have my own source code uart.cpp (Given in the question) which I want to compile, the external library is serialib that contains two main files (serialib.h and serialib.cpp), you will want to replace the following commands with respect to the files you have
Step 1: Compiling with position independent code
g++ -c -Wall -Werror -fpic serialib.cpp
Step 2: Creating a shared library
g++ -shared -o libserialib.so serialib.o , here the library is libserialib.so.
Step 3: Linking your source code with library
g++ -L /home/debian -lserialib uart.cpp -o uart
g++ -L /home/debian -Wall -o test uart.cpp -lserialib
You may save the library at a different path and you may have a different name of course. Suppose you have a library called libabc.so at the directory /home/user/myDir then the commands will be like:
g++ -L /home/user/myDir -labc your_code.cpp -o your_code
g++ -L /home/user/myDir -Wall -o test your_code.cpp -labc
test is out own program, lserialib is actually looking for libserialib.so and not serialib.o as gcc/g++ assumes all libraries start with lib and end with .so or .a and you can see the same goes for labc as it will look for libabc.so thus it is important to make sure your library name begins with lib and ends with .so or .a
Step 4: Making library available at run time
Here we provide the path where the library is actually stored, I saved it in the directory /home/debian which is why my command looks like:
export LD_LIBRARY_PATH=/home/debian:$LD_LIBRARY_PATH
if your library is saved at /path/to/file then the command will look like:
export LD_LIBRARY_PATH=/path/to/file:$LD_LIBRARY_PATH
This is to help the loader find the shared library and to view this path: echo $LD_LIBRARY_PATH and to unset this: unset LD_LIBRARY_PATH
To execute the program type either ./test or ./uart and in case of any modification to the main source code (uart.cpp in this case) , simply repeat step 3. I found the following link very useful: http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html . Thank you to all of you who took time to read this question and especially those who gave me suggestions. If anyone has more or better solutions, feel free to post them here to assist future readers :).

Can't make executable portable

I made a little c++ program with this library: http://libtins.github.io
I compile with: g++ -o arp arp.cpp -ltins
It runs fine (Ubuntu 14.04 64 bit), however if i send the executable to a friend, he gets this error when running:
error while loading shared libraries: libtins.so.3.4: cannot open shared object file: No such file or directory
I've looked up on stackoverflow and found something about statically linking and dynamically linking, also tried some g++ arguments but no success.
Is it even possible, to create a binary that "contains" the shared object itself?
Thanks
You can use -static to link the libraries statically.
g++ -o arp arp.cc -ltins -static
To build libtins statically, you could refer to the following section in its README:
Static/shared build
Note that by default, only the shared object is compiled. If you would
like to generate a static library file, run:
cmake ../ -DLIBTINS_BUILD_SHARED=0

Executing cross-compiled C++ program using Boost on Raspberry Pi

I have built a GCC cross toolchain for the RPi and can cross-compile C++ source and successfully run it after copying the executable to the RPi.
Next I built the Boost libraries targeting ARM, using the cross toolchain. I can successfully build and link C++ source to those Boost libraries using the cross toolchain on my PC.
I then copied the program, dynamically linked to Boost, to the RPi and copied all built libraries into /usr/local/lib on the Pi. However, executing fails:
$ ./my_program
./my_program: error while loading shared libraries: libboost_system.so.1.60.0: cannot open shared object file: No such file or directory
Again, this library, libboost_system.so.1.60.0, exists in /usr/local/lib.
I also tried
export LD_LIBRARY_PATH='/usr/local/lib'
but that doesn't change anything. What am I doing wrong?
EDIT:
I build all source files like this (rpi-g++ is a symlink to my cross-compiler):
rpi-g++ -c -std=c++1y -Wall -Wextra -pedantic -O2 -I /path/to/cross/boost/include *.cpp
rpi-g++ -o myprog *.o -L /path/to/cross/boost/lib/ -lboost_system -pthread
EDIT 2:
When linked with
rpi-g++ -o myprog *.o -L /path/to/cross/boost/lib/ -rdynamic -lboost_system -pthread
the problem remains the same. I have checked and verified everything suggested by Technaton as well. Strangely, ldd insists that the created executable is "not a dynamic executable" (checked that on my PC and on the RPi), which doesn't make sense to me.
There are several things you can check. I've posted a complete check list here, but judging from your linker command line, number 5 is probably the culprit.
Check that your library and your program are correctly build for the target architecture. You can verify that by using file ./myprog and file libboost_system.so.1.60.0.
Make sure that you have copied the actual shared object, and not a link to it.
Ensure that the shared object file's permissions are sane (0755).
Run ldconfig -v and check that your shared object file is picked up. Normally, /usr/local/lib is in the standard library search path, and LD_LIBRARY_PATH is not required.
Make sure that your program is actually dynamically linked by running ldd ./myprog. Judging from your linker command line, that is the problem: You're missing -rdynamic.
Check the paths returned from ldd: If you have linked with rpath, the library search path might be screwed up. Try again without -rpath.

Statically linking matio library using g++

How do you statically link matio, a library for reading mat-files, mainly used by matlab and octave into an executable?
If the file main.cpp holds matio functionality the compiler call
g++ -o main main.cpp -Imatio/include matio/lib/libmatio.a
fails with a bunch of error messages like: undefined reference to `inflateEnd'. This can be resolved by also adding zlib to the compiler call:
g++ -o main main.cpp -Imatio/include matio/lib/libmatio.a -lz
Now the error messages differ with something like undefined reference to `__intel_sse2_strlen'. So it appears that the zlib library is necessary for the comilation.
I now have the following questions:
What do you need to do to statically link the matio library in an executable?
Why do I need to add the zlib library even though I configured and compiled matio with ./configure --without-libz?
To build matio without zlib you apparently need to invoke configure with
./configure --with-zlib=no
(Checked this from configure.ac and config/matio_zlib.m4.)
In case you want to build matio with icc, Intel's developer pages tell that __intel_sse2_strlen is defined in libirc.a on Linux and libirc.lib on Windows.
To compile matio with the gcc do
./configure --with-zlib=no CC=gcc
afterwards, the matio library is statically linkable with the call posted in the question