Развертывание Yesod в Heroku, не может строить статически - PullRequest
26 голосов
/ 28 декабря 2011

Я очень новичок в 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

Я попытался добавить 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.

На моем компьютере все работает нормально.Я использую 64-битную версию archlinux с ghc 7.0.3. Сообщение в блоге на официальном блоге Йесода выглядело довольно легко, но я в этом тупике.У кого-нибудь есть идеи?Если есть способ заставить эту штуку работать без статического построения, я тоже открыт для этого.

РЕДАКТИРОВАТЬ

За 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

Ответы [ 3 ]

54 голосов
/ 28 декабря 2011

Понятия не имею, что такое Йесод, но я точно знаю 1002 *, что означает каждая из ваших других ошибок.

Во-первых, вы должны не пытаться связывать статически. Полученное предупреждение совершенно верно: если вы статически связываете и используете одну из подпрограмм, для которых вы получаете предупреждение, то вы должны организовать работу в системе с точно та же версия 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.0, libnsl.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-для-Linux Linux

5 голосов
/ 28 декабря 2011

У вас есть несколько проблем.

Вы не должны создавать производственные двоичные файлы на передовых дистрибутивах. Библиотеки в производственной системе не будут напрямую совместимы.

Вы не должны связывать glibc статически - он всегда будет пытаться загрузить дополнительные библиотеки во время выполнения. Например сборка на основе процессора. Вот о чем ваши первые предупреждения.

Последние ошибки компоновщика выглядят так, как будто они связаны с отсутствующей библиотекой openssl в командной строке.

Но в целом - понизьте ваш дистрибутив.

0 голосов
/ 13 июля 2013

У меня были похожие проблемы с запуском в Heroku (который использует glibc-2.11), где у меня было приложение, которое требовало glibc-2.14, но у меня не было доступа к источнику, и я не мог пересобрать его. Я перепробовал много вещей, но ничего не получалось.

Мой обходной путь - запустить сервис на Amazon Elastic Beanstalk и просто предоставить интерфейс API.

...