How to compile all dependencies and shared libs into one binary - c++

I want to compile all dependencies etc and shared libraries into the binary?
How to do that?
g++ -std=c++11 txtocr.cpp -o txtocr -llept -ltesseract
Tesseract depends on leptonica and some shared tesseract libraries.. But how to compile everything into the binary so it would be 100% portable

I believe the answer is "It depends". If you only have the shared library without the code of the library I am afraid the answer will be NO as not all information you need in order to build a static application are within your dynamic library.

Related

Linking OpenSSL into a dynamic library

I'm trying to static link OpenSSL into my program.
It works fine when linking into the executable. I need to use OpenSSL in a shared library (so, or dll) that I dynamically load later on when the process executes.
Trying to statically link OpenSSL into the shared library causes errors due to OpenSSL not being compiled with -fPIC. Is it possible to do this without recompiling openssl?
Also, is there a better way to do this?
I'm trying to static link OpenSSL into my program.
In this case, its as simple as:
gcc prog.c /usr/local/lib/libssl.a /usr/local/lib/libcrypto.a -o prog.exe -ldl
It works fine when linking into the executable.
Devil's advocate... Does it work fine with Position Independent Code (PIE)? PIE on a program is the equivalent to PIC on a shared object (some hand waiving).
gcc -fPIE prog.c /usr/local/lib/libssl.a /usr/local/lib/libcrypto.a -o prog.exe -ldl
According to the GCC folks, you can compile with fPIC, and then build a shared object with -fPIC or a relocatable executable with -fPIE. That is, its OK to use -fPIC for both.
Trying to statically link OpenSSL into the shared library causes errors due to OpenSSL not being compiled with -fPIC.
That's easy enough to fix. You simply specify shared in configure:
./config shared no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl
make
sudo make install
I think you can also (notice the lack of shared):
export CFLAGS="-fPIC"
./config no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl
make
sudo make install
not being compiled with -fPIC. Is it possible to do this without recompiling openssl?
NO, you have to compile with PIC to ensure GCC generates relocatable code.
Also, is there a better way to do this?
Usually you just configure with shared. That triggers -fPIC, which gets you relocatable code.
There's other things you can do, but they are more intrusive. For example, you can modify Configure line (like linux-x86_64), and add -fPIC in the second field. The fields are separated by colons, and the second field is $cflags used by the OpenSSL build system.
You can see an example of modifying Configure at Build OpenSSL with RPATH?

Static and Dynamic/Shared Linking with MinGW

I want to start with a simple linking usage to explain my problem. Lets assume that there is a library z which could be compiled to shared library libz.dll(D:/libs/z/shared/libz.dll) or to static library libz.a (D:/libs/z/static/libz.a).
Let I want to link against it, then I do this:
gcc -o main.exe main.o -LD:/libs/z/static -lz
According to this documentation, gcc would search for libz.a, which is
archive files whose members are object files
I also can do the following:
gcc -o main.exe main.o -LD:/libs/z/shared -lz
It is not mentioned in the documentation above that -l flag will search for lib<name>.so.
What will happen if I libz.a and libz.dll will be in the same directory? How the library will be linked with a program? Why I need the flags -Wl,-Bstatic and -Wl,-Bdynamic if -l searches both for shared and static libraries?
Why some developers provide .a files with .dll files for the same modules, if I compile a shared library distribution?
For example, Qt provides .dll files in bin directory with .a files in lib directory. Is it the same library, but built like shared and static, respectively? Or .a files are some kind of dummy libraries which provide linking with shared libraries, where there are real library implementations?
Another example is OpenGL library on Windows. Why every compiler must provide the static OpenGL lib like libopengl32.a in MingW?
What are files with .dll.a and .la extensions used for?
P.S. There are a lot of questions here, but I think each one depends on the previous one and there is no need to split them into several questions.
Please, have a look at ld and WIN32 (cygwin/mingw). Especially, the direct linking to a dll section for more information on the behavior of -l flag on Windows ports of LD. Extract:
For instance, when ld is called with the argument -lxxx it will attempt to find, in the first directory of its search path,
libxxx.dll.a
xxx.dll.a
libxxx.a
cygxxx.dll (*)
libxxx.dll
xxx.dll
before moving on to the next directory in the search path.
(*) Actually, this is not cygxxx.dll but in fact is <prefix>xxx.dll, where <prefix> is set by the ld option -dll-search-prefix=<prefix>. In the case of cygwin, the standard gcc spec file includes -dll-search-prefix=cyg, so in effect we actually search for cygxxx.dll.
NOTE: If you have ever built Boost with MinGW, you probably recall that the naming of Boost libraries exactly obeys the pattern described in the link above.
In the past there were issues in MinGW with direct linking to *.dll, so it was advised to create a static library lib*.a with exported symbols from *.dll and link against it instead. The link to this MinGW wiki page is now dead, so I assume that it should be fine to link directly against *.dll now. Furthermore, I did it myself several times with the latest MinGW-w64 distribution, and had no issues, yet.
You need link flags -Wl,-Bstatic and -Wl,-Bdynamic because sometimes you want to force static linking, for example, when the dynamic library with the same name is also present in a search path:
gcc object1.o object2.o -lMyLib2 -Wl,-Bstatic -lMyLib1 -Wl,-Bdynamic -o output
The above snippet guarantees that the default linking priority of -l flag is overridden for MyLib1, i.e. even if MyLib1.dll is present in the search path, LD will choose libMyLib1.a to link against. Notice that for MyLib2 LD will again prefer the dynamic version.
NOTE: If MyLib2 depends on MyLib1, then MyLib1 is dynamically linked too, regardless of -Wl,-Bstatic (i.e. it is ignored in this case). To prevent this you would have to link MyLib2 statically too.

Linux based OS with static libraries: what can I do?

I have a linux based OS with a lot of system libraries compiled as static libraries.
How can I use such libraries in my application, and link them to my final binary?
You use them as you do use shared libraries, except that you link against statically. An introduction to GCC - shared libraries and static libraries article will get you started.
I've trouble to understand. If you are linking with something like
g++ -o myprog myprog.o obj1.o obj2.o -L/path/to/lib -L/path2/to/lib -llib1 -llib2 -lib3
the linker called through the gcc or g++ wrapper will do "the right thing(tm)", if liblib1.so exist in the library path (/path/to/lib, /path2/to/lib plus a set of system specific directories where system libraries probably are), it will be linked dynamically, if not liblib1.a will be linked statically. The only thing to be aware of, is that if there are mutual dependencies in static libaries (lib1 needs lib2 and lib2 needs lib1), you may need to repeat them several times or use the --start-group and --end-group options of ld to mark libraries which needs to be considered together.

Making a shared library from existing object files

I have a project in my IDE. I need to make a shared library of it to use in extensions. I don't want to make a copy of this project with shared-library settings. Is there any way to build a shared library using the object files (.o) from my already existing project? As I understand, I can write a makefile for this.
I assume you're on some sort of Unix and are probably using the GNU toolchain. In that case, to create a proper shared library, you'd need to compile your code using the position-independent code flags (-fpic or -fPIC) before you can create a shared library. Unless your .o files are already compiled with those flags, chances are you won't end up with a working shared lib.
If they already are compiled for position independent code, the usual g++ -shared ... should do the trick.
g++ -shared -fPIC -o myshared.so *.o

Creating dummy shared object (.so) to depend on other shared objects

I'm trying to create a shared object (.so) that will make it so, by including one shared object with -lboost, I implicitly include all the boost libraries. Here's what I tried:
#!/bin/sh
BOOST_LIBS="-lboost_date_time-gcc43-mt -lboost_filesystem-gcc43-mt"
#truncated for brevity
g++ $BOOST_LIBS -shared -Wl,-soname,libboost.so.1 -o libboost.so.1.0
ln -si libboost.so.1.0 libboost.so.1
ln -si libboost.so.1 libboost.so
After placing all 3 created files (libboost.so libboost.so.1 libboost.so.1.0) in the same directory as all the boost libraries, I tried compiling a test program with it (which depends on -lboost_date_time-gcc43-mt):
g++ -lboost test.cpp
Doing this, I got the same undefined reference message as not having -lboost. Having -lboost_date_time-gcc43-mt works, but that's too wordy :) How do I get -lboost to automatically bring in the other shared libraries?
You don't. Not really, anyway.
The linker is stripping out all of the symbol dependencies because the .so doesn't use them.
You can get around this, perhaps, by writing a linker script that declares all of the symbols you need as EXTERN() dependencies. But this implies that you'll need to list all of the mangled names for the symbols you need. Not at all worth the effort, IMO.
I don't have a solution for creating a dummy '.so', but I do have something that will simplify your life... I highly suggest that you try using cross-platform make (CMake). In CMake, linking against those libraries is easy:
FIND_PACKAGE(Boost 1.37 COMPONENTS date_time filesystem REQUIRED)
ADD_EXECUTABLE(myexecutable ${myexecutable_SRCS})
TARGET_LINK_LIBRARIES(myexecutable ${Boost_LIBRARIES})
The commands above, if placed in a "CMakeLists.txt" file, is all you need to:
Verify that Boost 1.37 or later is installed, with the "date_time" and "filesystem" libraries installed.
Create an executable named "myexecutable" from the sources listed in the corresponding variable.
Link the executable "myexecutable" against the boost "date_time" and "filesystem" libraries.
See also: Why the KDE project switched to CMake.
Actually, making one .so depend on all boost .so files is quite possible (but might not actually help you). I've just tried this:
$ export BOOST_ROOT=/home/ghost/Work/Boost/boost-svn
$ g++ -shared -Wl,-soname,libboost.so -o libboost.so $BOOST_ROOT/stage/lib/libboost_program_options.so
$ g++ -L . -I $BOOST_ROOT first.cpp -lboost -Wl,-R$BOOST_ROOT/stage/lib
$ LD_LIBRARY_PATH=.:$BOOST_ROOT/stage/lib ./a.out
And it did work. However, note that dancing with -R and LD_LIBRARY_PATH. I don't know an way how you can include the path to Boost .so inside your libboost.so so that they are used both for linking and actually running the application. I can include rpath inside libboost.so just fine, but it's ignored when resolving symbols for the application.