"Телевидение – это НЕ реальная жизнь. В действительности людям обычно приходится ходить на работу, а не сидеть за столиком кафе." Билл Гейтс

Содержание:

6. Установка основного системного программного обеспечения

Не рекомендуется использовать оптимизацию. Она может ускорить работу программы, но при этом могут возникнуть проблемы при компиляции и запуске. Если пакет не удается скомпилировать с включенной оптимизацией, необходимо её отключить, и выполнить повторную компиляцию. Даже если компиляция пакета была успешной, с включенной оптимизацией, существует риск что компиляция была выполнена неправильно, потому что могут быть сложные взаимодействия между кодом и инструментами сборки. Обращаем внимание, что аргументы -march и -mtune не использованы. Они могут вызвать проблемы с программами набора временных инструментов, таких как Binutils, GCC и Glibc. Потенциальные преимущества при использовании оптимизации компилятора не так высоки по сравнению с рисками.
Порядок установки пакетов очень важен. Необходимо строго соблюдать последовательность сборки и установки пакетов, для гарантии того, что устанавливаемый пакет не будет иметь ссылку на каталог /tools. По этой же причине, не следует компилировать пакеты параллельно. Выполняя компиляцию параллельно, можно сэкономить время (особенно на многопроцессорных или многоядерных машинах), но это может привести к тому, что если программа имеет связи с каталогом /tools при выполнении она может перестать работать когда этот каталог будет удалён.
Как правило, редакторы LFS препятствуют созданию и установке статических библиотек. Первоначальная цель использования большинства статических библиотек в современных Linux системах устарела. Кроме того, связывание статической библиотеки в программу может быть не самым лучшим решением. Если требуется обновление библиотеки, для устранения проблем безопасности, то все программы, которые используют статическую библиотеку, должны выполнить повторную компоновку (линковку), чтобы изменить ссылку на новую версию библиотеки. Поскольку использование статических библиотек не всегда бывает очевидным, программы (и процедуры, необходимые для выполнения повторной компоновки) могут быть неизвестными.
В процедурах будет удалена или закрыта возможность установки большинства статических библиотек. Как правило, такое правило передается аргументом --disable-static в сценарий configure. В некоторых случаях, необходимы альтернативные пути решения. Особенно это относится к пакетам glibc и gcc, где наличие статических библиотек остается неотъемлемым для общего процесса сборки пакетов.

6.2. Подготовка виртуальных файловых систем ядра

Различные файловые системы, экспортируемые ядром, используются для связи с ним. Они являются виртуальными, поскольку нет диска, на котором они бы использовались. Содержимое такие файловых систем располагается в памяти.
Создадим структуру каталогов, куда будет выполнено монтирование виртуальных файловых систем.

mkdir -pv $LFS/{dev,proc,sys,run}

Когда ядро выполняет загрузку системы, ему требуется наличие нескольких устройств, таких как console и null. Эти узлы должны быть созданы на диске, для того, чтобы они были доступны после того, как запустится udevd и дополнительно, когда Linux запустится с init=/bin/bash. Создадим такие устройства:

mknod -m 600 $LFS/dev/console c 5 1
mknod -m 666 $LFS/dev/null c 1 3


Рекомендуемый метод заполнения каталога (ссылки на устройства) /dev - примонтировать виртуальную файловую систему (такую, как tmpfs) в каталог /dev, и разрешить устройствам динамически создаваться на этих файловых системах по мере их обнаружения или возможности доступа к ним. Создание устройств обычно выполняется во время процесса загрузки программы Udev. Но поскольку в новой системе ещё отсутствует эта программа, следовательно устройства добавлены не будут. Необходимо вручную связать устройства из каталога /dev хост-системы. Привязка - это особый вид монтирования, который позволяет создавать зеркало каталога в указанной точке монтирования в другом местоположении:

mount -v --bind /dev $LFS/dev

Теперь, необходимо примонтировать оставшиеся виртуальные файловые системы:

mount -vt devpts devpts $LFS/dev/pts -o gid=5,mode=620
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
mount -vt tmpfs tmpfs $LFS/run


Значение параметров монтирования для devpts:
gid=5 Это гарантирует, что все созданные devpts узлы устройств будут принадлежать группе с идентификатором 5 (GID 5). Этот идентификатор будет использоваться позднее для группы tty. Вместо имени группы, используется идентификатор, потому что в хост-системе, может использоваться иной идентификатор для группы tty.
mode=0620 Это гарантирует, что все созданные devpts узлы будут иметь режим 0620 (чтение пользователем, запись пользователем, запись группой). Одновременно с вышеуказанной командой такой подход гарантирует что devpts создаст узлы устройств в соответствии с требованиями grantpt (), имея в виду вспомогательную библиотеку Glibc pt_chown ( по умолчанию не установлена) которая не требуется.
В некоторых хост-системах, каталог /dev/shm является символической ссылкой на /run/shm. /run tmpfs был установлен выше, поэтому нужно создать только каталог.

if [ -h $LFS/dev/shm ]; then
mkdir -pv $LFS/$(readlink $LFS/dev/shm)
fi

6.3. Управление пакетами

Менеджер пакетов позволяет отслеживать установку файлов, делая процесс удаления и обновления пакетов существенно проще. Кроме файлов и библиотек, пакетный менеджер будет управлять установкой файлов конфигурации.
Некоторые моменты, которые необходимо учесть при обновлении пакетов до новых версий, особенно если обновление происходит на запущенной системе:
Если необходимо обновить пакет Glibc до новой версии безопаснее всего выполнить сборку всей системы LFS заново. Также, можно выполнить пересборку всех пакетов в порядке их зависимостей. Не такой подход не рекомендуется.
Если пакет содержащий разделяемую (shared) библиотеку обновлён, и наименование библиотеки изменилось, тогда все пакеты, которые динамически скомпонованы к библиотеке нужно заново компилировать, с указанием на новую версию библиотеки.(нет никакой корреляции между версией пакета и имени библиотеки). Например, пакет foo-1.2.3 который установил разделяемую библиотеку с наименованием libfoo.so.1. Допустим, обновили пакет до новой версии - foo-1.2.4, который установил новую версию разделяемой библиотеки libfoo.so.2. В данном случае, все пакеты, динамически слинкованные на библиотеку libfoo.so.1 должны быть заново скомпилированы с указанием на новую версию библиотеки libfoo.so.2. Не следует удалять предыдущие версии библиотек до тех пор, пока все пакеты, которые на неё ссылаются не перекомпилированы.
Ниже приведены некоторые общие методы управления пакетами. До принятия решения о менеджере пакетов, проведём некоторое исследование различных методов, особенно обращаем внимание на их недостатки:
Установка в отдельные каталоги. Это упрощенная техника, для которой не требуются дополнительные программы или пакеты, для управления установкой. Каждый пакет устанавливается в отдельный каталог. Например пакет foo-1.1 будет установлен в каталог /usr/pkg/foo-1.1 и символическая ссылка будет создана с /usr/pkg/foo на каталог /usr/pkg/foo-1.1. При установке новой версии пакета foo-1.2, он будет установлен в каталог /usr/pkg/foo-1.2 а предыдущая символическая ссылка будет заменена символической ссылкой на каталог с новой версией пакета.
Переменные окружения, такие как PATH, LD_LIBRARY_PATH, MANPATH, INFOPATH и CPPFLAGS необходимо расширить, включив каталог /usr/pkg/foo. Для большого количества пакетов, такая техника становится неуправляемой.
Управление пакетами с использованием символических ссылок. Это вариация предыдущей техники. Каждый пакет устанавливается аналогично, но вместо создания символической ссылки, каждому файлу создаётся символическая ссылка в иерархию каталогов /usr. Это исключает необходимость модификации значений переменных окружения. Такие ссылки могут быть созданы пользователям вручную, для автоматизации создания пакетов, однако, многие менеджеры пакетов были созданы с использованием именной такого метода. Наиболее популярные из них - Stow, Epkg, Graft, и Depot.
Установка должна быть подделана, чтобы пакет считал что его установка производится в каталог /usr, однако, на самом деле, он будет установлен в иерархие каталогов /usr/pkg. Установка пакетов таким способом может быть нетривиальной задачей. Например, будет произведена установка пакета libfoo-1.1. Следующие инструкции не позволят установить пакет должным образом:

./configure --prefix=/usr/pkg/libfoo/1.1
make
make install


Установленный таким образом пакет будет работать, но те пакеты, которые имеют от него зависимости, могут не иметь ссылки на libfoo как и следовало ожидать. Если компилируется пакет, который ссылается на libfoo, можно заметить, что он связан с /usr/pkg/libfoo/1.1/lib/libfoo.so.1 вместо /usr/lib/libfoo.so.1 как и следовало ожидать. Правильный подход заключается в использовании переменной окружения DESTDIR чтобы подделать установку пакета. Такой метод работает следующим образом:

./configure --prefix=/usr
make
make DESTDIR=/usr/pkg/libfoo/1.1 install


Большинство пакетов поддерживают такой способ, но некоторые нет. Для несовместимых пакетов, понадобится вручную выполнить установку пакета, или еще проще устанавливать такие пакеты в каталог /opt.
На основе временной метки. Файлу присваивается метка времени, перед установкой пакета. После установки, выполняется команда find с соответствующими параметрами, результат выполнения которой будет представлять из себя журнал со всеми файлами установленных после указанной метки времени. Пакетный менеджер, использующий такой подход имеет журнал установки.
Этот метод имеет преимущество - простота, но имеет и несколько недостатков. В процессе установки, файлы, которые были установленны с другими метками времени, которые отличаются от текущего времени, не будут отслеживаться пакетным менеджером. Также, возможно устанавливать один пакет за раз. Журналы ненадежны, если два пакета установлены их двух разных терминалов.
Отслеживание сценариев установки. Этот метод заключается в записи команд, выполняемых сценарием установки. Есть два подхода, как использовать данный метод:
Переменная окружения LD_PRELOAD может быть указана на предварительно загруженную библиотеку перед установкой. В процессе установки эта библиотека отслеживает пакеты, которые будут установлены присоединяя себя к различным исполняемым файлам, таким как cp, install, mv для отслеживания системных вызовов, которые вносят изменения в файловую систему. Для работоспособности этого метода, все исполняемые файлы должны быть динамически связаны без использования битов suid или sgid. Предзагрузка библиотеки может вызвать нежелательные побочные эффекты в процессе установки. Поэтому, рекомендуется выполнить тесты, для того, чтобы гарантировать, что пакетный менеджер не испортил что-либо и отследил все необходимые файлы.
Второй подход заключается в использовании программы strace, которая регистрирует все системные вызовы, во время выполнения сценариев установки.
Создание архивов для пакетов. При этой схеме, установка будет подменена в отдельное дерево каталогов, как описано в разделе Управление пакетами с использованием символических ссылок. После установки, архив с пакетом создается используя установленные файлы. Этот архив теперь будет использоваться для установки пакета либо на локальном компьютере, либо может использоваться на других машинах.
Этот подход используется большинством пакетных менеджеров в коммерческих дистрибутивах. Примеры пакетных менеджеров которые следуют этому подходу - RPM (который, кстати, требуется в базовой спецификации Linux Standard Base Specification (LSB), pkg-utils, apt дистрибутива Debian и система портов Gentoo. Подсказка, описывающая, как принять этот стиль управления пакетами для систем LFS, находится здесь.
Дистрибутив Slackware использует основанную на tar систему для архивации пакетов. Эта система намеренно не обрабатывает зависимости пакетов как это делают более сложные менеджеры пакетов. Подробнее об управлении пакетов в Slackware см. здесь.
Пользовательское управление пакетами. Эта схема является уникальной для LFS была разработана Матиасом Бенкманом, и описание доступно по ссылке Hints Project. Суть схемы в том, что каждый пакет, будет установлен как отдельный пользователь в стандартном местоположении. Файлы, принадлежащие пакету легко идентифицируются, путём определения пользовательского идентификатора. Особенности и недостатки этого подхода слишком сложны для описания в этом разделе. Подробнее см. здесь.
Одно из преимуществ системы LFS является то, что нет файлов, у которых есть строгая привязка к местоположению на диске. Можно запаковать корневой раздел (около 250MB в несжатом виде для базовой сборки LFS), например программой tar, скопировать по сети или записать на компакт-диск. А затем выполнить распаковку в требуемое место, и выполнить конфигурацию некоторых файлов, для правильного функционирования системы. Файлы, которые потерубется изменить включают в себя: /etc/hosts, /etc/fstab, /etc/passwd, /etc/group, /etc/shadow, /etc/ld.so.conf, /etc/sysconfig/rc.site, /etc/sysconfig/network, и /etc/sysconfig/ifconfig.eth0.
Может потребоваться дополнительная модификация ядра, в зависимости от разницы в аппаратной составляющей.
Могут возникнуть проблемы при копировании между аналогичными, но не идентичными архитектурами. Например, набор инструкций системы Intel не идентичен AMD, и версии некоторых процессоров могут иметь инструкции, которые недоступны в более ранних версиях.

6.4. Вход в окружение Chroot

Как пользователь root выполним следующую команду, для входа, с использованием созданного ранее набора временных инструментов, находящихся во временном каталоге tools:

chroot "$LFS" /tools/bin/env -i \
HOME=/root \
TERM="$TERM" \
PS1='(lfs chroot) \u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
/tools/bin/bash --login +h


Аргумент -i передаёт команде env значение, которое указывает полностью очистить все переменные окружения в окружении chroot. После чего, только переменные окружения HOME, TERM, PS1 и PATH будут указаны заново. Параметр TERM=$TERM устанавливает значение переменной окружения за пределами chroot окружения. Эта переменная необходима таким программам как vim и less для корректной работы. Если необходимы другие переменные окружения, такие как CFLAGS или CXXFLAGS, это как раз то место, где их можно указать.
Теперь нет необходимости использовать переменную окружения LFS, потому что вся работа будет ограничена файловой системой LFS. Так происходит, потому что оболочке Bash ранее сообщался в значении переменной $LFS путь до корня файловой системы, но на данный момент, она является корневым каталогом (/).
Необходимо обратить внимание что в переменной окружения PATH путь /tools/bin записан в последнюю очередь. Это означает, что временный инструмент не будет более использоваться после установки его окончательной версии. Это происходит, когда оболочка не «запоминает» пути к исполняемым бинарным файлам — по этой причине, хэширование выключено, указанием параметра +h к программе bash.
Когда оболочка запустится, bash выдаст приглашение командной строки вида "I have no name!". Это нормально, потому что файл /etc/passwd ещё не создан.
Если был сделан выход из среды chroot по каким-либо причинам (перезагрузка, например), необходимо убедиться в том, что виртуальные файловые системы были заново примонтированы, как рассказано в "6.2. Подготовка виртуальных файловых систем ядра". Далее входим в окружение chroot снова, чтобы продолжить установку.

6.5. Создание каталогов

Создадим стандартное дерево каталогов:

mkdir -pv /{bin,boot,etc/{opt,sysconfig},home,lib/firmware,mnt,opt}
mkdir -pv /{media/{floppy,cdrom},sbin,srv,var}
install -dv -m 0750 /root
install -dv -m 1777 /tmp /var/tmp
mkdir -pv /usr/{,local/}{bin,include,lib,sbin,src}
mkdir -pv /usr/{,local/}share/{color,dict,doc,info,locale,man}
mkdir -v /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -v /usr/libexec
mkdir -pv /usr/{,local/}share/man/man{1..8}
case $(uname -m) in
x86_64) mkdir -v /lib64 ;;
esac
mkdir -v /var/{log,mail,spool}
ln -sv /run /var/run
ln -sv /run/lock /var/lock
mkdir -pv /var/{opt,cache,lib/{color,misc,locate},local}


По умолчанию, созданные каталоги имеют права 755, но это нежелательно для всех каталогов. В командах приведенных выше, сделаны два изменения. Первое для каталога пользователя root, и второе для каталогов временных файлов.
Первое изменение гарантирует, что не каждый может войти в каталог /root так же, как обычный пользователь будет работать со своим домашним каталогом. Следующее изменение гарантирует что любой пользователь может записывать в дерево каталогов /tmp, но не может удалять файлы других пользователей. Последнее запрещено так называемым «sticky bit» - старший бит (1) в бит-маске 1777. Дерево каталогов основано на стандарте иерархий файловой системы (Filesystem Hierarchy Standard,FHS).

6.6. Создание основных файлов и символических ссылок

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

ln -sv /tools/bin/{bash,cat,dd,echo,ln,pwd,rm,stty} /bin
ln -sv /tools/bin/{env,install,perl} /usr/bin
ln -sv /tools/lib/libgcc_s.so{,.1} /usr/lib
ln -sv /tools/lib/libstdc++.{a,so{,.6}} /usr/lib
for lib in blkid lzma mount uuid
do
ln -sv /tools/lib/lib$lib.so* /usr/lib
done
ln -svf /tools/include/blkid /usr/include
ln -svf /tools/include/libmount /usr/include
ln -svf /tools/include/uuid /usr/include
install -vdm755 /usr/lib/pkgconfig
for pc in blkid mount uuid
do
sed 's@tools@usr@g' /tools/lib/pkgconfig/${pc}.pc \
> /usr/lib/pkgconfig/${pc}.pc
done
ln -sv bash /bin/sh


Описание ссылок
/bin/bash Большинство bash сценариев указывают на /bin/bash.
/bin/cat Этот путь жестко закодирован в сценарии конфигурирования Glibc.
/bin/dd Путь к dd будет жестко закодирован в утилите /usr/bin/libtool.
/bin/echo Используется для тестирования Glibc. Наборам тестов требуется /bin/echo.
/usr/bin/install Путь к install будет жестко закодирован в файле /usr/lib/bash/Makefile.inc.
/bin/ln Путь к ln будет жестко закодирован в файле /usr/lib/perl5/5.28.0/<target-triplet>/Config_heavy.pl.
/bin/pwd Некоторые configure сценарии, в частности Glibc's, имеют жестко закодированный путь.
/bin/rm Путь к rm будет жестко закодирован в файле /usr/lib/perl5/5.28.0/<target-triplet>/Config_heavy.pl.
/bin/stty Этот путь жестко закодирован в программе Expect, кроме того он необходим для выполнения набора тестов такими пакетами как Binutils и GCC.
/usr/bin/perl Большинство Perl сценариев имеют жестко закодированный путь к программе perl.
/usr/lib/libgcc_s.so{,.1} Эти cссылки требует Glib для правильной работы библиотеки pthreads.
/usr/lib/libstdc++{,.6} Эти ссылки необходимы для некоторых тестов в Glibc, а также для поддержки C ++ в GMP.
/usr/lib/lib{blkid,lzma,mount,uuid}.{a,la,so*} Эти ссылки не позволяют утилитам systemd иметь ссылки на каталог /tools.
/bin/sh Многие сценарии оболочки имеют жестко закодированный путь к /bin/sh.
Исторически, Linux поддерживает список примонтированных файловых систем в файле /etc/mtab. Современные ядра Linux имеют поддержку такого списка внутри себя, и предоставляют его через виртуальный каталог /proc. Для осуществления поддержки тех утилит и программ, которым нужны ссылка на /etc/mtab необходимо создать следующую символическую ссылку:

ln -sv /proc/self/mounts /etc/mtab

Для осуществления возможности авторизации пользователем root от имени «root», должны быть соответствующие записи в в файлах /etc/passwd и /etc/group.
Необходимо создать файл /etc/passwd:

cat > /etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/dev/null:/bin/false
daemon:x:6:6:Daemon User:/dev/null:/bin/false
messagebus:x:18:18:D-Bus Message Daemon User:/var/run/dbus:/bin/false
nobody:x:99:99:Unprivileged User:/dev/null:/bin/false
EOF


Фактический пароль для root (символ «x» здесь используется только для заполнения) будет указан позднее.
Необходимо создать файл /etc/group:

cat > /etc/group << "EOF"
root:x:0:
bin:x:1:daemon
sys:x:2:
kmem:x:3:
tape:x:4:
tty:x:5:
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:
messagebus:x:18:
systemd-journal:x:23:
input:x:24:
mail:x:34:
nogroup:x:99:
users:x:999:
EOF


Созданные группы не являются частью какого-либо стандарта. Эти группы необходимы для конфигурации Udev, и частично общей конвенцией используемой рядом существующих дистрибутивов Linux. Кроме того, некоторые наборы тестов зависят от конкретных пользователей и групп. Специфкация LSB (The Linux Standard Base) рекомендует, чтобы кроме группы root с идентификатором группы (GID), равным 0, присутствовала группа bin с GID, равным 1. Все другие имена групп и идентификаторы GID могут свободно выбираться системным администратором, поскольку хорошо написанные программы не зависят от номеров GID, а используют только имя группы.
Для того, чтобы убрать приглашение коммандной строки «I have no name!», необходимо запустить новую командную оболочку. Когда был установлен пакет Glibc и файл /etc/group был создан, имя пользователя и группы, теперь будут работать:

exec /tools/bin/bash --login +h

Аргумент +h. сообщает программе bash не использовать собственный механизм хеширования путей. Без этого аргумента, bash будет запоминать пути к двоичным файлам которые выполнялись. Для того, чтобы использовать новые скомплированные пакеты, по мере их установки, аргумент +h будет использован на всём протяжении.
Программы login, agetty, и init (и другие) используют файлы с записями о событиях (log - файлов), например кто и когда авторизовался в системе. Однако, эти программы не смогут записывать файлы, до тех пор, пока их нет. Необходимо создать такие файлы, и назначить им правильные права:

touch /var/log/{btmp,lastlog,faillog,wtmp}
chgrp -v utmp /var/log/lastlog
chmod -v 664 /var/log/lastlog
chmod -v 600 /var/log/btmp


Файл /var/log/wtmp хранит записи когда каждый пользователь выполняет авторизацию в системе. Файл /var/log/faillog хранит записи о неудачных попытках входа в систему. Очень полезно при проверке угроз в системе безопасности, хакерских атаках, попыток взлома методом перебора. Прочитать содержимое можно с помощью команды faillog. Файл /var/log/btmp хранит записи неудачных попыток входа в систему. Здесь следует искать следы активности взломщиков.
Файл /run/utmp хранит записи о тех пользователях, которые на данные момент авторизованы в системе. Он создётся динамически, в процессе выполнения сценариев загрузки.

6.7. Заголовочные файлы API Linux-4.17.11

Заголовочные файлы Linux APIlinux-4.17.11.tar.xz) предоставляют API для использования его библиотекой C (Glibc). Ядро Linux должно предоставить интерфейс API (программный интерфейс приложения, интерфейс прикладного программирования) для использования их системной библиотекой Си (Пакет Glibc в LFS). Это можно сделать путём извлечения необходимых заголовочных файлов которые содержатся в архиве с исходным кодом ядра.
Убедимся, что нет устаревших файлов и зависимостей от предыдущих компиляций. Команда, указанная ниже, выполнит более интенсивную очистку дерева исходных текстов. Иногда она является необходимой и можно выполнять эту команду после каждого наложения заплаток.

make mrproper

Необходимо извлечь видимые пользователем заголовочные файлы ядра из дерева исходного кода. Они будут помещены в промежуточный локальный каталог и скопированы в необходимое место, потому что процесс распаковки удаляет любые существующие файлы в целевом каталоге. Также имеются некоторые скрытые файлы, используемые разработчиками ядра. Такие файлы не требуются в LFS и могут быть удалены из промежуточного каталога.

make INSTALL_HDR_PATH=dest headers_install
find dest/include \( -name .install -o -name ..install.cmd \) -delete
cp -rv dest/include/* /usr/include


Содержимое пакета Linux API Headers.
Установленные каталоги:
/usr/include/asm, /usr/include/asm-generic, /usr/include/drm, /usr/include/linux, /usr/include/misc, /usr/include/mtd, /usr/include/rdma, /usr/include/scsi, /usr/include/sound, /usr/include/video, и /usr/include/xen
Краткое описание установленных заголовочных файлов:
/usr/include/asm/*.h Заголовочные файлы Linux API ASM
/usr/include/asm-generic/*.h Заголовочные файлы Linux API ASM
/usr/include/drm/*.h Заголовочные файлы Linux API DRM
/usr/include/linux/*.h Заголовочные файлы Linux API
/usr/include/mtd/*.h Заголовочные файлы Linux API MTD
/usr/include/rdma/*.h Заголовочные файлы Linux API RDMA
/usr/include/scsi/*.h Заголовочные файлы Linux API SCSI
/usr/include/sound/*.h Заголовочные файлы Linux API Sound
/usr/include/video/*.h Заголовочные файлы Linux API Video
/usr/include/xen/*.h Заголовочные файлы Linux API Xen

6.8. Man-pages-4.16

Пакет Man-pages содержит более чем 2200 справочных страниц.
Установим пакет Man-pages:

make install

6.9. Glibc-2.28

Пакет содержит стандартную библиотеку языка Си (GNU C Library). Эта библиотека предоставляет функции для выделения памяти, поиска каталогов, открытия и закрытия файлов, чтения и записи файлов, обработку строк, соответствия шаблонов (pattern matching), арифметические операции, и так далее.
Система сборки Glibc самодостаточная и выполнит установку хорошо, даже несмотря на то, что служебные файлы и компоновщик по прежнему указывают на каталог /tools. Перенастроить эти файлы нельзя до установки окончательного варианта пакета Glibc, потому что тесты программы autoconf завершатся с ошибкой и победят цель достижения чистой сборки.
Некоторые из программ пакета Glibc используют не совместимые со стандартом FHS каталоги и файлы, например каталог /var/db, предназначенный для хранения данных во время выполнения. Применяем патч (заплатку) чтобы исправить несовместимость со стандартом LSB:

patch -Np1 -i ../glibc-2.28-fhs-1.patch

Для начала создаём символическую ссылку для совместимости и чтобы избежать наличия ссылок на каталог /tools в конечной установке пакета glibc:

ln -sfv /tools/lib/gcc /usr/lib

Определяем каталог GCC include и создаём символическую ссылку для соблюдения стандартов LSB. Кроме того, для x86_64 создаём символическую ссылку для совместимости и правильной работы динамического загрузчика:

case $(uname -m) in
i?86) GCC_INCDIR=/usr/lib/gcc/$(uname -m)-pc-linux-gnu/8.2.0/include
ln -sfv ld-linux.so.2 /lib/ld-lsb.so.3
;;
x86_64) GCC_INCDIR=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include
ln -sfv ../lib/ld-linux-x86-64.so.2 /lib64
ln -sfv ../lib/ld-linux-x86-64.so.2 /lib64/ld-lsb-x86-64.so.3
;;
esac


Удаляем файл, который мог быть оставлен после предыдущей попытки сборки:

rm -f /usr/include/limits.h

В документации к пакету Glibc рекомендуется выполнять компиляцию в отдельном каталоге:

mkdir -v build
cd build


Подготовим Glibc к компиляции:

CC="gcc -isystem $GCC_INCDIR -isystem /usr/include" \
../configure --prefix=/usr \
--disable-werror \
--enable-kernel=3.2 \
--enable-stack-protector=strong \
libc_cv_slibdir=/lib
unset GCC_INCDIR


Значение опций, аргументов и параметров конфигурации: CC="gcc -isystem $GCC_INCDIR -isystem /usr/include" Установка пути к gcc и каталога с системными заголовочными файлами для избежания проблем создания недопустимых путей в отладочных символах.
--disable-werror Аргумент отключает опцию -Werror передаваемую в GCC. Это необходимо сделать для корректного выполнения набора тестов.
--enable-stack-protector=strong Аргумент усиливает безопасность системы, добавляя дополнительный код для проверки на переполнение буфера, например при переполнении буфера в стеке (Stack smashing).
libc_cv_slibdir=/lib Аргумент указывает корректную библиотеку для всех архитектур. Нет необходимости использовать lib64.
Скомпилируем пакет:

make

Выполнение наборов тестов пакета Glibc особенно важно. Не пропускаем их выполнение ни при каких обстоятельствах.

make check

Можно наблюдать некоторые ошибки при тестировании. Выполнение набора тестов Glibc сильно зависит от хост-системы. Ниже приведен список наиболее распространённых проблем, наблюдаемых в некоторых версиях LFS:
misc/tst-ttyname завершается с ошибкой в среде chroot LFS.
inet/tst-idna_name_classify завершается с ошибкой в среде chroot LFS.
posix/tst-getaddrinfo4 and posix/tst-getaddrinfo5 на некоторых архитектурах может завершиться с ошибкой.
nss/tst-nss-files-hosts-multi может завершиться с ошибкой по неизвестным причинам.
Математические тесты иногда не проходят, когда они запускаются на относительно старых процессорах Intel или AMD.
Хотя это и безобидное сообщение, но на этапе установки Glibc будет выдавать предупреждение об отсутствии файла /etc/ld.so.conf. Предотвращаем это предупреждение, выполнив команду:

touch /etc/ld.so.conf

Исправим сгенерированный Makefile чтобы пропустить ненужные проверки на корректность, которые могут завершиться неудачно в среде LFS:

sed '/test-installation/s@$(PERL)@echo not running@' -i ../Makefile

Установим пакет:

make install

Установим конфигурационный файл и выполним команду time directory для программы nscd:

cp -v ../nscd/nscd.conf /etc/nscd.conf
mkdir -pv /var/cache/nscd


Установим локали для обеспечения реакции системы на изменение языков. Ни одна из локалей не требуется, но если некоторые из них не будут установлены, при выполнении тестов в следующих пакетах важные проверки могут быть пропущены.
Отдельные локали можно установить с помощью программы localedef. Например, первая команда localedef ниже объединяет определение /usr/share/i18n/locales/cs_CZ без набора символов с помощью определения /usr/share/i18n/charmaps/UTF-8.gz charmap и добавляет результат в /usr/lib/locale/locale-archive.

mkdir -pv /usr/lib/locale
localedef -i cs_CZ -f UTF-8 cs_CZ.UTF-8
localedef -i de_DE -f ISO-8859-1 de_DE
localedef -i de_DE@euro -f ISO-8859-15 de_DE@euro
localedef -i de_DE -f UTF-8 de_DE.UTF-8
localedef -i en_GB -f UTF-8 en_GB.UTF-8
localedef -i en_HK -f ISO-8859-1 en_HK
localedef -i en_PH -f ISO-8859-1 en_PH
localedef -i en_US -f ISO-8859-1 en_US
localedef -i en_US -f UTF-8 en_US.UTF-8
localedef -i es_MX -f ISO-8859-1 es_MX
localedef -i fa_IR -f UTF-8 fa_IR
localedef -i fr_FR -f ISO-8859-1 fr_FR
localedef -i fr_FR@euro -f ISO-8859-15 fr_FR@euro
localedef -i fr_FR -f UTF-8 fr_FR.UTF-8
localedef -i it_IT -f ISO-8859-1 it_IT
localedef -i it_IT -f UTF-8 it_IT.UTF-8
localedef -i ja_JP -f EUC-JP ja_JP
localedef -i ru_RU -f KOI8-R ru_RU.KOI8-R
localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
localedef -i tr_TR -f UTF-8 tr_TR.UTF-8
localedef -i zh_CN -f GB18030 zh_CN.GB18030


Дополнительно, можно установить локаль необходимой страны, языка и набора символов
Вместо всего вышеизложенного, можно выполнить установку всех локалей за раз, представленных в файле glibc-2.28/localedata/SUPPORTED (он содержит все локали, перечисленные выше, и многие другие):

make localedata/install-locales

Используем команду localedef чтобы создать и установить те локали, которые не представленны в файле glibc-2.28/localedata/SUPPORTED если они необходимы.
Файл /etc/nsswitch.conf необходимо создать потому что настройки Glibc по умолчанию не будут правильно работать в сетевой (networked) среде.
Создаём новый файл /etc/nsswitch.conf:

cat > /etc/nsswitch.conf << "EOF"
# Begin /etc/nsswitch.conf
passwd: files
group: files
shadow: files
hosts: files dns
networks: files
protocols: files
services: files
ethers: files
rpc: files
# End /etc/nsswitch.conf
EOF


Установим и настроим данные о часовых поясах:

tar -xf ../../tzdata2018e.tar.gz
ZONEINFO=/usr/share/zoneinfo
mkdir -pv $ZONEINFO/{posix,right}
for tz in etcetera southamerica northamerica europe africa antarctica \
asia australasia backward pacificnew systemv; do
zic -L /dev/null -d $ZONEINFO -y "sh yearistype.sh" ${tz}
zic -L /dev/null -d $ZONEINFO/posix -y "sh yearistype.sh" ${tz}
zic -L leapseconds -d $ZONEINFO/right -y "sh yearistype.sh" ${tz}
done
cp -v zone.tab zone1970.tab iso3166.tab $ZONEINFO
zic -d $ZONEINFO -p America/New_York
unset ZONEINFO


Значение zic-команд:
zic -L /dev/null ... Создаёт POSIX временные зоны, без каких-либо секунд. Это условие для того, чтобы положить их в zoneinfo и zoneinfo/posix. Необходимо положить POSIX временные зоны в файл zoneinfo, иначе некоторые тесты будут завершаться с ошибками. На встраиваемых системах, где мало дискового пространства и нет необходимости обновлять данные о часовых поясах, можно сохранить около 1.9 МБ не используя каталог posix но тогда, некоторые приложения могут работать с ошибками а тесты могут не проходить.
zic -L leapseconds ... Создаёт правильные временные зоны, включая секунды. На встраиваемых системах, где мало дискового пространства и нет необходимости обновлять данные о часовых поясах и заботиться о правильном времени, можно сохранить около 1.9 МБ не используя каталог опустив каталог right.
zic ... -p ... Создаёт файл posixrules. Используем New York, потому что POSIX требует соблюдения правил летнего времени в соответствии с правилами США.
Один из способов определить местный часовой пояс - запустить следующие сценарий:

tzselect

После ответов не вопросы о местоположении, сценарий выдаст наименование временной зоны (например America/Edmonton). Есть и другие часовые пояса, которые указанны в файле: /usr/share/zoneinfo, такие как Canada/Eastern или EST5EDT котрые не распознаются запущеным сценарием, но могут быть использованы.
Создаём файл /etc/localtime:

cp -v /usr/share/zoneinfo/<xxx> /etc/localtime

<xxx> наименованием выбранной временной зоны (например, Canada/Eastern).
По умолчанию, динамический загрузкчик (/lib/ld-linux.so.2) выполняет поиск динамических библиотек в каталогах /lib и /usr/lib которые необходимы для запущенных программ. Однако, если есть каталоги, в которых содержаться динамические библиотеки, и эти каталоги отличаются от вышеуказанных, их необходимо добавить в файл /etc/ld.so.conf в том порядке, в котором необходимо, чтобы динамический загрузчик выполнял поиск. Есть ещё два известных каталога, где могу содержаться динамические библиотеки: /usr/local/lib и /opt/lib, поэтому, можно добавить эти каталоги в пути поиска библиотек динамического загрузчика.
Создаём новый файл /etc/ld.so.conf:

cat > /etc/ld.so.conf << "EOF"
# Begin /etc/ld.so.conf
/usr/local/lib
/opt/lib
EOF


При желании динамический загрузчик может также выполнять поиск в каталоге включая содержимое найденных там файлов. Обычно файлы в этом каталоге включает одну строку, указывающую нужный путь библиотеки:

cat >> /etc/ld.so.conf << "EOF"
# Add an include directory
include /etc/ld.so.conf.d/*.conf
EOF
mkdir -pv /etc/ld.so.conf.d


Содержимое пакета Glibc.
Установленные каталоги: /usr/include/arpa, /usr/include/bits, /usr/include/gnu, /usr/include/net, /usr/include/netash, /usr/include/netatalk, /usr/include/netax25, /usr/include/neteconet, /usr/include/netinet, /usr/include/netipx, /usr/include/netiucv, /usr/include/netpacket, /usr/include/netrom, /usr/include/netrose, /usr/include/nfs, /usr/include/protocols, /usr/include/rpc, /usr/include/rpcsvc, /usr/include/sys, /usr/lib/audit, /usr/lib/gconv, /usr/lib/locale, /usr/libexec/getconf, /usr/share/i18n, /usr/share/zoneinfo, /var/cache/nscd, и /var/lib/nss_db
Краткое описание установленных программ и библиотек:
catchsegv Может использоваться для создания трассировки стека, когда программа завершается с ошибкой сегментации.
gencat Создает каталоги сообщений.
getconf Отображает значения конфигурации системы для специфичных переменных файловой системы.
getent Получает записи из административной базы данных.
iconv Выполняет преобразование набора символов.
iconvconfig Создает ускоренную загрузку iconv модулей файлов конфигурации.
ldconfig Настраивает привязки динамического компоновщика.
ldd помогает определить список разделяемых библиотек (shared libraries), от которых зависит программа.
lddlibc4 Помогает ldd с объектными файлами.
locale Отображает всевозможную информацию о текущей локали.
localedef Компилирует спецификации локали.
makedb Создает простую базу данных из текстового ввода.
mtrace Читает и интерпретирует файл трассировки памяти и отображает сводку в удобочитаемом формате.
nscd Служба (демон), которая предоставляет кэш для наиболее общих запросов службы имен.
pldd Список динамических общих объектов, используемых запущенными процессами.
sln Статически слиокнванные ln программы.
sotruss Выполняет трассировку вызовов процедуры разделяемой библиотеки для указанной команды.
sprof Считывает и отображает данные профилирования общих объектов.
tzselect Выясняет у пользователя его текущее местоположение и выводит описание часового пояса на устройство стандартного вывода.
xtrace Трассировка выполняемой программы, и выводит в реальном времени на устройство стандартного вывода выполняемые функции.
zdump распечатывает текущее время для каждого часового пояса, указанного в командной строке.
zic компилятор часовых поясов.
ld-2.28.so Программа выполняет поиск и загружают динамические библиотеки, необходимые программам, а также подготавливают программы к запуску и запускают их.
libBrokenLocale Используется внутри Glibc как грубый хак, чтобы обработать запущенную сломанную программу (например некоторые приложения Motif). Изучаем комментарии в файле glibc-2.28/locale/broken_cur_max.c для получения более подробной информации.
libSegFault Обработчик сигнала ошибки сегментации, используемый catchsegv.
libanl Асинхронная библиотека поиска имен.
libc Стандартная библиотека языка Си.
libcidn Используется внутри Glibc для обработки интернационализированых доменных имён в функции getaddrinfo().
libcrypt Криптографическая библиотека.
libdl Интерфейс библиотеки динамической линковки.
libg Заглушка-библиотека, не содержащая функций. Раньше была библиотеки выполнения для g++.
libieee Связывание в этом модуле приводит к правилам обработки правил для математических функций определенные Институтом инженеров электротехники и электроники (IEEE). По умолчанию используется обработка ошибок POSIX.1.
libm Математическая библиотека.
libmcheck Включает проверку распределения памяти при линковке.
libmemusage Используется программой memusage чтобы помочь собрать информацию об использовании памяти в программе.
libnsl Библиотека сетевых сервисов.
libnss Библиотеки коммутаторов имен, содержащие функции для разрешение имен хостов, имен пользователей, имен групп, псевдонимов, служб, протоколов и т.д.
libpthread POSIX библиотека потоков.
libresolv Содержит функции для создания, отправки и интерпретации пакетов на серверы доменных имен в Интернете.
librpcsvc Содержит функции, предоставляющие разные службы RPC.
librt Содержит функции, обеспечивающие большую часть указанных интерфейсов в POSIX.1b расширении.
libthread_db Содержит функции, полезные для построения отладчиков для многопоточных программ.
libutil Содержит кл для «стандартных» функций, используемых в большинстве различных утилит Unix.

6.10. Перенастройка временного набора инструментов

Когда все библиотеки Си установлены, необходимо перенастроить используемый сейчас временный набор инструментов, чтобы он выполнял линковку новых скомпилированых программ с установленными библиотеками.
Выполним резервное копирование компоновщика /tools, и заменим его настроенным компоновщиком. Также будут созданы ссылки на их копии в каталоге /tools/$(uname -m)-pc-linux-gnu/bin:

mv -v /tools/bin/{ld,ld-old}
mv -v /tools/$(uname -m)-pc-linux-gnu/bin/{ld,ld-old}
mv -v /tools/bin/{ld-new,ld}
ln -sv /tools/bin/ld /tools/$(uname -m)-pc-linux-gnu/bin/ld


Необходимо изменить специальные файлы GCC так, чтобы они указывали на новый динамический компоновщик. После удаления всех экземпляров в каталоге «/tools» останутся только правильные пути к динамическому компоновщику. Также необходимо настроить некоторые файлы GCC для правильного поиска заголовочных файлов и файлов запуска Glibc. С помощью команды sed можно выполнить следующую команду:

gcc -dumpspecs | sed -e 's@/tools@@g' \
-e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
-e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
`dirname $(gcc --print-libgcc-file-name)`/specs


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

echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'


В результате выполнения этой команды не должно быть ошибок, и вывод (в зависимости от платформы) должен соответствовать следующей строке:

[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

Для 64-битной системы каталог /lib это место, где располагается динамический компоновщик, но доступ к нему обеспечен через символическую ссылку /lib64.
Для 32-битных систем интерпретатор должен быть /lib/ld-linux.so.2.
Убедимся что настройка стартовых файлов запуска выполнена правильно:

grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log

Вывод должен соответствовать следующей строке:

/usr/lib/../lib/crt1.o succeeded
/usr/lib/../lib/crti.o succeeded
/usr/lib/../lib/crtn.o succeeded


Проверим, что компилятор выполняет поиск заголовочных файлов в нужных местах:

grep -B1 '^ /usr/include' dummy.log

Вывод должен соответствовать следующей строке:

#include <...> search starts here:
/usr/include


Проверим, что компоновщик использует правильные пути поиска:

grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'

Ссылки на пути с наличием у компонента суффикса '-linux-gnu' должны быть проигнорированы, и вывод должен соответствовать следующей строке:

SEARCH_DIR("/usr/lib")
SEARCH_DIR("/lib")


Проверим что используется нужная библиотека libc:

grep "/lib.*/libc.so.6 " dummy.log

Вывод должен соответствовать следующей строке:

attempt to open /lib/libc.so.6 succeeded

Проверим что GCC использует правильный динамический компоновщик:

grep found dummy.log

Вывод (в зависимости от платформы в наименовании динамического компоновщика) должен соответствовать следующей строке:

found ld-linux-x86-64.so.2 at /lib/ld-linux-x86-64.so.2

Если вывод на выполнение команд не выводиться или команды не выполняются вовсе, то это признак того, что в предыдущих инструкциях была допущена серьезная ошибка. Исследуем предыдущие шаги и проверим правильность их выполнения. Постараемся найти ошибку в вводимых командах. Наиболее вероятно, что причина в проблемах - не правильная настройка специальных файлов при перенастройке временного набора инструментов. Все проблемы должны быть найдены и исправлены здесь, до выполнения следующих этапов.
Если все работает правильно, выполним очистку тестовых файлов:

rm -v dummy.c a.out dummy.log

Продаются
книги

Оставить отзыв

Установи и
БУДЕШЬ СЧАСТЛИВ!

Спасибо, Господи, что взял деньгами...

Scrooge
Dollar
Ruble
Ruble
Gold