Курс на Си. Подбельский. Курс программирования на Си. В., Фомин С. С. Курс программирования на языке Си Учебник
Скачать 1.57 Mb.
|
Стандартные библиотеки. Стандартные библиотеки UNIX хранятся в каталогах /lib или /usr/lib. Ссылка на библиотеки осуществляется при помощи ключа компоновщика -l, который задается в команде сс вызова компилятора языка Си после всех ключей и параметров компилятора. Непосредственно за ключом (без пробела) указывается идентификатор библиотеки, например: %cc . . . . -lx где x - часть имени библиотеки (полное имя библиотеки в данном случае libx.a; стандартный префикс для библиотеки «lib»; стандарт- ■■III Подготовка и выполнение программ ное расширение имени для библиотеки 'a'). Обратите внимание, что libx.a есть название библиотеки, а не отдельного модуля, поэтому суффикс '.a' не обозначает «модуль на ассемблере», как, например, на рис. 8.2. Стандартная библиотека языка Си просматривается компоновщиком автоматически, то есть указание этой библиотеки в командной строке вызова компилятора Си не требуется. Эта библиотека хранится в файле /lib/libc.a. Библиотека математических функций хранится в файле /lib/ libm.a, поэтому указание библиотеки в команде вызова компилятора будет таким: -lm. Напомним, что ключ -l, являющийся ключом компоновщика, необходимо разместить в командной строке вызова компилятора Си после всех других ключей и параметров, так как просмотр библиотеки должен происходить после компиляции, когда становится известно, какие функции из библиотеки нужны для построения исполняемого модуля. Создание и сопровождение собственных библиотек. В UNIX для создания и сопровождения библиотек объектных модулей служит программа ar (archivator - архиватор). Для библиотек в UNIX принят термин «архив»; отсюда в качестве расширения имени библиотеки используется буква 'а'. При создании библиотеки необходимо иметь в виду, что компоновщик просматривает библиотечный файл только один раз. Если объектный модуль функции ссылается на другие имена из той же библиотеки, то он должен быть расположен в библиотеке до этих объектных модулей. Некоторые версии UNIX содержат программу ranlib, которая создает оглавление библиотеки, что позволяет компоновщику ld обращаться к элементам библиотеки в произвольном порядке. В некоторых реализациях UNIX функция построения оглавления библиотеки встроена в программы ar и ld. Главное назначение программы ar - создание и обновление библиотечных файлов, используемых компоновщиком, однако ее можно применять и для любых других, аналогичных целей. Формат команды ar: ar -ключ [ключ...] [позиционное_имя] архив имя. . . Параметры в команде отделяются пробелами. Параметр позиционное_имя не является обязательным. Ключей может быть несколько, тогда они записываются без пробелов и только с одним знаком '-'. Параметр архив задает имя архивного файла. Параметр имя... является списком имен объектных модулей, которые либо находятся в архиве, либо должны быть туда помещены. Ключи программы ar имеют следующий смысл: -d - исключить указанные (с помощью параметра имя...) файлы из архивного файла; -г - заменить указанные (параметром имя...) файлы в архивном файле. Если вместе с ключом r задается необязательный ключ u, то заменяются только файлы, имеющие более поздние даты модификации, чем файлы в архиве. Этот же ключ используется для включения в библиотеку новых файлов, то есть файлы, указанные параметром имя... и отсутствующие в библиотеке, добавляются в архив. Обычно новые файлы помещаются в конец архива. Если указать имя файла из архива в параметре по- зиционное_имя, то можно новые файлы поместить до или после этого файла. Для этого необходимо соответственно добавить к ключу -r необязательные литеры b (before) или a (after); -t - вывести в стандартный поток вывода оглавление архивного файла. При задании параметра имя... печатается информация только об указанных этим параметром файлах. Этот же ключ используется для включения в библиотеку новых файлов, то есть файлы, указанные параметром имя... и отсутствующие в библиотеке, добавляются в архив; -p - вывести в стандартный поток вывода указанные (параметром имя...) файлы из архива; -x - извлечь из архива указанные (параметром имя...) файлы. Если не задан параметр имя..., из архива извлекаются все файлы. В любом случае собственно архивный файл не изменяется; -v - выдавать пояснительные сообщения; -c - создать архивный файл. Обычно программа ar при необходимости создает архивный файл сама. Данный ключ подавляет информационное сообщение, выдаваемое при создании архивного файла. Для размещения в личной библиотеке объектных модулей функций иллюстративной программы необходимо выполнить следующую команду: %ar -rv libtree.a add_node.o new_node.o print.o Здесь libtree.a - имя библиотеки (архивного файла). Ключ -r задает режим замены объектных модулей, хранящихся в библиотеке, на объектные модули, список которых приведен в командной строке вызова архиватора ar после имени библиотеки. Так как в момент обработки указанной команды библиотеки не существовало, она будет создана автоматически. Ключ -v определяет режим вывода пояснительных сообщений о работе архиватора ar. После занесения объектных модулей в библиотеку необходимо при помощи программы ranlib скорректировать (или создать) оглавление библиотеки, выполнив команду %ranlib libtree.a Рекомендуется ознакомиться с описанием программы ranlib до ее использования. Например, справку о ней можно получить так: %man ranlib Проверим созданную библиотеку, распечатав ее оглавление: %ar -t libtree.a _ _.SYMDEF add_node.o new_node.o print.o Первая строка - вызов программы-архиватора (ar). Последние 4 строки - это результат работы команды ar. Оглавление библиотеки содержится в разделе библиотеки _ _.SYMDEF. Остальные строки - это имена объектных модулей, находящихся в библиотеке. После того как библиотека объектных модулей создана, можно построить исполняемый модуль программы сортировки на основе бинарного дерева с помощью команды: %cc -o tree tree.c -ltree Здесь транслируется головной модуль (tree.c), объектные модули на этапе компоновки выбираются из библиотеки libtree.a, и строится исполняемая программа с именем tree. Ключ компоновщика -l позволяет задать имя библиотеки объектных модулей (полное имя библиотеки: libtree.a). Предположим, что в исходный текст одной из функций (например, add_node( )) были внесены изменения. Тогда для построения обновленного варианта исполняемой программы необходимо выполнить следующие команды: %cc -c add_node.c %ar -rv libtree.a add_node.o %cc -o tree tree.o -ltree На этот раз нет необходимости в повторной трансляции головного модуля (он не подвергался правке), поэтому в последней строке задано имя уже существующего объектного модуля tree.o. Применим в той же иллюстративной программе утилиту make для поддержания личной библиотеки объектных модулей в таком состоянии, когда она всегда содержит объектные модули, полученные из последних версий соответствующих исходных модулей. Выше был приведен пример файла зависимостей утилиты make, в котором все объектные модули, используемые для построения исполняемого модуля программы сортировки, указывались в командной строке вызова компилятора. В варианте make-файла, ориентированном на применение личной библиотеки объектных модулей, появляются два целевых файла: исполняемая программа сортировки (tree) и библиотека объектных модулей (libtree.a), причем исполняемая программа зависит от содержимого (объектных модулей) библиотеки. Взаимозависимость этих объектов определяется следующим образом: tree: tree.o \ add_node.o \ new_node.o \ print.o \ libtree.a libtree.a: libtree.a(add_node.o) \ libtree.a(new_node.o) \ libtree.a(print.o) Обратите внимание, как указаны зависимость целевого файла tree от библиотеки libtree.a и, в свою очередь, ее зависимость от объектных модулей. Объектный модуль из библиотеки libtree.a указывается так: имя_библиотеки(имя_модуля). Для окончательного оформления make-файла используем два встроенных макроса утилиты make: $@ - задает имя текущего целевого файла (в нашем случае - последнего (libtree.a)); $? - значение этого макроса вычисляется утилитой make - это имена всех модулей, которые подвергались изменениям. Приведем один из вариантов полного текста make-файла (напомним, что его имя по умолчанию - makefile), позволяющего обновлять целевые файлы (исполняемую программу и библиотеку объектных модулей) в соответствии с изменениями в исходных текстах функций, входящих в состав иллюстративной программы: tree: tree.o \ add_node.o \ new_node.o \ print.o \ libtree.a libtree.a: libtree.a(add_node.o) \ libtree.a(new_node.o) \ libtree.a(print.o) ar -rv $@ $? ranlib $@ cc -o tree tree.c -ltree Теперь, для того чтобы построить исполняемый модуль, учитывающий все внесенные изменения в любые функции программы сортировки, необходимо просто набрать на клавиатуре команду make. После внесения изменений, например в исходный текст функции new_node( ), и при выполнении команды make получим на экране дисплея следующий протокол: %make cc -o -c new_node ar -rv libtree.a new_node.o r - new_node.o ranlib libtree.a cc -o tree tree.c -ltree Строка, следующая за командой вызова архиватора ar (r - new_ node.o), - это сообщение архиватора о замене объектного модуля new_node.o в библиотеке libtree.a. Контрольные вопросы Опишите упрощенную схему подготовки программ к выполнению, характерную для большинства операционных систем. Дайте определения исходного и объектного модулей. Объясните необходимость существования объектного модуля. Перечислите возможные технологии сборки готовой к выполнению программы. Для чего служит утилита make в операционных системах семейства UNIX? Опишите схему подготовки исполняемой программы в ОС UNIX. Что является исходными данными для утилиты make? Дайте определение целевого файла. Приведите формат файла описаний зависимостей модулей. Припомните формат команды make. Что позволяет использование библиотек объектных модулей? Опишите процесс трансляции и выполнения программ из командной строки ОС UNIX. Приложение 1 ТАБЛИЦЫ КОДОВ ASCII Таблица П1.1. Коды управляющих символов (0-31)
|