Учтите, что средства оптимизации усложняют отладку программы. Кроме того, бывают случаи, когда наличие оптимизации приводит к проявлению скрытых ошибок, незаметных ранее.
Компиляторы 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проста. Ей указываются целевые модули , участвующие в процессе построения исполняемого файла, и правила , по которым протекает этот процесс. Также задаются зависимости , определяющие, когда конкретный целевой модуль должен быть перестроен.
В нашем тестовом проекте reciprocalтри очевидных целевых модуля: reciprocal.o, main.oи сама программа reciprocal. Правила нам уже известны: это рассмотренные выше командные строки. А вот над зависимостями нужно немного подумать. Ясно, что файл reciprocalзависит от файлов reciprocal.oи main.o, поскольку нельзя скомпоновать программу, не создав оба объектных файла. Последние должны перестраиваться при изменении соответствующих исходных файлов. Нельзя также забывать о файле reciprocal.hpp: он включается в оба исходных файла, поэтому его изменение тоже затрагивает объектные файлы.
Помимо очевидных целевых модулей должен также существовать модуль clean. Он предназначен для удаления всех сгенерированных объектных файлов и программ, чтобы можно было начать все сначала. Правило для данного модуля включает команду rm, удаляющую перечисленные файлы.
Чтобы передать всю эту информацию утилите make, необходимо создать файл Makefile. Его содержимое будет таким:
reciprocal: main.o reciprocal.o
g++ $(CFLAGS) -о reciprocal main.o reciprocal.o
main.o: main.c reciprocal.hpp
Читать дальше