将Yesod部署到Heroku,不能静态构build

我对Yesod非常陌生,而且我很难静态构buildYesod,所以我可以部署到Heroku。

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

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

它不再build立。 我得到了一大堆警告,然后是一堆未定义的引用,如下所示:

 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编译而不用-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到这里build议的LD_LIBRARY_PATH,然后得到以下错误:

 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端启动时,会导致分段错误。

一切工作正常在我的电脑上。 我使用ghc 7.0.3运行64位archlinux。 在Yesod博客的博客文章看起来很容易,但我很难在这一点上。 任何人有任何想法? 如果有办法让这件事情没有build立静态我也打开了。

编辑

每个Employed Russians答案我做了以下来解决这个问题。

首先在项目目录下创build一个新的目录lib ,并将缺失的共享库复制到其中。 您可以通过运行ldd path/to/executableheroku run ldd path/to/executable并比较输出来获取此信息。

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

最后,我创build了一个Ubuntu 11.10虚拟机,并从那里构build并部署到Heroku,这有一个足够老的glibc,它可以在Heroku主机上工作。

编辑:我写了一个关于Yesod wiki的教程

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

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

与stream行的观点相反,静态链接在Linux上生成的可移植可执行文件更less ,而不是更多。

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

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

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

但是这就是你要做的:你build立在一个使用glibc-2.14(或更新版本)的系统上,并且你正在使用glibc-2.13(或更早版本)的系统上运行。

另一件你需要知道的是,glibc是由200多个二进制文件组成的,它们必须完全匹配。 两个关键的二进制文件是/lib/ld-linux.so/lib/libc.so.6 (但还有很多: libpthread.so.0libnsl.so.1等等)。 如果其中一些二进制文件来自不同版本的glibc,通常会发生崩溃。 而这正是你在试图将你的glibc-2.14 libc.so.6放在LD_LIBRARY_PATH上时所得到的 – 它不再与system /lib/ld-linux匹配。

那么解决scheme是什么? 有几种可能性(增加难度):

  1. 您可以将ld-2.14.so/lib/ld-linux符号链接的目标)复制到目标系统,并显式调用它:

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

    这通常起作用,但是可能会混淆查看argv[0]的应用程序,并中断自身重新执行的应用程序。

  2. 你可以build立在一个较旧的系统上。

  3. 你可以使用appgcc (这个选项已经消失,看到这个描述以前是什么)。

  4. 你可以设置一个与目标系统相匹配的chroot环境,并在chroot里面构build。

  5. 你可以build立一个Linux-to-oldLinux交叉编译器

你有几个问题。

你不应该在出血的边缘分布上构build生产二进制文件。 生产系统上的库不会向前兼容。

你不应该静态链接glibc – 它总是会在运行时尝试加载额外的库。 例如基于cpu的程序集。 这是你的第一个警告。

最后一个链接器错误看起来像是在命令行上与缺less的openssl库相关。

但总而言之 – 降级你的分配。

我有类似的问题发射到Heroku(使用glibc-2.11),我有一个需要glibc-2.14的应用程序,但我没有访问到源,无法重新构build它。 我尝试了很多东西,没有任何工作。

我的解决方法是在Amazon Elastic Beanstalk上启动服务,并提供一个API接口。