Что такое кросс компиляция

Русские Блоги

Подробное объяснение кросс-компиляции

Глава 1 Введение в кросс-компиляцию

1.1 Что такое кросс-компиляция

Те, кто еще не занимался встроенным программированием, могут не понимать концепцию кросс-компиляции, так что же такое кросс-компиляция? Что оно делает?

Прежде чем объяснить, что такое кросс-компиляция, вы должны сначала понять, что такое локальная компиляция.

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

Например, на платформе x86 мы пишем программы и компилируем их в исполняемые программы. Таким образом, мы используем инструменты на платформе x86 для разработки исполняемых программ для самой платформы x86. Этот процесс компиляции называется локальной компиляцией.

Кросс-компиляция может быть понята как то, что под текущей платформой компиляции скомпилированная программа может работать на другой целевой платформе с другой архитектурой, но сама платформа компиляции не может запустить программу:

Например, на платформе x86 мы пишем программы и компилируем их в программы, которые могут работать на платформе ARM. Скомпилированные программы не могут работать на платформе x86, и для запуска их необходимо поместить на платформу ARM.

1.2 Почему происходит кросс-компиляция

Основная причина кросс-компиляции:

1.3 Почему кросс-компиляция трудна?

Сложность кросс-компиляции заключается в двух аспектах:

Разные архитектуры имеют разные характеристики машины

Среда хоста отличается от целевой среды во время кросс-компиляции

Для подробного сравнения, пожалуйста, обратитесь к этой статье, которая была написана подробно, поэтому я не буду вдаваться в подробности здесь:Introduction to cross-compiling for Linux

Глава 2 Кросс-компиляция цепочки

2.1 Что такое цепочка кросс-компиляции

Разберитесь, что такое кросс-компиляция, а затем давайте посмотрим, что такое цепочка кросс-компиляции.

Во-первых, процесс компиляции представляет собой сложный процесс, состоящий из различных подфункций и в порядке, как показано ниже:

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

В то же время процесс компиляции является последовательным процессом, который должен включать порядок, в котором используются инструменты. Каждый инструмент соединен последовательно в соответствии с последовательностью, которая образует цепную структуру.

следовательно, Кросс-компиляция цепочки Это полный набор инструментов, состоящий из нескольких подинструментов, сформированных для компиляции программного кода кроссплатформенной архитектуры. В то же время он скрывает детали предварительной обработки, компиляции, сборки, компоновки и т. Д. Когда мы указываем исходный файл (.c), он автоматически вызывает различные подинструменты в соответствии с процессом компиляции и автоматически генерирует окончательный образ двоичной программы (.bin). ).

Примечание. Строго говоря, кросс-компилятор ссылается на кросс-компилированный gcc, но на самом деле для удобства мы часто говорим, что кросс-компилятор представляет собой цепочку кросс-инструментов. В этой статье не проводится различие между этими двумя понятиями, оба относятся к цепочке компиляции

2.2 Правила именования цепочек кросс-компиляции

Когда мы используем цепочки кросс-компиляции, мы часто видим такие имена:

Среди них соответствующий префикс:

Правила именования этих цепочек кросс-компиляции кажутся универсальными, и существуют определенные правила:

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

Глава 3 включены инструменты

3.1 Binutils

Подпрограммы, включенные в инструмент Binutils:

3.2 GCC

Пакет компиляторов GNU поддерживает C, C ++, Java, Ada, Fortran, Objective-C и многие другие языки.

3.3 GLibc

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

3.4 GDB

GDB используется для отладки программ

Глава 4 Как получить цепочку кросс-компиляции

Теперь, когда мы понимаем функцию цепочки кросс-компиляции, где мы получаем цепочку кросс-компиляции, которая нам нужна при разработке для встроенных систем?

Есть три основных способа получения

4.1 Загрузить уже подготовленную цепочку кросс-компиляции

Используйте цепочки кросс-компиляции, скомпилированные другими для определенных платформ ЦП. Нам просто нужно найти правильный, скачать его и использовать.

Адрес загрузки общей цепочки кросс-компиляции:

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

4.2 Используйте инструменты для настройки цепочки кросс-компиляции

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

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

4.3 Построение цепочки кросс-компиляции с нуля

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

Конечно, если он собран, он, безусловно, будет самым полезным. По крайней мере, процесс компиляции и зависимости относительно ясны. Детали, возможно, должны пройти через соответствующий протокол или стандарт, но, по крайней мере, скелет будет более понятным.

Для подробного процесса строительства, пожалуйста, обратитесь к последующим статьям, в которых есть подробные параметры и шаги:
Подробное объяснение кросс-компиляции 2 Создание цепочки кросс-компиляции из нуля

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

Читайте также:  Update failed discord что делать

Источник

Национальная библиотека им. Н. Э. Баумана
Bauman National Library

Персональные инструменты

Кросс-компилятор

Содержание

Применение кросс-компиляторов

Канадский крест

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

При использовании канадского креста c GSS могут быть четыре вида:

Конечный результат кросс-компилятор (4) не сможет работать на построение машины А; вместо этого она будет работать на машине B для компиляции приложения в исполняемый код, чтобы потом быть скопированным на машину C и выполненным на компьютере С.

Термин канадский крест возник потому, что в то время, когда эти проблемы обсуждались, в Канаде было три национальных политических партии.

Кросс-компиляция с GCC

GCC, бесплатная программа из коллекции компиляторов, может быть настроена для кросс компиляции. Она поддерживает множество платформ и языков.

Кросс-компиляцией GCC требует, чтобы часть стандартной библиотеки целевой платформы C была доступна на хост-платформе. Программист может выбрать для составления полную библиотеку C, но этот выбор может быть ненадежным. Альтернативой является использование файла, который представляет собой небольшую библиотеку C, содержащий только самые необходимые компоненты, необходимые для компиляции C в исходный код.

Бесплатный Pascal

Бесплатный Паскаль был разработан с самого начала в качестве кросс-компилятора. Исполняемый файл компилятора (ppcXXX где XXX-целевая архитектура) способен производить исполняемые файлы для всех ОС той же архитектуры. Например, ppc386 способен производить исполняемые файлы для i386-Linux, для i386-Win32 и для i386-go32v2 (DOS) и всех других ОС. Для компиляции на другой архитектуре архитектура кросс-версии компилятора должна быть построена первой.

Источник

Кросс-компиляция в docker. Почему бы и нет?

Что такое кросс-компиляция? Какие есть инструменты для сборки бинарных файлов для Windows в Linux? Как настроить docker-контейнер для всего этого? Вот лишь небольшая часть вопросов, которые будут обсуждаться ниже.

Инструменты

Кросс-компиляция позволяет получить исполняемый код для платформы, отличной от той, на которой запускается этот процесс.

В рамках данной статьи рассмотрим кросс-компиляцию для платформы Windows в Linux.

Примером кросс-компилятора может служить Mingw-w64. По сути он предоствляет лишь инструмент для сборки приложения, но, если Вам необходимы сторонние библиотеки, которые не являются частью STL, придется собирать их и зависимости. Так же можно использовать готовые бинарные файлы, так как это описано в этой статье.

Упростить настройку сборки позволяет проект mxe, который предоставляет не только инструменты, но и библиотеки. С их списком можно ознакомиться на официальном сайте. При установке библиотек используется контроль зависимостей, т.е. будет установлен требуемый пакет и все необходимое для его работы. Инструменты поставляются в пред-настроенной конфигурации, например, для статической сборки 64-битных приложений. Это существенно облегчает сборку.

Среда mxe разворачивается в локальной папке пользователя. Для этого достаточно установить зависимости через пакетный менеджер и клонировать репозиторий. В корне репозитория находится Makefile, который и выполняет установку заданных в целях библиотек, добавляет инструменты для сборки и т.д.

Важно отметить, что среда сборки локализуется в пределах своей папки, это позволяет настроить индивидульную среду под каждое приложение.

Контейнеризируй это

Допустим, что сборка релиза для Windows у нас настроена на локальной машине. Релизы выходят довольно часто, в некоторых версиях добавляются новые библиотеки, а, некоторые, например, удаляются. В один прекрасный день начальник требует скинуть сборку релиза на новичка. Как ему настроить свою среду сборки? Какие библиотеки нужно взять из репозитория mxe, а для каких выполнить сборку из исходников?

На этот случай можно завести bash-скрипт, который будет разворачивать всю среду в заданной папке. И после пытаться поддерживать этот скрипт в актуальном состоянии. Но, как и документация к проекту, в один критически важный момент он может устареть.

Хорошим решением будет изолировать нашу среду для сборки внутри docker-контейнера. Сам docker-файл будет содержать самодостаточный набор инструкций по развертыванию среды, а наличие контейнера позволит избежать захламления домашней системы лишними библиотеками.

Собираем все вместе

Для демонстрации возьмем простой Qt-проект — SimpleQtProject. Этот проект собирается утилитой qmake, и состоит из одной единственной формы. Сделано это, конечно же, для простоты. Так же в папке docker лежит файл для сборки контейнера.

Рассмотрим docker-файл проекта. По сути он состоит из нескольких основных частей:

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

Пропустим первый пункт и перейдем непосредственно к установке mxe.
Клонируем репозиторий:

На момент написания статьи последним релизом был build-2019-06-02. Здесь не используется ветка мастер по простой причине: необходима повторяемость сборки. В противном случае, при добавлении новых коммитов в мастер сборка может сломаться.

Далее настраиваем систему сборки:

Данная команда добавит инструменты (экземпляры cmake и Mingw-w64 и пр.) для статической сборки проекта под 64-битную архитектуру, а после соберет с их помощью Qt.

Следующим шагом добавим в PATH путь к исполняемым файлам mxe:

После того, как среда сборки настроена, можно перейти непосредственно к последнему пункту:

Здесь следует пояснить несколько моментов. Предполагается, что при запуске контейнера, в папку /app/src/ будет смонтирована папка с исходниками, содержащая *.pro файл, а в директории /app/res/ смонтировано место, куда следует сложить результаты сборки.

Ниже приведен пример команды для создания docker-image, ее необходимо запускать в папке docker рассматриваемого проекта:

Читайте также:  какая рыба подойдет для ухи

Сборка же запускается там же:

Перед выполнение команды необходимо создать папку result в директории docker для копирования результатов.

Кастомизация сборки

По умолчанию mxe предоставляет MinGW версии 5.5.0 (по крайней мере это справедливо для сборки build-2019-06-02).

Если в проекте используются новые фичи С++ 17, то такая версия компилятора неудовлетворительна. К счастью, среда сборки предоставляет более новые версии в виде отдельных плагинов. Для решения нашей задачи, необходимо в команду сборки библиотек добавить инструкцию по использованию соответствующего плагина:

Данная команда создаст комплект для статической сборки 64-битных приложений с использованием компилятора седьмой версии (7.4.0). Если такой комплект уже существует, то он изменен не будет.

Со списком всех доступных плагинов можно ознакомиться на странице.

В директории mxe/src содержатся *.mk файлы, которые описывают параметры сборки того или иного пакета. При необходимости можно внести требуемые коррективы в уже существующий пакет или добавить свой собственный. Структура файлов описана вот тут — https://github.com/mxe/mxe/wiki/Add-a-New-Package:-Full-Version.

Для копирования pзависимостей проект mxe предоставляет утилиту copydlldeps.sh. Но это не единственный полезный инструмент, с их олным списокм можно ознакомиться на странице.

CMake и статическая линковка Qt

Так сложилось, что в своем проекте я использовал Qt и систему сборки CMake. Когда было принято решение о сборке проекта для Windows, отличным решением выглядело собрать все используя статическую линковку, чтобы пользователям предоставлять один бинарь, без каких-либо зависимостей.

Разбирая целую гору ошибок линковщика, удалось выяснить, что такая сборка из коробки не работает, вообще нигде. Дело в том, что qmake при использовании статической линковки генерирует *.cpp-файл, в котором находятся инструкции по импортированию плагинов, примерно такого вида:

Так же добавляются флаги и библиотеки для этапа линковки в Makefile.

Можно попробовать поэкспериментировать вот с такой конструкцией в CMakeLists.txt:

В конце концов, я пришел к решению динамически линковать (по возможности) все внешние библиотеки и копировать вместе с исполняемым файлом еще и необходимые dll с помощью copydlldeps.sh. Более подробно про разворачивание под Qt под Windows описано в статье.

В заключении

Выше было показано, как за несколько простых шагов можно настроить среду для кросс-компиляции проекта. Но, к сожалению, в реальных условиях все не так радужно.

Хоть проект mxe предоставляет внушительный список библиотек, но все равно он может не включать тех, которые нужны именно Вам, или включать слишком новые версии. Да, есть возможность самому создать пакет или, на худой конец, собрать библиотеку из исходников. Но не все можно сбилдить кросс-компилятором, так мне не удалось сделать это с проектом cpprestsdk, потому что ему нужен установленный vcpkg.

Это дело каждого — использовать кросс-компиляцию или нет. Мне это принесло неплохой профит. Я настроил сборку под несколько дистрибутивов Linux и Windows в отдельных docker-контейнерах для своего проекта SecureDialogues, добавил один make-файл для запуска процесса поочередно для каждого контейнера. Далее запускаю make и через некоторое время получаю бинарные файлы для требуемых ОС в локальной папке.

Источник

Осваиваем кросс-компиляцию с помощью Clang и LLVM

Каждый, кто когда-либо пробовал собрать программу на C/C++ через кросс-компиляцию знает, насколько болезненным может быть этот процесс. Главными причинами столь печального положения вещей являются недружелюбность систем сборки при конфигурации кросс-компиляции, а также запутанность процесса настройки набора утилит (тулчейна).

Одним из основных виновников этих проблем, по моему опыту, является тулчейн GNU — древний мамонт, на котором много десятилетий строится весь мир POSIX. Подобно многим компиляторам былых времён, семейство GCC и binutils никогда не ориентировалось на поддержку множества различных целей сборки в одной установке, и единственным способом хоть как-то добиться желаемого была настройка полной кросс-билд-системы для каждой целевой платформы на каждом хосте.

Например, если вы хотите собрать что-то для FreeBSD на машине под Linux с помощью GCC, вам потребуется:

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

Clang как кросс-компилятор

Эти досадные ограничения побудили меня обратить внимание на LLVM (и Clang), который изначально создан как полноценный тулчейн для кросс-компиляции, и при этом практически полностью совместим с GNU. Один единственный инстанс LLVM способен собирать и компилировать код для каждой поддерживаемой платформы; помимо него для сборки нужен лишь sysroot.

Несмотря на то, что он ещё не может сравниться по удобству с тулчейнами современных языков (такими, как gc и GOARCH / GOOS в Go), это всё же настоящий глоток свежего воздуха по сравнению со сложностями настроек тулчейнов GNU. Вы можете просто установить его из пакетов для вашего дистрибутива (если только он не сильно старый), и сразу избежать всех сложностей с множественными установками GCC.

Когда весь тулчейн доступен, для компиляции и сборки вашего проекта необходим ещё sysroot, содержащий все необходимые библиотеки и заголовочные файлы.

Добываем sysroot

Быстрее всего раздобыть работающую системную папку для нужной ОС можно, скопировав её напрямую из существующей системы (для этого зачастую подходит контейнер Docker). Например, вот так я скопировал работающий sysroot из виртуалки с FreeBSD 13-CURRENT AArch64 с помощью tar и ssh

При копировании по сети, а не локально, неплохо также сжать получившийся tarball

Запускаем кросс-компилятор

Когда всё готово, остаётся лишь запустить Clang с правильными аргументами:

К сожалению, macOS больше не поддерживается в LLD, ввиду того, что поддержка формата Mach-O была заброшена несколько лет назад. В связи с этим единственным способом собрать исполняемый файл формата Mach-O является использование линкера ld64 (нативного, или в кросс-системе, если вы сами его соберёте). Хотя утилита ld.bfd из binutils всё ещё его поддерживает.

Читайте также:  Бросить делать что то на английском

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

Всё получилось! Теперь мы можем использовать этот кросс-тулчейн для сборки более крупных программ, и ниже я расскажу, как использовать его для сборки реальных проектов.

Опционально: создаём папку с тулчейном LLVM

LLVM предоставляет практически полностью совместимые альтернативы для всех утилит, входящих в binutils (за исключением разве что as ), с префиксом llvm- в имени.

Наиболее критичной из них является LLD, который полностью подменяет системный линковщик для целевой платформы и может заменить одновременно как ld.bfd из GNU, или gold из GNU/Linux или BSD, так и LINK.EXE от Microsoft при сборке под MSVC. Он поддерживает сборку на (практически) каждой платформе, поддерживаемой LLVM, таким образом устраняя необходимость в нескольких специфических линковщиках.

Быстрым решением для этой проблемы будет создание папки тулчейна, содержащей символические ссылки, которые переименовывают утилиты LLVM в стандартные программы из binutils :

Опционально: создаём обёртки Clang для упрощения кросс-компиляции

Понимая, насколько громоздко и сложно каждый раз не забыть выписать все параметры корректно в каждом из случаев, я обычно пишу короткие обёртки для clang и clang++ с целью упростить сборку для конкретной целевой платформы:

Кросс-сборка с помощью Autotools, Cmake и Meson

Autotools, Cmake и Meson, возможно, самые популярные системы сборки для open-source проектов на C и C++ (извини, SCons). Все три поддерживают кросс-компиляцию прямо «из коробки», хотя с некоторыми особенностями.

Autotools

Я также задал сборку линковщика Gold, который написан на С++ и может использоваться как неплохой тест на то, как наш импровизированный тулчейн способен компилировать программы на C++.

Если стадия конфигурации не сломается по какой-то причине (вроде не должно), мы можем далее запустить GNU Make и собрать binutils :

CMake

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

Для сборки под триплет aarch64-pc-freebsd тулчейн файл может быть таким:

В этом файле я назначил вышеупомянутую обёртку как кросс-компилятор кода C и C++ для целевой платформы. Также можно использовать напрямую Clang с подходящими параметрами, но это не настолько прямолинейно и потенциально более подвержено ошибкам.

Meson

Подобно CMake, Meson полагается на файлы тулчейнов (так называемые «cross files»), которые определяют, какие программы должны быть использованы для сборки под текущую целевую платформу. Благодаря тому, что они написаны на TOML-подобном языке, они очень просты и понятны:

Бонус: статическая сборка с musl и Alpine Linux

Статическая сборка программ на C и C++ иногда может спасти вас от множества проблем совместимости библиотек, особенно когда вы не можете контролировать, что именно будет установлено на той целевой платформе, под которую вы планируете сборку. Однако сборка статических бинарников на GNU/Linux довольно непроста, поскольку Glibc всячески препятствует попыткам слинковаться с ним статически.

Система разрешения имён (NSS), встроенная в glibc, является одной из главных причин интенсивного использования функций dlopen()/dlsym(). Это связано с использованием сторонних плагинов, вроде mDNS, используемых для разрешения имён.

Musl — это альтернанивный вариант стандартной библиотеки для Linux, которая гораздо терпимее к статической линковке, и нынче включена в большинство крупных дистрибутивов. Этих пакетов зачастую вполне достаточно для статической сборки вашего кода, по крайней мере пока вы планируете оставаться в рамках чистого C.

Настройка контейнера с Alpine

Хорошей отправной точкой является тарболл с minirootfs от Alpine, который предназначен специально для контейнеров, а потому очень маленький:

Теперь мы можем сделать chroot внутрь образа

К сожалению, по неизвестным мне причинам Alpine не предоставляет статические версии некоторых библиотек (например, libfmt ). Поэтому внедрять копию зависимостей в проект является вполне обычной практикой для C++, и потому это довольно несложно.

Также не забывайте каждый раз запускать apk upgrade внутри sysroot, чтобы поддерживать локальную копию Alpine в актуальном состоянии.

Сборка статических программ на C++

Написание обёртки для статической линковки с Musl и Clang

Заключение

К сожалению, не всё то золото, что блестит, и так бывает довольно часто. До сих пор встречаются костыли, которые собираются только с помощью GCC из-за грязных GNUизмов (да-да, Glibc, это про тебя). Кросс-компиляция под Windows/MSVC также невозможна ввиду сильной запутанности всего тулчейна Visual Studio.

Кроме того, хотя сборка под целевую платформу путём указания в Clang верного триплета стала гораздо проще, чем когда-то была, она всё равно нервно курит, поглядывая на то, насколько тривиальна кросс-компиляция в случае с Rust или Go.

Из новых языков отдельного упоминания заслуживает Zig, поскольку его целью является также облегчение сборки кода на C и C++ под другие платформы.

Команды zig cc и zig c++ потенциально могут стать удивительным швейцарским ножом для кросс-компиляции, благодаря тому, что Zig содержит в себе clang и множество частей из разных проектов, такие как Glibc, Musl, libc++ и MinGW. Благодаря этому любая нужная библиотека собирается, если надо, прямо на лету:

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

Источник

Портал знаний