web-dev-qa-db-fra.com

Déployer Yesod sur Heroku, impossible de construire de manière statique

Je suis très nouveau à Yesod et j'ai du mal à construire Yesod de manière statique. Je peux donc me déployer à Heroku.

J'ai changé le fichier .cabal par défaut pour refléter la compilation statique

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

Et ça ne construit plus. Je reçois toute une série d'avertissements, puis un Tas de références non définies comme celle-ci:

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

Si je compile seulement avec -static et sans -optl-static Tout se passe bien, mais l'application se bloque quand elle essaie de démarrer Démarrer sur 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

J'ai essayé d'ajouter libgmp.so.10 à LD_LIBRARY_PATH comme suggéré dans ici , Puis j'ai obtenu l'erreur suivante:

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

Il semble que la version de libc que je compile soit différente de. J'ai également essayé d'ajouter libc au lot de bibliothèques de la même manière que pour libgmp, mais il en résulte une erreur de segmentation Lorsque l'application démarre du côté Heroku.

Tout fonctionne bien sur mon PC. J'utilise un archlinux 64 bits avec ghc 7.0.3. Le blog sur le blog officiel de Yesod semblait assez facile Mais je suis perplexe à ce stade. Quelqu'un a des idées? S'il y a un moyen de faire fonctionner cette chose sans bâtiment statique, je suis ouvert à cela aussi.

MODIFIER

Pour Employed Russians réponse j'ai fait ce qui suit pour résoudre ce problème.

D'abord créé un nouveau répertoire lib sous le répertoire du projet et y copié les bibliothèques partagées manquantes. Vous pouvez obtenir cette information en exécutant ldd path/to/executable et heroku run ldd path/to/executable et en comparant la sortie.

J'ai ensuite fait heroku config:add LD_LIBRARY_PATH=./lib afin qu'au démarrage de l'application l'éditeur de liens dynamique recherche les bibliothèques dans le nouveau répertoire lib.

Enfin, j'ai créé une machine virtuelle Ubuntu 11.10, puis construite et déployée sur Heroku à partir de là. Elle possède une glibc suffisamment ancienne pour fonctionner sur l'hôte Heroku.

Edit: J'ai depuis écrit un tutoriel sur le Yesod wiki

25
asm

Je n'ai aucune idée de ce qu'est Yesod, mais je sais que exactement ce que chacune de vos autres erreurs signifie.

Tout d'abord, vous devriez pas essayer de créer un lien statique. L’avertissement que vous obtenez est tout à fait exact: si vous établissez une liaison statique et utilisez l’une des routines pour lesquelles vous recevez cet avertissement, vous devez vous arranger pour que le système fonctionne avec un système identique à exactement version de libc.so.6 que celle que vous avez utilisée au moment de la compilation.

Contrairement aux idées reçues, les liens statiques produisent moins _, pas plus, des exécutables portables sous Linux.

Vos autres erreurs de liaison (statiques) sont dues à l'absence de libopenssl.a au moment de la liaison.

Mais supposons que vous allez suivre la voie "saine" et utiliser des liens dynamiques.

Pour la liaison dynamique, Linux (et la plupart des UNIX) prend en charge la compatibilité descendante: un ancien fichier binaire continue de fonctionner sur les systèmes les plus récents. Mais ils ne supportent pas la compatibilité en aval (un binaire construit sur un système plus récent exécutera généralement not sur un système plus ancien).

Mais c’est ce que vous essayez de faire: vous avez construit sur un système avec glibc-2.14 (ou plus récent) et vous utilisez un système avec glibc-2.13 (ou plus ancien).

Vous devez également savoir que la glibc est composée de plus de 200 fichiers binaires qui doivent tous correspondre à exactement. /lib/ld-linux.so et /lib/libc.so.6 (mais il en existe beaucoup plus: libpthread.so.0, libnsl.so.1, etc., etc.). Si certains de ces fichiers binaires proviennent de versions différentes de glibc, vous obtenez généralement un blocage. Et c’est exactement ce que vous avez obtenu lorsque vous avez essayé de placer votre glibc-2.14 libc.so.6 sur le LD_LIBRARY_PATH - il ne correspond plus au système /lib/ld-linux.

Alors, quelles sont les solutions? Il y a plusieurs possibilités (en difficulté croissante):

  1. Vous pouvez copier ld-2.14.so (la cible de /lib/ld-linux lien symbolique) sur le système cible et l'appeler explicitement:

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

    Cela fonctionne généralement, mais peut confondre une application qui regarde argv[0] et se casse pour les applications qui se re-exécutent elles-mêmes.

  2. Vous pouvez utiliser un système plus ancien.

  3. Vous pouvez utiliser appgcc (cette option a disparu, voir this pour une description de ce qu’elle était).

  4. Vous pouvez configurer un environnement chroot correspondant au système cible et construire à l'intérieur de ce chroot.

  5. Vous pouvez vous construire un compilateur croisé Linux-to-old

51
Employed Russian

Vous avez plusieurs problèmes.

Vous ne devez pas créer de fichiers binaires de production sur les distributions Edge saignantes. Les bibliothèques du système de production ne seront pas compatibles en aval.

Vous ne devriez pas lier statiquement glibc - au moment de l'exécution, le système essaiera de charger des bibliothèques supplémentaires. Par exemple, une assemblée basée sur un processeur. C'est ce que vos premiers avertissements concernent.

Les dernières erreurs de l'éditeur de liens semblent liées à une bibliothèque OpenSSL manquante sur la ligne de commande.

Mais dans l’ensemble, rétrogradez votre distribution.

5
user239558

J'ai eu des problèmes similaires lors du lancement de Heroku (qui utilise glibc-2.11), où j'avais une application nécessitant glibc-2.14, mais je n'avais pas accès à la source et ne pouvais pas la reconstruire. J'ai essayé beaucoup de choses et rien n'a fonctionné.

Ma solution consistait à lancer le service sur Amazon Elastic Beanstalk et à ne fournir qu'une interface API.

0
idrinkpabst