Бывает, что перед разработчиком встаёт задача собрать проект, запускающийся на одной платформе, но при этом для разработки проекта используется другая. Для этих целей применяется кросс-компилятор - специальная сборка компилятора, работающая на host-платформе, и генерирующая код для target-платформы. Здесь я расскажу как собирать gcc с хостом на x86, генерирующий код под sparc.
Думаю вкратце понятно что такое кросс-компилятор, и для чего он нужен, поэтому немного о данной заметке. Во многом это будет вольный конспект данного поста. Основное различие в том, что там автор собирал компилятор для arm, а я делаю это для sparc, что вносит свои коррективы. Ну и я попытался немного автоматизировать данный процесс.
Итак, поехали. Создаём какую-нибудь директорию, и скачиваем туда всё необходимое:
Это набор необходимых пакетов. Здесь используется транковская версия gcc (можно и стабильную) и транковская версия glibc. Последнее связано с тем что >=gcc-5 не собирает glibc-2.22 из-за ошибок компиляции. Недавно вышел glibc-2.23, но я его не пробовал.
gcc использует сторонние библиотеки, поэтому для сборки нужно их заранее подготовить:
Теперь создадим директорию куда будем устанавливать компилятор и библиотеки:
Сначала соберём binutils. В нём содержатся кросс-ассемблер, кросс-линкер и прочие инструменты:
Далее ставим некоторые файлы ядра чтобы приложения могли использовать спарковские системные вызовы
Собираем только компиляторы без библиотек
Конфигурацию gcc следует подстраивать под себя, мне обычно нужно чтобы компилятор имел фронтенды только для c/c++/fortran (опция --enable-languages), а также чтобы он умел lto.
Теперь ставим заголовочные файлы glibc. При этом создадим заглушку для libc.so. Тут стоит обратить внимание на опцию "-fno-stack-protector", без неё версия для sparc не соберётся.
Теперь соберём библиотеки поддержки компилятора. В них, например, содержится обработка исключений c++.
Непосредственно собираем и устанавливаем glibc
И последнее - собираем и устанавливаем стандартную библиотеку c++:
Собственно, всё, теперь можно использовать кросс-компилятор. Пока что мне не удалось собрать версию под 64 бита с multilib'ом - т.е. чтобы компилятор целевой платформой имел sparc64, но при этом умел генерить 32-х битный код, но в целом это не большая потеря. Можно тупо собрать две версии компилятора.
Также у автора оригинального поста есть скрипт для автоматической сборки, но я его не тестировал.
Думаю вкратце понятно что такое кросс-компилятор, и для чего он нужен, поэтому немного о данной заметке. Во многом это будет вольный конспект данного поста. Основное различие в том, что там автор собирал компилятор для arm, а я делаю это для sparc, что вносит свои коррективы. Ну и я попытался немного автоматизировать данный процесс.
Итак, поехали. Создаём какую-нибудь директорию, и скачиваем туда всё необходимое:
$ mkdir tmp && cd tmp
$ svn checkout svn://gcc.gnu.org/svn/gcc/trunk gcc_trunk
$ wget http://ftp.gnu.org/gnu/binutils/binutils-2.25.tar.gz
$ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/testing/linux-4.4-rc3.tar.xz
$ git clone git://sourceware.org/git/glibc.git
$ wget http://ftp.gnu.org/gnu/glibc/glibc-2.22.tar.xz
$ wget http://www.mpfr.org/mpfr-current/mpfr-3.1.3.tar.xz
$ wget https://gmplib.org/download/gmp/gmp-6.1.0.tar.xz
$ wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.2.tar.gz
$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.15.tar.bz2
$ for i in *.tar*; do tar -xpvf $i; done
Это набор необходимых пакетов. Здесь используется транковская версия gcc (можно и стабильную) и транковская версия glibc. Последнее связано с тем что >=gcc-5 не собирает glibc-2.22 из-за ошибок компиляции. Недавно вышел glibc-2.23, но я его не пробовал.
gcc использует сторонние библиотеки, поэтому для сборки нужно их заранее подготовить:
$ pushd gcc_trunk/
$ ln -s ../mpfr-3.1.3 mpfr
$ ln -s ../gmp-6.1.0 gmp
$ ln -s ../mpc-1.0.2 mpc
$ ln -s ../isl-0.15 isl
$ popd
Теперь создадим директорию куда будем устанавливать компилятор и библиотеки:
$ mkdir cross
$ export PREFIX="`pwd`/cross" # Директория установки
$ export TARGET="sparc-sun-linux" # Целевая архитектура
$ # export TARGET="sparc64-sun-linux" # Это если нам нужен 64-х битный sparc
$ export PATH="$PREFIX"/bin:$PATH # Пути для бинарников
Сначала соберём binutils. В нём содержатся кросс-ассемблер, кросс-линкер и прочие инструменты:
$ export BINUTILS_OBJS="`pwd`/binutils_objs"
$ export BINUTILS_SRC="`pwd`/binutils-2.25/"
$ mkdir -p "$BINUTILS_OBJS"
$ pushd "$BINUTILS_OBJS" > /dev/null
$ "$BINUTILS_SRC"/configure --prefix="$PREFIX" --target=$TARGET --with-sysroot
$ make -j5
$ make install
$ popd > /dev/null
Далее ставим некоторые файлы ядра чтобы приложения могли использовать спарковские системные вызовы
$ export LINUX_SRC="`pwd`/linux-4.4-rc3"
$ pushd "$LINUX_SRC" > /dev/null
$ export LINUX_ARCH="sparc"
$ # export LINUX_ARCH="sparc64" # Это для 64-х битной версии
$ make ARCH=$LINUX_ARCH INSTALL_HDR_PATH="$PREFIX/$TARGET" headers_install
$ popd > /dev/null
Собираем только компиляторы без библиотек
$ export GCC_OBJS="`pwd`/gcc_objs"
$ export GCC_SRC="`pwd`/gcc_trunk"
$ mkdir -p "$GCC_OBJS"
$ pushd "$GCC_OBJS" > /dev/null
$ "$GCC_SRC"/configure --prefix="$PREFIX" --target=$TARGET --enable-languages=c,c++,fortran --enable-gold=yes --enable-ld=yes --enable-lto CFLAGS="-O3" CXXFLAGS="-O3"
$ make -j5 all-gcc
$ make install-gcc
$ popd > /dev/null
Конфигурацию gcc следует подстраивать под себя, мне обычно нужно чтобы компилятор имел фронтенды только для c/c++/fortran (опция --enable-languages), а также чтобы он умел lto.
Теперь ставим заголовочные файлы glibc. При этом создадим заглушку для libc.so. Тут стоит обратить внимание на опцию "-fno-stack-protector", без неё версия для sparc не соберётся.
$ export GLIBC_OBJS="`pwd`/glibc_objs"
$ export GLIBC_SRC="`pwd`/glibc"
$ mkdir -p "$GLIBC_OBJS"
$ pushd "$GLIBC_OBJS" > /dev/null
$ "$GLIBC_SRC"/configure --prefix="$PREFIX"/$TARGET/ --build=$MACHTYPE --host=$TARGET --target=$TARGET --with-headers="$PREFIX"/$TARGET/include CFLAGS="-O2 -fno-stack-protector" CPPFLAGS="-O2 -fno-stack-protector"
$ make install-bootstrap-headers=yes install-headers
$ make -j5 csu/subdir_lib
$ install csu/crt1.o csu/crti.o csu/crtn.o "$PREFIX"/$TARGET/lib
$ "$PREFIX"/bin/$TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o "$PREFIX"/$TARGET/lib/libc.so
$ touch "$PREFIX"/$TARGET/include/gnu/stubs.h
$ popd > /dev/null
Теперь соберём библиотеки поддержки компилятора. В них, например, содержится обработка исключений c++.
$ pushd "$GCC_OBJS" > /dev/null
$ make -j5 all-target-libgcc
$ make install-target-libgcc
$ popd > /dev/null
Непосредственно собираем и устанавливаем glibc
$ pushd "$GLIBC_OBJS" > /dev/null
$ make -j8
$ make install
$ popd > /dev/null
И последнее - собираем и устанавливаем стандартную библиотеку c++:
$ pushd "$GCC_OBJS" > /dev/null
$ make -j8
$ make install
$ popd > /dev/null
Собственно, всё, теперь можно использовать кросс-компилятор. Пока что мне не удалось собрать версию под 64 бита с multilib'ом - т.е. чтобы компилятор целевой платформой имел sparc64, но при этом умел генерить 32-х битный код, но в целом это не большая потеря. Можно тупо собрать две версии компилятора.
Также у автора оригинального поста есть скрипт для автоматической сборки, но я его не тестировал.
Комментариев нет:
Отправить комментарий
Примечание. Отправлять комментарии могут только участники этого блога.