Теперь, когда программное обеспечение корректно сконфигурировано, все, что осталось сделать - это откомпилировать его. Этот этап обычно прост и не вызывает серьезных проблем.
В обществе свободного ПО любимой утилитой для компиляции исходных кодов является make. Она имеет два преимущества:
Действия, которые должны быть выполнены для получения из исходных кодов
откомпилированной версии, хранятся в файле с именем
Makefile
или GNUMakefile
. На
самом деле, когда вызывается команда make, она
считывает этот файл (если он существует) из текущего каталога. В противном
случае файл может быть указан при помощи опции -f
команды
make.
make оперирует в соответствии с системой
зависимостей, поэтому компиляция бинарного файла
(«цели»)
требует прохождения нескольких этапов («зависимостей»).
Например, для создания (воображаемого) бинарного файла
glloq
должны быть откомпилированы и скомпонованы
объектные файлы main.o
и
init.o
(промежуточные файлы процесса компиляции). Эти
объектные файлы также являются целями, чьими зависимостями являются
соответствующие файлы исходных текстов.
Этот текст представляет собой только небольшое введение для выживания в жестоком мире make. Для получения исчерпывающей информации обратитесь к O'Reilly Managing Projects with Make (второе издание) авторов и .
Обычно при использовании make принято придерживаться некоторых соглашений. Например:
make без аргумента просто компилирует программу, не устанавливая ее.
make install компилирует программу (но не всегда), а
затем устанавливает необходимые файлы в нужное место в файловой системе.
Некоторые файлы не всегда устанавливаются корректно
(man
, info
), пользователю
может понадобиться скопировать их самому. Иногда команда make
install должна быть выполнена повторно в подкаталогах. Обычно это
касается модулей сторонних разработчиков.
make clean удаляет все временные файлы, созданные в процессе компиляции, а также, в большинстве случаев, и исполняемые файлы.
Первым этапом является компиляция программы, а, следовательно, ввод команды (выдуманный пример):
$ make gcc -c glloq.c -o glloq.o gcc -c init.c -o init.o gcc -c main.c -o main.o gcc -lgtk -lgdk -lglib -lXext -lX11 -lm glloq.o init.o main.o -o glloq
Превосходно. Бинарный файл был корректно скомпилирован. Мы готовы перейти к следующему этапу, который представляет собой установку файлов дистрибутива (бинарные файлы, файлы данных и т.п.). Смотрите раздел Раздел 5, «Установка».
Если вы достаточно любопытны,
чтобы заглянуть в файл Makefile
, вы найдете в нем
известные команды (rm, mv, cp и др.), а также странные
строки наподобие $(CFLAGS)
.
Это
переменные,
представляющие собой строки, которые обычно объявляются в начале файла
Makefile
, а затем заменяются их значениями. Это
весьма полезно, если вы хотите использовать одни и те же опции компиляции
несколько раз подряд.
Например, вывести на экран строку «foo
»
при помощи команды make all можно так:
TEST = foo all: echo $(TEST)
В большинстве случаев установлены следующие переменные:
CC
: это компилятор. Обычно это cc, синонимом
которого в большинстве свободных систем является gcc. Если вы в
нерешительности - используйте gcc.
LD
: это программа, используемая для обеспечения
последнего этапа компиляции (см. раздел Раздел 1.2.2, «Четыре этапа компиляции»). По
умолчанию это программа ld.
CFLAGS
: это дополнительные аргументы, передаваемые
компилятору на первом этапе компиляции. Среди них:
-I<путь>
: сообщает компилятору, где искать
дополнительные заголовочные файлы (напр.:
-I/usr/X11R6/include
разрешает добавление заголовков из
каталога /usr/X11R6/include
).
-D<символ>
: определяет дополнительный символ;
полезен для программ, компиляция которых зависит от определенных ранее
символов (напр.: использование файла string.h
, если
определен HAVE_STRING_H
).
Часто строки компиляции выглядят следующим образом:
$(CC) $(CFLAGS) -c foo.c -o foo.o
LDFLAGS
(или LFLAGS
): это
аргументы, используемые на последнем этапе компиляции. Среди них:
Не паникуйте, это может случится с любым. Вот наиболее общие случаи:
glloq.c:16: decl.h: No such file or directory
Компилятор не смог найти соответствующий заголовочный файл. Вообще-то эта ошибка должна была быть предупреждена на этапе конфигурирования программы. Решение этой проблемы:
Проверьте, действительно ли заголовок существует на диске в одном из
следующих каталогов: /usr/include
,
/usr/local/include
,
/usr/X11R6/include
или в одном из их подкаталогов.
Если его там нет, сделайте поиск по всему диску (при помощи find или
locate), и, если вы все еще не нашли его, проверьте, установлена ли
у вас библиотека, соответствующая этому заголовку. Примеры использования
команд find и locate вы можете найти в соответствующих им
страницах руководства.
Проверьте, действительно ли этот заголовок доступен для чтения (чтобы
проверить это, наберите less
<path>/<file>.h
)
Если это каталог типа /usr/local/include
или
/usr/X11R6/include
, вам иногда придется добавить
компилятору новый аргумент. Откройте соответствующий
Makefile
(будьте внимательны при открытии этого
файла, т.к. он должен находиться в каталоге, где произошел сбой компиляции
[36]) в своем любимом текстовом редакторе (Emacs, Vi
и т.п.). Взгляните на строку, вызвавшую ошибку, и добавьте строку
-I<путь>
(<путь>
- это
путь к каталогу, в котором может быть найден заголовочный файл) сразу после
компилятора (gcc
или $(CC)
). Если
вы не знаете, куда добавить эту опцию, добавьте ее в начало файла после
CFLAGS=<чего-то-там>
или после
CC=<чего-то-там>
.
Запустите еще раз make, и если это все равно помогает, проверьте, чтобы эта опция (см. предыдущий пункт) во время компиляции была добавлена в строку со сбоем.
Если это все равно не помогло, обратитесь с просьбой помочь решить проблему к местному гуру или к сообществу свободного ПО (см. раздел Раздел 6.2, «Техническая поддержка»).
glloq.c:28: `struct foo' undeclared (first use this
function)
Структуры - это специальные типы данных, используемые всеми программами. Многие из них определяются системой в заголовочных файлах. Это означает, что проблема, несомненно, была вызвана отсутствием или неправильным использованием заголовочного файла. Правильный способ решения проблемы:
Попробуйте проверить, определена ли структура программой или системой. Решением является использование команды grep для того, чтобы увидеть, определена ли структура в одном из заголовков.
Например, если вы находитесь в корне дистрибутива:
$ find . -name '*.h'| xargs grep 'struct foo' | less
На экран может быть выведено множество строк (например, каждый раз, когда функция использует определенную структуру этого типа). Если она присутствует, извлеките строку, в которой определена структура, «grep'нув» заголовочный файл.
struct foo { <содержимое структуры> };
Проверьте, соответствует ли она той, что имеется у вас. Если да, то это
значит, что заголовочный файл не включен в сбойный файл
.c
. Есть два решения:
Если нет, проделайте то же самое с системными заголовочными файлами
(которые обычно находятся в каталогах
/usr/include
,/usr/X11R6/include
или /usr/local/include
). Но на этот раз используйте
строку #include <<имя_файла>.h>
.
Если эта структура все-таки не существует, попробуйте выяснить, в какой из
библиотек (т.е. наборе функций, собранных вместе в одном пакете) она должна
была быть определена (взгляните на файл INSTALL
или
README
, чтобы узнать, какие библиотеки используются
программой и какие их версии требуются). Если версия нужной для программы
библиотеки не соответствует той, что установлена в вашей системе - вам
понадобится обновить эту библиотеку.
Если это все еще не помогает, проверьте, нормально ли работает эта программа с вашей архитектурой (некоторые программы еще не были портированы во все системы UNIX®). Проверьте также, правильно ли вы сконфигурировали программу (например, когда выполняли команду configure) для своей архитектуры.
Это довольно сложная для решения проблема, т.к. зачастую это ошибка, находящаяся в определенной строке, но уже после того, как компилятор ее обнаружил. Иногда это просто не определенный ранее тип данных. Если вы встречаете сообщение об ошибке следующего вида:
main.c:1: parse error before `glloq_t main.c:1: warning: data definition has no type or storage class
это означает, что не определен тип данных glloq_t
.
Решение этой проблемы более или менее похоже на решение предыдущей
проблемы.
Эту проблему легко решить: недостаточно свободного дискового пространства
для создания бинарного файла из исходного кода. Решение заключается в
освобождении места на разделе с каталогом установки (удалите временные
файлы или файлы с исходными текстами, деинсталлируйте программы, которыми
вы не пользуетесь, измените размер раздела и т.п.). Проверьте, чтобы он был
распакован не в /tmp
, а в
/usr/local/src
, во избежание бесполезной траты
пространства на разделе /tmp
. Кроме того, размер
этого каталога обычно ограничен несколькими десятками мегабайт вследствие
дисковых квот (прим. переводчика). Проверьте, нет ли на вашем диске файлов
core
[37]. Если таковые имеются - удалите их или сделайте так, чтобы они
были удалены в том случае, если они принадлежат другому пользователю.
/usr/bin/ld: cannot open -lglloq: No such file or
directory
Это означает, что программа ld (используемая gcc на последнем
этапе компиляции) не в состоянии найти библиотеку. Чтобы задействовать
библиотеку, ld ищет файл, чье имя находится в аргументах типа
-l<библиотека>
. Этот файл -
lib<библиотека>.so
. Если ld не в состоянии
найти ее - выводится сообщение об ошибке. Для решения проблемы, следуйте
указанным ниже инструкциям:
Проверьте существование файла на диске при помощи команды locate.
Обычно, графические библиотеки могут быть найдены в
/usr/X11R6/lib
. Например:
$ locate libglloq
Если поиск ничего не дал, вы можете выполнить поиск при помощи команды find (т.е.: find /usr -name libglloq.so*). Если вы все еще не можете найти библиотеку, вам придется ее установить.
Как только библиотека найдена, проверьте доступна ли она для программы
ld: файл /etc/ld.so.conf
определяет место поиска библиотек. Добавьте подозреваемый каталог в конец
этого файла (вам может понадобиться перегрузить свой компьютер, чтобы
изменения вступили в силу). Вы также можете добавить этот каталог, изменив
содержимое переменной окружения LD_LIBRARY_PATH
.
Например, если нужно добавить каталог
/usr/X11R6/lib
, введите:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/X11R6/lib
Если это все рано не помогает, проверьте, чтобы библиотека имела формат
исполняемого файла (или ELF) при помощи команды file. Если это
символическая ссылка, проверьте, «живая» ли это ссылка, и
не указывает ли она на несуществующий файл (например, при помощи
nm libglloq.so). Файл может иметь неверные разрешения
(например, если вы используете учетную запись, отличную от root
, и
если библиотека защищена от чтения).
glloq.c(.text+0x34): undefined reference to
`glloq_init'
Это проблема символа, который не был решен на последнем этапе компиляции. Обычно это проблема библиотеки. Причин может быть несколько:
сперва необходимо выяснить, предполагалось ли
наличие символа в библиотеке. Например, если это символ, начинающийся с
gtk
, он принадлежит библиотеке
gtk
. Если имя библиотеки можно легко определить
(frobnicate_foobar
), вы можете вывести список
символов библиотеки при помощи команды nm. Например,
$ nm libglloq.so 0000000000109df0 d glloq_message_func 000000000010a984 b glloq_msg 0000000000008a58 t glloq_nearest_pow 0000000000109dd8 d glloq_free_list 0000000000109cf8 d glloq_mem_chunk
Добавление опции -o
к nm позволит
вам вывести в каждой строке имя библиотеки, упростив тем самым поиск.
Допустим, что мы ищем символ bulgroz_max
, тогда
простейшим решением будет следующий поиск:
$ nm /usr/lib/lib*.so | grep bulgroz_max $ nm /usr/X11R6/lib/lib*.so | grep bulgroz_max $ nm /usr/local/lib/lib*.so | grep bulgroz_max /usr/local/lib/libfrobnicate.so:000000000004d848 T bulgroz_max
Превосходно! Символ bulgroz_max
определен в библиотеке
frobnicate
(перед ее именем стоит заглавная буква
T
). Теперь вам осталось только добавить строку
-lfrobnicate
в строку компиляции, отредактировав файл
Makefile
: добавьте ее в конец строки, в которых
определены переменные LDFLAGS
или
LFGLAGS
(или, на худой конец, с
CC
), или в строку, соответствующую созданию конечного
бинарного файла.
компиляция производится с версией библиотеки, которая не подходит для
данного программного продукта. Прочтите файлы README
или INSTALL
, чтобы узнать, какая версия должна быть
использована.
корректно скомпонованы не все объектные файлы дистрибутива. Отсутствует
файл, в котором определена эта функция. Введите nm -o
*.o, чтобы узнать, какой это файл, и добавьте соответствующий
файл .o
в строку компиляции, если он отсутствует.
можеть быть проблемная функция или несуществующая переменная. Попробуйте удалить ее: отредактируйте проблемный исходный файл (его имя указано в начале сообщения об ошибке). Это не лучшее решение и оно может привести к непредвиденному поведению программы с нарушением сегментации при запуске и т.п.).
Segmentation fault (core dumped)
Иногда компилятор немедленно «вываливается» и выводит это сообщение об ошибке. По этому поводу я могу только посоветовать вам установить более свежую версию компилятора.
Для процесса компиляции на различных этапах необходимо временное дисковое
пространство; если его не хватает, компиляция прерывается. Поэтому вам
может потребоваться очистить раздел, но будьте осторожны, т.к. могут
зависнуть некоторые выполняющиеся программы (X-сервер, каналы и
др.), если вы удалите некторые файлы. Вы должны соображать, что вы делаете!
Если /tmp
является частью раздела, содержащего не
только этот каталог (например, корневой раздел), найдите и удалите все
файлы core
. Одним из вариантов является изменение
размера раздела, если для этого есть достаточно свободного пространства или
может быть уменьшен какой-нибудь другой раздел.
make/configure in infinite recursion
Зачастую это проблема со временем в вашей системе. Программе make необходимо знать дату в компьютере и дату проверяемых ею файлов. Она сравнивает даты и использует результат для того, чтобы определить, не является ли цель более старшей, чем зависимости.
Некоторые проблемы с датой могут привести к тому, что make будет бесконечно собирать сам себя (или будет вновь и вновь выполнять сборку поддерева в бесконечной рекурсии). В этом случае применение touch (которая здесь используется для настройки проблемных файлов на текущую дату) обычно помогает решить проблему.
$ touch *
Или так (грубо, но эффективно):
$ find . | xargs touch
[36]
Проанализируйте сообщение об ошибке, выданное make'ом. Обычно
последние строки должны содержать название каталога (сообщение, типа
make[1]: Leaving directory
`/home/queen/Project/foo'
). Выберите сообщение с самым
старшим номером. Чтобы убедиться в том, что это именно тот каталог,
зайдите в него и выполните make, чтобы получить ту же самую ошибку.
[37] Файл, создаваемый системой, когда процесс пытается обратиться к области памяти, доступ к которой ему запрещен. Эти файлы используются для анализа причины такого поведения и устранения проблемы.