Linux executable file as shared library - c++

I'm trying to compile an executable file which i want also to use as shared library. When i'm clearly compile and linking it as "executable" - everything fine - file could start and work correctly. At this phase i cant correctly linking other libraries with it (tons of redefinitions in log). When i'm trying to add options -Fpic -shared - program copiles successfully, but starting with segmentation fault. How can i make it executable and "sharedlibrary" at the same time?

A single file cannot be a shared library and an executable at the same time. But you can link your object files twice to make both. It'd go something like this:
g++ -c -o module.o module.cpp # create an object that has no main()
g++ -shared -fPIC -o libmodule.so module.o # build shared library
g++ -o program module.o main.cpp # build executable
Or instead, the last line could link the shared library (in which case you'll need the library present when you run the executable):
g++ -o program -l module main.cpp

Related

c++ shared library in custom directory is not found

I want to use a shared library (resides in a custom directory) into an executable.
I've created this makefile
all: SayHello
SayHello: compiledObjects/SayHello.o myLib/libNames.so
g++ compiledObjects/SayHello.o -o SayHello -Icommons -LmyLib -lNames
compiledObjects/SayHello.o: SayHello.cpp
g++ -c SayHello.cpp -o compiledObjects/SayHello.o
myLib/libNames.so: commons/Names.cpp commons/Names.h
g++ -shared -fPIC commons/Names.cpp -o myLib/libNames.so
That create correctly the executable and shared library infact I can Execute the program using this command
LD_LIBRARY_PATH=/custom/path/to/lib/myLib/libNames.so
./SayHello
How can I execute ./SayHello without specify LD_LIBRARY_PATH?
I'm not using any IDE and I'm on linux.
Use the -rpath option to link your executable. See the ld(1) manual page for more information.
P.S. Your makefile appears to have a bug. If you successfully make your program, and immediately run make again, looks like your makefile will attempt to recompile the program again, even though nothing has changed.
After all, the whole purpose of a makefile is to avoid doing unneeded compilations.
The SayHello.o build target should be compiledObjects/SayHello.o.
You need to tell g++ to pass the -rpath option to the linker using -Wl,-rpath. Also, you need to specify a path to the -rpath option.
Putting it all together your last build step should look like this:
SayHello: compiledObjects/SayHello.o myLib/libNames.so
g++ compiledObjects/SayHello.o -o SayHello -Icommons -LmyLib -lNames -Wl,-rpath=/custom/path/to/lib/myLib/
Relative RPATH:
If you want to specify an RPATH relative to your binary you should use
$ORIGIN as a placeholder: -rpath='$ORIGIN/rel/path'.

linker delets library and does not recognize it

I am compiling a C program with g++ and linking it to a library mylib.lib which is located in the same folder as the sourcecode by:
user$ g++ myprog.c -o mylib.lib
and the compiler behaves in a strange way. first of all it gives the error 'undefined reference to fun1' . this should not happen because fun1 is in mylib.lib. secondly it deletes mylib.lib . I also tried a different way:
user$ g++ myprog.c mylib.lib
In this case I get the same error: 'undefined reference to fun1'
Finally I tried to add mylib by:
renamed mylib.lib to libmylib.lib
2.
user$ g++ myprog.c -L/Dima/Tests -l mylib
In this case the error is 'cannot find lmylib' although it is located in /Dima/Tests. how do I compile it correctly?
You're not building a library, you are trying to create an executable program named mylib.lib. That's why the linker is invoked.
If you want to create a library, it depends on the toolchain you target, but generally speaking you only create object files, and create an archive of those object files.
For the GNU toolchain (GCC and the GNU binutils linker) you use the ar program to create this archive.
$ g++ mylib.c -c # Create object file named `mylib.o`
$ ar crv libmylib.a mylib.o # Create the static library
Now you have a static library containing the object file myprog.o which is compiled from myprog.c. To use it do something like
$ g++ myprog.c -L. -lmylib -o myprog
The above command tells the linker to look in the current directory (-L.) and link with the library mylib (the linker automatically looks for libmylib.a).
Also, when using the GNU linker it's important that you put the libraries after any source or object files.

Executing a binary with a shared library in linux

I am making a simple hello world program to learn about linking shared libraries in linux. I have managed to compile the main program into an executable with the shared library using the following:
g++ -fPIC -c lab2_hello_main.cpp <--create position independent objects
g++ -fPIC -c lab2_hello_sub.cpp
g++ -fPIC -shared -Wl,-soname=libfuncs.so.1.0 *.o -o libfuncs.so.1.0 -lc <--make the shared library
ln -s libfuncs.so.1.0 libfuncs.so <-- soft links for compiling and running
ln -s libfuncs.so.1.0 libfuncs.so.1
g++ -o hello_dyn lab2_hello_main.cpp -L/mypath -lfuncs <-- Linking the library to main
When I do an ldd on hello_dyn I get an output stating that the library can't be found:
"libfuncs.so.1.0 => not found"
The other libraries it looks for automatically are fine.
Anyone know why this might be?
Your shared library's location is not in the linker's search path. You can confirm this by adding the directory in which your library is located to the LD_LIBRARY_PATH environment variable and then run ldd again. See the ld.so(8) man page for details.

C++ multi-stage linking

Ok, so this might not be a great question, but I'm a bit stuck.
I have 3 programs:
pegio.c/pegio.h - Does hardware initialization and functions for my device
PegIOHandler.cpp/PegIOHandler.h - Handles I/O for device
PegRTU.cpp - Main function
My project implements the opendnp3 (which allows one to transmit data using the DNP3 protocol) library.
Now, to compile it I first compile the pegio.c file
gcc -c pegio.c -o pegio.o
Easy, up to here I understand.
Secondly I compile the IOHandler and reference pegio.c as it uses it.
g++ -c PegIOHandler.cpp pegio.c -o PegIOHandler.o -std=c++0x
Now it gives me the following output.
g++: warning: pegio.o: linker input file unused because linking not done
But, it still creates the object file. HOWEVER, PegIOHandler implements opendnp3 header files, which is included in PegIOHandler.cpp and PegIOHandler.h. When I attempt to compile these files without using the '-c', it tells me that there are undefined references to the opendnp3 files. I know I have to link them to my project, but how do I do that?
Then compililing my third and final file:
g++ PegRTU.cpp pegio.o PegIOHandler.o -o pegrtu -std=c++0x
This now tells me that there are undefined references to the opendnp3 files.
So: How do I link the opendnp3 library to my project / code files???
Thanks!
Ouch. So many misunderstandings. You don't need the previously compiled object files to compile further source files to object code. However, you do need to link them together at the end of the compilation process, including any libraries required. All in all:
gcc -c pegio.c -o pegio.o
g++ -c PegIOHandler.cpp -o PegIOHandler.o -std=c++0x
g++ -c PegRTU.cpp -o PegRTU.o -std=c++0x
g++ -o executable_name *.o -lopendnp3 # or whatever linker flag is needed for OpenDNP3
And pretty please, read this.

How to create a shared library (.so) in an automake script?

Given some source file test.cpp I would like to create a shared library libtest.so . I am trying to do this within the scope of an automake file however I cannot seem to get this to work.
For example under g++ I do the following:
g++ -shared -fPIC test.cpp -o libtest.so
Then I can create another file that will depend on the shared library as follows:
g++ mytest.cpp libtest.so -o blah
I have read that automake only supports making shared libraries via libtool. I have tried to get my automake script to work as follows but it never seems to produce an .so . The closest I have gotten is for it to produce an .la and .o file:
In configure.ac:
AC_ENABLE_SHARED
AC_DISABLE_STATIC
AC_PROG_LIBTOOL(libtool)
in Makefile.am
lib_LTLIBRARIES=libtest.la
libtest_la_SOURCES=test.cpp
libtest_la_CFLAGS=-fPIC
libtest_la_CPPFLAGS=-fPIC
libtest_la_CXXFLAGS=-fPIC
libtest_la_LDFLAGS= -shared -fPIC
Could someone give me an example of building an .so based on the above?
If you just put LT_INIT in configure.ac and in Makefile.am, do:
lib_LTLIBRARIES = libtest.la
libtest_la_SOURCES = test.cpp
libtest_la_LDFLAGS = -version-info 0:0:0
you should get a .so. You should not specify -fPIC to CFLAGS, etc. The -version-info
specifier is not necessary, but is a good idea.