How to create a shared object library (*.so) with mysql connector? - mysql

I have written a very simple application in C, for which I would like to have a connection with MySQL database. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>
#include <my_global.h>
void runtime_tile_opt(void);
int main(void) {
runtime_tile_opt();
return 0;
}
void runtime_tile_opt() {
printf("MySQL client version: %s\n", mysql_get_client_info());
}
If i run gcc -o runtime $(mysql_config --cflags) runtime.c $(mysql_config --libs), everything works fine, all libraries seemed to be properly linked, and if I run the executable, I get a legitimate-looking output:
MySQL client version: 5.5.49
However, I would like to make a shared library out of it. So I'm trying to create an object file, with -fPIC flag:
gcc -c -fPIC runtime.c $(mysql_config --cflags) -o runtime.o $(mysql_config --libs)
The outputs of mysql_config --libs mysql_config --cflags are:
-L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -ldl
-I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -g -DNDEBUG
Finally, I create my .so:
gcc runtime.o -shared -o runtime.so
All of the above went with no errors whatsoever. However, some library is not linked apparently, since when I run a file with this plugin loaded, I get:
/home/michal/thesis/Drafts/runtime/runtime.so: undefined reference to `mysql_get_client_info'
This function is defined in the header files I included. I'm not very experienced with gcc, but I look at it and it looks as though I linked what I had to link. Any ideas where did I fail?

You still need to pass the correct -l flags to the compiler when creating a shared library. They should be the same flags you pass when creating a binary, i.e.
gcc -shared -o runtime.so $(mysql_config --cflags) runtime.o $(mysql_config --libs)
Note that the order of options is important! First pass all options, then all files and lastly libraries (-l... operands).

Related

Mysql library cannot be found

I have mysql-devel installed. Relevant libraries live under /usr/inlcude/mysql
Here's my sample code to be compiled on Centos7:
#include <my_global.h>
#include <mysql/mysql.h>
int main(int argc, char **argv)
{
printf("MySQL client version: %s\n", mysql_get_client_info());
exit(0);
}
Error message:
Mysql_test.c:1:23: fatal error: my_global.h: No such file or directory
#include <my_global.h>
What is the problem? Should I create echos of all libraries under /usr/include/mysql to the primary path /usr/include?
You probably need to add mysql include to your compilation, as you suspected:
-I/usr/include/mysql
Then just
#include <mysql.h>
#include <my_global.h>
If you using gcc include like this :
#include <mysql/my_global.h>
If you use gcc dont need to specify -I
Depend where is mysql include dir . And where is located my_global.h
EDIT :
g++ -g -Wall -I/usr/local/include test2.o Test.o -o test
Soo add to you compiler this : -I/usr/local/include and include like this #include <mysql/my_global.h>
TO solve undefined reference you need to like to the library path . mysqlclient.a/.so
And add this too to link the library
g++ -g -Wall -I/usr/local/include -L/path_to_lib -lmysqlclient test2.o Test.o -o test

Compiling nginx module with dependant library

I have followed the tutorial here to build a simple nginx module with success: https://github.com/perusio/nginx-hello-world-module
I can build and run that code with no issue and it functions correctly.
I now want to add a dependancy of MySQL to the simple nginx module so I have used the MySQL C Connector http://dev.mysql.com/doc/refman/5.6/en/c-api-building-clients.html.
The simplest program you can write is this (taken from http://zetcode.com/db/mysqlc/):
mysql_test.c
#include <my_global.h>
#include <mysql.h>
int main(int argc, char **argv)
{
printf("MySQL client version: %s\n", mysql_get_client_info());
exit(0);
}
You then compile like so:
$ gcc mysql_test.c -o mysql_test `mysql_config --cflags --libs`
This works fine.
Now, when I try to include the two header files my_global.h and mysql.h with my simple nginx hello-world module, I need a way of specifying those build flags, else it won't find those header files. At the moment, when I run make, after it successfully builds all other modules, I now get:
cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs -I src/http -I src/http/modules -I src/mail \
-o objs/addon/nginx-hello-world-module/ngx_http_hello_world_module.o \
/vagrant/nginx-hello-world-module/ngx_http_hello_world_module.c
/vagrant/nginx-hello-world-module/ngx_http_hello_world_module.c:33:23: fatal error: my_global.h: No such file or directory
#include <my_global.h>
^
compilation terminated.
make[1]: *** [objs/addon/nginx-hello-world-module/ngx_http_hello_world_module.o] Error 1
make[1]: Leaving directory `/vagrant/nginx'
make: *** [build] Error 2
My question is: How do I get nginx to include those build flags when building my module?
I haven't found any information regarding the building of dependencies with Nginx.
Thanks!
Compilation Controls
--with-cc-opt=parameters
sets additional parameters that will be added to the CFLAGS variable.
--with-ld-opt=parameters
sets additional parameters that will be used during linking.
Source
For the MySQL Connector C it will be something like:
--with-cc-opt="-I/usr/include/mysql"
--with-ld-opt="-L/usr/lib64/mysql"
And in you module's config file:
CORE_LIBS="$CORE_LIBS -lmysqlclient"
During compilation it might also complain about _GNU_SOURCE being redefined and it will fail if you use -Werror without implementing a workaround.

MySQL: Library not loaded from C program

I'd like to test the very simple C API connection with my MySQL server. And I'm using it on mac. So Here are the codes:
#include <stdio.h>
#include <mysql.h>
int main(void)
{
printf("MySQL client version: %s\n", mysql_get_client_info());
exit(0);
}
I use gcc to compile it
gcc -c `mysql_config --cflags` main.c
It succeeds. But when I tried to run it
./main.o
The error is like this
-bash: ./main.o: Permission denied
I can log in to the MySQL by anonymous and run select version():
shell>mysql
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.6.25 |
+-----------+
1 row in set (0.00 sec)
Thanks to Sean, there is a mistake in my compilation. It supposes to be
gcc -o main `mysql_config --cflags` main.c `mysql_config --libs`
After that when I run ./main
I get another error:
dyld: Library not loaded: libmysqlclient.18.dylib
Thanks everyone!
I've solved this by adding the path of libmysqlclient.dylib to the DYLD_LIBRARY_PATH environment variable.
Here is the command for someone may need it.
export DYLD_LIBRARY_PATH=/usr/local/mysql/lib
The -c argument to gcc means:
Compile or assemble the source files, but do not link.
Which means you are not producing a valid executable. You need an additional step:
gcc -c `mysql_config --cflags` main.c
gcc -o main main.o `mysql_config --libs`
This can also be combined into a single line:
gcc -o main `mysql_config --cflags` main.c `mysql_config --libs`
Then you should be able to run ./main
Your compilation ststement looks wrong.
gcc -c `mysql_config --cflags` main.c
does not produce an executable binary. -c option is used to produce the object file, not an executable. It stops after compilation, linking is not done.
Rather, to generate the binary, you should write
gcc main.c -o outfile <any other oprions>
where the -o <file> is used to place the output (binary) to <file>and run the outfile like
./outfile

Unable to compile a program on server which runs on my machine locally

I have a project that compiles and runs on my system but when I try to run it on server it is giving compile-time errors. Here are the portion of the Makefile I use to compile it on my system:
CC = gcc
CFLAGS = -g -Wall
COMPLILEFLAGS = `mysql_config --include`
LINKERINFO = `mysql_config --cflags --libs`
exec: main.o
$(CC) $(CFLAGS) -o exec main.o $(LINKERINFO)
main.o: main.c
$(CC) $(CFLAGS) $(COMPLILEFLAGS) -c main.c
When I run the same file on the server I get the following error:
gcc -g -Wall -I/usr/include/mysql -c main.c
In file included from main.c:13:
/usr/include/mysql/my_global.h:688: error: redefinition of typedef ‘my_bool’
/usr/include/mysql/mysql.h:55: note: previous declaration of ‘my_bool’ was here
In file included from main.c:13:
/usr/include/mysql/my_global.h:699: error: redefinition of typedef ‘my_socket’
/usr/include/mysql/mysql.h:69: note: previous declaration of ‘my_socket’ was here
In file included from main.c:13:
/usr/include/mysql/my_global.h:1102: error: redefinition of typedef ‘my_ulonglong’
/usr/include/mysql/mysql.h:132: note: previous declaration of ‘my_ulonglong’ was here
In file included from main.c:14:
/usr/include/mysql/my_getopt.h:64: warning: ‘enum loglevel’ declared inside parameter list
The main.c file is:
#include <stdio.h>
#include <mysql.h>
#include <my_global.h>
int main (void)
{
return 0;
}
Can anyone suggest a possible work around this problem. All I want is to increase the portability of this code. One option I can think of is to make the files compiler and linker are using within my source and use them for compiling and linking.
By the way I am using mysql-server version 5.5 and server has mysql-server version 5.3
Looking at MySQL's documentation I found that old versions included a warning that stated that my_global.h should be included before mysql.h for compiling on Windows.
Try reversing the order of the includes and see if that fixes the issue. If it does, a bug is to be filed with MySQL urgently.

makefile error ----> make: *** No rule to make target `mysql.h'

This might sound like a dumb question. But here goes..... I am using a C program called db_access.c which interacts with MySQL (in Ubuntu 10.10 with MySQL Server version: 5.1.49-1ubuntu8.1 (Ubuntu)). Inside the program, I have: include "mysql.h"
When I do the following, everything works out right:
gcc -I/usr/include/mysql db_access.c -lmysqlclient -o db_access
./db_access
Problem arises when I try to integrate it into an existing (and working makefile). The contents of the makefile:
all: MappingServer
#Macro definitions
CC = gcc
CFLAGS = -lm
INCLUDES = -I/usr/include/mysql
LIBS = -L/usr/lib/mysql -lmysqlclient
MappingServer.o: MappingServer.c map_registration.h
$(CC) $(CFLAGS) -c MappingServer.c
route_aggregation.o: route_aggregation.c map_registration.h
$(CC) $(CFLAGS) -c route_aggregation.c
db_access.o: db_access.c map_registration.h mysql.h
$(CC) $(CFLAGS) $(INCLUDES) -c db_access.c
MappingServer: MappingServer.o route_aggregation.o db_access.o
$(CC) $(LIBS) -o MappingServer MappingServer.o route_aggregation.o db_access.o
clean:
-rm MappingServer.o route_aggregation.o db_access.o
I have two other C programs, MappingServer.c and route_aggregation.c. These 3 files need to be compiled together. By the way, I also did:
root#ahuq-kitchen:/home/ahuq/MappingServer# mysql_config --cflags
-I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -DUNIV_LINUX -DUNIV_LINUX
and
root#ahuq-kitchen:/home/ahuq/MappingServer# mysql_config --libs
-Wl,-Bsymbolic-functions -rdynamic -L/usr/lib/mysql -lmysqlclient
So I think the paths are OK. When I do: make all
I get:
root#ahuq-kitchen:/home/ahuq/MappingServer# make all
gcc -lm -c MappingServer.c
gcc -lm -c route_aggregation.c
route_aggregation.c: In function ‘vtysh_input’:
route_aggregation.c:602: warning: function returns address of local variable
make: *** No rule to make target `mysql.h', needed by `db_access.o'. Stop.
Why is this happening?
the line
db_access.o: db_access.c map_registration.h mysql.h
tells make that db_access.o depends on db_access.c, map_registration.h and mysql.h. make complains because mysql.h cannot be found in the current directory (it's in /usr/include/mysql).
see the question Makefile updated library dependency for how to specify libraries as dependencies in make
You put "mysql.h" as a dependency, but it's not in the current directory, so Make thinks it needs to build it, but doesn't know how.
try to remove all the lines like:
MappingServer.o: MappingServer.c map_registration.h
if the map_registration.h is included in the c file, make is smart enough to find it. The only thing to be noticed may be to set the search file path using: -I.