======Часть III. Глава 5. Сборка кросс-тулчейна====== Содержание * [[software:linux_server:lfs:chapter05#5.1. Введение|5.1. Введение]] * [[software:linux_server:lfs:chapter05#5.2. Binutils-2.42 - Проход 1|5.2. Binutils-2.42 - Проход 1]] * [[software:linux_server:lfs:chapter05#5.3. GCC-13.2.0 - Проход 1|5.3. GCC-13.2.0 - Проход 1]] * [[software:linux_server:lfs:chapter05#5.4. Заголовочные файлы Linux-6.7.4 API|5.4. Заголовочные файлы Linux-6.7.4 API]] * [[software:linux_server:lfs:chapter05#5.5. Glibc-2.39|5.5. Glibc-2.39]] * [[software:linux_server:lfs:chapter05#5.6. Libstdc++ из GCC-13.2.0|5.6. Libstdc++ из GCC-13.2.0]] =====5.1. Введение===== В этой главе дано описание, как создать кросс-компилятор и связанные с ним инструменты. Несмотря на то, что на данном этапе кросс-компиляция имитируется, принципы его работы те же, что и для настоящего кросс-тулчейна. Программы, скомпилированные в этой главе, будут установлены в каталог **$LFS/tools**, чтобы они были отделены от файлов, установленных в следующих главах. Библиотеки, же, устанавливаются на свое постоянное место, поскольку они относятся к системе, которую мы хотим создать. =====5.2. Binutils-2.42 - Проход 1===== |Пакет Binutils содержит компоновщик, ассемблер и другие инструменты для работы с объектными файлами.|| |Приблизительное время сборки:|1 SBU| |Требуемое дисковое пространство:|663 MB| **Примечание** \\ Вернитесь назад и перечитайте примечания в разделе Общие инструкции по компиляции. Понимание информации, помеченной как важная, может впоследствии избавить вас от многих проблем. Очень важно, чтобы Binutils был скомпилированным первым, потому что и Glibc, и GCC выполняют различные тесты на доступных компоновщике и ассемблере, чтобы определить, какие из их функций следует включить. В документации пакета Binutils рекомендуется выполнять сборку в отдельном каталоге, создадим его: mkdir -v build cd build **Примечание** \\ Для того, чтобы значения SBU, перечисленные в остальной части книги, были вам полезны, измерьте время, необходимое для сборки этого пакета, начиная с настройки и заканчивая установкой. Чтобы добиться этого, оберните команды сборки командой time: **time { ../configure ... && make && make install; }**. Теперь подготовьте Binutils к компиляции: ../configure --prefix=$LFS/tools \ --with-sysroot=$LFS \ --target=$LFS_TGT \ --disable-nls \ --enable-gprofng=no \ --disable-werror \ --enable-default-hash-style=gnu **Значение параметров настройки:** * **--prefix=$LFS/tools** Указывает сценарию configure подготовить к установке пакет Binutils в каталог $LFS/tools. * **--with-sysroot=$LFS** Для кросс-компляции указывает системе сборки искать в $LFS библиотеки целевой системы, если необходимо. * **--target=$LFS_TGT** Поскольку название машины в значении переменной LFS_TGT может отличаться от значения, которое возвращает сценарий config.guess, этот аргумент укажет сценарию configure как настроить систему сборки пакета Binutils для создания кросс-компоновщика. * **--disable-nls** Этот параметр отключает интернационализацию, так как i18n не требуется для временных инструментов. * **--enable-gprofng=no** Этот параметр отключает сборку gprofng, который не нужен для временного инструментария. * **--disable-werror** Этот параметр предотвращает остановку сборки в случае появления предупреждений от компилятора хоста. * **--enable-default-hash-style=gnu** По умолчанию компоновщик генерирует как хеш-таблицу в стиле GNU, так и классическую хеш-таблицу ELF для общих библиотек и динамически связанных исполняемых файлов. Хеш-таблицы необходимы только для динамического компоновщика, выполняющего поиск символов. В LFS динамический компоновщик (предоставляемый пакетом Glibc) всегда будет использовать хеш-таблицу в стиле GNU, к которой запросы выполняются быстрее. Так что классическая хеш-таблица ELF совершенно бесполезна. Этот параметр указывает компоновщику по умолчанию генерировать только хеш-таблицу в стиле GNU, поэтому мы можем избежать траты времени на создание классической хеш-таблицы ELF при сборке пакетов или не тратить дисковое пространство для ее хранения. Скомпилируйте пакет: make Установите пакет: make install Подробная информация об этом пакете находится в [[software:linux_server:lfs:chapter08#8.19. Binutils-2.42|Разделе 8.19.2, «Содержимое пакета Binutils.»]] =====5.3. GCC-13.2.0 - Проход 1===== |Пакет GCC содержит коллекцию компиляторов GNU, которая включает компиляторы C и C++.|| |Приблизительное время сборки:|3.8 SBU| |Требуемое дисковое пространство:|4.1 GB| **Примечание** \\ В этой главе часто возникают недоразумения, хотя применяются те же процедуры, что и в любой другой главе, следуйте инструкции которую получили ранее ([[software:linux_server:lfs:partintro#iii. Общие инструкции по компиляции|Инструкции по сборке пакетов]]). Сначала распакуйте пакет gcc-13.2.0 из архива, а затем перейдите в созданный каталог. Только после этого следует приступить к приведенным ниже инструкциям. tar -xf ../mpfr-4.2.1.tar.xz mv -v mpfr-4.2.1 mpfr tar -xf ../gmp-6.3.0.tar.xz mv -v gmp-6.3.0 gmp tar -xf ../mpc-1.3.1.tar.gz mv -v mpc-1.3.1 mpc На хостах x86_64 измените имя каталога по умолчанию для 64-битных библиотек на «lib»: case $(uname -m) in x86_64) sed -e '/m64=/s/lib64/lib/' \ -i.orig gcc/config/i386/t-linux64 ;; esac В документации к GCC рекомендуется собирать GCC в отдельном каталоге: mkdir -v build cd build Подготовьте GCC к компиляции: ../configure \ --target=$LFS_TGT \ --prefix=$LFS/tools \ --with-glibc-version=2.39 \ --with-sysroot=$LFS \ --with-newlib \ --without-headers \ --enable-default-pie \ --enable-default-ssp \ --disable-nls \ --disable-shared \ --disable-multilib \ --disable-threads \ --disable-libatomic \ --disable-libgomp \ --disable-libquadmath \ --disable-libssp \ --disable-libvtv \ --disable-libstdcxx \ --enable-languages=c,c++ **Значение параметров настройки:** * **--with-glibc-version=2.39** Этот параметр указывает версию Glibc, которая будет использоваться на целевой системе. Он не имеет отношения к libc хост-дистрибутива, потому что все, скомпилированное в этом разделе, будет выполняться в среде chroot, которая изолирована от libc хост-дистрибутива. * **--with-newlib** Поскольку работающая библиотека C еще недоступна, это гарантирует, что константа inhibit_libc будет определена при сборке libgcc. Это предотвращает компиляцию любого кода, требующего поддержки libc. * **--without-headers** При создании полного кросс-компилятора GCC требует наличия стандартных заголовков, совместимых с целевой системой. Для наших целей эти заголовки не понадобятся. Этот параметр предотвращает их поиск GCC. * **--enable-default-pie и --enable-default-ssp** Эти параметры позволяют GCC по умолчанию компилировать программы с некоторые функциями усиливающими безопасность (более подробная информация о них приведена в примечание о PIE и SSP в Главе 8). На данном этапе это не является строго обязательным, поскольку компилятор будет создавать только временные исполняемые файлы. Но лучше, чтобы временные пакеты были максимально приближены к тем, что будут в готовой системе LFS. * **--disable-shared** Этот параметр заставляет GCC статически связывать свои внутренние библиотеки. Он необходим потому что общие библиотеки требуют Glibc, который еще не установлен в целевой системе. * **--disable-multilib** На x86_64, LFS не поддерживает конфигурацию multilib. Этот аргумент никак не влияет на работу с архитектурой x86. * **--disable-threads, --disable-libatomic, --disable-libgomp, --disable-libquadmath, --disable-libssp, --disable-libvtv, --disable-libstdcxx** Эти аргументы отключают поддержку расширений для работы с многопоточностью, libatomic, libgomp, libquadmath, libssp, libvtv и стандартной библиотеки C++ соответственно. Эти функции могут не скомпилироваться при сборке кросс-компилятора и не нужны для задач кросс-компиляции временной libc * **--enable-languages=c,c++** Этот параметр обеспечивает сборку только компиляторов C и C++. Это единственные языки, которые нужны сейчас. Скомпилируйте GCC, выполнив: make Установите пакет: make install Во время сборки GCC установил пару внутренних системных заголовочных файлов. Обычно один из файлов limits.h, включает соответствующие системные ограничения **limits.h**, в данном случае **$LFS/usr/include/limits.h.** Однако во время сборки **GCC $LFS/usr/include/limits.h** не существует, поэтому только что установленный внутренний заголовочный файл является частичным, автономным файлом и не включает расширенные функции системного файла. Этого достаточно для сборки Glibc, но полный внутренний заголовочный файл понадобится позже. Создайте полную версию внутреннего заголовочного файла с помощью команды, идентичной той, что система сборки GCC использует обычно: **Примечание** \\ В приведенной ниже команде показан пример подстановки вложенных команд, используя два метода: обратные кавычки и конструкцию $(). Его можно было бы переписать, используя один и тот же метод для обеих замен, но сделано так, чтобы продемонстрировать, как их можно использовать одновременно. В целом метод $() предпочтительнее. cd .. cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \ `dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/include/limits.h Подробная информация об этом пакете находится в [[software:linux_server:lfs:chapter08#8.28.2. Содержимое пакета GCC|Разделе 8.28.2. «Содержимое пакета GCC.»]] =====5.4. Заголовочные файлы Linux-6.7.4 API===== |Заголовочные файлы Linux API (в linux-6.7.4.tar.xz) предоставляют API ядра для использования Glibc.|| |Приблизительное время сборки:|менее 0.1 SBU| |Требуемое дисковое пространство:|1.5 GB| ====5.4.1. Установка заголовочных файлов==== Ядро Linux должно предоставлять интерфейс прикладного программирования (API) для использования системной библиотекой C (Glibc в LFS). Это делается путем установки заголовочных файлов C, которые поставляются в архиве с исходным кодом ядра Linux. Убедитесь, что в пакете нет устаревших файлов: make mrproper Теперь извлеките видимые пользователю заголовочные файлы ядра из исходного кода. Рекомендуемый способ make «headers_install» использовать нельзя, так как для этого требуется rsync, который может быть недоступен. Заголовочные файлы сначала помещаются в /usr, а затем копируются в нужное место. make headers find usr/include -type f ! -name '*.h' -delete cp -rv usr/include $LFS/usr ====5.4.2. Содержимое заголовочных файлов Linux API==== |**Установленные заголовочные файлы:**|/usr/include/asm/*.h, /usr/include/asm-generic/*.h, /usr/include/drm/*.h, /usr/include/linux/*.h, /usr/include/misc/*.h, /usr/include/mtd/*.h, /usr/include/rdma/*.h, /usr/include/scsi/*.h, /usr/include/sound/*.h, /usr/include/video/*.h, and /usr/include/xen/*.h| |**Созданные каталоги:**|/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, and /usr/include/xen| ===Краткое описание=== |/usr/include/asm/*.h|Заголовочные файлы Linux API ASM| |/usr/include/asm-generic/*.h|Заголовочные файлы Linux API ASM Generic| |/usr/include/drm/*.h|Заголовочные файлы Linux API DRM| |/usr/include/linux/*.h|Заголовочные файлы Linux API Linux| |/usr/include/misc/*.h|Заголовочные файлы Linux API Miscellaneous| |/usr/include/mtd/*.h|Заголовочные файлы 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| =====5.5. Glibc-2.39===== |Пакет Glibc содержит основную библиотеку C. Эта библиотека предоставляет основные процедуры для выделения памяти, поиска в каталогах, открытия и закрытия файлов, чтения и записи файлов, обработки строк, сопоставления с образцом, арифметики и так далее|| |Приблизительное время сборки:|1.5 SBU| |Требуемое дисковое пространство:|846 MB| ====5.5.1. Установка пакета Glibc==== Во-первых, создайте символическую ссылку для соответствия требованиям LSB. Кроме того, для совместимости с x86_64 создайте символическую ссылку, необходимую для правильной работы загрузчика динамической библиотеки: case $(uname -m) in i?86) ln -sfv ld-linux.so.2 $LFS/lib/ld-lsb.so.3 ;; x86_64) ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64 ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64/ld-lsb-x86-64.so.3 ;; esac **Примечание** \\ Приведенная выше команда верна. Команда ln имеет несколько вариантов синтаксиса, поэтому обязательно ознакомьтесь с info coreutils ln и [[https://man.archlinux.org/man/ln.1|ln(1)]], прежде чем сообщать об ошибке. Некоторые программы, использующие Glibc, применяют несовместимый с FHS каталог /var/db для хранения своих данных времени выполнения. Установите следующий патч, чтобы такие программы хранили свои данные в местах, совместимых с FHS: patch -Np1 -i ../glibc-2.39-fhs-1.patch В документации к Glibc рекомендуется собирать Glibc в отдельном каталоге: mkdir -v build cd build Убедитесь, что утилиты ldconfig and sln установлены в /usr/sbin: echo "rootsbindir=/usr/sbin" > configparms Затем подготовьте Glibc к компиляции: ../configure \ --prefix=/usr \ --host=$LFS_TGT \ --build=$(../scripts/config.guess) \ --enable-kernel=4.19 \ --with-headers=$LFS/usr/include \ --disable-nscd \ libc_cv_slibdir=/usr/lib ===Значение параметров настройки:=== * **--host=$LFS_TGT, --build=$(../scripts/config.guess)** Комбинация этих опций указывает на то, что система сборки Glibc настраивается на кросс-компиляцию с использованием кросс-компоновщика и кросс-компилятора в $LFS/tools. * **--enable-kernel=4.19** Этот параметр позволяет Glibc выполнять компиляцию библиотеки с поддержкой ядра 4.19 и более поздних версий. Поддержка более старых ядер не включена. * **--with-headers=$LFS/usr/include** Этот аргумент позволяет скомпилировать библиотеку с заголовочными файлами, недавно установленными в каталоге $LFS/usr/include, таким образом, пакету будет известно, какие функции есть у ядра, чтобы оптимизировать себя. * **libc_cv_slibdir=/usr/lib** Этот аргумент гарантирует, что библиотека будет установлена в /usr/lib вместо стандартного /lib64 на 64-битных машинах. * **--disable-nscd** Параметр отключает сборку демона кэша службы имен, который больше не используется. На этом этапе может появиться следующее предупреждение: configure: WARNING: *** These auxiliary programs are missing or *** incompatible versions: msgfmt *** some features will be disabled. *** Check the INSTALL file for required versions. Отсутствующая или несовместимая программа msgfmt, как правило, безвредна. msgfmt является частью пакета Gettext, который должен предоставлять хост-дистрибутив. **Примечание** \\ Поступали сообщения о том, что этот пакет может не компилироваться при «параллельной сборке». Если это произойдет, повторно запустите команду make с параметром -j1. Скомпилируйте пакет: make Установите пакет: **Важно** \\ Если переменная LFS настроена неправильно, и, несмотря на рекомендации, вы выполняете сборку от имени пользователя root, следующая команда установит только что собранный Glibc в вашу хост-систему, что, скорее всего, сделает её непригодной для использования. Поэтому дважды проверьте, правильность настройки среды и что вы вошли в систему не под учетной записью root, прежде чем запускать следующую команду. make DESTDIR=$LFS install ===Значение опции make install:=== * **DESTDIR=$LFS** Переменная make DESTDIR используется почти всеми пакетами для определения места установки пакета. Если она не задана, по умолчанию для установки используется корневой каталог (/). Здесь мы указываем, что пакет должен быть установлен в $LFS, который станет корневым каталогом в [[software:linux_server:lfs:chapter07#7.4. Вход в окружение Chroot|Разделе 7.4. «Вход в окружение Chroot»»]] . Исправьте жестко запрограммированный путь к исполняемому загрузчику в ldd: sed '/RTLDLIST=/s@/usr@@g' -i $LFS/usr/bin/ldd **Внимание** \\ На этом этапе необходимо остановиться и убедиться, что основные функции (компиляция и компоновка) нового кросс-тулчейна работают должным образом. Чтобы выполнить проверку работоспособности, выполните следующие команды: echo 'int main(){}' | $LFS_TGT-gcc -xc - readelf -l a.out | grep ld-linux Если все работает правильно, ошибок быть не должно и вывод последней команды будет иметь вид: [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] Обратите внимание, что для 32-разрядных машин имя интерпретатора будет /lib/ld-linux.so.2. Если выходные данные отображаются не так, как указано выше, или их вообще нет, значит, что-то сделано неправильно. Разберитесь с проблемой и повторите шаги выше, чтобы исправить ее. Эта проблема должна быть решена, прежде чем вы продолжите. Как только все будет хорошо, удалите тестовый файл: rm -v a.out **Примечание** \\ Сборка пакетов в следующей главе послужит дополнительной проверкой правильности сборки временного кросс-тулчейна. Если какой-либо пакет, особенно Binutils или GCC, не удается собрать, это указывает на то, что что-то пошло не так с установленными ранее Binutils, GCC, или Glibc. Подробная информация об этом пакете находится в [[software:linux_server:lfs:chapter08#8.5.3. Содержимое пакета Glibc|Раздел 8.5.3. «Содержимое пакета Glibc.»]] =====5.6. Libstdc++ из GCC-13.2.0===== |Libstdc++ — это стандартная библиотека C++. Она нужна для компиляции кода C++ (часть GCC написана на C++), когда мы собирали [[software:linux_server:lfs:chapter05#5.3. GCC-13.2.0 - Проход 1|GCC-Проход 1]], нам пришлось отложить её установку, потому что она зависит от библиотеки Glibc, которой еще не было в целевом каталоге.|| |Приблизительное время сборки:|0.2 SBU| |Требуемое дисковое пространство:|1.1 GB| ====5.6.1. Установка библиотеки Libstdc++==== **Примечание** \\ Libstdc++ является частью исходников GCC. Сначала вы должны распаковать архив GCC и перейти в каталог gcc-13.2.0. Создайте отдельный каталог сборки для libstdc++ и перейдите в него: mkdir -v build cd build Подготовьте libstdc++ к компиляции: ../libstdc++-v3/configure \ --host=$LFS_TGT \ --build=$(../config.guess) \ --prefix=/usr \ --disable-multilib \ --disable-nls \ --disable-libstdcxx-pch \ --with-gxx-include-dir=/tools/$LFS_TGT/include/c++/13.2.0 ===Значение параметров настройки:=== * **--host=...** Указывает, что должен использоваться кросс-компилятор, который мы только что собрали, вместо того, который находится в /usr/bin. * **--disable-libstdcxx-pch** Этот аргумент предотвращает установку предварительно скомпилированных include-файлов, которые на данном этапе не нужны. * **--with-gxx-include-dir=/tools/$LFS_TGT/include/c++/13.2.0** Указывает каталог установки для include-файлов. Поскольку libstdc++ является стандартной библиотекой C++ для LFS, этот каталог должен соответствовать местоположению, в котором компилятор C++ ($LFS_TGT-g++) будет искать стандартные включаемые файлы C++. При обычной сборке эта информация автоматически передается в Libstdc++ при выполнении configure из каталога верхнего уровня. В нашем случае эта информация должна быть указана явно. Компилятор C++ добавит путь sysroot $LFS (указанный при сборке GCC Проход 1) к пути поиска include-файлов, поэтому фактически он будет искать в $LFS/tools/$LFS_TGT/include/c++/13.2.0. Комбинация переменной DESTDIR (в приведенной ниже команде make install) и этого аргумента обеспечивает установку заголовочных файлов туда. Скомпилируйте Libstdc++, выполнив: make Установите библиотеку: make DESTDIR=$LFS install Удалите архивные файлы libtool, поскольку они потенциально опасны при кросс-компиляции: rm -v $LFS/usr/lib/lib{stdc++{,exp,fs},supc++}.la Подробная информация об этом пакете находится в [[software:linux_server:lfs:chapter08#8.28.2. Содержимое пакета GCC|Разделе 8.28.2. «Содержимое пакета GCC.»]]