web-dev-qa-db-ja.com

YesodをHerokuにデプロイすると、静的にビルドできません

私はYesodに非常に慣れていないので、Herokuにデプロイできるように、Yesodを静的に構築することに問題があります。

静的コンパイルを反映するようにデフォルトの.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のバージョンが違うようです。 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にビルドしてデプロイしました。これには、Herokuホストで動作する十分古いglibcがあります。

編集: Yesod wiki にチュートリアルを書いてから

27
asm

Yesodが何であるかはわかりませんが、他の各エラーの意味が正確にわかっています。

最初に、静的リンクをしないでください。あなたが受け取る警告は正確です:if静的にリンクし、警告を受けているルーチンの1つを使用する場合は、次のように調整する必要があります。ビルド時に使用したものと同じバージョンのlibc.so.6を正確にシステムで実行します。

一般的な考えに反して、スタティックリンクはlessを生成しますが、Linuxではポータブル実行可能ファイルを生成しません。

その他の(静的)リンクエラーは、リンク時にlibopenssl.aがないために発生します。

しかし、「正常な」ルートに進み、動的リンクを使用するとします。

動的リンクの場合、Linux(および他のほとんどのUNIX)は下位互換性をサポートしています。古いバイナリは新しいシステムでも引き続き機能します。ただし、上位互換性はサポートされていません(新しいシステムで構築されたバイナリは、一般に古いシステムでは実行されません)。

しかし、それはあなたがやろうとしていることです:glibc-2.14(またはそれ以降)のシステムで構築し、glibc-2.13(またはそれ以前)のシステムで実行しています。

もう1つ知っておく必要があるのは、glibcが200以上のバイナリで構成されており、すべてが完全に一致する必要があることです。 2つの主要なバイナリは/lib/ld-linux.so/lib/libc.so.6です(ただし、libpthread.so.0libnsl.so.1など、他にも多数あります)。これらのバイナリの一部が異なるバージョンのglibcからのものである場合、通常はクラッシュします。そして、それは、glibc-2.14 libc.so.6LD_LIBRARY_PATHに配置しようとしたときに得られたものとまったく同じです。これは、システム/lib/ld-linuxと一致しなくなりました。

それで、解決策は何ですか?いくつかの可能性があります(難易度が高くなります)。

  1. ld-2.14.so/lib/ld-linux symlinkのターゲット)をターゲットシステムにコピーして、明示的に呼び出すことができます。

    /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-olderLinuxクロスコンパイラーを自分で構築できます

55

あなたにはいくつかの問題があります。

最先端のEdgeディストリビューションには、本番環境のバイナリを構築しないでください。実動システム上のライブラリーには、上位互換性がありません。

Glibcを静的にリンクしないでください。常に実行時に追加のライブラリをロードしようとします。たとえば、CPUベースのアセンブリ。それが最初の警告です。

最後のリンカエラーは、コマンドラインで欠落したopensslライブラリに関連しているように見えます。

しかし、全体として、ディストリビューションをダウングレードしてください。

5
user239558

Hergli(glibc-2.11を使用)の起動に同様の問題があり、glibc-2.14を必要とするアプリケーションがありましたが、ソースにアクセスできず、再構築できませんでした。私は多くのことを試しましたが、何もうまくいきませんでした。

私の回避策は、Amazon Elastic Beanstalkでサービスを起動し、APIインターフェイスを提供することでした。

0
idrinkpabst