Making a shared library from existing object files - c++

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

Related

How can I override shared library in LD_LIBRARY_PATH with clang++?

I'm trying to compile a shared library I wrote in C++ to use a specific version of another shared library in the current directory, however it seems to be ignoring that and it uses the (older and incompatible) .so file in my LD_LIBRARY_PATH at runtime. How would I go about overriding the .so file it uses to use my own? I also need to retain the older version for another use on the same system.
Here's my command I'm using to compile: clang++ /data/openpilot/selfdrive/df/libs/libSNPE.so -lsymphony-cpu -lsymphonypower -I/data/openpilot/phonelibs/snpe/include -std=c++14 -lstdc++ -fPIC -o d_f.so dynamic_follow.cc -shared
/data/openpilot/selfdrive/df/libs/libSNPE.so being the library I want to use.
I also tried to use the -l flag before my library file, however it returns cannot find -l/data/openpilot/selfdrive/df/libs/libSNPE.so
Confirmed to still use the library in LD_LIBRARY_PATH with this command as well: clang++ -Wl,-rpath,/data/openpilot/selfdrive/df/libs -L/data/openpilot/selfdrive/df/libs -lSNPE -lsymphony-cpu -lsymphonypower -I/data/openpilot/phonelibs/snpe/include -std=c++14 -stdlib=libc++ -fPIC -o d_f.so dynamic_follow.cc -shared
The -L flag tells where to look for libraries at link time, while LD_LIBRARY_PATH tells where to look for libraries at run-time. So whatever path you set at link-time, this will be ignored when running the executable.
You need to have LD_LIBRARY_PATH include the directory of your dynamic library at run-time for your executable to find it. So you may run your executable like this:
LD_LIBRARY_PATH=/data/openpilot/selfdrive/df/libs:"$LD_LIBRARY_PATH" ./your-exec

How to compile all dependencies and shared libs into one binary

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.

g++ trying (failing) to link statically to libstdc++ for shared object

I'm trying to create a shared object using a number of .O files created with the -fPIC command. When I run g++ with the -shared argument it appears to be trying to statically link to the libstdc++.a library, which of course fails. I'm trying to figure out why it's automatically trying to link statically when I'm not using the -static-stdc++ argument.
when I try creating the shared object I get the error ...libstdc++.a(ios) relocate R_x86_64_325 against 'vtable for std::ios_base': cannot be used when making a shared object
I ran G++ with the -V argument and received and can see LD receives the argument -lstdc++.
When linking together a single shared object, you need to do this from existing .o files. You can not do this from existing .so files; this would link those .so files to your .so file, but not into your .so file. So gcc seeks out and finds an archive of .o files (.a) and tries to link them. But since those are not compiled for relocation (no -fPIC), these can not be used to create .so files.
Your options are:
dynamically link your .so to the libstdc++ (and thus make it depending on the .so file that is installed in the system)
build .o files for libstdc++ and compile them with -fPIC then compile from those your .so file (here it does not matter if you use the .o files directly or an ar archive)
For the first (that I would recommend) option the following will suffice (it is from a makefile that I use for creating malloc/free intercepting .so files)
gcc -shared -lstdc++ -o your.so yourfiles.o
I'll bet it's finding the static library first in its library search path, or ONLY finding the static library. Make sure that the appropriate version of the shared version is installed and can be found. You can probably truss your g++ run to hunt down the order in which it's opening libraries.

linking issue - trying to build a library and use another archive with it

Is it possible to build a library that uses another, already compiled library?
I have some make files that are used to normally build an executable. When making the executable, I use -L ../include/lib1.a to include the original library.
Now, I am building a separate program that is calling the classes from the executable, which was never built into a library, just compiled to the executable with a link like
${CPP} -c ${INC} ${CFLAGS} MyFile.cpp ${OBJ} ${LIB2} -lm
Where LIB2 includes the reference to lib1.a
Now I want to access the class MyFile.cpp directly, and when I build it to its own library lib2.a, and try to call it from the new program, I get a bunch of errors that the classes it references are missing. This is in spite of the fact that when building the new program I am linking in both lib1.a and lib2.a
Should:
-L../include/lib1.a
not be:
-L../include -llib1
I.e. -L denotes the library search path and -l the archive name?
Yes, you should be able to do it. It would be helpful to see the exact errors you are getting.
If you compile your sources into a library and supply the libraries they use on the command line, the compiler is liable to put the other library(s) into your new one. If that happens, and then someone tries to build a program against your library and those others, they will get a whole mess of "doubly-defined symbol" errors.
When you build lib2.a it will not contain the objects files contained in lib1.a.
Your final executable has to link in both of them.

How do I source/link external functions in C or C++?

EDIT: I suppose I should clarify, in case it matters. I am on a AIX Unix box, so I am using VAC compilers - no gnu compilers.
End edit
I am pretty rusty in C/C++, so forgive me if this is a simple question.
I would like to take common functions out of a few of my C programs and put them in shared libraries or shared objects. If I was doing this in perl I would put my subs in a perl module and use that module when needed.
For the sake of an example, let's say I have this function:
int giveInteger()
{
return 1034;
}
Obviously this is not a real world example, but if I wanted to share that function, how would I proceed?
I'm pretty sure I have 2 options:
Put my shared function in a file, and have it compile with my main program at compile time. If I ever make changes to my shared function, I would have to recompile my main program.
Put my shared function in a file, and compile it as a shared library (if I have my terms correct), and have my main program link to that shared library. Any changes I make to my shared library (after compiling it) would be integrated into my main program at runtime without re-compiling my main program.
Am I correct on that thinking?
If so, how can I complish either/both of those methods? I've searched a lot and I seem to find information how how I could have my own program link to someone else's shared library, but not how to create my own shared functions and compile them in a way I can use them in my own program.
Thanks so much!
Brian
EDIT: Conclusion
Thanks everyone for your help! I thought I would add to this post what is working for me (for dynamic shared libraries on AIX) so that others can benefit:
I compile my shared functions:
xlc -c sharedFunctions.c -o sharedFunctions.o
Then make it a shared object:
xlc -qmkshrobj -qexpfile=exportlist sharedFunctions.o
xlc -G -o libsharedFunctions.so sharedFunctions.o -bE:exportlist
Then link it another program:
xlc -brtl -o mainProgram mainProgram.c -L. -lsharedFunctions
And another comment helped me find this link, which also helped:
http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/topic/com.ibm.vacpp7a.doc/proguide/ref/compile_library.htm
Thanks again to all who helped me out!
Yeah you are correct. The first is called a static library, while the second is called a shared library, because the code is not bound to the executable at compile time, but everytime again when your program is loaded.
Static library
Compile your library's code as follows:
gcc -c *.c
The -c tells the program not to link the object file, but just leaves you with object files for each .c file that was compiled. Now, archive them into one static library:
ar rcs libmystuff.a *.o
man ar will tell you what the rcs options mean. Now, libmystuff.a is a archive file (you can open it with some zip-file viewers) which contain those object files, together with an index of symbols for each object file. You can link it to your program:
gcc *.c libmystuff.a -o myprogram
Now, your program is ready. Note that the order of where the static libraries appear in the command matter. See my Link order answer.
Shared library
For a shared library, you will create your library with
gcc -shared -o libmystuff.so *.c
That's all it takes, libmystuff.so is now a shared object file. If you want to link a program to it, you have to put it into a directory that is listed in the /etc/ld.so.conf file, or that is given by the -L switch to GCC, or listed in the LD_LIBRARY_PATH variable. When linking, you cut the lib prefix and .so suffix from the library name you tell gcc.
gcc -L. -lmystuff *.c -o myprogram
Internally, gcc will just pass your arguments to the GNU linker. You can see what arguments it pass using the -### option: Gcc will print the exact arguments given to each sub process.
For details about the linking process (how some stuff is done internally), view my Linux GCC linker answer.
You've got a third option. In general, your C++ compiler should be able to link C routines. The necessary options may vary from compiler to compiler, so R your fine M, but basically, you should be able to compile with g++ as here:
$ g++ -o myapp myapp.cpp myfunc.c giveint.c
... or compile separately
$ gcc -c myfunc.c
$ gcc -c giveint.c
$ g++ -c myapp.cpp
$ g++ -o myapp myapp.o myfunc.o
You also need to include your declaration of the functions; you do that in C++ as
extern "C" {
int myfunc(int,int);
int giveInterger(void);
}
You need to distinguish between recompiling and relinking.
If you put giveInteger() into a separate (archive) library, and then modify it later, you'll (obviously) need to recompile the source file in which it is defined, and relink all programs that use it; but you will not need to recompile such programs [1].
For a shared library, you'll need to recompile and relink the library; but you will not have to relink or recompile any of the programs which use it.
Building C++ shared libraries on AIX used to be complicated; you needed to use makeC++SharedLib shell script. But with VAC 5.0 and 6.0 it became quite easy. I believe all you need to do is [2]:
xlC -G -o shr.o giveInteger.cc
xlC -o myapp main.cc shr.o
[1] If you write correct Makefile (which is recommended practice), all of this will happen automatically when you type make.
[2] There is a certain feature of AIX which may complicate matters: by default shared libraries are loaded into memory, and "stick" there until subsequent reboot. So you may rebuild the shr.o, rerun the program, and observe "old" version of the library being executed. To prevent this, a common practice is to make shr.o world-unreadable:
chmod 0750 shr.o