[devel] erlang: asking for a hint, possibly with --as-needed

Mikhail Yakshin =?iso-8859-1?q?greycat_=CE=C1_altlinux=2Eorg?=
Вс Фев 11 23:24:09 MSK 2007


Dmitry V. Levin wrote:
> On Sat, Feb 10, 2007 at 10:47:51PM +0300, Mikhail Yakshin wrote:
>> Я тут взялся глобально перелопачивать Erlang
> 
> Значит, всеобщее счастье не за горами. :)

Я, пожалуй, не так сильно оптимистичен...

>> 2. Эрланг - это довольно объемный пакет, собирается где-то по 30-40
>> минут на сборку.
> 
> На каких мощностях?  Тот пакет, который сейчас в Сизифе, собирается раза в
> 2 быстрее.

Видимо, на сборочных серверах и полностью в tmpfs. Какой смысл сравнивать?

>> Сборочное окружение субъективно мною характеризуется
>> как "невменяемое": масса хаков вокруг autoconf на тему поддержки
>> совместимости с win32, вывернутая наизнанку схема генерации
>> Makefile <-> Makefile.in,
> 
> Это как?  Из Makefile формируются Makefile.in?

Все Makefile, как правило, не генерящиеся. В них записано по 3 строчки
вроде:

include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
include $(ERL_TOP)/make/otp_subdir.mk

Через несколько уровней вызовов этих мейкфайлов из $(ERL_TOP)/make/,
которые там что-то у себя внутри детектят, дефайнят и в зависимости от
этого принимают какие-то решения, в итоге каким-то образом управление
передается в Makefile.in, лежащий в той же директории, тоже не генерящийся.

Масла в огонь подливает то, что по сути там не 1 проект, а под сотню
разных проектов, вложенных друг в друга. В некоторых местах иерархии
есть свой корень, свой собственный configure и там целое отдельное
приложение, библиотека или статический object

>> 3. Проблемы в #10657 побеждены посредством -fno-stack-protector, как в
>> Ubuntu.
> 
> На первом этапе это логичное решение, но потом придётся найти что-то
> получше.

Чем дальше я копаюсь с erlang - тем больше убеждаюсь в том, что это
такое нечто, которое проще как-то собрать, забыть и не трогать, пока не
сломается что-то критичное. По хорошему - там надо бы начинать с полной
перестройки всей системы сборки, его раскладывания файлов (которое
абсолютно не соответствует идеологии FHS) и т.п.

На Erlang, насколько я понял, есть целых 2 приложения для простых
смертных в этом мире: ejabberd (xmpp-сервер) и yaws (http-сервер).
Остальное - огромная куча какого-то проприетарного и очень специфичного
софта для телефонии имени самого Ericson'а и т.п.

>> 4. Сама сборка пестрит большим количеством warning'ов об undefined
>> symbol в verify-elf (потому что там масса .so-шек, подгружаются
>> виртуальной машиной на лету, как плагины) и одним TEXTREL'ом в районе
>> сборки с openssl - оно у нас там уже давно стоит на relaxed.
> 
> Во что превращается этот TEXTREL на x86-64?

Пока еще не добрался.

>> 5. Есть проблема со сборкой erl_interface - это некий компонент erlang
>> (интерфейс к C), без которого он работать теоретически может, но
>> ejabberd без него не соберется.
>>
>> Я подозреваю, что проблема в --as-needed и порядке линковки. На других
>> системах (Fedora, BSD, Debian), люди говорят, что все собирается. Кусок
>> лога:
>>
>> gcc -pipe -Wall -O2 -march=i586 -mtune=i686 -fno-stack-protector -Wall
>> -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
>> -Wnested-externs -Winline -fno-strict-aliasing -I. -I../include
>> -Iconnect -Iencode -Idecode -Imisc -Iepmd -Iregistry -Ii686-pc-linux-gnu
>>   -Ilegacy -o
>> /home/greycat/RPM/BUILD/otp_src_R11B-3/lib/erl_interface/bin/i686-pc-linux-gnu/erl_call
>> prog/erl_call.c prog/erl_start.c \
>> 	
>> -L/home/greycat/RPM/BUILD/otp_src_R11B-3/lib/erl_interface/obj/i686-pc-linux-gnu
>> -lei -lrt -lresolv -lnsl
>> /tmp/.private/greycat/ccawXslX.o: In function `main':
>> erl_call.c:(.text+0x1994): undefined reference to `__erl_errno'
>> /home/greycat/RPM/BUILD/otp_src_R11B-3/lib/erl_interface/obj/i686-pc-linux-gnu/libei.a(ei_connect.o):
>> In function `ei_do_receive_msg':
>> ei_connect.c:(.text+0x2d6): undefined reference to `__erl_errno'
>> ei_connect.c:(.text+0x319): undefined reference to `__erl_errno'
>> ei_connect.c:(.text+0x331): undefined reference to `__erl_errno'
> 
> Так и есть, libei.a не слинковано с тем, что содержит определение
> символа __erl_errno.
> 
>> Подскажите, что тут можно проверить и куда смотреть?
> 
> Посмотреть в лог сборки libei.a -- скорее всего там неправильный порядок
> линкуемых библиотек или даже просто нет нужной линкуемой библиотеки.

Понятно, спасибо. libei.a собирается вполне обычным способом из
следующих objects в таком порядке:

> ei_connect.o
ei_resolve.o eirecv.o send.o send_exit.o send_reg.o decode_atom.o
decode_big.o decode_bignum.o decode_binary.o decode_boolean.o
decode_char.o decode_double.o decode_fun.o decode_intlist.o
decode_list_header.o decode_long.o decode_pid.o decode_port.o
decode_ref.o decode_skip.o decode_string.o decode_trace.o
decode_tuple_header.o decode_ulong.o decode_version.o decode_longlong.o
decode_ulonglong.o encode_atom.o encode_bignum.o encode_binary.o
encode_boolean.o encode_char.o encode_double.o encode_fun.o
encode_list_header.o encode_long.o encode_pid.o encode_port.o
encode_ref.o encode_string.o encode_trace.o encode_tuple_header.o
encode_ulong.o encode_version.o encode_longlong.o encode_ulonglong.o
epmd_port.o epmd_publish.o epmd_unpublish.o ei_decode_term.o ei_format.o
ei_locking.o ei_malloc.o ei_portio.o ei_printterm.o
> ei_pthreads.o
ei_trace.o ei_x_encode.o eimd5.o get_type.o show_msg.o ei_compat.o
hash_dohash.o hash_foreach.o hash_freetab.o hash_insert.o hash_isprime.o
hash_lookup.o hash_newtab.o hash_remove.o hash_resize.o hash_rlookup.o
reg_close.o reg_delete.o reg_dirty.o reg_dump.o reg_free.o reg_get.o
reg_getf.o reg_geti.o reg_getp.o reg_gets.o reg_make.o reg_open.o
reg_purge.o reg_resize.o reg_restore.o reg_set.o reg_setf.o reg_seti.o
reg_setp.o reg_sets.o reg_stat.o reg_tabstat.o

Значком ">" я отметил интересующие нас сейчас objects. Определяться
__erl_errno должна по идее в ei_pthreads.o, а используется в
ei_connect.o. Только здесь какая-то ерунда получается: если посмотреть в
ei.h, то там эта переменная определена как:

#if defined(_REENTRANT) || defined(VXWORKS) || defined(__WIN32__)
/* 'erl_errno' as a function return value */
volatile int* __erl_errno_place(void) __attribute__ ((__const__));
#define erl_errno (*__erl_errno_place ())
#else /* !_REENTRANT && !VXWORKS && !__WIN32__ */
extern volatile int __erl_errno;
#define erl_errno __erl_errno
#endif /* !_REENTRANT && !VXWORKS && !__WIN32__ */

Насколько я понял - _REENTRANT - это какой-то флаг-характеристика
системы. Не знаю, должен он быть установлен он у нас или нет и за что
отвечает (гугл однозначного ответа на этот вопрос не дает), но, в данном
случае, насколько я проверил - не установлен. В итоге у нас есть простое
определение переменной и просто алиас на нее:

extern volatile int __erl_errno;
#define erl_errno __erl_errno

В ei_pthreads.c же, где по идее и должно быть реальное объявление (без
extern) этой переменной, есть 2 варианта ее определения:

1. volatile __declspec(thread) int __erl_errno = 0;
2. static volatile int __erl_errno;

Вариант 1 засунут под ifdef __WIN32__, вариант 2 - под ifdef VXWORKS. У
нас, очевидно, ни один из них. В итоге что получается, когда есть
extern, но нет реально объявленной переменной?

К коду ei_connect.c претензий нет - там все достаточно чисто -
используется именно erl_errno, запрос к __erl_errno получается именно
из-за дефайна.

Видимо, на всех тех машинах, где Erlang собирается под Linux/BSD, стоит
этот _REENTRANT => нет такого понятия, как __erl_errno вообще? Есть
какие-то мысли, как это правильно исправить? Все упирается, видимо, в
то, что такое дефайн _REENTRANT, почему у нас его нет и что сломается от
того, если я его определю?

Плюс, после того, как разберемся с этим вопросом, ei_pthreads.o и
ei_connect.o в порядке линковки надо поменять местами, я правильно понимаю?

-- 
WBR, Mikhail Yakshin AKA GreyCat
ALT Linux [http://www.altlinux.ru] [xmpp:greycat на altlinux.org]



Подробная информация о списке рассылки Devel