Всем привет, возникло такое чувство, что только у меня возникают какие-то проблемы с кросс-компиляцией util-linux, потому что в интернетах на этот счёт пусто, но мне кажется, что моя проблема должна возникать просто у всех.
Итак, я собрал тулчейн (gcc, glibc, sysroot). Беру util-linux-2.27.1, распаковываю его, собираю:
$ ./configure --build=x86_64-pc-linux-gnu --host=arm-rpi-linux-gnueabihf
$ make V=1
Отлично, это всё прошло без ошибок. Смотрим, что там натворил libtool:
$ arm-rpi-linux-gnueabihf-objdump -x .libs/libblkid.so | grep RPATH
RPATH /tmp/util-linux-2.27.1/.libs
Собиралось это добро такой командой: http://pastebin.com/fsaCgF5n
Выхлоп от команды был следующий: http://pastebin.com/6geAwkKk
Было бы нехорошо такой бинарник ставить в таргет. Но ничего, на этот счёт у libtool есть свой костыль — relink. При make install перелинкуются заново все библиотеки без добавления каталога сборки в rpath.
Пробуем:
make install V=1 DESTDIR=/tmp/dest
Терпим фиаско при попытке релинка libblkid. Выхлоп по делу: http://pastebin.com/6ej6KNaw
Теперь сравниваем, как libtool вызывал gcc при первой линковке и при второй, пробуем также запускать обе команды с -Wl,--verbose
и делаем следующие выводы:
Команды отличаются только тем, что в первую приходит -Wl,-rpath -Wl,/tmp/util-linux-2.27.1/.libs ./.libs/libuuid.so
, а во вторую -L/tmp/dest/usr/lib -L/usr/lib -luuid
.
Не линкуется во второй раз, потому что когда линкер ищет libc.so, то из-за флагов -L
у второй команды он сначала пойдёт по этим директориям, в первой ничего не найдёт, а вот во второй найдёт /usr/lib/libc.so, представляющий собой ld-script, и дело закончится попыткой слинковаться с libc.so с хоста.
Осталось понять, откуда такие флаги у второй команды. Не вопрос, libtool'у аргументом приехал libuuid.la (libuuid тоже входит в состав util-linux), смотрим в него, а там:
# Directory that this library needs to be installed in:
libdir='/usr/lib'
Потом смотрим в код libtool, который поставляется с util-linux-2.27.1, строка 7342:
# We cannot seem to hardcode it, guess we'll fake it.
add_dir="-L$libdir"
# Try looking first in the location we're being installed to.
if test -n "$inst_prefix_dir"; then
case $libdir in
[\\/]*)
add_dir+=" -L$inst_prefix_dir$libdir"
;;
esac
fi
add="-l$name"
Весь скрипт здесь: http://pastebin.com/fds2eKCA
Не копал, куда дальше уезжает эта переменная add_dir
, но её изменение в этом месте приводит к изменению тех самых флагов -L
, которые приезжают линкеру.
Простое решение, казалось бы, приходит сразу. Убираем add_dir="-L$libdir"
, потому что нам не нужно, чтобы линкеру передавался /usr/lib
с хоста. Однако это вызывает массу вопросов:
- Для чего-то же это сделано. Для чего-то при установке в DESTDIR линкеру передаётся и путь без DESTDIR тоже. Почему-то ведь нет проверки на то, кросс-компиляция это или нет. Почему-то никак не учитывается sysroot, хотя в libtool есть некая переменная
lt_sysroot
. Поэтому первый вопрос: почему сделано именно так? - Что сломается, если это изменить? Здесь я имею в виду не только util-linux, но и другие пакеты на libtool.
- Почему я не нахожу других людей, сталкивающихся с этой проблемой? Очевидно, не я один кросс-компилирую util-linux. Может, я что-то делаю не так? Максимум, что я находил, это письмо разработчика buildroot с аналогичным вопросом. Ответы на него были полезными, но они не отвечают на мои вопросы.
Я также пробовал смотреть, как кросс-компилируют util-linux в других проектах:
- CLFS безнадёжно протух, там очень древние версии всего, и там непохоже, чтобы они как-то пытались решить эту проблему. Возможно, там она и не возникает, но я пойти по их руководству и проверить пока не пробовал.
- Buildroot не решает эту проблему. Он маскирует её другой, незаметной проблемой. Он накладывает патчи на libtool, после чего relink не выполняется в принципе, и в таргет отправляются бинарники с rpath, указывающим на каталог сборки на хосте.
- В Gentoo при сборке util-linux на libtool тоже накладываются патчи, но они, как мне показалось, не касаются этой проблемы. Попытка кросс-компилировать util-linux с помощью portage успехом не увенчалась, до сборки дело просто не дошло. Я собрал тулчейн crossdev'ом, потом начал делать emerge, указав
--root
и--config-root
, но portage не смог распарсить профиль. Возможно, дело в моей специфической конфигурации, но с этой проблемой мне предстоит справляться самому.
Основной и наиболее общий вопрос из всего этого: как всё-таки собрать util-linux правильно?