*************** ВВЕДЕНИЕ *****************
Итак дорогие мои, начнём забивание мозгов тем что "НИНУ́ЖНА".
С чего начать? Первое что приходит на ум, это как устроена система с точки зрения самой системы. Но это тупиковый путь, т.к. тема безгранична и до сути вопроса в практической плоскости данного топика можно никогда не добраться, поэтому задекларируем что мы это знаем.
Для построения системы потребуется немного чистого диска, для знакомства хватит пяти гигов(на самом деле всего 600-800 метров, но накладные расходы на сборку и исходники...).
Потребуется система, способная собрать gcc и glibc, что на самом деле довольно не тривиальная задача.
Потребуется специально огороженный юзер.
Вот с него и начнём.
Делается он так:
Консоль:
groupadd clfs
useradd -s /bin/bash -g clfs -d /home/clfs clfs
mkdir -pv /home/clfs
chown -v clfs:clfs /home/clfs
passwd clfs
вроде всё как всегда, что особенного?
Если вот прямо сейчас зайти в учётку этого юзера, то он получит все стандартные атрибуты обычного пользователя, на которые, в повседневности никто не смотрит, а тупо пользуется.
Это набор стандартных системных переменных, вот в них-то и вся соль.
Система сама их назначает из глобальных установок в /etc/profile, /etc/skell и остальных конфигураций в /etc, коих там вагон и не один.
Так вот для собирания(из исходников) кросскомпилятора gcc это всё высокотоксичный актив и от него нужно держаться подальше.
Для этого есть инструмент в самой системе - это индивидуальный профиль bash. Хранится он в `$HOME/.bash_profile и `$HOME/.bashrc. Первый инициатор этих установок, а второй - собственно установки.
Работает это так - при логине в профиль, система опрашивает домашний каталог на предмет наличия этих файлов и если они присутствуют, то глобальные настройки из /etc игнорируются.
Для нашей задачи это выглядит так:
cat $HOME/.bash_profile
exec env -i HOME=${HOME} TERM=${TERM} PS1='\u:\w\$ ' /bin/bash
cat ~/.bashrc
set +h
umask 022
CLFS=/mnt/clfs
LC_ALL=POSIX
PATH=/cross-tools/bin:/bin:/usr/bin
export CLFS LC_ALL PATH
unset CFLAGS CXXFLAGS PKG_CONFIG_PATH
вот теперь надо пояснить что есть что.
exec env -i HOME=${HOME} TERM=${TERM} PS1='\u:\w\$ ' /bin/bash
эта строчка указывает системе использовать переменные окружения только из домашнего каталога, никакие другие переменные, кроме объявленных локально не будут учитываться.
set +h
в баше есть функция кеша $PATH, укоряющая поиск приложений, т.е. однажды найденная программа ls по пути /usr/bin/ls, все последующие разы будет находиться по нему, не пересматривая весь $PATH, что разумно для простоты работы. Так вот set +h эту функцию отключает, теперь каждый раз, когда пользователь вводит какую либо команду, она будет находится обходом всего пути указанного в $PATH, зачем это надо я чуть позже растолкую.
CLFS=/mnt/clfs
просто переменная, указывающая где у нас "чистый лист".
LC_ALL=POSIX
тоже понятно? Для тугих - отмена всех языковых установок - только посикс, лютый хардкор девственной консоли.
PATH=/cross-tools/bin:/bin:/usr/bin
собственно PATH, тут важна последовательность поиска, первый же путь оказавшийся валидным и будет применён, если имеется /usr/bin/ls и /cross-tools/bin/ls, то использован будет последний, т.к. он первый в поиске. Это важно для правильного линкования, т.к. задача собрать кроскомпилятор не связанный с базовой системой ничем.
export CLFS LC_ALL PATH
собственно инициация переменных указанных выше.
unset CFLAGS CXXFLAGS PKG_CONFIG_PATH
отмена флагов компилятора если вдруг таковые были где-то заявлены системой.
Собственно с этим всё. Войдя в эту учётку стоит применить :
Консоль:
source ~/.bash_profile
и мы получим необходимый инструмент для дальнейшего продвижения.
..продолжение следует.
*** Добавлено: 29.09.2020 14:37:17 ***
..продолжим.
Сам по себе компилятор работать не может, ему нужен определённый обвяз. Фундаментом является связка с\с++, уже на ней строится всё остальное - фортраны, бейсики и прочий зоопарк из рептилий и всяких растов.
Подробно останавливаться на том кто есть кто я тут не буду, просто перечислю что нужно:
file
linux(заголовочные файлы ядра)
m4
ncurses
pkg-config
gmp
mpfr
mpc
isl(опционально, пакет не обязательный, но иногда дюже полезный, подробности можно почитать на сайте самого проекта http://isl.gforge.inria.fr/ )
binutils
gcc(собственно виновник этого треша)
glibc
но!!!
это только обвязка! Сам кросс-компилятор собирается отдельно с опорой вот на этот список.
Тут следует немного отступить от темы и погрузится теорию и практику собственно "сборки из исходных кодов".
Тема бездонная и крайне неоднозначная, но без базовых знаний дальнейшее будет просто непонятно.
...
*** Добавлено: 29.09.2020 15:32:12 ***
... про исходники.
Систем сборки существует море, и каждый день кто-то изобретает что-то новое. Но.. есть исторически сложившаяся практика применения самых древних, первых систем, и, негласное соглашение программистов, работающих над основами системы, использовать только их, вернее Её. Система на основе configure→make→make install.
Вот с её помощью и собирается базовый набор компиляции.
Там не сложно :
В дереве исходников запускается скрипт configure, который обрабатывает по своему алгоритму всё доступное пространство переменных(вот тут то и нужен наш огород!) и составляет последовательность компиляции.
Далее, если конфигурация завершается положительно, make, на основе выхлопа configure собирает всё в бинарные файлы.
А напоследок make же, на основе выхлопа configure выполняет процедуру install, устанавливая собранное в заранее обговоренные места.
configure, в зависимости от прямоты рук тех, кто его составлял принимает кучу аргументов, расписывающих какие переменные использовать, как и куда устанавливать программы, библиотеки и прочее.
вот тут то и встречается главная засада всех новичков - "как это работает вообще?!!!"... что тут можно посоветовать? - читайте доки(авось поможет). Важно понимать - без знания как этим пользоваться самостоятельно что-то собрать не получится... хотя... дуракам порой везёт, как знать, как знать...
*** Добавлено: 29.09.2020 16:28:29 ***
ну ладно, это всё лирика.
Практика - критерий истины, это нужно знать.
Попробуем создать первый кросс-тул.(их два).
Дальше можно просто копипастить шаги в консоль, позже я прокомментирую что зачем, пока тупо Ctrl+C & Ctrl+V...
Открываем консоль и становимся root'ом натурально:
0.
Консоль:
Сейчас все действия выполняются от root'а, пока я явно не укажу другое(п. 5)
1.
Консоль:
export CLFS=/mnt/clfs
mkdir -pv ${CLFS}
mount -v /dev/sdb2 ${CLFS}
install -dv ${CLFS}/tools
ln -sv ${CLFS}/tools /
install -dv ${CLFS}/cross-tools
ln -sv ${CLFS}/cross-tools /
!!! ахтунг !!! /dev/sdb2 - это пример! ставьте своё!
2.
Консоль:
groupadd clfs
useradd -s /bin/bash -g clfs -d /home/clfs clfs
mkdir -pv /home/clfs
chown -v clfs:clfs /home/clfs
passwd clfs
3.
Консоль:
chown -vR clfs:clfs ${CLFS}/tools
chown -vR clfs:clfs ${CLFS}/cross-tools
chown -v clfs:clfs /tools
chown -v clfs:clfs /cross-tools
cd ${CLFS}
mkdir sources
!!! ахтунг !!!
Теперь нужно запастись исходниками. Можно просто шарить по сети и тупо качать, можно на сайте проекта прочитать пункт
http://www.linuxfromscratch.org/lfs/vie … ction.htmlно есть одно "НО", я описываю создание немного более расширенной версии LFS, а именно multilib, там более жёсткие требования к среде, поэтому не всё что описано в LFS будет работать.
вот полный набор ссылок для кросс-компилятора:
1.
ftp://ftp.astron.com/pub/file/file-5.39.tar.gz2.
https://www.kernel.org/pub/linux/kernel … 8.9.tar.xz3.
http://ftp.gnu.org/gnu/m4/m4-1.4.18.tar.xz4.
http://ftp.gnu.org/gnu/ncurses/ncurses-6.2.tar.gz5.
http://sourceforge.net/projects/pkgconf … 8-1.tar.gz6.
http://ftp.gnu.org/gnu/gmp/gmp-6.2.0.tar.xz7.
http://www.mpfr.org/mpfr-4.1.0/mpfr-4.1.0.tar.xz8.
https://ftp.gnu.org/gnu/mpc/mpc-1.2.0.tar.gz9.
http://isl.gforge.inria.fr/isl-0.22.1.tar.xz(лучше использовать из git !!! →
https://repo.or.cz/w/isl.git )
10.
http://ftp.gnu.org/gnu/binutils/binutils-2.35.tar.xz11.
http://ftp.gnu.org/gnu/gcc/gcc-10.2.0/gcc-10.2.0.tar.xz12.
http://ftp.gnu.org/gnu/glibc/glibc-2.32.tar.xzВсё это нужно поместить в только что созданный каталог ${CLFS}/sources и присвоить нашему огороженному юзеру, а потом и войти в учётную запись:
4.
Консоль:
chown -vR clfs:clfs ${CLFS}/sources
su - clfs
5.(!!! ахтунг !!! теперь очень важные танцы с бубной !!!) мы теперь пользователь clfs и все действия в дальнейшем выполняются от его имени, пока я явно не укажу другое!!!
Консоль:
cat > ~/.bash_profile << "EOF"
exec env -i HOME=${HOME} TERM=${TERM} PS1='\u:\w\$ ' /bin/bash
EOF
cat > ~/.bashrc << "EOF"
set +h
umask 022
CLFS=/mnt/clfs
LC_ALL=POSIX
PATH=/cross-tools/bin:/bin:/usr/bin
export CLFS LC_ALL PATH
unset CFLAGS CXXFLAGS PKG_CONFIG_PATH
EOF
source ~/.bash_profile
6.
Консоль:
export CLFS_HOST=$(echo ${MACHTYPE} | sed -e 's/-[^-]*/-cross/')
export CLFS_TARGET="x86_64-unknown-linux-gnu"
export CLFS_TARGET32="i686-pc-linux-gnu"
export BUILD32="-m32"
export BUILD64="-m64"
cat >> ~/.bashrc << EOF
export CLFS_HOST="${CLFS_HOST}"
export CLFS_TARGET="${CLFS_TARGET}"
export CLFS_TARGET32="${CLFS_TARGET32}"
export BUILD32="${BUILD32}"
export BUILD64="${BUILD64}"
EOF
cd ${CLFS}/sources
Ну вот теперь можно собирать...
продолжение следует...
*** Добавлено: 29.09.2020 19:28:58 ***
gramozeka пишет:Ну вот теперь можно собирать...
...ну да, ну да, собирать. Надо прояснить некоторые моменты до того как.
Есть два подхода к процессу сборки - первый самый тупой и надёжный: зайти в дерево исходника и скомандовать "ату яво! фас!", как там в фильме: "...машина надёжная, убойная, 75 патронов, но весит...", это срабатывает для маленьких наколеночных вещей ака "Hello World!", но для чего-то серьёзного это не годится(если конечно важен не просто результат, а предсказуемый и, что важнее, обратимый результат, когда всё можно обернуть взад).
Для второго нужны скрипты, как правило на баше(не обязательно). В них прописывается весь сценарий сборки целиком, задача просто запустить скрипт и он всё что нужно выполнит.
В первой иттерации пакетирование(ещё одна фишка) не нужно, всё будем делать "по живому", но таки скриптиками запастись стоит...
*** Добавлено: 29.09.2020 20:20:19 ***
сама процедура проста:
распаковываем архив, заходим в него, выполняем последовательность команд:
./configure --prefix=/cross-tools
make -j4
make install
тут важен --prefix=/cross-tools (выше мы сделали симлинк в главном дереве системы на реальное расположение директории). Это нужно для того, чтоб готовые программы, оказавшись в изоляции, продолжали считать своё местоположение от корня.
Но это не всё, для каждого архива набор специфических установок разный. Чуть позже я залью обновлённое дерево на гитлаб, а пока просто приведу по порядку сборки для каждого архива:
file-5.39
./configure --prefix=/cross-tools
make
make install
linux-5.8.9
make mrproper
make INSTALL_HDR_PATH=dest headers_install
mkdir -pv /tools/include || true
cp -rv dest/include/* /tools/include
m4-1.4.18
sed -i 's/IO_ftrylockfile/IO_EOF_SEEN/' lib/*.c
echo "#define _IO_IN_BACKUP 0x100" >> lib/stdio-impl.h
./configure --prefix=/cross-tools
make
make install
сид тут редактирует устаревшие или глюкнутые артефакты, такого будет много, не пугайтесь.
ncurses-6.2
sed -i s/mawk// configure
./configure \
--prefix=/cross-tools \
--with-shared \
--without-debug \
--without-ada \
--enable-widec \
--enable-overwrite \
--without-gpm
make -C include
make -C progs tic
install -v -m755 progs/tic /cross-tools/bin
pkg-config-lite-0.28-1
./configure \
--prefix=/cross-tools \
--build=${CLFS_TARGET} \
--with-pc-path=/tools/lib64/pkgconfig:/tools/share/pkgconfig
make
make install
gmp-6.2.0
./configure \
--prefix=/cross-tools \
--enable-cxx \
--disable-static
make
make install
mpfr-4.1.0
LDFLAGS="-Wl,-rpath,/cross-tools/lib" \
./configure \
--prefix=/cross-tools \
--disable-static \
--with-gmp=/cross-tools
make
make install
mpc-1.2.0
LDFLAGS="-Wl,-rpath,/cross-tools/lib" \
./configure \
--prefix=/cross-tools \
--disable-static \
--with-gmp=/cross-tools \
--with-mpfr=/cross-tools
make
make install
isl-0.22.1
LDFLAGS="-Wl,-rpath,/cross-tools/lib" \
./configure \
--prefix=/cross-tools \
--disable-static \
--with-gmp-prefix=/cross-tools
make
make install
binutils-2.35
mkdir -v build
cd build
AR=ar AS=as \
../configure \
--prefix=/cross-tools \
--host=${CLFS_HOST} \
--target=${CLFS_TARGET} \
--with-sysroot=${CLFS} \
--with-lib-path=/tools/lib:/tools/lib64 \
--disable-nls \
--disable-static \
--enable-64-bit-bfd \
--enable-gold=yes \
--enable-plugins \
--enable-threads \
--disable-werror
make
make install
тут надо пояснить - некоторые проекты требуют, чтоб дерево исходников и директория сборки различались, поэтому создаём отдельную площадку где будет сборка.
gcc-10.2.0 - первый ход, предварительный. Далее директория для сборки будет создаваться вообще вне дерева исходников, для удобства.
patch -Np1 -i ../gcc-10.2.0-specs-1.diff
echo -en '\n#undef STANDARD_STARTFILE_PREFIX_1\n#define STANDARD_STARTFILE_PREFIX_1 "/tools/lib/"\n' >> gcc/config/linux.h
echo -en '\n#undef STANDARD_STARTFILE_PREFIX_2\n#define STANDARD_STARTFILE_PREFIX_2 ""\n' >> gcc/config/linux.h
touch /tools/include/limits.h
mkdir -v ../gcc-build
cd ../gcc-build
AR=ar \
LDFLAGS="-Wl,-rpath,/cross-tools/lib" \
../gcc-10.2.0/configure \
--prefix=/cross-tools \
--build=${CLFS_HOST} \
--host=${CLFS_HOST} \
--target=${CLFS_TARGET} \
--with-sysroot=${CLFS} \
--with-local-prefix=/tools \
--with-native-system-header-dir=/tools/include \
--disable-shared \
--with-mpfr=/cross-tools \
--with-gmp=/cross-tools \
--with-mpc=/cross-tools \
--with-isl=/cross-tools \
--without-headers \
--with-newlib \
--disable-decimal-float \
--disable-libgomp \
--disable-libssp \
--disable-libatomic \
--disable-libitm \
--disable-libsanitizer \
--disable-libquadmath \
--disable-libvtv \
--disable-threads \
--with-isl=/cross-tools \
--enable-languages=c,c++ \
--with-glibc-version=2.11
make -j4 all-gcc all-target-libgcc
make install-gcc install-target-libgcc
сам патч вот тут - https://gitlab.com/Gramozeka/kokoro/-/b … ecs-1.diff , он исправляет пути для автоматического линковщика, чтоб получившийся прекомпилятор не ломился в родительскую систему за каждой мелочёвкой, это важная примочка, но есть современные средства позволяющие получать тот же результат, но тогда надо полностью следовать путём предлагаемым в официальном руководстве и забыть о multilib.
glibc-2.32 32-бита.
mkdir -v ../build
cd ../build
echo "libc_cv_slibdir=/tools/lib" >> config.cache
BUILD_CC="gcc" \
CC="${CLFS_TARGET}-gcc ${BUILD32}" \
BUILD_CXX="g++" \
CXX="${CLFS_TARGET}-g++ ${BUILD32}" \
AR="${CLFS_TARGET}-ar" \
RANLIB="${CLFS_TARGET}-ranlib" \
../glibc-2.32/configure \
--prefix=/tools \
--host=${CLFS_TARGET32} \
--build=${CLFS_HOST} \
--enable-kernel=3.2 \
--with-binutils=/cross-tools/bin \
--with-headers=/tools/include \
--enable-add-ons \
--enable-obsolete-nsl \
--enable-obsolete-rpc \
--enable-profile \
--enable-static-nss \
--disable-werror
make -j4
make install
glibc-2.32 64-бита.
mkdir -v ../build
cd ../build
echo "libc_cv_slibdir=/tools/lib64" >> config.cache
BUILD_CC="gcc ${BUILD64}" \
CC="${CLFS_TARGET}-gcc ${BUILD64}" \
BUILD_CXX="g++ ${BUILD64}" \
CXX="${CLFS_TARGET}-g++ ${BUILD64}" \
AR="${CLFS_TARGET}-ar" \
RANLIB="${CLFS_TARGET}-ranlib" \
../glibc-2.32/configure \
--prefix=/tools \
--host=${CLFS_TARGET} \
--build=${CLFS_HOST} \
--libdir=/tools/lib64 \
--enable-kernel=3.2 \
--with-binutils=/cross-tools/bin \
--with-headers=/tools/include \
--enable-add-ons \
--enable-obsolete-nsl \
--enable-obsolete-rpc \
--enable-profile \
--enable-static-nss \
--cache-file=config.cache --disable-werror
make -j4
make install
Тут надо пояснить - материнская система должна уметь в мультилиб! Это без вариантов.
gcc-10.2.0_cross
Собственно первый ход кросс-компиляции, всё что выше это только прелюдия была.
patch -Np1 -i ../gcc-10.2.0-specs-1.diff
echo -en '\n#undef STANDARD_STARTFILE_PREFIX_1\n#define STANDARD_STARTFILE_PREFIX_1 "/tools/lib/"\n' >> gcc/config/linux.h
echo -en '\n#undef STANDARD_STARTFILE_PREFIX_2\n#define STANDARD_STARTFILE_PREFIX_2 ""\n' >> gcc/config/linux.h
mkdir -v ../gcc-build
cd ../gcc-build
AR=ar \
LDFLAGS="-Wl,-rpath,/cross-tools/lib" \
../gcc-10.2.0/configure \
--prefix=/cross-tools \
--build=${CLFS_HOST} \
--target=${CLFS_TARGET} \
--host=${CLFS_HOST} \
--with-sysroot=${CLFS} \
--with-local-prefix=/tools \
--with-native-system-header-dir=/tools/include \
--disable-static \
--enable-languages=c,c++ \
--with-mpc=/cross-tools \
--with-mpfr=/cross-tools \
--with-gmp=/cross-tools \
--with-isl=/cross-tools
make -j4 AS_FOR_TARGET="${CLFS_TARGET}-as" \
LD_FOR_TARGET="${CLFS_TARGET}-ld"
make install
Выполнив всё это, мы получим первый кросс-компилятор, способный собрать полноценное дерево cross-tools, с помощью которого можно собрать готовую систему, причём платформу можно выбирать в широких пределах, на то он и "кросс"... ну а можно и просто хелоуворды кАнпилять, какая разница в общем-то...
PS// об одной "мелочи" я не рассказал, это такая фича как
это девелоперская примочка, позволяющая тестировать собранное на предмет багов и вообще годности к использованию. Она важна с академической точки зрения, но простому обывателю мало пригодна и понятна, однако знать о ней нужно и даже иногда пользоваться. Только стоит учесть - если на сборку(make) глибса уйдёт примерно минут десять, то на make check после неё уйдёт более часа.
продолжение обязательно будет...
*** Добавлено: 30.09.2020 02:19:08 ***
...продолжим.
Маленькое лирическое отступление.
Современные тенденции в мире Linux меня лично не очень радуют. Корпорации медленно но верно прибирают к рукам все наработки сообщества. Потерингиада уже показывает своё истинное нутро, лишая по большей части манёвра и превращая систему в аналог Венды. Это удручает, но многим нравится, с этим тоже нужно считаться. Я несколько раз пробовал это поделие(systemD), но каждый раз убеждался - не стоит тратить на него время, оно как раковая опухоль, суёт свои метастазы в каждый уголок системы, а по последним сведениям и уже в ядро! Мутная, глюкавая, абсолютно не прозрачная прога пытается стать самой системой - это не юникс-вей! Кто бы что не говорил, нравится? Пользуйтесь, дело хозяйское, мы пока ещё в относительно свободном мире. Но по этой дороге я не ходок...
Итак, кросс-тул нейтрален, на его базе можно и системДЭ собрать, главное понимать что творишь, а там дело техники, но не спрашивайте меня как это делать, на сайте проекта есть ветка посвящённая этому чуду-юду.
А я по старинке, на SysVinit.
*******************************************
Важный момент. Мультилиб специфическая штука и во многих дистрах уже свернули работы по его поддержке, поэтому собрать gcc с его поддержкой будет проблематично. Я не совсем дока по части железа, поэтому стопроцентной гарантии не дам, но полный набор инструментов я построил на Intel(R) Core(TM) i5-3550 CPU @ 3.30GHz , обладатели аналогичных железок могут ими воспользоваться.
Лежит тут - https://gitlab.com/Gramozeka/kokoro/-/t … ross-tools
Достаточно распаковать оба архива в нужное место и после небольших манипуляций можно делать chroot в полностью готовую для сборки системы среду. Она уже умеет в мультилиб, поэтому иметь какую-то продвинутую систему не обязательно, лишь бы она(система) умела в chroot, и могла в 64-битное ядро, более-менее свежее.
********************************************
продолжу описание процесса.
...после сборки gcc-10.2.0_cross, мы всё ещё сильно зависим от материнской системы, нам нужны всякие тары, сиды, перлы и прочие питоны с башами. Второй этап это создание этих всех инструментов с привязанным к ним компилятором, который будет зависим только от самого себя.
Вот нужные инструменты по порядку сборки:
gmp
mpfr
mpc
isl
zlib
binutils
gcc
ncurses
bash
bzip2
check
coreutils
diffutils
file
findutils-
gawk
grep
gzip
m4
make
patch
sed
tar
xz
СТОП!!!!!! ЭТО ОТДЕЛЬНАЯ ПЕСТНЯ́!
gettext
bison
perl
Python
multiarch_wrapper
texinfo
util-linux
vim
Некоторые повторяются? ..хм, да, есть такое. Сейчас объясню механизм.
Наша цель с помощью работающей системы с компилятором А, построить работающую систему с компилятором С.
Но, прямым ходом, этого сделать нельзя, ибо динамическая линковка наше всё. Но её можно обмануть.
Схематично это работает так:
А собирает В1(выше это оно) с привязкой к посторонней директории в корне(это важно), со своим набором библиотек и заголовков, никак не слинкованными с основной системой.
Далее В1, собирает для себя вспомогательные инструменты и В2, которые привязаны только к нему, слинкованы с ним, и не имеют с материнской системой ничего общего.
Единственный недостаток - это всё привязано не к корню системы "/ ", а к директории в корне, при том, что имеет некоторые связи с В1.
Так вот когда мы соберём С с помощью В2 основываясь на реальном корне системы "/", мы избавимся и от В1, и от В2, и получим самодостаточный компилятор в нативной среде. Для этого нам понадобится chroot.(но это чуть позже)
В этот раз, мы уже имеем компилятор который к материнской системе не принадлежит, всё ещё оставаясь огороженным пользователем clfs, добавим несколько переменных и изменим саму среду сборки:
Консоль:
export CC="${CLFS_TARGET}-gcc ${BUILD64}"
export CXX="${CLFS_TARGET}-g++ ${BUILD64}"
export AR="${CLFS_TARGET}-ar"
export AS="${CLFS_TARGET}-as"
export RANLIB="${CLFS_TARGET}-ranlib"
export LD="${CLFS_TARGET}-ld"
export STRIP="${CLFS_TARGET}-strip"
echo export CC=\""${CC}\"" >> ~/.bashrc
echo export CXX=\""${CXX}\"" >> ~/.bashrc
echo export AR=\""${AR}\"" >> ~/.bashrc
echo export AS=\""${AS}\"" >> ~/.bashrc
echo export RANLIB=\""${RANLIB}\"" >> ~/.bashrc
echo export LD=\""${LD}\"" >> ~/.bashrc
echo export STRIP=\""${STRIP}\"" >> ~/.bashrc
Это очень важный момент, так как в окружении пользователя глобально объявлены переменные CC, CXX и т.д., то при умолчании, скрипты configure, сперва будут искать в системе именно эти компиляторы и инструменты, а в некоторых, так и вовсе только эти переменные и отвечают за правильное обращение к сборочному процессу, а т.к. хеширование у оболочки отключено, то в первую очередь будет найден наш новый кросс-компилятор
x86_64-unknown-linux-gnu-gcc , а не системный gcc.
После объявления этих переменных, можно начинать собирать вторую часть кросс-компилятора(выше список). Подробно расписывать все 33 позиции наверно не стоит, слишком уж много места это занимает.
Подробно можно посмотреть вот тут - https://gitlab.com/Gramozeka/kokoro/-/t … ary-System
там всё должно быть понятно, если есть желание, то немного доработав(заменив или убрав переменные скрипта) можно просто собирать вручную.
На счет "СТОП!!!!!! ЭТО ОТДЕЛЬНАЯ ПЕСТНЯ́!". Это один из тонких моментов.
Некоторые вещи, такие как perl или python, при сборке крайне неразборчивы и мало-управляемые, поэтому практически не пригодны для кросс-компиляции, т.к. собираясь, они находят в системе самих же себя установленных, и наглухо линкуются с тем, что есть, запретить это или как-то ограничить просто не реально. Поэтому, дойдя до этого места, дособирать кросс-тул придётся уже в chroot-окружении.
***************************************
Вернёмся к вопросу возможности материнской системы к собиранию мультилиба, выше ссылка на два архива, если нет возможности собрать нативный мультилиб, то можно воспользоваться уже готовым кросс-тулом, в нем уже собраны все нужные вещи, в том числе и эта пестня с питонами и перлами...
Кто-то заметил - а что за приблуда multiarch_wrapper ? В самом низу поясню зачем это.
*************************************************
... дойдя до этого места, дособирать кросс-тул придётся уже в chroot-окружении.
Для этого, собрав всё до xz включительно, нужно выйти из учетки clfs, он больше не нужен и его можно удалить из системы полностью, необходимо, оставаясь root'ом, создать в устанавливаемой системе необходимое дерево процессов ака proc, dev, var и т.д., создать ноды(что это вообще за чертовщина!?) и прочие моменты, монтируем это всё хозяйство в ядро работающей системы и выполняем chroot:
(!!!Ахтунг!!! Теперь мы root! Практически партизан в тылу врага, поэтому делаем всё очень вдумчиво и аккуратно.)
Консоль:
mkdir -pv ${CLFS}/{dev,proc,run,sys}
mknod -m 600 ${CLFS}/dev/console c 5 1
mknod -m 666 ${CLFS}/dev/null c 1 3
mount -v -o bind /dev ${CLFS}/dev
mount -vt devpts -o gid=5,mode=620 devpts ${CLFS}/dev/pts
mount -vt proc proc ${CLFS}/proc
mount -vt tmpfs tmpfs ${CLFS}/run
mount -vt sysfs sysfs ${CLFS}/sys
[ -h ${CLFS}/dev/shm ] && mkdir -pv ${CLFS}/$(readlink ${CLFS}/dev/shm)
а теперь Горбатый!!!(чрутимся в наш шалашик):
Консоль:
chroot "${CLFS}" /tools/bin/env -i \
HOME=/root TERM="${TERM}" PS1='\u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
/tools/bin/bash --login +h
Выполнив это мы увидим вот такую картинку:
Консоль:
I have no name!:/#
теперь мы единственный и безраздельный пользователь с безграничными полномочиями в системном пространстве будущей системы, в которой пока нет ничего, кроме пустоты.
Теперь нужно построить всё системное дерево "как у людей":
Консоль:
chown -Rv 0:0 /tools
chown -Rv 0:0 /cross-tools
mkdir -pv /{bin,boot,dev,{etc/,}opt,lib{,64},mnt}
mkdir -pv /{proc,media/{floppy,cdrom},run/{,shm},sbin,srv,sys}
mkdir -pv /var/{lock,log,mail,spool}
mkdir -pv /var/{opt,cache,lib/{misc,locate},local}
ln -sv lib /var/lib64
install -dv /root -m 0750
install -dv {/var,}/tmp -m 1777
ln -sv ../run /var/run
mkdir -pv /usr/{,local/}{bin,include,lib{,64},sbin,src}
mkdir -pv /usr/{,local/}share/{doc,info,locale,man}
mkdir -pv /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv /usr/{,local/}share/man/man{1..8}
install -dv /usr/lib/locale
ln -sv ../lib/locale /usr/lib64
ln -sv /tools/bin/{bash,cat,echo,grep,pwd,stty} /bin
ln -sv /tools/bin/file /usr/bin
ln -sv /tools/lib/libgcc_s.so{,.1} /usr/lib
ln -sv /tools/lib64/libgcc_s.so{,.1} /usr/lib64
ln -sv /tools/lib/libstd* /usr/lib
ln -sv /tools/lib64/libstd* /usr/lib64
ln -sv bash /bin/sh
задать все те мелочи что мы делали прежде:
Консоль:
export BUILD32="-m32"
export BUILD64="-m64"
CLFS_TARGET32="i686-pc-linux"
CLFS_TARGET="x86_64-Phoniex-linux"
ну и прибить это всё гвоздями к учётной записи пока ещё единственного пользователя:
Консоль:
cat >> ${CLFS}/root/.bash_profile << EOF
export BUILD32="${BUILD32}"
export BUILD64="${BUILD64}"
export CLFS_TARGET32="${CLFS_TARGET32}"
export CLFS_TARGET="${CLFS_TARGET}"
EOF
Чтобы всё это заработало как надо, нужно создать системные декорации для root'а и системы сборки:
Консоль:
cat > /etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:/bin:/bin/false
daemon:x:2:6:/sbin:/bin/false
messagebus:x:27:27:D-Bus Message Daemon User:/dev/null:/bin/false
nobody:x:65534:65533:Unprivileged User:/dev/null:/bin/false
EOF
cat > /etc/group << "EOF"
root:x:0:
bin:x:1:
sys:x:2:
kmem:x:3:
tty:x:5:
tape:x:4:
daemon:x:6:
floppy:x:7:
disk:x:8:
lp:x:9:
dialout:x:10:
audio:x:11:
video:x:12:
utmp:x:13:
usb:x:14:
cdrom:x:15:
adm:x:16:
input:x:24:
messagebus:x:27:
mail:x:30:
wheel:x:39:
nogroup:x:65533:
EOF
touch /var/log/{btmp,faillog,lastlog,wtmp}
chgrp -v utmp /var/log/{faillog,lastlog}
chmod -v 664 /var/log/{faillog,lastlog}
chmod -v 600 /var/log/btmp
А теперь объявляем себя Государем Мира!
Консоль:
exec /tools/bin/bash --login +h
и увидим скромное:
Консоль:
root:/#
Т.к. ранее был собран минимальный набор системных функций, то простейшие команды уже доступны и можно смело перемещаться по системе.
Тут нужно оговориться - я собираю всё в специально организованном загончике, но можно всё делать и по живому, например в /tmp.
Делаем cd /tmp, распаковываем нужный исходник, например unxz /sources/gettext-0.21.tar.xz, переходим в него и собираем.
Все нужные опции можно подсмотреть в ветке Temporary-System тут https://gitlab.com/Gramozeka/kokoro/-/tree/master/ . Все программы из второго списка собираются в /tools, а после входа в чрут, туда же дособираются и эти :
gettext
bison
perl
Python
multiarch_wrapper
texinfo
util-linux
vim
Когда это всё собрано, можно приступать собственно к построению своей собственной системы, так, как взбредёт в голову. Есть конечно базовый минимум, который нужно построить чтобы просто удалить наши кросс-инструменты, вот примерный список :
linux-5.8.9
man-pages-5.08
glibc-2.32
tools-prep
link-glibc-32
zlib-1.2.11
bzip2-1.0.8
xz-5.2.5
zstd-1.4.5
file-5.39
ncurses-6.2
readline-8.0
m4-1.4.18
bc-3.1.5
flex-2.6.4
binutils-2.35
gmp-6.2.0
mpfr-4.1.0
mpc-1.2.0
isl-0.22.1
attr-2.4.48
acl-2.2.53
libcap-2.43
shadow-4.8.1
gcc-10.2.0-final
pkg-config-0.29.2
ncurses-6.2-final
sed-4.8
psmisc-23.3
gettext-0.21
bison-3.7.2
binutils-2.35_i686
grep-3.4
bash-5.0
libtool-2.4.6
gdbm-1.18.1
gperf-3.1
expat-2.2.9
inetutils-1.9.4
perl-5.32.0
XML-Parser-2.46
intltool-0.51.0
autoconf-2.69
automake-1.16.2
kmod-27
elfutils-0.181
libffi-3.3
openssl-1.1.1g
Python-3.8.5
re2c-2.0.3
ninja-1.10.1
meson-0.55.3
coreutils-8.32
check-0.15.2
diffutils-3.7
gawk-5.1.0
findutils-4.7.0
groff-1.22.4
grub-2.04
less-551
gzip-1.10
iproute2-5.8.0
kbd-2.3.0
libpipeline-1.5.3
make-4.3
patch-2.7.6
man-db-2.9.3
tar-1.32
texinfo-6.7
vim-8.2.1361
eudev-3.2.9
procps-ng-3.3.16
util-linux-2.36
e2fsprogs-1.45.6
sysklogd-1.5.1
sysvinit-2.97
libseccomp-2.5.0
iana-etc-2.30
libsigsegv-2.12
pcre-8.44
cpio-2.13
gc-8.0.4
gpm-1.20.7
libatomic_ops-7.6.10
lsb-release-1.4
После сборки shadow нужно задать пароль рута, после сборки bash который /bin/bash(не забыли, у нас есть ещё и /tools/bin/bash) нужно войти в новый баш, и продолжать уже из него...
Важная тонкость - есть такой пакет libffi, отвечает за интерфейсы программных вызовов при работе с процессором, так вот по умолчанию у неё стоит флаг сборки --with-gcc-arch=native, т.е. она собирается под тот процессор, который сейчас реально собирает, и если мы попытаемся перенести всю собранную систему на другое железо, с другим процессором(пусть даже и того же вендора), то есть большой шанс словить "Illegal Operation Errors" и полностью неработающую систему, чтобы это избежать нужно либо явно указывать архитектуру на которой в последствии всё это будет работать, либо выставлять некие виртуальные усреднения ака x86_64. Подробности читать тут - https://gcc.gnu.org/onlinedocs/gcc-10.2 … tions.html
...
Список дан в той последовательности, в которой он гарантированно соберётся, без конфликта зависимостей,цифры дело временное, на момент написания этого поста этот набор был собран и проверен, система загрузилась штатно, без костылей и примочек, можно собирать любой собственный софт по задачам.
Да-да, про ядро и настройки ни слова .
Это отдельное лютое шаманство.
Когда вот это всё собрано, собственно и наступает момент истины, насколько мы вообще представляем "как это работает".
Последовательность действий такова:
Сперва нужно выйти из системы в материнскую систему и войти обратно явно указав использовать /tools/bin/bash, это нужно для процедуры strip, она сильно уменьшает объём занимаемого пространства, буквально в разы, да и быстродействие повышает. Чистится всё хозяйство примерно так:
Консоль:
chroot ${CLFS} /tools/bin/env -i \
HOME=/root TERM=${TERM} PS1='\u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin \
/tools/bin/bash --login
Консоль:
/tools/bin/find /{,usr/}{bin,lib,lib64,sbin} -type f \
-exec /tools/bin/strip --strip-debug '{}' ';'
Сообщения :
File format not recognized
игнорируем, это значит что файл либо сценарий оболочки, либо служебный конфиг.
После можно ещё выполнить :
--strip-all
Консоль:
/tools/bin/find /{,usr/}{bin,sbin} -type f \
-exec /tools/bin/strip --strip-all '{}' ';'
но это уже на собственное усмотрение, один момент - не стоит делать --strip-all для
библиотек(в lib,lib64) это может привести к неработоспособности системы...
Выходим снова в хост-систему:
Консоль:
logout
и входим в уже полностью сформированную новую систему:
Консоль:
chroot "$CLFS" /usr/bin/env -i \
HOME=/root TERM="$TERM" \
PS1='(clfs chroot) \u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin \
/bin/bash --login
, а теперь само шаманство...
Сперва нужно построить всё в /etc
Есть уже подготовленный минимум для SysVinit лежит тут
http://www.linuxfromscratch.org/lfs/dow … 818.tar.xzНужно распаковать архив в в нём выполнить make install безо всего.
Затем необходимо настроить udev, там много чего можно сделать, самое простое :
Консоль:
bash /lib/udev/init-net-rules.sh
Затем сеть, в каноническом SysVinit это имеет свою специфику, подробно описано тут -
http://www.linuxfromscratch.org/lfs/vie … twork.htmlВсе инициирующие скрипты и настройки описаны тут -
http://www.linuxfromscratch.org/lfs/vie … usage.htmlНастройка глобального профиля баш целая наука, минимум описан тут -
http://www.linuxfromscratch.org/lfs/vie … ofile.html ,
http://www.linuxfromscratch.org/lfs/vie … putrc.html ,
http://www.linuxfromscratch.org/lfs/vie … hells.htmlКогда всё это сделано собственно остаётся только собрать своё ядро, установить загрузчик и всё, система готова. Правда она ещё ничерта не может, ни сеть толком, ни всяких гитов и иксов, но это уже другая глава, где нужно решать вопросы с пакетной системой, стратегический план построения системы, что нужно, а что не очень, как автоматизировать те или иные процессы и т.д.. Частично это описано тут - http://www.linuxfromscratch.org/blfs/view/svn/, но далеко не всё, тут уже личная квалификация рулит и педалит. Я конечно это всё решил по своему и сейчас пишу из вот этого всего, есть проект моих портянок, скорее всего через какое-то время(до месяца, возможно и дольше) я залью свой набор готовой системы под вот это ядро - https://gitlab.com/Gramozeka/kokoro , но это процесс не быстрый, так что придумывайте без меня, задавайте вопросы, что знаю подскажу.
*** Добавлено: 30.09.2020 03:39:24 ***
*********
отдельно про multiarch_wrapper.
Т.к. у нас мультилиб, встаёт вопрос - как сепарировать библиотеки и бинарники разных битностей.
Вот это multiarch_wrapper для того и нужен. Если библиотеки можно разнести по lib32 и lib64, то с бинарниками это всё сложнее, потом, когда система уже собрана, это всё решается в индивидуальном порядке, я например всю ветку 32-бит вынес в отдельный анклав в корне /i686 со своим системным деревом, практически контейнер аль-ля docker, но на этапе сборке это всё не так просто.
Работает он (multiarch_wrapper) очень просто, кто секёт в ссях может почитать сам:
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#ifndef DEF_SUFFIX
# define DEF_SUFFIX "64"
#endif
int main(int argc, char **argv)
{
char *filename;
char *suffix;
if(!(suffix = getenv("USE_ARCH")))
if(!(suffix = getenv("BUILDENV")))
suffix = DEF_SUFFIX;
if (asprintf(&filename, "%s-%s", argv[0], suffix) < 0) {
perror(argv[0]);
return -1;
}
int status = EXIT_FAILURE;
pid_t pid = fork();
if (pid == 0) {
execvp(filename, argv);
perror(filename);
} else if (pid < 0) {
perror(argv[0]);
} else {
if (waitpid(pid, &status, 0) != pid) {
status = EXIT_FAILURE;
perror(argv[0]);
} else {
status = WEXITSTATUS(status);
}
}
free(filename);
return status;
}
работает это так:
имеем приложение uasya_hakir под обе архитектуры( т.е. два бинарника с одинаковым названием, но разной битности). То, что на 32-bit переименовываем в uasya_hakir-32, а то что на 64-bit в uasya_hakir-64. Теперь создаём ссылку uasya_hakir на скомпилированный бинарник multiarch_wrapper.
И ??? Объявляем глобальную системную переменную USE_ARCH в двух видах : USE_ARCH=32 и USE_ARCH=64. Теперь, чтобы запустить 32-х битный вариант uasya_hakir , вызываем его так :
Консоль:
/$ USE_ARCH=32 uasya_hakir
или, если нам нужна 64-х битная версия то :
Консоль:
/$ USE_ARCH=64 uasya_hakir
или вообще :
Консоль:
/$ uasya_hakir
т.к. по умолчанию принята 64-bit архитектура. Врапер подменяет продолжение имени ссылки на необходимую цифру и вызывает это полное имя. Это нужно для двухголового питона и перла, на этапе сборки основной системы, подробней как я это устроил смотрите в скриптах на кокоро.
*** Добавлено: 30.09.2020 22:44:06 ***+
" si contuderis stultum in pila quasi tisanas feriente desuper pilo non auferetur ab eo stultitia eius " © Proverbs 27:22