最近有個項目需要生成靜態編譯的可執行文件,以便在其它linux的機器中運行,開始以為非常簡單,直接在編譯中加個-static選項不就是了,結果卻和我想的太不一樣了,下面說下我遇到的問題以及解決的方法。
開始按照設想應該只要在編譯中加個-static選項就可以了,不過卻報下面的錯誤:
cc -g -static -o test_server main_server.o main_db.o err_me.o -L/usr/lib/mysql/ -lmysqlclient -lpthread -ldl -lcrypt /usr/bin/ld: cannot find -lmysqlclient /usr/lib/gcc/i686-redhat-linux/4.6.2/http://www.cnblogs.com/../libpthread.a(libpthread.o): In function `sem_open': (.text+0x6917): warning: the use of `mktemp' is dangerous, better use `mkstemp' collect2: ld returned 1 exit status make: *** [test_server] Error 1
說是沒有找到-lmysqlclient,應該是沒有找到libmysqlclient.a庫,然后我到目錄/usr/lib/mysql/下去找,只有libmysqlclient.so的動態鏈接庫,因為加了-static后要使用靜態庫才能編譯成功,然后就在網上搜看看有沒有libmysqlclient.a的靜態庫下載。搜了好幾個小時一無所獲,偶然看到一個也是編譯與mysql庫有關的程序的選項,發現里面庫的路徑居然是/usr/local/mysql/lib/,然后我也到這個目錄去看了下,libmysqlclient.a文件真的在這里面,汗!!!這才想起自己以前是用源代碼安裝的mysql和mysql-dev的。
有了libmysqlclient.a庫文件,我立馬加入編譯選項中重新編譯,本以為萬事大吉了,結果還是報下面的錯:
cc -g -static -o test_server main_server.o main_db.o err_me.o -L/usr/local/mysql/lib/ -lmysqlclient -lpthread -ldl -lcrypt /usr/local/mysql/lib//libmysqlclient.a(mf_pack.c.o): In function `unpack_dirname': mf_pack.c:(.text+0x6dd): warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/local/mysql/lib//libmysqlclient.a(libmysql.c.o): In function `read_user_name': libmysql.c:(.text+0x2f21): warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/local/mysql/lib//libmysqlclient.a(mf_pack.c.o): In function `unpack_dirname': mf_pack.c:(.text+0x6ed): warning: Using 'endpwent' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/local/mysql/lib//libmysqlclient.a(client.c.o): In function `mysql_real_connect': client.c:(.text+0x34b6): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/lib/gcc/i686-redhat-linux/4.6.2/http://www.cnblogs.com/../libpthread.a(libpthread.o): In function `sem_open': (.text+0x6917): warning: the use of `mktemp' is dangerous, better use `mkstemp' /usr/local/mysql/lib//libmysqlclient.a(libmysql.c.o): In function `mysql_server_init': libmysql.c:(.text+0x2a4a): warning: Using 'getservbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/local/mysql/lib//libmysqlclient.a(dh.cpp.o): In function `TaoCrypt::DH::GeneratePrivate(TaoCrypt::RandomNumberGenerator&, unsigned char*)': dh.cpp:(.text+0x1a8): undefined reference to `pow' dh.cpp:(.text+0x1b8): undefined reference to `log' dh.cpp:(.text+0x1ca): undefined reference to `pow' collect2: ld returned 1 exit status make: *** [test_server] Error 1
先不管前面的警告,和面說明定義pow,然后再網上搜了下,必須在編譯選項中加-lm,然后再編譯下,終於是生成了可執行文件了。但是前面的警告是怎么回事,”warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking“,使用getpwnam的應用程序需要運行時共享庫glibc來鏈接。在網上找了很久也沒有找到怎么把警告去掉的方法,不過有個折中的方面,貌似也正是解決這個問題的方法,就是libmysqlclient.a庫用靜態連接,一些常用的庫用動態連接,因為程序是運行在linux中的,常用庫系統默認都會有的。一部分靜態連接,一部分動態連接的方法是:-Wl,-dn后面是靜態鏈接-Wl,-dy后面是動態連接,具體如下:
cc -g -o test_server main_server.o main_db.o err_me.o -Wl,-dn -L/usr/local/mysql/lib/ -lmysqlclient -Wl,-dy -lpthread -lm -ldl -lcrypt
總結:gcc很強大,自己學的只有皮毛,以后還要多用才行。