How to statically link libstdc++ - c++

I am trying to get my program working in another machine where libstdc++ versions is different. I am developing and compiling it on netbeans. I have specified the option -static-libstdc++ but the program continues trying to load libstdc++.so.6 in the local machine.
How can I get a fully static libstdc++ link?
Thanks.

Not sure of the exact circumstances here, but I ran into a similar problem just now with different versions of Mac OS X and gcc. I worked around it by copying the actual dylib I wanted into the same directory as the executable and changing DYLD_LIBRARY_PATH to have it search there first before /usr/lib.

Related

How to build c++ with all dependencies to run on another machine

I wrote c++ code that in including some libraries that I included using -l option. The code is right on my machine but I want finally run this code on another machine named B. I built it on my machine using c++11 and GNU GCC Compiler and attempt to run it on machine B but it errors :
error while loading shared libraries: libcppkafka.so.0.1: cannot open shared object file: No such file or directory
How can I build c++ code with all dependencies to disappear this error?
note: libcppkafka.so.0.1 is in my machine in path /usr/local/lib
note: I use codeblock IDE, so I appreciate that if solution will be codeblock compatible
note: Both machines are ubuntu 16.04
In order to achieve your goal you have 2 options.
You can copy your shared libraries(libcppkafka.so) with your executable and configure its location correctly.
Or you can avoid shared libraries by statically linking them to your program. For this you'll need to have static version of those libraries (libcppkafka in your case)
Since both machines are running the same distribution and version (Ubuntu 16.04), you could find out on the first machine the installed and useful packages, and install these on the second machine.
You'll need to copy the non-packaged things, e.g. in (some part of) /usr/local/lib
You could consider making a real .deb package for your thing (but that is more work).
Notice that an IDE is just an IDE and don't compile anything (an IDE is running external compiler commands; your compiler is GCC invoked as g++). You should perhaps compile on the command line (and you could even make that some shell script, to run on the other machine).

Built GCC 5.4 from source; executables thus built try to link incompatible libstdc++ and fail to run

I have followed instructions to build GCC from source. The only modifications I made for the configure were:
using a binary suffix of -5.4 so that I can use the compiler as g++-5.4 for instance.
setting --configure-multilib because it wouldn't run otherwise.
I'm doing this for testing some of my code by compiling it with various different compilers. On this Centos 7 system I've got the system gcc (4.8.2) as well as clang (also compiled from source) running, and now I'd like to see 5.4 working.
Based on these instructions, inside the source code I've put these statements to make the linker happy.
#define _GLIBCXX_USE_CXX11_ABI 0
Now that the executables compile and link, I'm getting this when I run them...
/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by <program name>)
I can't quite tell here but I do know enough to see that the actual symlink /usr/lib64/libstdc++.so.6 links to the older one (/usr/lib64/libstdc++.so.6.0.19), and the one built as part of GCC 5.4 lives somewhere else (/usr/local/lib64/libstdc++.so.6.0.21). This would indicate that this program I built using 5.4 is looking at the right (old) stdlib shared lib, so something else is amiss.
The new compiler is generating code which expects to be linked to the newer libstdc++, rather than the system one. The linker finds that this expectation is not met, so it throws an error.
To fix this you will have to ensure that the correct path is being used to find and link libstdc++. There are a few options:
Use the -rpath linker option. This option adds a path to the directories to be used during dynamic linking. As it is a linker option, you pass it through using -Wl,<option> when invoking the compiler, for example:
g++ ... -Wl,-rpath=/usr/local/lib64 .... You may also need to add the path using the -L option.
Set environment variable LD_LIBRARY_PATH at runtime
See also: compiler-libstdc-version-vs-system-version
Since you are using Centos, you may also want to check out the devtoolset collection, which allows a parallel installation of newer GCC toolsets.
This would indicate that this program I built using 5.4 is looking at the right (old) stdlib shared lib
... as far as I can see, that is the wrong library, isn't it? Because it the program is built with the new g++ version, it should be using the new libstdc++, i.e. the one in /usr/local/lib64/libstdc++.so.6.0.21.
So then you might need to prepend that path to LD_LIBRARY_PATH to be able to load the program.

Glibc version mismatch

I have created .so library in my Ubuntu and run it on another machine. Got error:
/lib/tls/i686/cmov/libc.so.6: version `GLIBC_2.15' not found
I suppose this is general C++ library. But how to solve such problem? I can't change client configuration and that means I must to do something with my configuration. But what exactly I must do?
UPD
ldd -version returns
my machine:
ldd (Ubuntu EGLIBC 2.19-0ubuntu6.6) 2.19
host machine:
ldd (Ubuntu EGLIBC 2.11.1-0ubuntu7.8) 2.11.1
On the target machine, run ldd --version and check the output which will tell you what version of GLIBC_ they have.
You can then roll yours back to match their version.
Statically link your executable so it doesn't need their Clib.
You can also alter your program to use the older version, once you know what it is, that is.
See this SO solution for how to do that. How can I link to a specific glibc version?
You have to make sure that you are linking to corresponding or older versions of GLIBC. GCC has flag --sysroot which allows you to define which libs are used.
This may help with details: https://sourceware.org/glibc/wiki/Testing/Builds
The point is that creating a shared library necessarily means that you need to link it to the C library (glibc, in your case). That means that calls to C library functions (which the stdc++ library does) get replaced with actual correct symbol locations in the C library.
Now, if the C library on the compiling/linking machine is not the same as on the target machine, this must fail, and hence, libc version gets checked.
Solutions is to either statically link your .so (which honestly doesn't make much sense, usually), or just correctly compile and link it for your target machine.
Beside compiling everything static, which is usually a bad
idea or does not work at all, the only way to solve the isssue
is to recompile your binary for the target platform.
Install a virtual machine or chroot with the same Ubuntu version
as on the target platform and compile there. There are also solutions
like sbuild or pbuilder/cowbuilder which automates this for Debian/Ubuntu packages.

SFML 1.6 without admin priviliges

So I have this SFML 1.6 application that works well on Mac OS X Lion. Currently the way I have it is that the SFML frameworks are in /Library/Frameworks and it works well, however to install on other machines it requires admin privileges. So I want to do one of the following:
Be able to install the libraries in /User/idk/Library/Frameworks or similar
Package the libraries and the app into a Mac disk image and have it reference the libraries from there
Statically link the libraries
Now since the program is built using the Terminal with makefiles, I would prefer the solution to be in the Terminal rather than XCode, but if absolutely necessary then I guess I could somehow import the project to XCode.
So can anyone explain (precisely) how to do any of the three above, whichever is the easiest to do?
By the way I'm using the LLVM GCC 4.2 that ships with XCode 4.1 for the compilation.
EDIT:
How about someone tries the other two, aside from statically linking?
I solved it so... kind of a waste of bounty points... SUCKS FOR YOU! :P
I did something quite simple and was surprised no one else had suggested it:
I used install_name_tool to change the names and dependencies of the SFML dynamic libraries so that they can be placed in the same directory as the executable, or in a special folder, but that's relative to the executable's directory. So it requires no admin privileges, and I easily packaged it all into an application bundle.
You should probably statically link to SFML. To do this you will have to compile SFML as a static library. The easiest way to do this is probably to modify the Xcode project that comes with SFML ("SFML with Intel 64 bits.xcodeproj"). You need to change the Mach-O type of the libraries to Static Library.
I've uploaded the modified version of SFML with Intel 64 bits.xcodeproj that I use, you can get it here. (This project requires GCC4.2, and so only works with Xcode 3).
Statically linking to SFML is very similar to dynamically linking to it, just remember that you also need to link to Cocoa.framework, OpenGL.framework, and CoreFoundation.framework.
Also note that if you want to deploy to OSX 10.4 or earlier, you should statically link to libfreetype. The libfreetype that is supplied with the OS is in a different location in 10.4 and earlier, and this causes problems when it is dynamically linked.

libstdc++ GLIBCXX version errors

when I compile a c++ program in my computer using g++ and transfer the executable to run it on my university server, I get
./main: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by ./main)
./main: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ./main)
./main: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.11' not found (required by ./main)
The program runs well on my computer, and I don't have privileges to install any new software on my university servers.
any help ?
Thanks
It seems you are using the standard library as a shared library (default behaviour) when linking your program at home.
So rather than really "linking" the library, your linker just resolves some symbols and does another operation, while delaying the actual loading of the library to run-time.
When you execute your program at your university computer, the loader (the program which actually loads your program in memory and throws the main thread) looks for the libraries your program needs and tries to load them (look for LD_LIBRARY_PATH in linux if you feel curious).
The problem here is that you are linking your program at home with a version of the stdlib that is not the same version as what you have at the university. So when the loader tries to find the library, it fails, and so your program cannot be run.
Solutions:
a) To avoid all these problems use static linking instead of dynamic linking. I am not sure if this is possible with stdlib, but I think it is worth to test it (see: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html and look for "-static" flag)
b) You can try to compile your program at your university computer so it will use the version there.
c) Try to know which stdlib version is installed there and install the same version in your compiler machine.
d) You can try to copy your home version of stdlib to the same folder your application is. This usually works because the loader tends to search for shared libraries in the current application folder before looking in the path set in the environment variable LD_LIBRARY_PATH (linux)
Hope that helps.
P.S.:
Here you have a nice introduction to static vs shared/dynamic libraries http://www.network-theory.co.uk/docs/gccintro/gccintro_25.html
And here (http://en.wikipedia.org/wiki/Library_%28computing%29) a not so nice but more complete library description.
The version of libstdc++.so.6 is too old on the university computer. You have two options:
Statically link with -static. The C++ library will then be merged into the final binary.
Copy the correct version to somewhere in your home directory, then reference it either by passing -rpath /path/to/library/directory at build time, or setting the LD_LIBRARY_PATH environment variable to point to the directory containing the newer libstdc++.so.6.
You can copy your version of the /usr/lib/libstdc++.so.6 to a subdirectory of your home directory of the server, say ~/lib and then run:
$ LD_LIBRARY_PATH=$HOME/lib ./main
Or if you prefer
$ export LD_LIBRARY_PATH=$HOME/lib
$ ./main
And the program should load your private library instead of the system one.
What platforms are you trying to compile for? i.e. 'Your computer' and your 'University servers' ?
You could try compiling your program with the static linking option. This will generate a statically linked executable with all lib dependencies loaded already.
Cheers,