KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Марк Митчелл - Программирование для Linux. Профессиональный подход

Марк Митчелл - Программирование для Linux. Профессиональный подход

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

int main() {

printf("Hello, worldn");

}

Нажатие клавиши <Tab> в строке вызова функции printf() приведет к следующему результату:

int main() {

  printf("Hello, worldn");

}

По мере работы с редактором Emacs читатели изучат и другие средства форматирования. Особенность редактора заключается в том. что он позволяет программировать практически любые операции, связанные с автоматическим форматированием. Благодаря этому были реализованы режимы редактирования множества видов документов, разработаны игры[3] и даже СУБД.

1.1.3. Синтаксические выделения

Помимо форматирования программного кода Emacs упрощает чтение файлов, написанных на C/C++, выделяя цветом различные синтаксические элементы. Например, ключевые слова могут быть выделены одним цветом, названия встроенных типов данных — другим, а комментарии — третьим. Подобный подход облегчает нахождение некоторых широко распространенных синтаксических ошибок.

Чтобы включить режим цветовых выделений, откройте файл ~/.emacs и вставьте в него такую строку:

(global-font-lock-mode t)

Сохраните файл, выйдите из Emacs и перезапустите редактор. Теперь можете открыть нужный исходный файл и наслаждаться!

Внимательные читатели, возможно, обратили внимание на то, что строка, вставленная в файл .emacs, выглядит написанной на языке LISP. Это и есть LISP! Большая часть редактора Emacs реализована именно на этом языке. На нем же можно писать расширения к редактору.

1.2. Компиляторы GCC

Компилятор превращает исходный текст программы, понятный человеку, в объектный код. исполняемый компьютером. Компиляторы, доступные в Linux-системах, являются честью коллекции GNU-компиляторов, известной как GCC (GNU Compiler Collection).[4] В нее входят компиляторы языков С, C++, Java, Objective-C, Fortran и Chill. В этой книге нас будут интересовать лишь первые два.

Предположим, имеется проект, в который входят два исходных файла: один написан на С (main.c; листинг 1.1), а другой — на C++ (reciprocal.cpp; листинг 1.2). После компиляции оба файла компонуются вместе, образуя программу reciprocal,[5] которая вычисляет обратное заданного целого числа.

Листинг 1.1. (main.c) Исходный файл на языке С

#include <stdio.h>

#include "reciprocal.hpp"


int main(int argc, char **argv) {

 int i;

 i = atoi(argv[1]);

 printf("The reciprocal of %d is %gn", i, reciprocal(i));

 return 0;

}

Листинг 1.2. (reciprocal.cpp) Исходный файл на языке C++

#include <cassert>

#include "reciprocal.hpp"


double reciprocal (int i) {

 // Аргумент не должен быть равен нулю

 assert(i != 0);

 return 1.0/i;

}

Есть также файл заголовков, который называется reciprocal.hpp (листинг 1.3).

Листинг 1.3. (reciprocal.hpp) Файл заголовков

#ifdef __cplusplus

extern "С" {

#endif


extern double reciprocal(int i);


#ifdef __cplusplus

}

#endif

Первый шаг заключается в превращении исходных файлов в объектный код.

1.2.1. Компиляция одного исходного файла

Компилятор языка С называется gcc. При компиляции исходного файла нужно указывать опцию -с. Вот как, например, в режиме командной строки компилируется файл main.с:

% gcc -с main.с

Полученный объектный файл будет называться main.o.

Компилятор языка C++ называется g++. Он работает почти так же, как и gcc. Следующая команда предназначена для компиляции файла reciprocal.cpp:

% g++ -c reciprocal.cpp

Опция -с говорит компилятору о необходимости получить на выходе объектный файл (он будет называться reciprocal.o). Без неё компилятор g++ попытается скомпоновать программу и создать исполняемый файл.

В процессе написания любой более-менее крупной программы обычно задействуется ряд дополнительных опций. К примеру, опция -I сообщает компилятору о том, где искать файлы заголовков. По умолчанию компиляторы GCC просматривают текущий каталог, а также каталоги, где установлены файлы стандартных библиотек. Предположим, наш проект состоит из двух каталогов: src и include. Следующая команда даст компилятору g++ указание дополнительно искать файл reciprocal.hpp в каталоге ../include :

% g++ -с -I ../include reciprocal.cpp

Иногда требуется задать макроконстанты в командной строке. Например, в коммерческой версии программы нет необходимости осуществлять избыточную проверку утверждения в файле reciprocal.cpp; она нужна лишь в целях отладки. Эта проверка отключается путем определения макроконстанты NDEBUG. Можно, конечно, явно добавить в файл директиву #define, но это означает изменение исходного текста программы. Проще сделать то же самое в командной строке:

% g++ -c -D NDEBUG reciprocal.cpp

Аналогичным образом можно задать конкретный уровень отладки:

% g++ -с -D NDEBUG=3 reciprocal.cpp

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

% g++ -с -O2 reciprocal.cpp

Учтите, что средства оптимизации усложняют отладку программы. Кроме того, бывают случаи, когда наличие оптимизации приводит к проявлению скрытых ошибок, незаметных ранее.

Компиляторы gcc и g++ принимают множество различных опций. Получить их полный список можно в интерактивной документации. Для этого введите следующую команду:

% info gcc

1.2.2. Компоновка объектных файлов

После того как файлы main.c и reciprocal.cpp скомпилированы, необходимо скомпоновать их. Если в проект входит хотя бы один файл C++, компоновка всегда осуществляется с помощью компилятора g++. Если же все файлы написаны на языке С, нужно использовать компилятор gcc. В нашем случае имеются файлы обоих типов, поэтому требуемая команда выглядит так:

% g++ -о reciprocal main.o reciprocal.o

Опция -о задает имя файла, создаваемого в процессе компоновки. Теперь можно осуществить запуск программы reciprocal:

% ./reciprocal 7

The reciprocal of 7 is 0.142857

Как видите, компилятор g++ автоматически подключил к проекту стандартную библиотеку языка С, содержащую реализацию функции printf(). Для компоновки дополнительных библиотек (например, модуля функций графического интерфейса пользователя) необходимо воспользоваться опцией -l. В Linux имена библиотек почти всегда начинаются с префикса lib. Например, файл подключаемого модуля аутентификации (Pluggable Authentication Module, РАМ) называется libpam.a. Чтобы скомпоновать его с имеющимися файлами, введите такую команду:

% g++ -о reciprocal main.o reciprocal.o -lpam

Компилятор автоматически добавит к имени библиотеки префикс lib и суффикс .a.

Как и в случае с файлами заголовков, компилятор ищет библиотечные файлы в стандартных каталогах, в частности /lib и /usr/lib. Для задания дополнительных каталогов предназначена опция -L, которая аналогична рассматривавшейся выше опции -I. Следующая команда сообщает компоновщику о том, что поиск библиотечных файлов нужно осуществлять прежде всего в каталоге /usr/local/lib/pam:

% g++ -o reciprocal main.o reciprocal.o -L/usr/local/lib/pam -lpam

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

% gcc -o app app.o -L. -ltest

1.3. Автоматизация процесса с помощью GNU-утилиты make

Те, кто программируют в Windows, привыкли работать в той или иной интегрированной среде разработки. Программист добавляет в нее исходные файлы, а среда автоматически создает проект. Аналогичные среды доступны и в Linux, но мы не будем рассматривать их. Вместо этого мы научим читателей работать с GNU-утилитой make, знакомой большинству Linux-программистов. Она позволяет автоматически перекомпилировать программу.

Основная идея утилиты make проста. Ей указываются целевые модули, участвующие в процессе построения исполняемого файла, и правила, по которым протекает этот процесс. Также задаются зависимости, определяющие, когда конкретный целевой модуль должен быть перестроен.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*