MySQL And C applications - c++

When building a application that accesses a MySQL database on linux using C/C++ i have to dynamically link into the mysql client library. Is there a way in which i can statically link the application so that the mysql client libraries are no longer required?
What is the best practice, with regards to C\C++ development, to include rather long queries in the application but outside the code? Using stored procedures an not possible as the database runs on a MySQL 4 server.

Should be easy to create the static mysql client libs. If you downloaded the source, you just need to make sure you configure it appropriately:
./configure --enable-static
This should build libmysql/libmysqlclient.a (or possibly libmysql/.libs/libmysqlclient.a) which should be easy to link statically into your executable.
You'll need your executable to be licensed under the GPL or you'll need to buy an appropriate license from the MySQL folks.

The following compile command-line worked for me to statically link the mysql client libs:
gcc -I/usr/include/mysql -c mysql.c
gcc -o mysql mysql.o -static -lmysqlclient -static-libgcc -lm -lz -lpthread
However, I received the following warnings, which may or may not be a problem for you. It seems to be saying that there is a dependency on the target machine having the same glibc version as your build machine.
/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/libmysqlclient.a(mf_pack.o): In function `unpack_dirname':
(.text+0x6cc): warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/libmysqlclient.a(libmysql.o): In function `read_user_name':
(.text+0x5ed7): warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/libmysqlclient.a(mf_pack.o): In function `unpack_dirname':
(.text+0x6e1): warning: Using 'endpwent' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/libmysqlclient.a(my_gethostbyname.o): In function `my_gethostbyname_r':
(.text+0x3c): warning: Using 'gethostbyname_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/libmysqlclient.a(libmysql.o): In function `mysql_server_init':
(.text+0x695d): warning: Using 'getservbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

Related

overridding glibc function in shared library to downgrade glibc required version in cross compilation

I have a C++ 3rd party library in source code. It is self-contained and does not refer to any other library. It uses C++14, hence it requires a modern gcc compiler.
I want to use some of its functions in a software application compiled for RHEL5 with an old version of gcc, which does not understand modern C++.
To solve the problem I am creating with gcc 7.2 a shared library (.so) which exposes a plain and simple C api. I would like the so file to be self contained hence I use the link line:
g++ -shared -static-libstdc++ -static-libgcc
I am not using the option -static, as I could not get it to work, despite I used -fPIC when generating my object files. Probably because the static libraries for libstdc++ might be compiled without fPIC. So ldd shows that my so has some dependencies on libc and libm. objectdump -T shows that most of these dependencies are compatible with RHEL5, because they require a version of GLIBC older than 2.5. However there is one dependency on memcpy which requires GLIBC 2.14. This does not come directly from my source code, but probably from libstdc++ or libgcc, which are being statically linked.
Is there any way I can provide my own implementation of memcpy and tell the linker to use that everywhere, instead of the one from glibc?

Glibc issue using g++

I have a problem, i'm compiling my C++ app in Linux machine. Then i move executable to other machine, but i have an error:
./server: /lib64/libc.so.6: version `GLIBC_2.7' not found (required by ./server)
How can i fix it? Without recompiling on second machine where this error happens (it is my client machine)
Compile command:
g++ -o server test.cpp server.cpp ... -lboost_system -lboost_thread -std=c++0x
Thanks!
Your app is using glibc-2.7 library, and app can not find it on other machine. It probably have older version of this library. You have following options:
Upgrade this library on target host
Link you app against older library version
Use static linking
Ship library together with app
How statically link to just one library:
gcc main.c mylibrary.a -o main
Note that most distros do not install static libraries by default.
There are three choices:
compile on the original machine with -static given to the compiler, which will include the relevant libraries in your binary [and possibly give you a warning or two about "this may not work right"]
compile the code on the new machine.
Install the correct version of library on the target machine.
I tend to use option 1 most of the time, but have used all three at various points.

How can I create a static library for my program?

I have downloaded the OpenSSL binary file. I would like to create a static library for my C++ program in Ubuntu.
Meaning that they are in the same directory.
http://www.openssl.org/source/
Add -static parameter to gcc when you are linking. I expect you want to static binary without any dynamic loaded libraries. In other case, add full path to libssl.a as object file to linking in your build system. You have not specified how are you going to build your application.
Manually, you would use something like:
gcc -o application yourcode.c yourcode2.c /usr/lib/libssl.a
or better
gcc -static -o application yourcode.c yourcode2.c -lssl
Downloading binary for Linux is bad idea in most cases. If you want static binary, this should help. If you need custom build of library with special features, you need to download and build that library from sources yourself.
Anyway, similar question to yours is answered here at Static link of shared library function in gcc
You might also check Linux static linking is dead? to discover there are maybe too many problems to even consider static linking.
And if you need more information about linking under Linux, check nice tutorial at http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html

Wrapping different versions of static library in dynamic libraries

In my project there is a dependency on a static library (just called libsomething from now on) from a 3rd party. Recently, libsomething has become available in another version. My task is to provide my software with support for the old and the new version. Only one version of libsomething is used at run-time at any given time, but which version this is should be configurable between program runs.
I am using MSVC2005 on WinXP, a secondary objective is to become prepared to switch over to Linux and GCC.
Since both versions of libsomething are using the same symbols, linking them both into my executable is out of the question as the symbols of both versions are going to clash all over at link-time.
While I could create two executables (one linking against the old version, the other one using the new version), I cannot implement a decision on which executable to call in the final deployment environment (legacy reasons).
I came up with the idea of creating a dynamic library wrapper for each version of libsomething and linking them at run-time depending on some config file. With MSCV, this would mean going down the road of using LoadLibrary(), GetProcAddress(), etc., while on Linux I would have to use dlopen() and dlsym().
I understand that using libtool (i.e., libtldl) is wrapping this platform-dependency for using shared libraries. Is this an appropriate path to follow? Are there better (or, at least, different) ways? Do alternatives for libtldl exist as open-source?
I know you said you couldn't use two executables due to the decision of which to execute, but couldn't you exec back and forth between executables depending on which version is selected at configuration?
On Linux it would be easier for you to link to shared library and use symlinks to correct version - IMO it's much easier than using dlopen() + dlsym().
Thus you would create shared libraries for the old and new versions of your library:
g++ -shared -o libshared.so.1.1 -Wl,-soname=libshared.so.1 -L. -Wl,--whole-archive libstatic.a.old -Wl,-no-whole-archive
and
g++ -shared -o libshared.so.1.2 -Wl,-soname=libshared.so.1 -L. -Wl,--whole-archive libstatic.a.new -Wl,-no-whole-archive
Create the symlinks:
ln -s libshared.so.1.1 libshared.so.1
ln -s libshared.so.1 libshared.so
Build your application, linking it to the old version of the library. I suppose both versions are binary compatible (ABI not broken), but the new one could have some new symbols.
g++ -o myapp myapp.cpp -L. -lshared
Since shared library's SONAME is libshared.so.1 your application will depend on it and will search libshared.so.1 in paths from /etc/ld.so.conf or LD_LIBRARY_PATH
Before you run your application you may set the libshared.so.1 symlink to point to libshared.so.1.2 or libshared.so.1.1.
Little info about the linker options used here:
--whole-archive
For each archive mentioned on the command line after the --whole-archive option, include every object file in the archive in the
link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared
library, forcing every object to be included in the resulting shared library. This option may be used more than once.
Two notes when using this option from gcc: First, gcc doesn't know about this option, so you have to use -Wl,-whole-archive.
Second, don't forget to use -Wl,-no-whole-archive after your list of archives, because gcc will add its own list of archives to your
link and you may not want this flag to affect those as well.
-soname=name
When creating an ELF shared object, set the internal DT_SONAME field to the specified name. When an executable is linked with a
shared object which has a DT_SONAME field, then when the executable is run the dynamic linker will attempt to load the shared object
specified by the DT_SONAME field rather than the using the file name given to the linker.
It has been few years now but I'd like to mention another solution for completeness. Instead of manual dlopen and dlsym you could generate simple stubs for all necessary functions and on first call (or at program startup) decide which library version is needed, load it and resolve the addresses.
You could write a script specifically tailored for your project or use Implib.so tool:
# This will generate mylib.so.init.c and mylib.so.tramp.S
# which implement stubs. These need to be linked to your
# executable.
$ implib-gen.py mylib.so
Implib.so is Linux-only atm but should be easily adaptable to Windows.

compile against libc++ statically

I wrote some custom c++ code and it works fine in ubuntu, but when I upload it to my server (which uses centos 5) its fails and says library is out of date. I googled all around and centos cannot use the latest libraries. How can I compile against the stl so that it is included in the binary and it doesn't matter that centos uses an old library?
P.S. I don't want to upload the source to the server and compile there.
In your linking step, you can simply add the "-static" flag to gcc:
http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Link-Options.html#Link-Options
You may install on your Ubuntu box the compiler that fits the version of the library on your server.
You may ship your application with libstdc++.so taken from the system you compiled it at, provided you tune the linking so it gets loaded instead of centos' one.
You may compile it statically. To do this, you should switch your compiler from g++ to
gcc -lgcc_s -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
Choose whatever you like. Note that approaches (2) and (3) may arise the problem of dependencies: your project (particularly, the stdc++ implementation that, being statically linked, is now a part of your app) may require some functions to present in the system libraries on centos. If there are no such functions, your application won't start. The reason why it can happen is that ubuntu system you're compiling at is newer, and forward compatibility is not preserved in linux libraries.