Pull to refresh

Кросс-компиляция в OS X под Linux используя crosstool-ng

Reading time4 min
Views13K


В данной заметке речь пойдёт о замечательном средстве автоматизации сборки кросс-тулчейнов crosstool-ng, практически незаменимого инструмента для любого уважающего себя embedded-разработчика. Если вам приходилось по-серьёзному собирать софт из x86-linux под arm-linux, то вы наверняка слышали о нём.

В данном руководстве рассматривается не столько кросс-компиляция по архитектуре, сколько кросс-компиляция по системе — сборка под Linux в Darwin.

Disclaimer

В интернете есть несколько статей по сборке crosstool-ng под OS X, например на benmont.com и в официальном руководстве. Тем не менее, в некоторых статьях встречается множество ошибок и устаревших сведений, а в других описываются лишь общие черты. Здесь будет описан мой путь, по которому я успешно собрал toolchain в июле 2013.

Подготовка

Эта часть зависит от того, какой пакетный менеджер вы используете в OS X — MacPorts или Homebrew. Я для себя давно выбрал ports-way, так что буду писать исходя из этого.

1. Регистрозависимая файловая система
Тут всё просто, в OS X есть утилита Disk Utility, воспользуемся ей для создания нового раздела. Потребуется 5+ Гб.



2. Инструменты
Предполагается, что у вас установлен MacPorts. Установим следующие пакеты:

ncurses
lzma
libtool
binutils
gsed
gawk
grep
gcc48

Проверим, какие версии gcc есть в системе: sudo port select --list gcc. Нам нужна mp-gcc48 — выбираем по-умолчанию командой sudo port select --set gcc mp-gcc48.

3. Установка crosstool-ng
Собирать сам инструментарий достаточно просто, воспользуемся официальной инструкцией:

hg clone http://crosstool-ng.org/hg/crosstool-ng
cd crosstool-ng
./bootstrap

Вынужден прервать официальную инструкцию: в файле kconfig/zconf.hash.c не хватает строчки
#include <stddef.h>

./configure \
--with-objcopy=/opt/local/bin/gobjcopy \
--with-objdump=/opt/local/bin/gobjdump \
--with-readelf=/opt/local/bin/greadelf \
--with-sed=/opt/local/bin/gsed \
--with-libtool=/opt/local/bin/glibtool \
--with-grep=/opt/local/bin/grep \
--with-install=/opt/local/bin/ginstall
make
sudo make install

Это установит ct-ng в /usr/local/bin. Домашняя директория ct-ng: /usr/local/lib/ct-ng.hg+default-2685dfa9de14 в зависимости от ревизии. В этой директории отредактируем файл scripts/functions, заменив строчку для Darwin строчкой от Linux:
--- scripts/functions.orig  2013-07-09 22:15:12.000000000 +0400
+++ scripts/functions   2013-07-06 04:28:41.000000000 +0400
@@ -460,7 +460,7 @@
                 mode="$(stat -c '%a' "$(dirname "${dir}")")"
                 ;;
             Darwin|*BSD)
-                mode="$(stat -f '%Lp' "$(dirname "${dir}")")"
+                mode="$(stat -c '%a' "$(dirname "${dir}")")"
                 ;;
             *)
                 CT_Abort "Unhandled host OS $CT_SYS_OS"

Это потому, что ct-ng случайно хавает версию gstat из GNU-набора, вместо оригинального stat из OS X. Полюбуйтесь красотой и изящностью здешнего кода и закройте файл.

Можете также скопировать скрипт ct-ng.comp для bash-completion, работает хорошо.
Теперь нужно выбрать временную папку, в которой будут коваться наш замечательный cross-toolchain и его sysroot. У меня это /Volumes/Unixen/ct-config, перейдите в вашу папку и начнём настройку.

Настройка crosstool-ng

Прежде чем начать настройку, унаследуем конфигурацию от шаблона. Нас интересует x86_64-unknown-linux-gnu:

cd /Volumes/Unixen/ct-config
ct-ng x86_64-unknown-linux-gnu
ct-ng menuconfig

После этого вы видите меню, в котором мы будем настраивать наш инструментарий.

1. Paths and misc options
Здесь важно указать опции Local tarballs directory (/Volumes/Unixen/src) и Prefix directory (/Volumes/Unixen/${CT_TARGET}), не забудьте создать /Volumes/Unixen/src.

2. C compiler
Здесь я отключил поддержку Java и Fortran, потому что не знаю, как поведёт себя GCC при сборке с включёнными фичами. Обязательно отключаем [ ] Link libstdc++ statically into the gcc binary, иначе будет ошибка
collect2: error: ld returned 1 exit status
ld: library not found for -lcrt0.o 

3. Debug facilities
Здесь придётся отключить поддержку dmalloc и ltrace, так как иначе будут нерешаемые проблемы. В разделе gdb следует отключить [ ] Native gdb и, если нет необходимости, отключить [*] Enable python scripting (проблема с python, но решение будет ниже). Я использую версию gdb version (7.3.1).

4. Companion libraries
Здесь строго следующие версии библиотек, иначе будут ошибки компиляции и autotools, эти версии подбирал методом тыка, зачастую помогал выбор более свежей.
      * GMP version (5.0.2)
      * MPFR version (3.1.2)
      * PPL version (0.11.2)
      * CLooG version (0.15.11)
      * MPC version (1.0.1)

Сборка toolchain

Практически всё готово. В процессе сборки может возникнуть следующая ошибка (версия ядра указана моя):
[ERROR]    /Volumes/Unixen/ct-config/.build/src/linux-3.8.11/arch/x86/tools/relocs.c:8:17: fatal error: elf.h: No such file or directory

Поэтому заранее позаботимся об этом, взяв elf.h из доверенного источника. Если под рукой нет, возьмите мой elf.h. Класть нужно в /usr/include.

Ещё нужно подправить лимит открытых файлов (RE: Libc iconvdata compilation problem):
ulimit -n 1024

Если во время сборки у вас возникнет ошибка в gdb, если вы не отключили [*] Enable python scripting раньше:
configure: error: python is missing or unusable

то отредактируйте файл .build/gdb-*/gdb/python/python-config.py, закомментировав строки
#            if getvar('LINKFORSHARED') is not None:
#                libs.extend(getvar('LINKFORSHARED').split())

Кажется, всё готово.
ct-ng build

На Macbook Air с i5 сборка идёт порядка 69 минут, причём у вас скорее всего в середине всплывут какие-нибудь ошибки. Так что отойти далеко от компьютера не получится.

Заключение




/Volumes/Unixen $ du -csh ct-config/
4,0G    ct-config/
4,0G    итого

/Volumes/Unixen $ x86_64-unknown-linux-gnu/bin/x86_64-unknown-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=x86_64-unknown-linux-gnu/bin/x86_64-unknown-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/Volumes/Unixen/x86_64-unknown-linux-gnu/libexec/gcc/x86_64-unknown-linux-gnu/4.7.3/lto-wrapper
Configured with: /Volumes/Unixen/ct-config/.build/src/gcc-4.7.3/configure --build=x86_64-build_apple-darwin12.4.0 --host=x86_64-build_apple-darwin12.4.0 --target=x86_64-unknown-linux-gnu --prefix=/Volumes/Unixen/x86_64-unknown-linux-gnu --with-sysroot=/Volumes/Unixen/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/sysroot --enable-languages=c,c++ .....
Target: x86_64-unknown-linux-gnu
Thread model: posix
gcc version 4.7.3 (crosstool-NG hg+default-2685dfa9de14) 

Можно попробовать что-нибудь собрать:
cd linux-source-3.9
export PATH=$PATH:/Volumes/Unixen/x86_64-unknown-linux-gnu/bin
export C_INCLUDE_PATH=/usr/include:/opt/local/include:/Volumes/Unixen/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/sysroot/usr/include
make ARCH=x86_64 CROSS_COMPILE=x86_64-unknown-linux-gnu- all -j4

Успехов,
Xlab was there.
Tags:
Hubs:
Total votes 30: ↑29 and ↓1+28
Comments9

Articles