0% нашли этот документ полезным (0 голосов)
32 просмотров30 страниц

GCC 2014

Документ представляет методические указания по выполнению лабораторных работ по курсу 'Системное программное обеспечение' для студентов направлений 'Информатика и вычислительная техника' и 'Информационные системы и технологии'. В нем рассматриваются процессы компиляции, использование компилятора g++ для языка C++, а также автоматизация компиляции с помощью утилиты make. Цель работы заключается в ознакомлении студентов с компиляцией и разработкой программного обеспечения в операционной системе FreeBSD.

Загружено:

shuvaev.v.6
Авторское право
© © All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd
0% нашли этот документ полезным (0 голосов)
32 просмотров30 страниц

GCC 2014

Документ представляет методические указания по выполнению лабораторных работ по курсу 'Системное программное обеспечение' для студентов направлений 'Информатика и вычислительная техника' и 'Информационные системы и технологии'. В нем рассматриваются процессы компиляции, использование компилятора g++ для языка C++, а также автоматизация компиляции с помощью утилиты make. Цель работы заключается в ознакомлении студентов с компиляцией и разработкой программного обеспечения в операционной системе FreeBSD.

Загружено:

shuvaev.v.6
Авторское право
© © All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ

Федеральное государственное бюджетное образовательное учреждение


высшего профессионального образования
«НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙ
ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

УТВЕРЖДАЮ
Проректор-директор ИК

А.В. Замятин
« » 2013 г.

КОМПИЛЯТОРЫ. КОМПИЛЯЦИЯ ПРОГРАММНОГО


ОБЕСПЕЧЕНИЯ В ОС FreeBSD

Методические указания к выполнению лабораторных работ


по курсу «Системное программное обеспечение»
для студентов направлений 230100 «Информатика и вычислительная
техника» и 230400 «Информационные системы и технологии»

Составитель: И.И. Савенко

Издательство
Томского политехнического университета
2013
УДК 629.76
ББК 00000
А00
Савенко И.И.
А00 Компиляторы. Компиляция программного обеспечения в ОС
FreeBSD: методические указания к выполнению лабораторных ра-
бот по курсу «Системное программное обеспечение» для студен-
тов направлений 230100 «Информатика и вычислительная техни-
ка» и 230400 «Информационные системы и технологии»
Института кибернетики
ТПУ / Cост.: И.И. Савенко; Томский политехнический уни-
верситет. – Томск: Изд-во Томского политехнического универси-
тета, 2014. – 28 с.
УДК 000000
ББК 00000

Методические указания рассмотрены и рекомендованы


к изданию методическим семинаром кафедры
АиКС ИК
« 01 » сентября 2014 г.

Зав. кафедрой АиКС


доктор технических наук,
профессор __________Г.П. Цапко

Председатель учебно-методической
комиссии __________

Рецензент
Кандидат технических наук, доцент кафедры АиКС ИК ТПУ
А.С. Фадеев

© Составление. ФГБОУ ВПО НИ ТПУ, 2014


© Савенко И.И., составление, 2014

2
Содержание
ВВЕДЕНИЕ .....................................................................................................4
1 Процесс компиляции. Компиляторы. .....................................................5
2 Компиляция приложения, разработанного на языке С++ ....................7
2.1 Предупреждение об ошибках ...........................................................9
2.2 Оптимизация программы ..................................................................9
2.3 Разделенная трансляция ..................................................................10
2.4 Заключение .......................................................................................12
3 Автоматизация процесса компиляции, используя утилиту make
(GNU make)....................................................................................................13
3.1 Структура make-файла.....................................................................13
3.2 Использование переменных ............................................................15
3.3 Функции (GNU make) ......................................................................16
3.4 Использование переменной VPATH. .............................................17
3.5 Заключение .......................................................................................18
ЗАКЛЮЧЕНИЕ .............................................................................................19
Список используемых источников .............................................................24
Приложение 1. Исходный код демонстрационной программы ...............25
Приложение 2. Основной список ключей компилятора g++ ...................27
Приложение 3. Ключи утилиты GNU make ...............................................28

3
ВВЕДЕНИЕ
Unix-подобные операционные системы (ОС) являются основными
ОС используемыми в научных центрах. Их использование позволяет
получить максимум производительности от аппаратного обеспечения
при выполнение сложных математических расчетов. Таким образом,
разработка собственных программ для Unix-подобных ОС является од-
ной из важных задач, которую должен уметь решать программист.
Целью данной работы является ознакомление с таким понятием как
компиляция, а также получение навыков по разработке программного
обеспечения в операционной системе FreeBSD.

4
1 Процесс компиляции. Компиляторы.

С каждым годом Unix-подобные операционные системы (ОС) ста-


новятся все более популярными в качестве ОС персональных компью-
теров. Чаще всего ОС данного типа используются в качестве серверных
ОС, а также в организациях, которые не могут позволить себе использо-
вать платные ОС либо в научных центрах, где необходимо получить
максимум от аппаратного обеспечения. Для Unix-подобных систем раз-
работано огромное количество программного обеспечения (ПО), но их
специфическое использование и узкая направленность принуждает про-
граммистов разрабатывать собственное ПО, которое будет решать необ-
ходимые им задачи.
Языки программирования (ЯП) – это средство, позволяющее опи-
сывать вычисления понятные как для вычислительных машин, так и для
людей. Любое программное обеспечение на всех компьютерах мира
написано на том или ином ЯП. Перед тем как осуществить запуск раз-
работанной программистом программы, ее исходный код должен быть
преобразован в вид, который сможет быть выполнен на компьютере.
Такое преобразование выполняют компиляторы. Простыми словами,
компилятор – это программа, считывающая исходный код программы, и
транслирует (преобразовывает) его в эквивалентный код на другом язы-
ке – целевом (Рис. 1). В качестве целевого языка могут выступать раз-
личные языки, это зависит от компилятора, а также от ЯП на котором
разрабатывалось ПО. Также компилятор сообщает программисту об
ошибках в исходном коде, которые были обнаружены во время транс-
ляции.
Исходная программа

Компилятор

Целевая программа

Рис. 1. Компилятор

Исходный код программы может исчисляться миллионами строчек


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

Препроцессор
Модифицированная исходная
программа

Компилятор

Целевая ассемблерная программа

Ассемблер
Перемещаемый машинный код

Библиотечные файлы
Компоновщик/загрузчик Перемещаемые объектные файлы

Целевая программа

Рис. 2. Система обработки языка

Сборка исходной программы иногда поручается отдельной про-


грамме, именуемой препроцессором. Одна из его функций это раскры-
тие макросов в инструкции на исходном языке. После того, как исход-
ная программа была модифицирована препроцессором, она передается
компилятору. Как было упомянуто выше, на выходе компилятора не
обязательно может быть машинный код, на выходе может быть целевая
программа на языке ассемблера, так как в отличие от машинного кода,
его проще создать и отлаживать. Далее исходная программа, преобразо-
ванная в программу на языке ассемблера, преобразуется в перемещае-
мый машинный код при помощи компьютерной программы (компиля-
тора) Ассемблер. Тут необходимо заметить, что как и сам язык
ассемблера, ассемблеры бывают различными в зависимости от архитек-
туры вычислительной машины, операционной системы.
Исходные программы, состоящие из нескольких модулей, чаще
всего компилируются по частям (разделенная трансляция), таким обра-
зом, полученный перемещаемый машинный код необходимо объеди-
нить (скомпоновать) с другими частями машинного кода, а также с биб-
лиотечными файлами. Этим как раз и занимаются Компоновщик

6
(Linker) и Загрузчик (Loader). Процесс компоновки не так уж и прост,
как может показаться, некоторые особенности будут рассмотрены ниже.
Выбор компилятора при разработке программ зависит как от ОС,
архитектуры ЭВМ, а также от ЯП и его версии. Наиболее популярным
компилятором при разработке приложений под ОС Windows является
MSVC++, разработанный компанией Microsoft. Что же касается Unix-
подобных систем, то тут чаще всего используется пакет компиляторов
GCC. В данном пакете содержатся компиляторы для различных ЯП,
например C (компилятор gcc), C++(компилятор g++), Java (компилятор
gjc), Objective C и других, а также компиляторы для различных архитек-
тур (ARM, x86 и т.д.) [1].
В ходе лабораторной работы в качестве исходного языка для напи-
сания программы будет использоваться язык программирования C++.
Программа на языке С++ будет преобразована компилятором в машин-
ный код. Целью данной работы не является разработка собственного
компилятора, поэтому мы не будем глубоко погружаться в структуру
компилятора и рассматривать другие существующие языковые процес-
соры, например, интерпретаторы. Главное понять, как осуществляется
преобразование исходного кода программы в машинный код.

2 Компиляция приложения, разработанного на языке С++

Для сборки программы разработанной на языке С++ необходимо


использовать специальный компилятор g++ из пакета компиляторов. В
отличие от компилятора gcc, данная команда (g++) по умолчанию под-
ключает (линкует) стандартную библиотеку stdc++.
Перейдем к практике, для начала напишем простую программу, ко-
торая суммирует 2 целых числа, переданные программе через аргумен-
ты (пример вызова программы с аргументами в операционной системе
Windows: C:\[Link] ‘аргумент 1’ ‘аргумент 2’. Для этого мы будем
использовать текстовый редактор «Easy Editor», запуск которого осу-
ществляется командой – ee. Следующая строка, открывает для редак-
тирования файл [Link] в редакторе Easy Editor, в случае, если файл не
существует он будет создан автоматически.
%ee [Link]

Листинг 1
#include <iostream> //подключение заголовочного файла
/**
* argc - содержит количество переданных аргументов
7
* argv - значения аргументов
*/
int main( int argc, const char* argv[] )
{
int x; //Инициализация переменой целочисленного типа
int y;

// убедимся, что всего было передано 3 параметра


// 1 - имя самой программы (добавляется автоматически)
// 2 - первое слагаемое
// 3 - второе слагаемое
if ( argc == 3 ) { //условный оператор
x = atoi( argv[1] ); //функция atoi – преобразует
значение аргумента в целочисленное значение
y = atoi( argv[2] );

std::cout << x << " + " << y << " = " << x + y <<
std::endl;
}
}
В листинге 1 приведен исходный код программы на языке С++, ко-
торая осуществляет сложение двух чисел. Если приведенный в листинге
1 код вам не понятен, вы можете познакомиться с основами языка С++,
которые отлично описаны на сайте [2].
Перейдем к компиляции, чтобы откомпилировать нашу программу
необходимо вызвать компилятор g++ и указать путь к файлу с исход-
ными данными в качестве параметра.
%g++ [Link]
%ls
%[Link] [Link]
В результате создался исполняемый файл с именем по умолчанию
[Link], если проводить аналогию с операционной системой Windows, был
создан *.exe файл. Для того, чтобы запустить данную программу необ-
ходимо воспользоваться следующей командой.
%./[Link] 45 43
45 + 43 = 88
Если вас не устраивает имя программы, присвоенное по умолча-
нию, то при компиляции можно задать новое, используя ключ –o.
%g++ [Link] –o demo
Вышеуказанное - это минимальное, что можно получить от всех
возможностей компилятора. На самом деле, умение использовать опре-
деленный набор ключей компиляции, позволит разрабатывать безоши-
бочные приложения, а также за минимальный промежуток времени. Как
8
вы могли заметить, компиляция довольно медленный процесс, даже на
примере одного файла, а представьте, сколько времени займет данный
процесс если программа состоит из нескольких тысяч файлов, поэтому
очень важно использовать правильный набор ключей, чтобы сократить
время компиляции (Приложение 2).

2.1 Предупреждение об ошибках

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


домление программиста об ошибках или предупреждениях в исходном
коде программы. Таким потенциально опасными местами в исходном
коде могут быть: неиспользуемые переменные, неверная операция в
условном операторе и другие. Пример:
%g++ [Link] –o demo -Wall
%[Link]: In function 'int main()':
%[Link]: warning: unused variable 'unusedVar'
Предупреждения, выдаваемые компилятором, очень важный и по-
лезный механизм их использование позволяет программистам исклю-
чить многих не заметных ошибок, которые возникнут уже во время ис-
пользования программы, что, конечно же, не понравится конечному
пользователю. Если рассматривать механизм предупреждения компиля-
тора g++, он позволяет включать несколько десятков видов предупре-
ждений, для каждого из которых имеется свой ключ компиляции. Пол-
ный список таких ключей можно посмотреть в руководстве, вызвав
команду:
%man g++;

2.2 Оптимизация программы

Под оптимизацией понимается процесс улучшения производитель-


ности программы: уменьшение объема памяти, занимаемой на жестком
диске программой, а также сокращение времени работы приложения.
Для того, чтобы оптимизировать приложение в компиляторе g++ при-
сутствуют следующие ключи (шаблон –Oуровень, где уровень меняется
от 0 до 3):
 -O0 – отключает оптимизацию, основная цель данного ключа,
обеспечить высокую скорость компиляции, а так же предсказу-
емость результатов отладки. Этот ключ используется по умол-
чанию;

9
 -O1 – мягкая оптимизация, незначительное увеличение скоро-
сти процесса компиляции, а также уменьшение размера целевой
программы;
 -O2 – использует практически все доступные компилятору ме-
тоды оптимизации, как скорости выполнения, так и размера
программы;
 -O3 – максимальная оптимизация, которая включает такие ме-
тоды оптимизации как развертку циклов и автоматическое
встраивание функций.
 -Os – позволяет автоматизировать размер программы.

Проведем не большой эксперимент, посмотрим время, затраченное


на компиляцию без оптимизации и с оптимизацией.
%time && g++ [Link] -o demo -std=gnu++98 && time && rm demo
81.616u 8.376s [Link].41 2.3% 4220+1401k 131+0io 25pf+0w
82.706u 8.534s [Link].67 2.4% 4251+1404k 131+0io 25pf+0w
Время компиляции: 0,158s
%time && g++ [Link] -o demo -std=gnu++98 -O1 && time && rm demo
82.712u 8.535s [Link].34 2.4% 4250+1404k 131+0io 25pf+0w
83.842u 8.731s [Link].67 2.4% 4283+1406k 131+0io 25pf+0w
Время компиляции: 0,196s
Как вы можете заметить, время компиляции не значительно, но
увеличилось. Конечно же, данный тест нельзя считать объективным, так
как система могла быть использована другими процессами, что и могло
замедлить время компиляции. Объективнее будет взять среднее время
компиляции после нескольких попыток компилирования.

2.3 Разделенная трансляция

Рассмотрим еще один интересный момент, который необходимо


учесть при компиляции программы. Демонстрационная программа
([Link]), используемая в данном методическом пособии, состоит все-
го лишь из одного файла с исходными данными, реальные же проекты
состоят из нескольких десятков и более. Конечно же, никто не запреща-
ет писать весь исходный код программы в одном файле, но тогда воз-
никнут следующие проблемы:
 тяжело организовать коллективную работу над программой;
 усложняется навигация по написанному коду;
 любое изменение в тексте файла с программой приводит к пол-
ной перекомпиляции, что, конечно же, занимает длительное
время.
10
Обратите внимание на последний пункт выше приведенного спис-
ка, компилятор g++ позволяет сократить время компиляции программы,
компилируя только модифицированные файлы исходной программы,
это и есть разделенная трансляция. Для проверки разделенной трансля-
ции усложним нашу демонстрационную программу. Для этого создадим
простейший класс, который будет осуществлять суммирование целых
чисел. Исходные коды классов представлены в Приложении 1. В ре-
зультате у нас получилось 3 файла [Link], summ.h, [Link].

Способ 1
Рассмотрим первый способ компиляции, без разделения трансля-
ции исходных файлов программы. Все максимально просто, необходи-
мо компилятору передать пути к файлам с расширением *.cpp.
%g++ [Link] [Link] -o demo -std=gnu++98
%./demo 45 43
45 + 43 = 88
Как вы можете заметить, программа успешно откомпилирована и
может быть использована. Для справки, если файлов много, то можно
воспользоваться шаблоном поиска файлов типа: *.cpp.
%g++ *.cpp -o demo -std=gnu++98 –Os

Способ 2
Разделенная трансляция подразумевает собой разбиение процесса
компиляции на 2 стадии:
 создание объектных файлов;
 компоновка, объектных файлов в целевую программу.
Создание объектных файлов обеспечивается при помощи исполь-
зования ключа –с, это делается следующим образом:
%g++ *.cpp –c
%ls -l *.o
-rw-r--r-- 1 root root 3316 23 июн 17:07 main.o
-rw-r--r-- 1 root root 803 23 июн 17:07 summ.o
В результате у нас получилось 2 объектных файла, которые полно-
стью соответствуют исходным файлам программы. Далее необходимо
осуществить компоновку объектных файлов, для этого необходимо вос-
пользоваться ключом –o.
%g++ *.o -o demo_o
%./demo_o 1 2
1 + 2 = 3
11
Таким образом, если внести изменения только в один из файлов, то
трансляции других файлов не является обязательной, достаточно со-
здать объектный файл модифицированного файла и скомпоновать его с
уже существующими объектными файлами.

2.4 Заключение

В данном разделе вы познакомились с основными возможностями


компилятора GCC. Используя эти возможности, вы сможете в любой
момент скомпилировать простейшую программу, написанную на языке
С++ с использованием оптимизации и разделённой трансляции. В сле-
дующем разделе речь пойдет об утилите make, которая позволит авто-
матизировать процесс компиляции, что позволит компилировать более
сложные программы.

12
3 Автоматизация процесса компиляции, используя утилиту make
(GNU make)

Надеюсь, вы не подумали, что программист, разрабатывая про-


грамму, каждый раз с использованием консоли прописывает команды,
которые мы с Вами разобрали выше, конечно же, есть способы автома-
тизации данного процесса. В следующей части методического пособия
мы разберем, как работает утилита make и что такое make-файл. В ходе
лабораторной работы используется ОС FreeBSD поэтому мы будем ис-
пользовать утилиту gmake, она является аналогом make, но имеет боль-
ший функционал. Так же необходимо заметить, что про использование
данной утилиты пишут целые книги, мы рассмотрим только самое важ-
ное и необходимое.
Утилита gmake предназначена для автоматизации процесса созда-
ния исполняемого файла из исходного кода, она также определяет какие
модули программы необходимо перекомпилировать. Использование
данной утилиты, значительно упрощает процесс сборки программы. В
данном методическом пособии рассмотрено минимальное количество
ключей утилиты gmake, так как утилиту gmake можно использовать и
без них, полный список приведен в приложении 3.
Сама по себе данная утилита работать не будет, ей необходимо со-
общить некоторые правила, по которым необходимо скомпилировать
приложение. Файл, который содержит правила, описывающие процесс
сборки приложения, называется make-файлом. Правила создания данно-
го файла будут описаны ниже.
Как уже было сказано, утилиту make можно запускать без ключей,
при запуске она автоматически проверяет текущую директорию на
наличие make-файла с название по умолчанию makefile. Если такой
файл отсутствует, то программист получит следующее сообщение об
ошибке:
%gmake
gmake: no target to make.
Если же вы решили всё-таки дать make-файлу другое название или
разместить его в другой директории, то для этого вам необходимо ис-
пользовать ключ –f. Пример:
%gmake –f path/to/makefile

3.1 Структура make-файла

13
Структура make-файла максимально простая, он состоит из целей и
макрокоманд. Чтобы описать цель необходимо задать:
имя цели – имя файла, который должен быть создан;
список зависимости – список имен файлов, от которых зависит
достижение цели;
список команд интерпретатора shell, которые должны быть вы-
полнены для достижения поставленной цели.
цель: зависимости
[tab] команда (где [tab] – символ табуляции)
Имя цели и список зависимостей составляют заголовок цели, запи-
сываются в одну строку и разделяются двоеточием. Цель может быть
ложная – это значит, что в качестве цели не будет выступать файл. Спи-
сок команд записывается со следующей строки, причем все команды
начинаются с обязательного символа табуляции. Любая строка в после-
довательности списка команд, не начинающаяся с табуляции или '#' -
считается завершением текущей цели и началом новой. Рассмотрим
простой пример make-файла позволяющего скомпилировать демонстра-
ционную программу:
all://ложная цель вызываемая по умолчанию
g++ [Link] [Link] -o demo

Данный пример отлично работает, но при таком описании, не учи-


тывается разделенная трансляция, что, конечно же, не верно. Модифи-
цируем make-файл возможностью использовать разделенную трансля-
цию, для этого добавим еще одну цель в файл, которая будет описывать
создание объектных файлов.
Листинг 2
all: demo
demo: main.o summ.o
g++ main.o summ.o -o demo
main.o:
g++ -c [Link]
summ.o: [Link]
g++ -c [Link]
Хочется отметить, что если в make-файле присутствует несколько
целей, то утилита make позволяет компилировать отдельные части про-
граммы, для этого достаточно указать в качестве параметра название
цели:
gmake summ.o
Давайте представим, что программа, которую мы разрабатываем,
состоит из 500 исходных файлов, при такой организации make-файла об
14
автоматизации процесса компиляции и речи быть не может. Чтобы это
исправить познакомимся с новым понятием как переменные и функции.

3.2 Использование переменных

Использование переменных позволяет избежать повторяемость не-


которых участков кода make-файла. Объявление переменных осуществ-
ляется несколькими способами, мы рассмотрим только 2 популярных
способа:
Способ 1
VARIABLE = VALUE

Ниже приведен пример, как использовать переменные данного ти-


па
Листинг 3
OCC=-O2
#объявление рекурсивной переменной CC содержащей в себе зна-
чение g++ и значение переменной OCC (переменная определяющая уро-
вень оптимизации) Важно! Значение переменной вычисляется в момент
обращения к ней.
CC=g++ $(OCC)
all: demo
demo: main.o summ.o
$(CC) main.o summ.o -o demo
main.o:
$(CC) -c [Link]
summ.o: [Link]
$(CC) -c [Link]
При таком способе инициализации переменной, одна и та же пере-
менная не может одновременно использоваться, как в левой части, так и
в правой части выражения, в противном случае это может привести к
бесконечной рекурсии.
Способ 2
VARIABLE := VALUE
Ниже приведен пример, как использовать переменные данного ти-
па
Листинг 4
CC:=g++
#Важно! Значение переменной вычисляется в момент обработки
оператора присваивания.

15
CC:= $(CC) -O2
demo: main.o summ.o
$(CC) main.o summ.o -o demo
main.o: [Link]
$(CC) -c [Link]
summ.o: [Link]
$(CC) -c [Link]
Использоваться может как один, так и другой способ инициализа-
ции, второй способ является оптимальным и надежным, так как нет
необходимости каждый раз вычислять значение переменной при ее ис-
пользовании, но все зависит от ситуации.
Очень важный механизм утилиты gmake – это автоматические пе-
ременные. Некоторые существующие автоматические переменные при-
ведены в Таблица 1.
Таблица 1
Список некоторых автоматических переменных
Имя автомати- Значение
ческой пере-
менной
$@ Имя цели обрабатываемого правила
$< Имя первой зависимости обрабатываемого правила
$^ Список всех зависимостей обрабатываемого правила

Пример использования представлен в листинге 5.


Листинг 5
CC:=g++
CC:= $(CC) -O2
demo: main.o summ.o
$(CC) $^ -o $@
main.o: [Link]
$(CC) -c $^
summ.o: [Link]
$(CC) -c $^

Перейдем к рассмотрению некоторых функций утилиты gmake.

3.3 Функции (GNU make)

Утилита gmake, в отличие от make, содержит большое количество


различных функций, позволяющих манипулировать строками (именами

16
файлов, переменными), например, некоторые из них: patsubst, wildcard,
addprefix, addsuffix и notdir (dir).
Общий вид вызова функций осуществляется следующим образом:
$(имя_функции параметр1, параметр2 ...)

$(patsubst шаблон,замена,текст) – находит в тексте разделенные


пробелом слова, удовлетворяющие «шаблону» и заменяет их на строку
«замена»;
$(wildcard шаблон) – результатом функции wildcard является спи-
сок разделенных пробелами имен существующих в данный момент
файлов, удовлетворяющих указанному «шаблону»;
$(addprefix префикс, список_слов) - функция addprefix добавляет
в начало каждого слова из списка слов, указанного вторым параметром,
строку, переданную ей в качестве первого параметра.
$(addsuffix префикс, список_слов) - функция addsuffix добавляет
в конец каждого слова из списка слов, указанного вторым параметром,
строку, переданную ей в качестве первого параметра.
$(dir список_имен) – функция для каждого имени файла из списка
имен, оставляет только имя директории, в которой этот файл располо-
жен. Именем каталога считается часть имени до последнего встреченно-
го символа «/» (включая и этот символ). Если имя файла не содержит
символов «/», его именем каталога считается строка «./».
$(notdir список_имен) – функция для каждого имени файла из
списка имен, оставляет только имя файла, удаляя из имени путь к фай-
лу.
Список существующих функций утилиты GNU make намного вы-
ше, в методическом пособии указаны только самые основные необхо-
димые для выполнения лабораторной работы.
Пример модифицированного make-файла c использования функ-
ций.
Листинг 6
demo: $(patsubst %.cpp, %.o, $(wildcard *.cpp))
g++ $^ -o $@
%.o: %.cpp
g++ -c $<

3.4 Использование переменной VPATH.

Переменная VPATH используется в make-файлах для указания


списка директорий (через пробел), где следует производить поиск фай-
лов. Ниже приведенный пример, показывает, что путь поиска состоит из
17
двух каталогов «.» – текущий каталог и «src». Поиск в этих директори-
ях осуществляется по порядку.
VPATH= . src

Если предположить, что файл [Link] находится в директории


«src», то следующее правило:
summ.o: [Link]

будет интерпретировано утилитой gmake, как:


summ.o: src/[Link]

3.5 Заключение

Последний пример make-файла (листинг 6) выглядит довольно ин-


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

18
ЗАКЛЮЧЕНИЕ

Разработка программного обеспечения для unix-подобных систем


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

19
Задание
1 Изучить основные ключи компилятора g++. Для этого вызовите
команду:
%man g++;
2 Разработать ПО в соответствии с вариантом. Входные данные
для программы необходимо передавать через аргументы. В коде про-
граммы осуществить проверку входных данных на корректность. Все
команды введённые в процессе выполнения лабораторной работы необ-
ходимо документировать в письменном отчете.
Вариант 1
Разработать программу, которая определяет факториал числа.
Вариант 2
Вывести случайное число в диапазоне, минимальное и макси-
мальное число диапазона задается через аргументы.
Вариант 3
Разработать программу для нахождения наименьшего общего
кратного двух чисел.
Вариант 4
Разработать программу для нахождения наибольшего общего де-
лителя двух чисел.
Вариант 5
Разработать программу, которая выводит на экран ряд Фибоначчи
до числа N переданного через аргумент.
Вариант 6
Разработать программу, которая определяет количество чисел в
слове переданного через аргумент.
Вариант 7
Разработать программу, которая определяет количество гласных
символов в слове.
Вариант 8
Разработать программу, которая считает количество слов в пред-
ложении переданного через аргумент. При передаче предложения в ка-
честве аргумента, строку необходимо поместить в двойные кавычки.
20
3 Специальным образом допустите синтаксическую ошибку в
программе. Сообщение об ошибке запишите в файл [Link] в вашей
домашней директории.
4 Используя механизм предупреждения компилятора gcc, добей-
тесь вывода текстового сообщения (предупреждения) в рабочей про-
грамме (без использования ключа –Wall, а выбрав из списка всех воз-
можных ключей, тот, который описывает вашу ошибку). Полученное
сообщение добавьте в файл [Link].
5 Оптимизируйте вашу программу, уменьшив объем памяти, ко-
торый она занимает на жестком диске. Определите время, которое было
затрачено на компиляцию до оптимизации и после (использовать можно
любой уровень оптимизации). Проведите пять экспериментов, составьте
таблицу с полученными данными. Сделайте выводы.
6 Разработанную программу представить в виде простого класса
на языке С++. Осуществить разделенную трансляцию исходных файлов.
Изменить содержимое одного из файлов и снова осуществить компиля-
цию. Проанализировать результаты (зафиксировать даты изменения
файлов в файле [Link]) и сделать выводы.
7 Написать простейший make-файл, который будет автоматиче-
ски собирать написанную вами программу, при компиляции необходи-
мо использовать ключ для вывода сообщений об ошибке. Переименуйте
make-файл в любое понравившееся вам имя и снова соберите проект
(Первая версия make-файла).
8 Создайте новый make-файл с возможностью разделенной
трансляцией (Вторая версия make-файла).
8.1 После успешного компилирования (информацию, получен-
ную в процессе компиляции, добавьте в файл [Link]) удали-
те один из объектных файлов, заново запустите процесс
компиляции (результат также добавьте в файл [Link]). Про-
анализируете полученный результат. Сделайте выводы.
8.2 Запустите утилиту make еще раз, полученное сообщение
также добавьте в файл [Link]. Сделайте выводы.
8.3 Используя ложную цель, добавьте в make-файл возможность
автоматического удаления объектных файлов после компи-
ляции.
9 Максимально оптимизируйте вторую версию make-файла, до-
бавив переменные (автоматические переменные) и функции, изученные
в ходе лабораторной работы (Третья версия).
10 Создайте в директории с вашей программой каталог с назва-
нием «src» переместите в него два файла описывающие ваш класс (*.h,
21
*.cpp), файл [Link] должен остаться в текущей директории. Добейтесь
успешной компиляции, доработав make-файл (четвертая версия), ис-
пользуя знания, полученные в ходе лабораторной работы (Возможно,
вам пригодится ключ –I компилятора g++ и переменная VPATH).
В результате проделанной работы, в вашей домашней директории
должны содержаться:
 исходные коды программы (3 файла или более);
 корректный исполняемый файл, соответствующий вашему ва-
рианту;
 файл [Link] – файл, содержащий сообщения об ошибках и
предупреждениях;
 файл [Link] – содержащий некоторую выходную информацию,
полученную в процессе выполнения работы;
 make-файлы (4 версии);
Необходимо написать отчет по лабораторной работе, продемон-
стрировать работу программы преподавателю, а также процесс компи-
лирования программы с использованием последней версии make-файла.
Ответить на контрольные вопросы.

22
Контрольные вопросы
1 Что вы понимаете под компиляцией? Как вы считаете, чем от-
личается компилятор от интерпретатора? Приведите примеры
компилируемых и интерпретируемых языков программирова-
ния.
2
3 Ниже приведены простейшие примеры make-файлов. Что будет
выведено на экране в результате выполнения make-файла?
Задание 1
var1 = one
var2 = $(var1) two
var1 = three
all:
@echo $(var2)
Задание 2
var1 := one
var2 := $(var1) two
var1 := three
all:
@echo $(var2)
Задание 3
var1 = one
var1 = $(var1) two
all:
@echo $(var1)
Задание 4
source_dirs := src lib
search_matches := $(addsuffix /*.cpp, $(source_dirs))
all:
@echo $(search_wildcards)

23
Список используемых источников
1. Альфред В. Ахо, Моника С. Лам, Рави Сети, Джеффри Д. Уль-
ман Компиляторы: принципы, технологии и инструментарий =
Compilers: Principles, Techniques, and Tools. - 2 изд.-
М.:Вильямс, 2008.
2. Основы языка программирования C++. Режим доступа:
[Link]

24
Приложение 1
(обязательное)
Исходный код демонстрационной программы
В заголовочном файле (summ.h) будет содержаться описание
класса.
#ifndef SUMM_H
#define SUMM_H

class CSumm {
public:
CSumm(int v1, int v2);
int calculate();
private:
int a;
int b;
};
#endif

В файле ([Link]) будет содержаться реализация описанного


класса.

#include "summ.h"
CSumm::CSumm(int v1, int v2) {
a = v1;
b = v2;
}

int CSumm::calculate() {
return a + b;
}

Модифицированный файл [Link] с точкой входа в программу.


#include <iostream>
#include "summ.h"
int main( int argc, const char* argv[] )
{
int x;
int y;
if ( argc == 3 )
{
x = atoi( argv[1] );
y = atoi( argv[2] );
CSumm * calc = new CSumm(x, y);
std::cout <<x<<" + "<<y<<"=" << calc->calculate() <<
std::endl;
25
}
return 0;
}

26
Приложение 2
(обязательное)
Основной список ключей компилятора g++
 v – версия компилятора
 o – путь к целевой программу
 std – указывает стандарт языка программирования (например
c++98, по умолчанию gnu++98)
 Wall – выводит любые предупреждения об ошибках.
 g – получение отладочной информации
 pipe – позволяет ускорить компиляцию, передача информации
между различными этапами осуществляется через каналы, без
использования промежуточных файлов.

27
Приложение 3
(обязательное)
Ключи утилиты GNU make
-b, -m. Эти опции игнорируются и служат для совместимости с
другими версиями make.
-C dir - Изменить каталог на dir перед чтением make_файлов или
выполнением чего-то ещё. Если указано несколько опций –C, то каждая
интерпретируется относительно предыдущей: -C / -C etc эквивалентно –
C /etc. Обычно, это используется с рекурсивными вызовами make.
-d - Печатать отладочную информацию в дополнении к нормаль-
ной. Отладочная информация показывает, какие файлы было решено
переделать, какие времена файлов сравнивались и с каким результатом,
какие файлы на самом деле должны быть переделаны, какие скрытые
правила подразумевались и какие были применены---всё интересное о
том, как make решал что делать.
-e - дать переменным из среды превосходство над переменными
из make-файлов.
-f file – Использовать file как makefile.
-i - Игнорировать все ошибки в командах, выполняемых для об-
новления файлов.
-I dir - В заданном каталоге dir ищутся включаемые make-файлы.
Если используется несколько опций –I для задания нескольких катало-
гов, то поиск осуществляется в порядке задания. В отличие аргументов
других флагов make, каталоги в –I флагах можно указывать сразу после
флага: -I dir разрешено, также как и –I dir. Этот синтаксис разрешён для
совместимости с флагом –I препроцессора C.
-j jobs - Указать число заданий (команд) выполняемых одновре-
менно. Если есть больше чем одна –j опция, то используется последняя.
Если –j опция задана без аргумента, то make не ограничивает число за-
даний, которые могут выполняться одновременно.
-k - Продолжать после ошибки настолько, насколько возможно.
Несмотря на то, что объект нельзя обновить, и то, что от этого зависит,
не может быть переделано, в тоже время есть другие зависимости этого
объекта, которые могут быть обработаны.
-l load - Указывает, что новые задания (команды) не должны
начинаться, если другие задания запущены и средняя загрузка, по край-
ней мере, load (дробное число). Без аргументов удаляется предыдущий
предел загрузки.

28
-n - Напечатать команду, которая должна выполняться, но не вы-
полнять её.
-o file - Не переделывать файл file, даже если он старее, чем его за-
висимости, и ничего не переделывать за счёт изменений в file. По суще-
ству, файл трактуется как очень старый и его правила игнорируются.
-p - Напечатать базу данных (правила и значения переменных) по-
лученную при чтении make-файлов; затем выполняться, как обычно или
как указано иначе. Это также печатает информацию о версии, даваемую
переключателем –v (смотри ниже). Чтобы напечатать базу данных без
попыток пересобрать любые файлы, используется make –p -f/dev/null.
-q – «Режим запроса». Никаких команд не запускается и ничего не
печатается; только возвращается код завершения, который равен нулю,
если заданный объект уже самый новый, иначе не ноль.
-r - Исключить использование встроенных скрытых правил. Также
очистить список суффиксов по умолчанию для правил суффиксов.
-s -Тихая работа; не печатать команды при их выполнении.
-S - Отменить действие опции -k . Этого никогда не требуется,
кроме как при рекурсиях make где –k может быть унаследована от верх-
него уровня make через MAKEFLAGS или если –k установлена в
MAKEFLAGS среды.
-t - Прикоснуться к файлам (пометить их как новые без действи-
тельного их изменения) вместо запуска команд к ним. Это используется,
чтобы симулировать, что команды выполнены, чтобы обмануть буду-
щие вызовы make.
-v - Напечатать версию программы make плюс copyright, список
авторов и уведомление об отказе от гарантий.
-w - Напечатать сообщение, содержащее рабочий каталог перед и
после других работ. Это может быть полезно для отслеживания ошибок
при сложных вложенных рекурсивных make командах.
-W file - Сделать вид, что объект file только что был модифициро-
ван. Когда еще используется –n флаг, то это покажет, чтобы случилось,
если бы этот файл был изменён. Без -n, это почти тоже самое, что как
запустить команду touch с данным файлом перед запуском make, кроме
того, что время модификации изменилось только в представлении make.

29
Учебное издание

САВЕНКО Игорь Игоревич

КОМПИЛЯТОРЫ. КОМПИЛЯЦИЯ ПРОГРАММНОГО


ОБЕСПЕЧЕНИЯ В ОС FreeBSD

Методические указания к выполнению лабораторных работ


по курсу «Системное программное обеспечение»
для студентов направлений 230100 «Информатика и вычислительная
техника» и 230400 «Информационные системы и технологии»

Отпечатано в Издательстве ТПУ в полном соответствии


с качеством предоставленного оригинал-макета

Подписано к печати 00.00.2013. Формат 60х84/16. Бумага «Снегурочка».


Печать XEROX. Усл. печ. л. 9,01. Уч.-изд. л. 8,16.
Заказ 000-13. Тираж 100 экз.
Национальный исследовательский Томский политехнический университет
Система менеджмента качества
Издательства Томского политехнического университета сертифицирована
NATIONAL QUALITY ASSURANCE по стандарту BS EN ISO 9001:2008

. 634050, г. Томск, пр. Ленина, 30


Тел./факс: 8(3822)56-35-35, [Link]

30

Вам также может понравиться