为了让项目中的程序能在docker中运行, 使用静态链接的方式, 让依赖更少,让docker的镜像更好制作, 在gcc中使用-static链接选项, 首先要通过命令:

yum install glibc-static

安装glibc的静态库版本. 这个包中,应该把:

都包含了,但是因为第三方库调用了glibc中的一些接口,导致这些接口总是链接的时候报警告,目前还没有遇到运行时的问题,警告信息如下:

gutils.c:(.text+0x5ae): warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
gutils.c:(.text+0x497): warning: Using 'getpwnam_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
gutils.c:(.text+0x4d5): warning: Using 'getpwuid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

目前这个警告还是无法去掉.

参考

linux – 将Yesod部署到Heroku,无法静态构建

我对Yesod很新,我在建立Yesod时遇到了麻烦

所以我可以部署到Heroku。

我已经更改了默认的.cabal文件以反映静态编译

if flag(production)
   cpp-options:   -DPRODUCTION
   ghc-options:   -Wall -threaded -O2 -static -optl-static
else
   ghc-options:   -Wall -threaded -O0

它不再构建。我得到了一大堆警告,然后一个 一些未定义的引用如下:

Linking dist/build/personal-website/personal-website ...
/usr/lib/ghc-7.0.3/libHSrts_thr.a(Linker.thr_o): In function
`internal_dlopen':
Linker.c:(.text+0x407): warning: Using 'dlopen' in statically linked
applications requires at runtime the shared libraries from the glibc
version used for linking
/usr/lib/ghc-7.0.3/unix-2.4.2.0/libHSunix-2.4.2.0.a(HsUnix.o): In
function `__hsunix_getpwent':
HsUnix.c:(.text+0xa1): warning: Using 'getpwent' in statically linked
applications requires at runtime the shared libraries from the glibc
version used for linking
/usr/lib/ghc-7.0.3/unix-2.4.2.0/libHSunix-2.4.2.0.a(HsUnix.o): In
function `__hsunix_getpwnam_r':
HsUnix.c:(.text+0xb1): warning: Using 'getpwnam_r' in statically
linked applications requires at runtime the shared libraries from the
glibc version used for linking
/usr/lib/libpq.a(thread.o): In function `pqGetpwuid':
(.text+0x15): warning: Using 'getpwuid_r' in statically linked
applications requires at runtime the shared libraries from the glibc
version used for linking
/usr/lib/libpq.a(ip.o): In function `pg_getaddrinfo_all':
(.text+0x31): warning: Using 'getaddrinfo' in statically linked
applications requires at runtime the shared libraries from the glibc
version used for linking
/usr/lib/ghc-7.0.3/site-local/network-2.3.0.2/
libHSnetwork-2.3.0.2.a(BSD__63.o): In function `sD3z_info':
(.text+0xe4): warning: Using 'gethostbyname' in statically linked
applications requires at runtime the shared libraries from the glibc
version used for linking
/usr/lib/ghc-7.0.3/site-local/network-2.3.0.2/
libHSnetwork-2.3.0.2.a(BSD__164.o): In function `sFKc_info':
(.text+0x12d): warning: Using 'getprotobyname' in statically linked
applications requires at runtime the shared libraries from the glibc
version used for linking
/usr/lib/ghc-7.0.3/site-local/network-2.3.0.2/
libHSnetwork-2.3.0.2.a(BSD__155.o): In function `sFDs_info':
(.text+0x4c): warning: Using 'getservbyname' in statically linked
applications requires at runtime the shared libraries from the glibc
version used for linking
/usr/lib/libpq.a(fe-misc.o): In function `pqSocketCheck':
(.text+0xa2d): undefined reference to `SSL_pending'
/usr/lib/libpq.a(fe-secure.o): In function `SSLerrmessage':
(.text+0x31): undefined reference to `ERR_get_error'
/usr/lib/libpq.a(fe-secure.o): In function `SSLerrmessage':
(.text+0x41): undefined reference to `ERR_reason_error_string'
/usr/lib/libpq.a(fe-secure.o): In function `initialize_SSL':
(.text+0x2f8): undefined reference to `SSL_check_private_key'
/usr/lib/libpq.a(fe-secure.o): In function `initialize_SSL':
(.text+0x3c0): undefined reference to `SSL_CTX_load_verify_locations'
(... snip ...)

如果我只是使用静态编译,而不是-optl-static 一切都很好,但应用程序在尝试时崩溃 从Heroku开始

2011-12-28T01:20:51+00:00 heroku[web.1]: Starting process with command
`./dist/build/personal-website/personal-website -p 41083`
2011-12-28T01:20:51+00:00 app[web.1]: ./dist/build/personal-website/
personal-website: error while loading shared libraries: libgmp.so.10:
cannot open shared object file: No such file or directory
2011-12-28T01:20:52+00:00 heroku[web.1]: State changed from starting
to crashed

我尝试将libgmp.so.10添加到LD_LIBRARY_PATH,如here所示 然后得到以下错误:

2011-12-28T01:31:23+00:00 app[web.1]: ./dist/build/personal-website/
personal-website: /lib/libc.so.6: version `GLIBC_2.14' not found
(required by ./dist/build/personal-website/personal-website)
2011-12-28T01:31:23+00:00 app[web.1]: ./dist/build/personal-website/
personal-website: /lib/libc.so.6: version `GLIBC_2.14' not found
(required by /app/dist/build/personal-website/libgmp.so.10)
2011-12-28T01:31:25+00:00 heroku[web.1]: State changed from starting
to crashed
2011-12-28T01:31:25+00:00 heroku[web.1]: Process exited

似乎我正在编译的libc的版本是 不同。我也尝试在批量库中添加libc 与libgmp相同的方式,但这会导致分段错误 当应用程序在Heroku方面启动时。

一切都在我的电脑上工作正常我正在运行64位archlinux与ghc 7.0.3。 The blog post on the official Yesod blog看起来很容易 但在这一点上我很失望。任何人都有什么想法?如果有办法让这个事情没有建立静态的工作,我也是开放的。

编辑

每个就业的俄罗斯人回答我做了以下修复这个。

首先在项目目录下创建一个新的目录lib,并将缺少的共享库复制到其中。您可以通过运行ldd路径/ to / executable和heroku运行ldd路径/到/可执行文件并比较输出来获取此信息。

然后我做了heroku配置:添加LD_LIBRARY_PATH =。/ lib,所以当应用程序启动时,动态链接器将在新的lib目录中查找库。

最后,我创建了一个ubuntu 11.10虚拟机,并从那里构建并部署到Heroku,这有一个足够长的glibc,它在Heroku主机上运行。

编辑: 我在Yesod wiki写了一个教程

最佳答案

我不知道Yesod是什么,但我确切知道你的其他错误是什么意思。

首先,您不应该尝试静态链接。您获得的警告是正确的:如果您静态连接,并使用您获取警告的其中一个例程,那么您必须安排在与完全相同版本的libc.so.6的系统上运行你在建造时使用

与普遍的观点相反,静态链接在Linux上产生更少的,而不是更多的便携式可执行文件。

您的其他(静态)链接错误是由链接时缺少libopenssl.a引起的。

但是让我们假设你要去“理智”的路线,并使用动态链接。

对于动态链接,Linux(和大多数其他UNIX)支持向后兼容性:旧的二进制文件继续在较新的系统上工作。但是它们不支持前向兼容性(一个基于较新的系统的二进制文件通常不会在较旧的系统上运行)。

但是这正是您尝试做的:您使用的是基于glibc-2.14(或更新版本)的系统,并且您正在使用glibc-2.13(或更早版本)的系统上运行。

您需要知道的另一件事是,glibc由大约200个二进制文件组成,必须完全匹配。两个关键二进制文件是/lib/ld-linux.so和/lib/libc.so.6(但还有更多的内容:libpthread.so.0,libnsl.so.1等)。如果这些二进制文件中有一些来自不同版本的glibc,那么您通常会遇到崩溃。这正是你所得到的,当你试图将你的glibc-2.14 libc.so.6放在LD_LIBRARY_PATH上 – 它不再匹配系统/ lib / ld-linux。

那么解决方案有哪些?有几种可能性(增加难度):

>您可以将ld-2.14.so(/ lib / ld-linux symlink的目标)复制到目标系统,并显式调用它:

/path/to/ld-2.14.so --library-path <whatever> /path/to/your/executable

这通常是有效的,但是可能会混淆使用argv [0]的应用程序,并重新执行自己的应用程序。 >你可以建立在旧的系统上。 >您可以使用appgcc(此选项已经消失,请参阅this以了解以前的描述)。 >您可以设置与目标系统匹配的chroot环境,并在该chroot内部构建。 >你可以建立一个Linux到老式的Linux编译器

相关文章

Static linking with flag –static fails

https://github.com/civetweb/civetweb/issues/439

I’d like to use static linking for my application with the --static flag, but get the following error

build/third-party/civetweb/libcivetweb.a(civetweb.o): In function `mg_start':
civetweb.c:(.text+0xe8ed): warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
build/third-party/civetweb/libcivetweb.a(civetweb.o): In function `mg_connect_client_impl.isra.17':
civetweb.c:(.text+0x3b9c): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
g++ -o build/sw-updater -pthread build/src/updater/main.o -Lbuild -Lbuild/third-party/civetweb -lsw

make slib works for me without any warning. Probably, it depends on the system.

I asked google about your warnings, and found it could be related to the GLibC Name Service Switch (NSS):

-static option for gcc?

Create statically-linked binary that uses getaddrinfo?

glibc uses libnss to support a number of different providers for address resolution services. Unfortunately, you cannot statically link libnss, as exactly what providers it loads depends on the local system’s configuration.

静态编译mysql库到程序中遇到的问题

最近有个项目需要生成静态编译的可执行文件,以便在其它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很强大,自己学的只有皮毛,以后还要多用才行。