- •Список сокращений
- •Введение
- •Маршрут разработки программ
- •Компилятор gnu gcc Toolchain
- •Компиляция одного файла
- •Компиляция нескольких файлов
- •Автоматизация сборки
- •Системные вызовы
- •Отладка программы
- •Принципы взаимодействия программ и ос
- •Библиотечные вызовы
- •Запуск и завершение процесса
- •Работа со строками
- •Системные вызовы для работы с файлами и потоками
- •Работа с файлами
- •Работа с потоками ввода-вывода
- •Библиотечные вызовы для работы с файлами и потоками
- •Работа с файлами
- •Работа с потоками ввода-вывода
- •Работа с директориями
- •Упражнения
- •Индивидуальные задания
- •Контрольные вопросы
- •Список литературы
Компиляция одного файла
В простейшем случае, если исходный код программы состоит из одного файла «.c», то наиболее удобным способом компиляции программы будет вызов gcc в командной оболочке со следующими атрибутами:
gcc main.c –o prg |
где «main.c» – имя файла с исходным кодом, «prg» – название результирующего исполняемого файла программы. Параметр -o необходим для явного указания имени исполняемого файла. Если он не указан, то исполняемый файл будет иметь название «a.out». После компиляции gcc самостоятельно присваивает файлу программы атрибуты на исполнение.
Помимо получения исполняемого файла, пакет GNU Toolchain дает возможность получения промежуточных файлов для этапов компиляции. Последовательность вызова команд с получением промежуточных файлов показана в Листинге Листинг 1.
Листинг 1. Поэтапная компиляция программы
gcc -E main.c –o main.i // исходный код после препроцессинга gcc -S main.i –o main.s // код программы на языке ассемблер as -E main.s –o main.o // машинный код gcc main.o –o prg // исполняемый файл из объектного файла |
Такой способ получения исполняемого файла может быть полезен для анализа разрабатываемой программы в разных представлениях.
Компиляция нескольких файлов
Если программа состоит из небольшого числа файлов с исходными кодами, то ее компиляцию также бывает удобно производить с помощью ручного ввода команд в командной оболочке. Для этого сначала необходимо каждый файл с исходными кодами («.c») преобразовать в объектный файл («.o»). Это можно сделать одной командой сразу для всех файлов:
gcc –c main.c file1.c file2.c |
или же для каждого файла по отдельности:
gcc –c main.c gcc –c file1.c gcc –c file2.c |
Вызов gcc для каждого файла по отдельности может быть удобен для ускорения процесса сборки программы путем преобразования в объектные только тех файлов с исходными кодами, в которых были внесены изменения относительно предыдущего этапа. Вне зависимости от выбранного способа вызова gcc, в рабочей директории появятся объектные файлы «.o», имеющие названия, соответствующие каждому «.c» файлу. Их необходимо собрать в один исполняемый файл:
gcc –c main.o file1.o file2.o –o prg |
После сборки в директории появится исполняемый файл с названием «prg».
По аналогии с Листингом Листинг 1, для каждого файла или группы файлов могут быть получены промежуточные представления.
Автоматизация сборки
Если программа состоит из большого числа файлов с исходными кодами, то получение исполняемого файла с помощью ручного ввода команд в терминале может быть достаточно трудоемкой. Чтобы упростить эту задачу в GNU Toolchain добавлено средство автоматизации сборки, которое называется «make». С помощью программы make можно задавать очень гибкие и сложные сценарии. По сути, она представляет собой интерпретатор специального языка программирования, созданного для компиляции программ. Сами сценарии сборки описываются в файлах с помощью заранее определенного синтаксиса. Их принято называть «make-файлами».
По умолчанию программа make ищет в текущей директории файл с названием «GNUmakefile», «makefile» или «Makefile». Если такой файл был найден, то make пытается его интерпретировать как исполняемый скрипт. В рамках общей практики make-файл принято называть именно как «Makefile».
Общий внутренний формат make-файла показан в Листинге Листинг 2.
Листинг 2. Формат make-файла
target1: зависимости
# комментарий
правила
target2: зависимости
правила
…
targetN: зависимости
правила
Каждый указанный target является меткой, которой соответствует последовательность правил – набор последовательно исполняемых команд для сборки программы. Зависимости – это перечень файлов или других target, необходимых для выполнения данного target. Имя исполняемого target передается программе make в качестве аргумента. Например, при вводе команды в командной оболочке
make foo |
будет запущена программа make, которая будет искать в текущей директории файл с названием «Makefile» и выполнять последовательность правил, соответствующих target «foo».
По умолчанию каждый target в Makefile должен приводить к созданию исполняемого файла, однако часто используются так называемые «фиктивные цели» - набор правил, которые должны быть выполнены, но после которых не будет создан исполняемый файл. Они обозначаются с помощью ключевого слова «.PHONY». Среди таких целей наиболее часто встречаются:
all – цель по умолчанию, будет вызываться без передачи конкретной цели в аргументах make;
clean – очистка промежуточных файлов, например, объектных;
clean_all – полная очистка как промежуточных, так и результирующих файлов.
Утилита make обладает достаточно большими возможностями, в том числе, make-файл может содержать в себе переменные, производить математические операции, работать с регулярными выражениями и т.д. В рамках данной лабораторной работы все возможности утилиты make рассмотрены не будут. Самостоятельно рекомендуем ознакомиться с документацией по make на официальном сайте [ CITATION Fre19 \l 1033 ].
