I built a dynamic library (.so file) on Ubuntu 12.04. Let's call it test.so. I had a test.cpp file, which calls some library functions. I first compiled test.cpp into test.o by:
g++ test.cpp -o -c test.o
It succeeded. Then I compiled test.o into test.so by:
g++ -shared test.o -o test.so
Also succeeded.
I did the similar thing but on Mac OS X.
I first got test.o by:
g++ test.cpp -o -c test.o
Then
g++ -dynamiclib test.o -o test.dylib
This failed, because I didn't provide the libraries that are used in test.cpp. I modified it:
g++ -dynamiclib test.o -o test.dylib -L/path/to/libraries -lLibraryName
Then it works.
Notice that for the first case, I didn't provide such a path to the libraries and the specific library used in test.cpp. Does someone know why I don't need to in the first case but need to in the second case?
The linker, with default options, does not behave the same on Linux and OSX. To get OSX linking to behave more like what you expect on linux, use the following link flag.
-Wl,-undefined,dynamic_lookup
Related
I have a source file, mything.cpp, and a library that was provided to me as notmine.h and notmine.a.
I need to produce a shared object that has all my stuff from mything.cpp and all the stuff from somelib.a. Here is what I did on the command line:
g++ -fpic -c -o mything.o mything.cpp
g++ -shared -o mything.so mything.o notmine.a
However, when I look at the final mything.so using ldd I see that it has a dependency on libnotmine.so, and when I check nm, I see that all the symbols that should have been supplied by notmine.a are undefined.
What am I doing wrong?
More details: notmine.a is actually liblua.a that I built locally. I think g++ might be getting confused because there is a liblua.so in the system directories
Finally figured it out. There are two options. The simpler is to use:
g++ -fpic -c -o mything.o mything.cpp
g++ -shared -o mything.so mything.o -L. -l:notmine.a
Alternatively, you can tell the linker you want to treat the .a as a bunch of object files with
g++ -fpic -c -o mything.o mything.cpp
g++ -shared -o mything.so mything.o -Wl,--whole_archive notmine.a -Wl,--no-whole-archive
The --Wl,-no-whole-archive is to prevent that flag from messing up the other steps the linker does with the system libraries
Problem
Say I've got a Linux executable MAIN that uses an old version of some shared library LIB.so (which it locates using LD_LIBRARY_PATH).
I'd like MAIN to also use my library MYLIB.so, except this uses a newer version of LIB.so.
MAIN and MYLIB.so both use functions that appear in both versions of LIB.so with the same name (but different implementations).
How do I get the application to also load the new version of LIB.so when it loads MYLIB.so?
What doesn't seem to work
I've tried compiling MYLIB.so with an RPATH option pointing to the new version of the library. However, while this correctly identifies the newer library when I run ldd MYLIB.so, when the application runs it only uses the old library implementation.
My compilation (using single file toy implementations for clarity) is as follows:
# compile old library implementation
g++ -c -Wall -Werror -fpic library_old.cpp
g++ -shared -o liblib.so library_old.o
# compile new library implementation
g++ -c -Wall -Werror -fpic library_new.cpp
g++ -shared -o new/liblib.so library_new.o
# compile my library against new liblib
g++ -c -Wall -Werror -fpic my_library.cpp
g++ -L`pwd`/new -shared -Wl,-rpath,`pwd`/new -o libmine.so my_library.o -llib
# compile application against old liblib
g++ -L`pwd` -Wall -Werror -o main main.cpp -llib -lmine
export LD_LIBRARY_PATH=`pwd`
I'm trying to learn how to build and use dynamic library in a c++ program. Everything is fine and my program run well when I launch it from Terminal (I'm on a mac OS X El Capitan). Surprisingly that's not the case when I try to launch it by clicking on the executable. I get a dyld: Library not loaded: liblibrary.so, Reason: image not found error.
All my files are in a same repertory. I build them with commands :
g++ -c -fPIC A.cpp
g++ -c -fPIC B.cpp
g++ -shared -fPIC A.o B.o -o library.so
g++ main.cpp library.so -o Program
Thank's in advance for your help.
I tried the following solutions :
Add a PATH, both in LD_LIBRARY_PATH and DYLD_LIBRARY_PATH
Change the library extention : library.so or library.dylib
Add an rpath g++ main.cpp library.so -Wl,-rpath,. -o Program and g++ main.cpp library.so -Wl,-rpath,$HOME/my_dir -o Program
You may need to give an explicit rpath (as an absolute path, not a relative one) at compile time (e.g. with g++ -Wall -Wl,-rpath,$HOME/yourdir main.cpp library.so -o Program), or setup some DYLD_LIBRARY_PATH, see this. You could need a .dylib suffix, not a .so one.
(I don't have any MacOSX any more, so I forgot the details)
Finally, I found the solution. Actually, dynamic library creation is different for macOS. What I tried since the beginning is only working for Linux.
So the Mac solution is:
g++ -dynamiclib -install_name "absolute_path/library.dylib" A.o B.o -o library.dylib
where:
-dynamiclib is the Mac equivalent for -shared.
-install_name "absolute_path/library.dylib" create an alias of library.dylib for the linker which is necessary to use library.dylib.
After that, the traditional command:
g++ main.cpp library.dylib -o Program
creates the executable if main.cpp and library.dylib are in the same directory.
The program can then be used everywhere in the system as long as library.dylib stays in the same place.
Following the comment of #Ssswift, relative path linking can be achieved with the command:
g++ -dynamiclib -install_name "#executable_path/library.dylib" A.o B.o -o library.dylib
The library can then follow the executable.
Thanks for your help.
I'm trying to run a simple makefile that looks like this:
T=-ansi -pedantic -Wall -Werror
a.out: test.o extra.o
gcc $(T) -c test.o extra.o
test.o: test.c test.h
gcc $(T) -c test.c
extra.o: extra.c extra.h
gcc $(T) -c extra.c
clean:
rm *.o a.out
But I seem to be getting warnings telling me that "linker input file unused because linking not done"
I tried removing the "-c" from the a.out directive, after the gcc, but that produced to give me more problems. I'm not sure how to go about proceeding from here, any ideas/input would be much appreciated.
EDIT: I'm running the program by "make -T", also removing the -c from a.out, causes the error" invalid symbol index"
You need to remove the -c from the a.out command:
a.out: test.o extra.o
gcc $(T) test.o extra.o
or, better:
a.out: test.o extra.o
gcc $(T) -o $# test.o extra.o
or, still better:
extra: test.o extra.o
gcc $(T) -o $# test.o extra.o
The error message is normally because you specify something like -lm on a command line with -c, but you're not doing that here. OTOH, you are listing object files with the -c option — that'll generate the warning:
gcc -ansi -pedantic -Wall -Werror -c test.o extra.o
^ this one, here
Those .o files are the linker inputs, but you're not linking. Drop the -c and you will generate a.out. That should proceed OK.
I think this is the first time I've seen a makefile used to build a.out. It is unusual in the extreme — not precisely wrong, but definitely not the way you normally use make. It has built-in rules to build programs from single source files, such as example from example.c. Normally, you give a program a meaningful name based on one of the source files. Note that creating a program test is usually a bad idea; there is a standard test command built into the typical shell and confusion is rampant.
I compiled LD_PRELOAD which uses boost (locks.hpp). Compile was successfull. I copied this LD_PRELOAD to other linux server, and when i run, error:
/usr/bin/java: symbol lookup error: /test/test.so: undefined symbol:
_ZN5boost11this_thread20disable_interruptionC1Ev
How can i fix this? Can i avoid this problem without installing boost on this server?
How i compile LD_PRELOAD:
g++ -fPIC -m32 -shared -Wl,-soname,test.so -ldl -o test.so test.cpp
Thanks!
It seems you have to get libboost_thread into your test.so file. Something along the lines of:
g++ -fPIC -m32 -shared -Wl,-soname,test.so -ldl -o test.so test.cpp \
/usr/lib/libboost_thread.a -lpthread
Since I wouldn't know the specifics for your system, the boost library might be in a different place than from mine.