一尘不染

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

linux

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

如果我仅使用just进行编译,-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添加到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版本不同。我也尝试像对libgmp一样将libc添加到库批次中,但是当应用程序在Heroku端启动时,这会导致分段错误。

在我的PC上一切正常。我正在使用ghc 7.0.3运行64位archlinux。
Yesod官方博客上的博客文章看起来很简单,但是我对此感到困惑。谁有想法?如果有一种方法可以在 不进行 静态构建的情况下使它正常工作,那么我也对此持开放态度。

编辑

每个Employed Russians答案我做了以下修复。

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

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

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

编辑:从那以后我就在Yesod Wiki上写了一个教程


阅读 501

收藏
2020-06-02

共1个答案

一尘不染

我不知道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.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],并中断那些自己重新执行的应用程序。

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

  2. 你可以使用appgcc(这个选项已经消失了,看到为它曾经被描述)。

  3. 您可以设置与目标系统匹配的chroot环境,并在该chroot中进行构建。

  4. 您可以构建自己的Linux到旧版Linux交叉编译器

2020-06-02