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

时间:2011-12-28 15:40:56

标签: linux haskell heroku static-linking yesod

我对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 ...)

如果我只使用-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

我尝试按照here中的建议将libgmp.so.10添加到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运行64位archlinux 7.0.3。 The blog post on the official Yesod blog看起来非常简单 但是我在这一点上很难过。有人有主意吗?如果有办法让这个东西工作没有静态构建我也会对此持开放态度。

修改

Employed Russians回答我做了以下修复此操作。

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

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

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

编辑: 我已经编写了关于Yesod wiki

的教程

3 个答案:

答案 0 :(得分:52)

我不知道Yesod是什么,但我知道完全你的其他错误意味着什么。

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

与流行的看法相反,静态链接在Linux上产生 less ,而不是更多可移植的可执行文件。

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

但是我们假设您将采用“理智”的路线,并使用动态链接。

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

但这就是你要做的事情:你建立在一个带有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上时 - 它不再与系统/lib/ld-linux匹配。

那么解决方案是什么?有几种可能性(越来越难):

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

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

    这通常有效,但可能会混淆查看argv[0]的应用程序,并会破坏重新执行的应用程序。

  2. 您可以在较旧的系统上构建。

  3. 您可以使用appgcc(此选项已消失,请参阅this了解以前的说明。)

  4. 您可以设置与目标系统匹配的chroot环境,并在chroot内部构建。

  5. 您可以自己构建一个Linux-to-oldLinux交叉编译器

答案 1 :(得分:5)

你有几个问题。

您不应该在前沿分布上构建生产二进制文件。生产系统上的库不能向前兼容。

您不应该静态链接glibc - 它将始终在运行时尝试加载其他库。例如基于cpu的程序集。这就是你的第一个警告。

最后一个链接器错误看起来与命令行上缺少的openssl库有关。

但总而言之 - 降级你的发行版。

答案 2 :(得分:0)

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

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