C++ - building static library question - c++

I built libbz2 (static variant) using MinGW (GCC 4.5.0) compilation system and now try to import this library into my MSVS2008 project.
I've done these things already and everything worked fine, for example, with zlib (which means that created C libraries are actually interchangeable).
However, when doing the same with libbz2, I face some unknown troubles - when I compile my MSVS2008-project I receive the following error on linking stage:
unresolved external symbol ___chkstk referenced in function _bzopen_or_bzdopen
I don't know why this happens (I think it's because some basic C runtimes are not fully compatible), but maybe someone knows how to fix this kind of error?
Maybe there is a manual way to somehow merge the implementation of MinGW-based ___chkstk into libbz2 static library?
Thank you.

I read your answer, but I think there's an easier (automatic) way of doing the manual merging of object files: use the CFLAG -static-libgcc, which will link in the necessary functions (what you are describing and doing manually).

Thanks everyone, I found the answer.
Basically, you can simply link to libgcc.a / libgcc.lib which was used when building the library.
The more convenient way that deals with the ___chkstk problem only means doing something like ar x libgcc.a (which produces many .o files) and then merging your libbz2 object files with __chkstk.o file.

I think it should be in linker options e.g. LDFLAGS=-static, while LDFLAGS=-static-libgcc still gives dynamically linked binaries...with any test.c:
gcc -c test.c
gcc -static-libgcc test.o
ldd a.out
libc.so.6 => /lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2
gcc -c test.c
gcc -static test.o
ldd a.out
not a dynamic executable
For librarian, simply use ar
ar q libtest.a <path>/libgcc.a

Related

How to know which 'sin' function does my program invoke when running?

I am using different versions of libm.a. One that I am playing with is fdlibm's libm.a (from Sun).
The problem is that I feel that my program does not call the functions in fdlibm's libm.a, but calls those of the system's glibc's libm.a.
#include "fdlibm.h"
int main(){
double x = sin(3);
}
The program is compiled C++ programs(because it has to be linked with other c++ programs):
g++ prog.cpp libm.a
where libm.a is the fdlibm's. (From Sun, http://www.netlib.org/fdlibm/readme)
Question 1
How can I know what does sin actually invoke at run-time? I heard about various tools like objdump, gdb... Which one can be used for my case and how?
Question 2
How can I enforce fdlibm's libm.a be used?
Thanks.
Question 1. I heard about various tools like objdump, gdb.
As with gdb.
Create file trace_sin.gdb
$ cat trace_sin.gdb
set confirm off
b sin
commands
bt
c
end
r
quit
And run your program:
$ gdb -q -x trace_sin.gdb ./a.out Reading symbols from ./a.out...(no
debugging symbols found)...done. Breakpoint 1 at 0x400498
Breakpoint 1, 0x000000314941c760 in sin () from /lib64/libm.so.6
#0 0x000000314941c760 in sin () from /lib64/libm.so.6
#1 0x0000000000400629 in main ()
As you see in my case sin comes from libm
Question 2. How can I enforce fdlibm's libm.a be used?
Just make sure than sin from fdlibm comes before libm's sin
I grew tired of linking/deferred loading of the .so version of a library, and somewhere I found that you can achieve a link to a specific libary, by specifying path to the library.
Perhaps this can help with your challenge.
example - I can change this command (and link to SDL2 .so)
$(CC) $(CC_FLAGS) $< -o $# -L../../bag -lbag_i686 -lSDL2
and achive the same with
$(CC) $(CC_FLAGS) $< -o $# -L../../bag -lbag_i686 /usr/local/lib/libSDL2.so
Explicitly identifying which lib to use.
On ubuntu, I can use 'locate' to find the full path of a file. It turns out that SDL2 (.so) lands in both /usr/local/lib and /usr/lib/x86_64-linux-gnu. I suppose the x86_64 is more appropriate for my system, and it also links.
I have used the following simple technique to 'gently specify' (not explicit) a library needed for link. This technique might be appropriate for you.
I had already created several libraries which I had to use, and they were all in one specific path: "/home//cvs-tools/lib1". )
When it came time to use the 1 boost lib I needed, I simply copied the latest libboost_chrono.a into "/home//cvs-tools/lib1". No .so in the way.
And touched my make files so that when I updated boost, rather than me trying to remember all implications, I simply added to my make file the copy of chrono.a to my lib1, and my normal build then updated lib1's copy.
So, by 'gently specific', I mean that a) my make file copied the b) specific COTS library (boost) into c) my lib1 directory, and thus picked up by the same -L.

Undefined symbol when loading a shared library

In my program I need to load a shared library dynamically with dlopen(). Both the program and the shared library are successfully cross-compiled for an ARM architecture with the cross-compiler installed on my x86. However, whenever the program tries to load the library at run time on ARM, it fails giving this error:
undefined symbol: _dl_hwcap
I cannot find the culprit of this error.
Let me give details on how the shared library (libmyplugin.so) is built on x86 first. I use the g++ cross-compiler as below:
/home/me/arm/gcc-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ -march=armv7-a -mfloat-abi=hard -c -s -fPIC -o build/module1.o module1.cpp
/home/me/arm/gcc-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ -march=armv7-a -mfloat-abi=hard -c -s -fPIC -o build/module2.o module2.cpp
/home/me/arm/gcc-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ -o dist/libmyplugin.so build/module1.o build/module2.o --sysroot /home/me/arm/sysroot/ -Wl,--no-as-needed -ldl -lX11 -lXext /home/me/arm/libstatic.a -shared -s -fPIC
Please pay attention to the following notes:
module1.cpp and module2.cpp are my source code files.
libstatic.a is a big archive of object .o files implementing the stuff directly invoked/referenced by module1.cpp and module2.cpp. These object files have been compiled by others for the same ARM architecture as mine, with the same compiler flags, but using a slightly more updated g++ compiler (v4.9 instead of my v4.8.3). Unfortunately, I have no control on the building of these objects.
--sysroot /home/me/arm/sysroot/ represents the remote filesystem of my ARM OS from which the local g++ cross-compiler can take the native libraries while linking.
-Wl,--no-as-needed -ldl -lX11 -lXext: these flags are required to force the dynamic loader to load the X11 libraries present on the system when my shared library is loaded by the program. In particular, --no-as-needed is required because the X11 libraries are NOT directly referenced by module1.o and module2.o; on the contrary the X11 libraries are referenced by the static library only.
Note that all the above setup works on x86. It's just that I don't understand what is the reason of the _dl_hwcap symbol not resolved when the program tried to load the library on ARM.
Do you have any idea how to investigate this issue?
There are a myriad of things that could be problematic, but here are four avenues of exploration. I am concentrating on the -shared in your link line, but the last item addresses that as well.
(A nice HOWTO on shared libraries is here:
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
a) Check your environment variable LD_LIBRARY_PATH. Since you aren't using RPATH to the linker (RPATH embeds a full path to the .so so you can find it at runtime), then the only way the linker can find your code is to search the LD_LIBRARY_PATH.
Make sure the .so or .0 you want is in the path.
b) Use the UNIX utility 'nm' to search .so (shared objects) and .a files for that symbol. For example, 'nm -D /usr/lib64/libpython2.6.so' will show all dynamic symbols
in the libpython.so, and you can look for symbols of interest:
For example, Is 'initgc' defined or used in libpython?
% nm -D /usr/lib64/libpython2.6.so | grep initgc
000003404300cf0 T initgc
The 'T' means TEXT or, yes, it is defined there. See if you can find the symbol in the module of interest using grep and nm. (A 'U' means undefined, which means it is defined in another module).
c) Another useful tool is 'ldd'. It shows all dynamic libraries that the library you are looking on depends on. For example:
% ldd /usr/lib64/libpython2.6.so
linux-vdso.so.1 => (0x00007fffa49ff000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00000033f0200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000033f0600000)
libutil.so.1 => /lib64/libutil.so.1 (0x00000033fea00000)
libm.so.6 => /lib64/libm.so.6 (0x00000033f0a00000)
libc.so.6 => /lib64/libc.so.6 (0x00000033efe00000)
/lib64/ld-linux-x86-64.so.2 (0x00000033efa00000)
If it can't find a library (because it's not on the LD_LIBRARY_PATH or wasn't specified in the RPATH), the library will turn up empty.
d) I am a little worried from your link line of seeing a '.a' file with a -shared option. Some compilers/linkers cannot use a '.a' (archive) file to create a '.so' file. '.so' files usually have to made from other '.so' files or '.o' files that have been compiled with -fPIC.
I would recommend (if you can), recompile /home/me/arm/libstatic.a so that it's a .so. If you can't do, you might have to make your final output a '.a' file as well. (In other words, get rid of the -shared command line option).
In summary: Check your LD_LIBRARY_PATH, use nm and ldd to look around at your .a and .so files, but I think the end result is that you may not be able to combine .so and .a files.
I hope this helps.
I think this symbol may be in the "ld-lsb" library needed by "Xext". On my system the library is a symlink "/lib64/ld-lsb-x86-64.so -> ld-linux-x86-64.so.2", but I am sure that is not the same on the arm. Maybe give it a whirl on your linker line?

Correctly linking GLX library in Ubuntu

I'm trying to compile one of these mixes of X11 + OpenGL, but I'm not having luck with the compiler. In particular, I get:
undefined symbol: glXMakeCurrent
I have tried
-lX11 -lGLU -lGL -lXext
as arguments to the linker, and some permutations of them, with no luck so far.
I'm running Ubuntu 12.04, and I have installed all the development packages related to opengl that I had a fuzzy idea could be related. I'm also developing in C++, something that could cause problems if the opengl headers are not prepared for it... but they are right?
I even looked for the symbol explicitly with an fgrep in /usr/lib/x86_64-linux-gnu/, but it is not there, and furthermore, `nm' says that there are no symbols.
So, what's the correct way of linking with glx?
EDIT: It is linking problem, the error is produced when python tries to load the compiled (and incorrectly linked) module. Not at compilation time.
EDIT: Here is the compilation log
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o build/debug/objects/alve/layouter/flowing_data.os -c -std=c++0x -g -I/usr /include/python2.7 -fPIC -I/opt/cairo_new/include/cairo/ -I/opt/boost_1_48_0/include -DMIC_RT_SPEED_BACKS -Icsrc csrc/alve/layouter/flowing_data.cpp
g++ -o build/debug/objects/alve/layouter/liblayouter.so -L/opt/cairo_new/lib -L/opt/boost_1_48_0/lib -shared build/debug/objects/alve/layouter/flowing_data.os build/debug/objects/alve/layouter/show_network.os -Lbuild/debug/lib -Llibdeps
Install file: "build/debug/objects/alve/layouter/liblayouter.so" as "build/debug/lib/liblayouter.so"
g++ -o build/debug/objects/alve/layouter/liblayouter_mod.so -L/opt/cairo_new/lib -L/opt/boost_1_48_0/lib -shared build/debug/objects/alve/layouter/module.os Lbuild/debug/lib -Llibdeps -lboost_python build/debug/objects/alve/layouter/liblayouter.so -lcairo -lX11 -lGL -lGLU -lXext
scons: done building targets.
and here is how the function is called:
glXMakeCurrent (dpy, win, ctx);
The message "undefined symbol" indicates that it's not a linker, but a compilation unit problem: The compiler does not know the symbol glXMakeCurrent because it has been neither declared, nor defined, but you use it.
Probably the GLX header has not been included.
Add
#include <GL/glx.h>
As it turns out OPs problem was related to the fact, that the build consisted of cascading shared objects forming a Python module. One shared object implements the actual OpenGL operations, while the other does the interfacing to the Python interpreter.
Now shared objects (.so) are fully qualified ELF binaries themself, each with their own import and export symbol table. A shared object can be configured to expose all the symbols of other shared object it links to. However a shared object will not see any symbols of the compilation units they're linked into (if you think about it, this is to be expected, as a shared object can not and should not make any assumptions about the environment it's going to be linked into).
Hence, when compiling and linking multiple shared object in a larger build it's important to individually link each shared object to any libraries it will need at runtime.
As #datenwolf ways, special precautions are needed for linking. Which are them is a mystery for me, but using ldd helps. So basically what I did was to use ldd in both the final and the intermediate shared objects. Despite the command line arguments, my library didn't get linked with libGL and its dependencies until I also included the '-lGL -lGLU -lX11' in the intermediate step (production of 'liblayouter.so').

Configuring a library to be included with C++ test

I would like to utilize the UnitTest++ library in a testing file. However, I am having some difficulty getting the library to be included at compile time. So here is my current directory structure:
tests/
UnitTests++/
libUnitTest++.a
src/
UnitTests++.h
unit/
test.cpp
I have just used the UnitTest++ getting started guide to just get the library setup. Here is test.cpp:
// test.cpp
#include <UnitTest++.h>
TEST(FailSpectacularly)
{
CHECK(false);
}
int main()
{
return UnitTest::RunAllTests();
}
And I am currently trying to compile with:
gcc -lUnitTest++ -L../UnitTest++/ -I../UnitTest++/src/ test.cpp
I am currently getting a bunch output with ld: symbol(s) not found at the end. So how would I be able to get the UnitTest++ library properly included when this program is compiled? I am on a Mac and I'd also like for there to be an easy way for people on a Linux machine to run these same tests.
Whew, I hope this provides enough information, if not please let me know.
I was able to build it in the following manner
gcc -L../UnitTest++/ -I../UnitTest++/src/ test.cpp -lUnitTest++ -lstdc++
or
g++ -L../UnitTest++/ -I../UnitTest++/src/ test.cpp -lUnitTest++
that links to libstdc++ automatically.
GCC documentation says:
-llibrary
-l library
Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.)
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified.
Thus, foo.o -lz bar.o' searches libraryz' after file foo.o but before bar.o. If bar.o refers to functions in `z', those functions may not be loaded.
I guess that's why the library symbols are not found when you first specify -lUnitTest++ and then test.cpp
Compile test.cpp to get test.o
and use
g++ test.o libUnitTest++.a -o ./exectest
to get the ./exectest executable
libUnitTest++.a is just an archive of all the object files of UnitTest++. You just need to link all the object files (your test object file + libUnitTest++.a)
Try editing the makefile that came with unittest++ and make it suitable for your case
The message ld: symbol(s) not found means you haven't compiled the library. So you need to go in the UnitTest++ folder, compile and install it.
I've never worked on a MAC, but in linux, libraries are usually compiled and installed with:
./configure
make
make install
In the UnitTest++ link you posted, you should simply:
make install
Then you will have the UnitTest++.so library in the libraries folder of your OS. Now the library can be linked with your program with the -lUnitTest++ command.
Usually you have to put -Lsomething before the -lsomething that requires it.

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