Ж.Арсено,
The Free Software Foundation Сан-Франциско, США
jla@ai.mit.edu
М. Тиман, Д. В. Хенкель-Уоллес,
Cygnis Support, Пало Альто, Калифорния, США
tiemann@cygnis.com, gymby@cygnis.com

Особые преимущества свободного программного обеспечения
Предварительные разъяснения
Как решить, что следует переносить
Написание переносимой программы
Препятствия переносимости со стороны аппаратуры
Проблемы, связанные с операционными системами
Переносимая разработка и установка
Частные случаи

Продукты FGS выполняются на десятках различных архитектур и в десятках систем, включая многие типы Unix, а также VMS и MS-DOS. Сравнительно небольшая команда проекта GNU сумела выполнить эту работу, обладая довольно ограниченными ресурсами. Почему программное обеспечение GNU настолько переносимо? Ответ - потому что это свободное программное обеспечение.

Особые преимущества свободного программного обеспечения

Основная причина технического успеха программного обеспечения GNU - его статус разрешенного для копирования. Это не хорошее программное обеспечение, которое случайно оказалось свободным; это хорошее программное обеспечение потому, что оно свободное программное обеспечение.

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

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

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

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

В качестве примеров будут рассмотрены четыре инструмента, позволяющие продемонстрировать широту подхода проекта GNU: редактор GNU Emacs, отладчик GDB, GNU-компилятор языка Си и библиотека BFD для работы с двоичными программными файлами. Эти компоненты выбраны потому, что каждый:

  • перенесен более чем на дюжину платформ
  • имеет нетривиальную часть для переноса
  • содержит новые решения в обеспечении переносимости
  • продолжает переноситься на новые платформы

Предварительные разъяснения

Начнем с объяснения терминов. Говоря "свободное программное обеспечение", мы имеем в виду, что пользователь свободен копировать, распространять, изучать и модифицировать или улучшать это программное обеспечение. В этом основная причина широкого распространения программного обеспечения GNU.

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

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

Как решить, что следует переносить

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

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

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

Написание переносимой программы

Программы GNU написаны на языке Си. Исключение составляют языковые расширения (например, Лисп или язык описания целевых машин системы GCC). Си был выбран по следующим причинам:

  • Си - мощный язык, поддерживающий системное программирование
  • Си легко реализуется в разнообразных архитектурах
  • Си - базовый язык ОС UNIX

Выбрав Си, мы постарались избежать традиционных ловушек. Наиболее широко цитируемое правило наших стандартов программирования: "никаких произвольных ограничений". Это означает запрет стратегически определенных таблиц и строк фиксированной длины.

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

Наш общий подход - избегать использования расширений в больших и широко распространенных программах таких, как Emacs, которая выполняется на многих разнообразных системах, или GCC, поскольку в начале процесса ее раскрутки требуется ее оттранслировать с помощью других компиляторов. Сделав перенос GCC более легким, мы облегчили и перенос остальных GNU-программ.

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

Если в ANSI-стандарте Си зафиксировано определенное поведение, мы пытаемся добиться внешней совместимости с ним, а также со стандартами POSIX. Когда стандарты противоречат друг другу, мы пытаемся предложить варианты, совместимые с каждым из них. Но мы не отказываемся и от реализации расширений, запрещенных стандартами ANSI или POSIX, если считаем, что они лучше (например, наши расширения Си). В таких случаях мы предоставляем опции (-ansi или -compartibility), чтобы отключить решения.

Препятствия переносимости со стороны аппаратуры

Две основных особенности аппаратуры, препятствующие переносимости -тип процессора и организация памяти. Для большей части программ GNU первая проблема разрешается путем перекомпиляции, но есть и исключения. Некоторые программы GNU содержат ассемблерный код. Для поддерживаемых процессоров предоставляются версии такого кода, однако проблемы иногда возникают. Например, alloca, функция, увеличивающая указатель стека для выделения памяти, неверно работала на системах, компиляторы которых реализовывали доступ к стеку не через sp, а через fp.

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

int c;
while ((c=getchar())|=EOF)
write (file_descriptor, &c, l);

Дело в том, что некоторые машины имеют обратный порядок байт в слове; приведенный фрагмент будет работать не всегда. В Emacs подобные действия реализованы аккуратно с помощью условных макросов.

Проблемы, связанные с операционными системами

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

Ориентированная на общий случай разработка приводит к более простой и понятной программе. Например, разработка модели ввода-вывода ведет к более четкой структуре программ, чем использование конкретных системных вызовов. Чрезвычайно трудно прояснить структуру множества вызовов ioctl и fnctl, имеющихся в различных системах, используя условную компиляцию. Кроме того, часто те или иные функции имеются в одних системах, но отсутствуют в других. Поставка таких функций вместе с программой гарантирует их наличие (поставляемые вместе с программами GNU функции часто бывают лучше своих системных аналогов).

Вот некоторые из свойств операционных систем, вызывавших трудности:

  • разные форматы объектных фалов;
  • коллизии между включаемыми файлами;
  • разные стили обработки сигналов и разная семантика сигналов;
  • разные соглашения об именах файлов;
  • разные ошибки в различных версиях одной и той же системы;
  • необоснованные расширения "стандартных" свойств;
  • разные оконные системы;
  • плохая документация (или ее отсутствие).

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

Переносимая разработка и установка

Будучи переносимым, программное обеспечение должно легко устанавливаться с минимальным числом переделок, связанных с различием платформ. За прошедшие годы было опробовано несколько стратегий. Одну из наиболее занимательных программ, configure, часто называли "Шоу Ларри Уолла", поскольку она выдавала забавные сообщения, пока проводилось всестороннее исследование системы.

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

configure sun4 +ansi +destdir=/usr/local/bin +target=sun3

настраивает программный пакет на построение в окружении Sun 4 для установки /usr/local/bin и для выполнения на Sun 3. Более того, запрашивается соответствие исходного текста ANSI-стандарту.

Мы планируем в конце концов внедрить configure повсеместно.

Частные случаи

GNU Emacs

Пожалуй, GNU Emacs - наиболее переносимая из больших систем проекта GNU, так как она выполняется на самом большом числе платформ. В то же время нельзя сказать, что обеспечение столь высокой степени переносимости существенно повлияло на ее исходный текст. Рассмотрим положительные аспекты Emacs в смысле переносимости.

Насколько она переносима?

Система GNU EMACS обеспечивает одно из наиболее согласованных программных окружений, доступных на современных компьютерах. Пользователь, сравнивая поведение EMACS на Sun, и на VAX под управлением VMS, может не найти никаких различий. Экраны выглядят одинаково, команды работают одинаковым образом. (Исключение составляют лишь имена файлов системы VMS.) Расширения, сделанные конечными пользователями, тоже выглядят одинаково и, более того, работают на любой другой платформе, оснащенной GNU EMACS.

Как это получилось?

Фундамент такой совместимости - раннее проектное решение использовать Лисп для разработки функциональной части редактора. Большая часть Си-программ системы связана с поддержкой среды Лиспа. Подавляющее большинство расширений редактора можно написать, не опасаясь наткнуться на особенности конкретного диалекта Си. Пользователи EMACS часто пишут сложные редактирующие программы, работающие потом на самых разных платформах.

Лисп-программы, относящиеся к редактированию, системно-независимы; однако несколько функций определяется отдельно специально для основной ОС. Вот пример из редактора каталогов dired:

(if (eq system-type "vax-vms)
     (vms-read-directory dirname
         dired-listing-switches buffer)
(if (file-directory-p dirname)
     (call-process "ls" nil buffer nil
        dired-listing-switches dirname)
...

Свободный лисповский символ vms-read-directory определен в файле, компилируемом для системы VMS. Условная компиляция применяется и к функциям, имеющимся не во всех версиях ОС UNIX.

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

Подсистема отображения должна учитывать возможности различных терминалов. Это достигается сведение всех существенных параметров в единую систему таблиц. Алгоритмы отображения ссылаются только на эти таблицы и не ссылаются на конкретные терминалы.

Рассмотренный уровень системы EMACS полностью системно независим. Многочисленные же различия между системами сведены в файле sysdep.c. Здесь можно узнать возраст и влияние множества вариантов системы EMACS - файл, по-видимому, содержит столько же директив препроцессора, сколько и операторов языка Си.

Более частные вопросы

Объекты Лиспа в Си-программах описывались структурами, поэтому для доступа к его компонентам надо учитывать способ выравнивания машины, чтобы правильно разместить в памяти указатели и части структур. Доступ был реализован макросами. Такая реализация оказалась вполне переносимой; для некоторых машин (например, для IBM PC-RT), потребовалась переделка этих макросов, но такие машины встречаются редко.

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

Все макроопределения, задающие специфику платформы, можно разделить на обусловленные аппаратурой (например, признак распространения знака) и связанные с ОС (такие, как поддержка сокетов или подпроцессов). Соответственно, они разделяются на два файла: описание машины и описание системы. Иногда макросы переопределяют стандартные установки. Оба включаемых файла (например, m-sparc.h и s-sunos4.h) указываются в файле config.h; тот в свою очередь вставляется во все Си-файлы системы EMACS. Файл config.h участвует и в порождении make-файла. Таким образом, кроме описания машины и системы специфицируют также и процесс построения. Описанный подход сработал очень хорошо; мы намерены использовать его и в будущих версиях.

Отладчик GNU

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

Первоначальная разработка

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

Интересным аспектом GDB была реализация машиннозависимого интерфейса. Ряд функций программы GDB представляли собой простые инкапсуляции макросов. Спецификация интерфейса макросов для внутренних функций нижнего уровня и функционального интерфейса над ним позволяла четко разделить перенос и расширение возможностей отладчика.

Развитие разработки

Версия 2 системы GDB помимо VAX работала на Sun 3. Архитектура Sun 3 отличается от архитектуры VAX некоторыми важными деталями (прежде всего, порядком байт в слове), но есть и общие черты: использование стека для передачи параметров, поддержка сходных форматов символьных таблиц, отсутствие конвейера длинных команд. GDB удалось преобразовать таким образом, что изменения не затронули машиннозависимых функций отладчика.

При переносе GDB на архитектуру SPARC пришлось многое переписать: параметры могли передаваться через регистры, регистровые окна использовались как стековые кэши, адреса возврата в стеке заменялся регистром, а на фоне команд передачи управления из-за их задержки могли выполняться другие команды.

Возникшие проблемы можно было бы решать двумя способами: реализовать специализированный вариант для SPARC или обобщить компоненты GDB. Первый способ казался более привлекательным, но означал запутывание текста многочисленными директивами условной компиляции. Был выбран второй способ; после того, как перенос на SPARC был завершен, GDB без проблем удалось перенести и на ряд других RISC-архитектур.

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

Эта история повторилась и в отношении формата объектных файлов UNIX System V: один из самых болезненных вопросов - выбор между adb и sdb. Заменяя программы, читающие файлы формата a.out, на их аналоги, рассчитанные на формат COFF, можно перенести отладчик с минимальными затратами.

Когда группа сопровождения системы GDB объявила о слиянии всех версий в новую редакцию, неожиданно возник поток откликов: более 130 разработчиков "приспособили" GDB для поддержки своих удаленных файлов и/или форматов объектных файлов. В сущности, они почувствовали, что достигнута точка, когда GDB приобрела все, что могла, будучи свободно переустанавливаемой, и настал момент, когда придется ограничиваться лишь локальными изменениями и улучшениями.

Переносимость или удобство сопровождения

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

BFD

Библиотека BFD (Binary File Descriptor) обеспечивает интерфейс высокого уровня с множеством различных форматов объектных файлов. В настоящее время она выполняется на дюжине различных систем.

В библиотеке BFD принят подход к переносимости, отличающий ее от систем GCC и EMACS. Во-первых, вместо того, чтобы пытаться свести все системы к одной модели, она для решения проблем переносимости определяет новые абстракции. Во-вторых, привязка к платформе происходит динамически.

Цель и функционирование

Когда началась разработка BFD, лишь немногие из инструментов GNU могли выполняться на системах, которые не были бы фактически порождены BSD. Мы считали, что будет необходимость в поддержке COFF, ELF и других форматов объектных файлов.

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

Новая абстракция

Ранние инструменты GNU полностью ориентировались на формат a.out. Операции выполнялись в том порядке, в котором их данные появлялись в файлах; структура файла совпадала с со структурой программы.

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

Первым текстом такого подхода была реализация программы strip для a.out при помощи перечисленных операций. С самого начала реальные приложения помогали нам обнаруживать пробелы в разработке. Переписывая какие-либо утилиты на базе BFD, мы одновременно порождали другой вариант, для COFF. Когда требовались еще нереализованные операции, мы их добавляли.

Поведение во время выполнения

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

Интерфейс с форматом объектного файла описывался следующей структурой:

struct bfd_target
{
   char *name;
   boolean byteorder_big_p;
   struct bfd_target
        *(*_bfd_check_format) (bfd*);
};

Так как формат описан в самой структуре bfd, нетрудно определить макрос, обеспечивающий вызов нужного метода:

bfd_send(some_bfd,msg_name,(args));

Реализационные соображения

Оказалось, что осуществить перенос BFD легче, чем мы сначала предполагали. Поскольку BFD не использует сигналы или другие существенно переменные части ОС UNIX, потребовалась минимальная условная компиляция.

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

BFD с самого начала разрабатывалась с возможностью переориентации на различные целевые машины. Каждый bfd содержит неинтерпретируемые данные, зависящие от целевой системы. Ни одна из внешних точек входа не использует эти данные, но программы нижнего уровня могут запоминать в них любую необходимую информацию. На самом деле имеется всего два таких блока: однородная память и память для архивов. Так, можно использовать архивы в стиле COFF и s-файлы.

Успехи

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

Приятным сюрпризом оказалась возможность одновременно работать с неоднородными двоичными данными, позволяющая различать каждый двоичных формат. Ядро GNU использует ее, посредством BFD читая объектные файлы.

Си-компилятор GNU

Си-компилятор GNU - это оптимизирующий компилятор программ, написанных на ANSI-стандарте языка Си или традиционном Си (описанном Керниганом и Ритчи), а также поддерживающий расширения Си, введенные GNU. Когда он был впервые реализован, он выполнялся на платформах VAX и Sun 3. Теперь он генерирует код для 22 процессоров и выполняется в 46 конфигурациях.

В этом разделе мы используем термин переориентируемость для описания свойств, зависящих от целевой платформы, и переносимость для описания свойств, зависящих от основной платформы.

Цели первоначальной разработки

Разработка системы GCC первоначально преследовала две цели. Первая - высококачественная реализация языка Си в соответствии с ANSI-стандартом с удовлетворительной скоростью компиляции, генерирующей оптимизированный код. Вторая - возможность переноса и/или переориентации на любую платформу, предназначенную для исполнения GNU ОС, как инструмент переноса последней.

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

EMACS и GDB различают "системную" и "машинную" зависимости. Реализация GCC углубляет классификацию, вводя различия между параметрами основной и целевой машин и определяя язык описания машин. GCC, в отличие от EMACS"а, не имеет встроенного интерпретатора и следует парадигме GDB, разрешающей пользователю иметь один Си-файл, в который помещаются функции, зависящие от целевой системы (например, отвечающие за формирование ассемблерного кода).

Когда две различные основные машины имеют одинаковые процессоры, но разные операционные системы, (например, VMS VAX и BSD VAX), большая часть "машинных" характеристик общая, но "системные" характеристики могут существенно отличаться: в Unix ненулевой код возврата означает ошибку, в VMS - наоборот. Чтобы сделать компилятор переносимым, такие отличия надо описать в системнозависимых файлах.

Основной и целевой файлы пишутся таким образом, чтобы их можно было вставить в файлы, маскируя некоторые определения. Так, "системные" различия не нужно затенять различиями между основной и целевой системами. Четко разделяя понятия, относящиеся к переносимости (основные параметры) , переориентируемости (целевые параметры) и функциональности (описание машины), GCC обеспечивает мощный и элегантный каркас для построения компилятора.

Развитие разработки

В течение двух лет GCC была перенесена более, чем на дюжину платформ. Виртуально все переносы были "местными" (построение компилятора производилось на той же системе, для которой он должен был генерировать код). Множество местных переносов, осуществленных "любителями", доказывает, что GCC в высшей степени переориентируемый компилятор.

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

Построение кросс-компилятора на SPARC для 680х0 было несложным. Правила выравнивания структур различны, но порядок байт одинаков. В то же время MIPS использует обратный порядок байт. Поэтому операции наподобие свертки констант (что сводится к выполнению целевых вычислений на основной машине во время компиляции) пришлось реализовывать тщательно. Не было предусмотрено лишь желание отдельных пользователей поддерживать GCC на многих машинах, генерируя код сразу для множества процессоров.

Факторы, вызвавшие изменения

Пожалуй, наибольшее препятствие для переноса GCC состояло в использовании компилятора основной машины для построения GCC в первый раз. Система GCC минимизирует число ограничений; ее разработка велась в предположении, что она будет транслироваться компиляторами с тем же качеством реализации. Это предположение почти никогда не подтверждалось: макроопределения часто не укладывались в фиксированные границы системных компиляторов, различные нестандартные в смысле ANSI платформы имели включаемые файлы, предназначенные для использования в окружении ANSI, другие файлы были просто ошибочными. Потребовалась большая работа, чтобы заставить GCC работать на этих платформах.

Заключение

Программное обеспечение GNU имело высокую степень переносимости с самого начала. Приобретая больший опыт, мы чувствуем, что оно со временем становится еще более переносимым; важность этого постоянно растет в нашем мире стандартов. Расширяя и улучшая свое программное обеспечение, мы просим компьютерное сообщество продолжать поддерживать нас в этом.


Наиболее полная информация по всем вопросам, касающимся проекта GNU:

Российский Центр Системного программирования тел. (095) 272-53-17 e-mail: help@rcsp.msk.su
Смирнов Юрий Петрович

Бесплатное копирование лент FSF: