Кросс -компилятор — это компилятор, способный создавать исполняемый код для платформы, отличной от той, на которой работает компилятор. Например, компилятор, работающий на ПК , но генерирующий код, который работает на устройствах Android, является кросс-компилятором.
Кросс-компилятор полезен для компиляции кода для нескольких платформ с одного хоста разработки. Прямая компиляция на целевой платформе может быть невозможна, например, на встраиваемых системах с ограниченными вычислительными ресурсами.
Кросс-компиляторы отличаются от компиляторов исходного кода . Кросс-компилятор предназначен для кроссплатформенной генерации программного обеспечения машинного кода, тогда как компилятор исходного кода переводит с одного языка кодирования на другой в текстовом коде. Оба являются инструментами программирования .
Основное применение кросс-компилятора — разделение среды сборки и целевой среды. Это полезно в нескольких ситуациях:
Использование виртуальных машин (например, JVM Java ) решает некоторые из причин, по которым были разработаны кросс-компиляторы. Парадигма виртуальной машины позволяет использовать один и тот же вывод компилятора на нескольких целевых системах, хотя это не всегда идеально, поскольку виртуальные машины часто медленнее, а скомпилированная программа может быть запущена только на компьютерах с этой виртуальной машиной.
Обычно архитектура оборудования отличается (например, кодирование программы, предназначенной для архитектуры MIPS на компьютере x86 ), но кросс-компиляция также применима, когда отличается только среда операционной системы , как при компиляции программы FreeBSD под Linux , или даже только системной библиотеки, как при компиляции программ с помощью uClibc на хосте glibc .
Канадский крест — это метод создания кросс-компиляторов для других машин, где исходная машина намного медленнее или менее удобна, чем целевая. Имея три машины A, B и C, одна использует машину A (например, работающую под управлением Windows XP на процессоре IA-32 ) для создания кросс-компилятора, который работает на машине B (например, работающей под управлением macOS на процессоре x86-64 ) для создания исполняемых файлов для машины C (например, работающей под управлением Android на процессоре ARM ). Практическое преимущество в этом примере заключается в том, что машина A медленная, но имеет собственный компилятор, в то время как машина B быстрая, но вообще не имеет компилятора, а машина C непрактично медленная для использования для компиляции.
При использовании канадского креста с GCC, как в этом примере, может быть задействовано четыре компилятора
Конечный кросс-компилятор (4) не сможет работать на сборочной машине A; вместо этого он будет работать на машине B, чтобы скомпилировать приложение в исполняемый код, который затем будет скопирован на машину C и выполнен на машине C.
Например, NetBSD предоставляет скрипт оболочки POSIX Unix с именем , который сначала создаст собственную цепочку инструментов с компилятором хоста; он, в свою очередь, будет использован для создания кросс-компилятора, который будет использоваться для сборки всей системы.build.sh
Термин «Канадский крест» появился потому, что в то время, когда обсуждались эти вопросы, в Канаде было три общенациональные политические партии. [1]
GCC , бесплатный набор компиляторов, может быть настроен на кросс-компиляцию. Он поддерживает множество платформ и языков.
GCC требует, чтобы скомпилированная копия binutils была доступна для каждой целевой платформы. Особенно важен GNU Assembler . Поэтому binutils сначала необходимо правильно скомпилировать с помощью переключателя, --target=some-target
отправленного в скрипт конфигурации . GCC также необходимо настроить с той же --target
опцией. Затем GCC можно запустить в обычном режиме, при условии, что инструменты, которые создает binutils , доступны в path , что можно сделать с помощью следующего (в UNIX-подобных операционных системах с bash):
PATH=/путь/к/binutils/bin:${PATH} сделать
Кросс-компиляция GCC требует, чтобы часть стандартной библиотеки C целевой платформы была доступна на хост-платформе . Программист может выбрать компиляцию полной библиотеки C, но этот выбор может быть ненадежным. Альтернативой является использование newlib — небольшой библиотеки C, содержащей только самые необходимые компоненты, необходимые для компиляции исходного кода C.
Пакеты GNU Autotools (то есть autoconf , automake и libtool ) используют понятия платформы сборки , платформы хоста и целевой платформы . Платформа сборки — это то место, где компилятор фактически компилируется. В большинстве случаев сборка должна быть оставлена неопределенной (по умолчанию она будет из host). Платформа хоста всегда является тем местом, где выходные артефакты компилятора будут выполняться независимо от того, является ли вывод другим компилятором или нет. Целевая платформа используется при кросс-компиляции кросс-компиляторов, она представляет, какой тип объектного кода будет создавать пакет; в противном случае настройка целевой платформы не имеет значения. [2] Например, рассмотрим кросс-компиляцию видеоигры, которая будет работать на Dreamcast . Машина, на которой компилируется игра, является платформой сборки , в то время как Dreamcast является платформой хоста . Имена host и target относятся к используемому компилятору и смещаются как son и grandson . [3]
Другой метод, который часто используют разработчики встраиваемых Linux-систем, включает в себя комбинацию компиляторов GCC со специализированными песочницами, такими как Scratchbox и Scratchbox 2 или PRoot. Эти инструменты создают « chrooted » песочницу, в которой программист может создавать необходимые инструменты, libc и библиотеки без необходимости устанавливать дополнительные пути. Также предоставляются средства для «обмана» среды выполнения, чтобы она «верила», что она действительно работает на предполагаемом целевом процессоре (например, на архитектуре ARM); это позволяет скриптам конфигурации и т. п. работать без ошибок. Scratchbox работает медленнее по сравнению с «неchrooted» методами, и большинство инструментов, которые находятся на хосте, должны быть перемещены в Scratchbox для работы.
Компания Manx Software Systems из Шрусбери , штат Нью-Джерси , начала производить компиляторы C в 1980-х годах, ориентированные на профессиональных разработчиков для различных платформ, включая IBM PC-совместимые и Mac .
Язык программирования Aztec C Мэнкса был доступен для множества платформ, включая MS-DOS , Apple II , DOS 3.3 и ProDOS , Commodore 64 , Mac 68k [4] и Amiga .
С 1980-х и вплоть до исчезновения Manx Software Systems версия Aztec C для MS-DOS [5] предлагалась как в качестве компилятора собственного режима, так и в качестве кросс-компилятора для других платформ с другими процессорами, включая Commodore 64 [6] и Apple II. [7] Интернет-дистрибутивы Aztec C все еще существуют, включая их кросс-компиляторы на основе MS-DOS. Они используются и сегодня.
Aztec C86 от Manx, их собственный режим 8086 компилятора MS-DOS, также был кросс-компилятором. Хотя он не компилировал код для другого процессора, как их кросс-компиляторы Aztec C65 6502 для Commodore 64 и Apple II, он создавал двоичные исполняемые файлы для тогдашних устаревших операционных систем для 16-битного семейства процессоров 8086.
Когда IBM PC был впервые представлен, он был доступен с выбором операционных систем, CP/M-86 и PC DOS были двумя из них. Aztec C86 был снабжен библиотеками ссылок для генерации кода для обеих операционных систем IBM PC . В течение 1980-х годов более поздние версии Aztec C86 (3.xx, 4.xx и 5.xx) добавили поддержку для MS-DOS "переходных" версий 1 и 2 [8] , которые были менее надежными, чем "базовая" MS-DOS версии 3 и более поздние, на которые Aztec C86 ориентировался до своей кончины.
Наконец, Aztec C86 предоставил разработчикам языка C возможность создавать ROM-способный "HEX" -код, который затем можно было перенести с помощью ROM-рекордера непосредственно на процессор на базе 8086. Паравиртуализация может быть более распространена сегодня, но практика создания низкоуровневого ROM-кода была более распространена на душу населения в те годы, когда разработка драйверов устройств часто выполнялась прикладными программистами для отдельных приложений, а новые устройства представляли собой кустарное производство . Нередко прикладные программисты взаимодействовали напрямую с оборудованием без поддержки производителя. Эта практика была похожа на современную разработку встраиваемых систем .
Томас Фенвик и Джеймс Гуднау II были двумя основными разработчиками Aztec-C. Фенвик позже стал известен как автор ядра Microsoft Windows CE или NK («Новое ядро»), как его тогда называли. [9]
Microsoft C (MSC) имеет более короткую историю, чем другие [10] , начиная с 1980-х годов. Первые компиляторы Microsoft C были созданы той же компанией, которая создала Lattice C , и были переименованы Microsoft в свои собственные, пока не был выпущен MSC 4, который был первой версией, которую Microsoft выпустила сама. [11]
В 1987 году многие разработчики начали переходить на Microsoft C, и многие другие последовали за ними в ходе разработки Microsoft Windows до ее нынешнего состояния. Появились такие продукты, как Clipper , а позже и Clarion , которые предлагали простую разработку приложений баз данных с использованием кросс-языковых методов, позволяя компилировать часть своих программ с помощью Microsoft C.
Borland C (калифорнийская компания) стала доступна для покупки за несколько лет до того, как Microsoft выпустила свой первый продукт на языке C.
Задолго до Borland, BSD Unix (Берклийский университет) получил C от авторов языка C: Кернигана и Ритчи , которые написали его в унисон, работая в AT&T (лаборатории). Первоначальными потребностями K&R был не только элегантный синтаксис 2-го уровня разбора для замены синтаксиса 1-го уровня разбора asm: он был разработан так, чтобы минимальное количество asm было написано для поддержки каждой платформы (первоначальный дизайн C был возможностью кросс-компиляции с использованием C с наименьшим количеством кода поддержки на платформу, что им было нужно.). Также вчерашний C напрямую связан с кодом ASM везде, где это не зависит от платформы. Сегодняшний C (тем более c++) больше не совместим с C, и лежащий в основе код asm может сильно отличаться от написанного на данной платформе (в Linux: он иногда заменяет и обходит вызовы библиотек с выбором дистрибьютора). Сегодняшний C — это язык 3-го или 4-го уровня, который используется по-старому, как язык 2-го уровня.
Программы на языке C долгое время были связаны с модулями, написанными на языке ассемблера . Большинство компиляторов C (даже современные компиляторы) предлагают проход языка ассемблера (который можно настроить для эффективности, а затем связать с остальной частью программы после сборки).
Компиляторы, такие как Aztec-C, преобразовывали все в язык ассемблера в отдельный проход, а затем собирали код в отдельный проход и были известны своим очень эффективным и небольшим кодом, но к 1987 году оптимизатор, встроенный в Microsoft C, был очень хорош, и только «критически важные» части программы обычно рассматривались для переписывания. Фактически, программирование на языке C заняло позицию «низкоуровневого» языка, при этом программирование стало многопрофильной растущей отраслью, а проекты стали крупнее, при этом программисты писали пользовательские интерфейсы и интерфейсы баз данных на языках более высокого уровня, и возникла необходимость в кросс-языковой разработке, которая сохраняется и по сей день.
К 1987 году, с выпуском MSC 5.1, Microsoft предложила кросс-языковую среду разработки для MS-DOS. 16-битный двоичный объектный код, написанный на языке ассемблера ( MASM ) и других языках Microsoft, включая QuickBASIC , Pascal и Fortran, можно было связать в одну программу в процессе, который они называли «Mixed Language Programming» (программирование на смешанных языках), а теперь «InterLanguage Calling» (межъязыковые вызовы). [12] Если BASIC использовался в этой смеси, основная программа должна была быть на BASIC для поддержки внутренней системы выполнения , которая компилировала BASIC, необходимый для сборки мусора и других его управляемых операций, которые имитировали интерпретатор BASIC, такой как QBasic в MS-DOS.
Соглашение о вызовах для кода C, в частности, состояло в том, чтобы передавать параметры в «обратном порядке» в стеке и возвращать значения в стеке, а не в регистре процессора . Были и другие правила программирования, чтобы заставить все языки работать вместе, но это конкретное правило сохранялось в ходе кросс-языковой разработки, которая продолжалась в 16- и 32-разрядных версиях Windows , а также в разработке программ для OS/2 , и которое сохраняется по сей день. Оно известно как соглашение о вызовах Pascal .
Другой тип кросс-компиляции, для которого Microsoft C использовался в то время, был в розничных приложениях, которым требовались карманные устройства , такие как Symbol Technologies PDT3100 (использовавшийся для инвентаризации ), который предоставлял библиотеку ссылок, ориентированную на считыватель штрихкодов на базе 8088. Приложение было создано на главном компьютере, а затем передано на карманное устройство (через последовательный кабель ), где оно запускалось, аналогично тому, что делается сегодня для того же рынка с использованием Windows Mobile такими компаниями, как Motorola , купившими Symbol.
На протяжении 1990-х годов и начиная с MSC 6 (их первого ANSI C- совместимого компилятора) Microsoft переориентировала свои C-компиляторы на развивающийся рынок Windows, а также на OS/2 и разработку программ с графическим интерфейсом пользователя . Совместимость со смешанными языками сохранялась вплоть до MSC 6 на стороне MS-DOS, но API для Microsoft Windows 3.0 и 3.1 был написан в MSC 6. MSC 6 также был расширен для обеспечения поддержки 32-разрядных сборок и поддержки появляющихся Windows for Workgroups и Windows NT , которые станут основой для Windows XP . Была введена практика программирования, называемая thunk, чтобы обеспечить передачу между 16- и 32-разрядными программами, которые использовали преимущества связывания во время выполнения ( динамическое связывание ) вместо статического связывания , которое было предпочтительным в монолитных 16-разрядных приложениях MS-DOS. Статическое связывание по-прежнему пользуется популярностью у некоторых разработчиков собственного кода, но, как правило, не обеспечивает той степени повторного использования кода , которая требуется новыми передовыми практиками, такими как Модель зрелости возможностей (CMM).
Поддержка MS-DOS по-прежнему обеспечивалась с выпуском первого компилятора C++ от Microsoft, MSC 7, который был обратно совместим с языком программирования C и MS-DOS и поддерживал генерацию как 16-, так и 32-разрядного кода.
MSC заняла место Aztec C86 . Рыночная доля компиляторов C перешла к кросс-компиляторам, которые использовали преимущества новейших и лучших функций Windows, предлагали C и C++ в одном пакете и по-прежнему поддерживали системы MS-DOS, которым уже было десять лет, а более мелкие компании, производившие компиляторы, такие как Aztec C, больше не могли конкурировать и либо переходили на нишевые рынки, такие как встраиваемые системы , либо исчезали.
Поддержка генерации MS-DOS и 16-битного кода продолжалась до версии MSC 8.00c, которая была включена в Microsoft C++ и Microsoft Application Studio 1.5, предшественника Microsoft Visual Studio — среды кросс-разработки, которую Microsoft предоставляет сегодня.
MSC 12 был выпущен вместе с Microsoft Visual Studio 6 и больше не поддерживал 16-битные двоичные файлы MS-DOS, вместо этого обеспечивая поддержку 32-битных консольных приложений, но обеспечивая поддержку генерации кода для Windows 95 и Windows 98 , а также для Windows NT . Библиотеки ссылок были доступны для других процессоров, работающих под управлением Microsoft Windows; эту практику Microsoft продолжает и по сей день.
MSC 13 был выпущен вместе с Visual Studio 2003, а MSC 14 — вместе с Visual Studio 2005. Обе версии по-прежнему создают код для старых систем, таких как Windows 95, но будут создавать код для нескольких целевых платформ, включая рынок мобильных устройств и архитектуру ARM .
В 2001 году Microsoft разработала Common Language Runtime (CLR), которая стала ядром для их компилятора .NET Framework в Visual Studio IDE. Этот слой операционной системы, который находится в API, позволяет смешивать языки разработки, скомпилированные на разных платформах, на которых работает операционная система Windows.
Среда выполнения .NET Framework и CLR предоставляют слой сопоставления с основными процедурами для процессора и устройств на целевом компьютере. Компилятор C командной строки в Visual Studio скомпилирует собственный код для различных процессоров и может использоваться для построения самих основных процедур.
Приложения Microsoft .NET для целевых платформ, таких как Windows Mobile на архитектуре ARM, кросс-компилируются на машинах Windows с различными процессорами, а Microsoft также предлагает эмуляторы и среды удаленного развертывания, требующие минимальной настройки, в отличие от кросс-компиляторов прошлых лет или на других платформах.
Библиотеки времени выполнения, такие как Mono , обеспечивают совместимость кросс-скомпилированных программ .NET с другими операционными системами, такими как Linux .
Библиотеки, такие как Qt и ее предшественники, включая XVT, обеспечивают возможность кросс-разработки на уровне исходного кода с другими платформами, при этом все еще используя Microsoft C для сборки версий Windows. Другие компиляторы, такие как MinGW, также стали популярными в этой области, поскольку они более напрямую совместимы с Unix, которые составляют не-Windows сторону разработки программного обеспечения, позволяя разработчикам ориентироваться на все платформы, используя знакомую среду сборки.
Free Pascal изначально разрабатывался как кросс-компилятор. Исполняемый файл компилятора (ppcXXX, где XXX — целевая архитектура) способен создавать исполняемые файлы (или просто объектные файлы, если внутреннего компоновщика нет, или даже просто файлы сборки, если внутреннего ассемблера нет) для всех ОС той же архитектуры. Например, ppc386 способен создавать исполняемые файлы для i386-linux, i386-win32, i386-go32v2 (DOS) и всех других ОС (см. [13] ). Однако для компиляции в другую архитектуру сначала необходимо собрать кросс-архитектурную версию компилятора. Получившийся исполняемый файл компилятора будет иметь дополнительное «ross» перед целевой архитектурой в своем имени. т. е. если компилятор создан для целевой x64, то исполняемый файл будет называться ppcrossx64.
Для компиляции для выбранной архитектуры-ОС можно использовать ключ компилятора (для драйвера компилятора fpc) -P и -T. Это также делается при кросс-компиляции самого компилятора, но устанавливается через параметр make CPU_TARGET и OS_TARGET. Ассемблер и компоновщик GNU для целевой платформы требуются, если Free Pascal еще не имеет внутренней версии инструментов для целевой платформы.
Clang изначально является кросс-компилятором, и во время сборки вы можете выбрать, на какие архитектуры Clang будет ориентироваться.
Гетерогенная система Plan 9 и ее набор инструментов не различают кросс- и нативную компиляцию. Makefiles независимы от архитектуры.
Это называется «Канадский крест», потому что на момент, когда название было необходимо, в Канаде было три национальные партии.
i386