Библиотека сайта rus-linux.net
Компиляция |
||
---|---|---|
Глава 12. Сборка и установка свободного програмного обеспечения |
Компиляция
Теперь, когда программное обеспечение корректно сконфигурировано, всё, что осталось сделать - это откомпилировать его. Этот этап обычно прост и не вызывает серьёзных проблем.
Make
В обществе свободного ПО любимой утилитой для компиляции исходных кодов является make. Она имеет два преимущества:
- Разработчик экономит время, потому что она позволяет ему эффективно управлять компиляцией своего проекта.
- Конечный пользователь может откомпилировать и установить программу при помощи нескольких команд, даже если у него отсутствуют знания о разработке программного обеспечения.
Действия,
которые должны быть выполнены для получения из исходных кодов
откомпилированной версии, хранятся в файле с именем Makefile
или GNUMakefile
.
На самом деле, когда вызывается команда make,
она считывает этот файл (если он существует) из текущего каталога. В
противном случае файл может быть указан при помощи опции -f
команды make.
Правила
make
действует в соответствии с системой зависимостей,
поэтому компиляция бинарного файла («цели»)
требуется прохождения нескольких этапов («зависимостей»).
Например, для создания (воображаемого) бинарного файла glloq
должны быть откомпилированы и скомпонованы объектные файлы main.o
и init.o
(промежуточные файлы процесса компиляции). Эти объектные файлы также
являются целями, чьими зависимостями являются соответствующие файлы
исходных текстов.
Этот текст представляет собой только небольшое введение для выживания в жестоком мире make. Для получения исчерпывающей информации обратитесь к O'Reilly Managing Projects with Make (второе издание) авторов Andrew Oram и Steve Talbott.
Поехали!
Обычно при использовании 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 |
Превосходно. Бинарный файл был корректно скомпилирован. Мы готовы перейти к следующему этапу, который представляет собой установку файлов дистрибутива (бинарные файлы, файлы данных и т.п.). Смотрите раздел «Установка».
Пояснения
Если вы достаточно любопытны, чтобы заглянуть в
файл Makefile
,
вы найдете в нём известные команды (rm,
mv, cp
и др.), а также странные строки наподобие $(CFLAGS)
.
Это
переменные,
представляющие собой строки, которые обычно объявляются в начале
файла Makefile
,
а затем заменяются их значениями. Это весьма полезно, если вы хотите
использовать одни и те же опции компиляции несколько раз подряд.
Например,
вывести на экран строку «foo
»
при помощи команды make all
можно так:
TEST = foo all: echo $(TEST) |
В большинстве случаев установлены следующие переменные:
CC
: это компилятор. Обычно это cc, синонимом которого в большинстве свободных систем является gcc. Если вы в нерешительности - используйте gcc.LD
: это программа, используемая для обеспечения последнего этапа компиляции (см. раздел «Четыре этапа компиляции»). По умолчанию это программа 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
<путь>/<файл>.h
) - Если
это каталог типа
/usr/local/include
или/usr/X11R6/include
, вам иногда придётся добавить компилятору новый аргумент. Откройте соответствующийMakefile
(будьте внимательны при открытии этого файла, т.к. он должен находиться в каталоге, где произошёл сбой компиляции [33]) в своём любимом текстовом редакторе (Emacs, Vi и т.п.). Взгляните на строку, вызвавшую ошибку, и добавьте строку-I<путь>
(<путь>
- это путь к каталогу, в котором может быть найден заголовочный файл) сразу после компилятора (gcc
или$(CC)
). Если вы не знаете, куда добавить эту опцию, добавьте её в начало файла послеCFLAGS=<чего-то-там>
или послеCC=<чего-то-там>
. - Запустите ещё раз make, и если это всё равно помогает, проверьте, чтобы эта опция (см. предыдущий пункт) во время компиляции была добавлена в строку со сбоем.
- Если это всё равно не помогло, обратитесь с просьбой помочь решить проблему к местному гуру или к сообществу свободного ПО (см. раздел «Техническая поддержка»).
- Проверьте,
действительно ли заголовок существует на диске в одном из следующих
каталогов:
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) для своей архитектуры.
- Попробуйте
проверить, определена ли структура программой или системой.
Решением является использование команды grep для того, чтобы
увидеть, определена ли структура в одном из заголовков.
parse error
Это довольно сложная для решения проблема, т.к. зачастую это ошибка, находящаяся в определённой строке, но уже после того, как компилятор её обнаружил. Иногда это просто не определенный ранее тип данных. Если вы встречаете сообщение об ошибке следующего вида:
main.c:1: parse error before `glloq_t main.c:1: warning: data definition has no type or storage class
это означает, что не определен тип данных
glloq_t
. Решение этой проблемы более или менее похоже на решение предыдущей проблемы.Замечание
Если мне не изменяет память, ошибка
parse error
может иметь место в старых библиотекахcurses
.no space left on device
Эту проблему легко решить: недостаточно свободного дискового пространства для создания бинарного файла из исходного кода. Решение заключается в освобождении места на разделе с каталогом установки (удалите временные файлы или файлы с исходными текстами, удалите программы, которыми вы не пользуетесь). Рекомендуется распаковывать его не в
/tmp
, а в/usr/local/src
, во избежание бесполезной траты пространства на разделе/tmp
. Кроме того, размер этого каталога обычно ограничен несколькими десятками мегабайт вследствие дисковых квот (прим. переводчика). Проверьте, нет ли на вашем диске файловcore
[34]. Если таковые имеются - удалите их или сделайте так, чтобы они были удалены в том случае, если они принадлежат другому пользователю./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
, и если библиотека защищена от чтения).
- Проверьте
существование файла на диске при помощи команды locate.
Обычно, графические библиотеки могут быть найдены в
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)
Иногда компилятор немедленно «вываливается» и выводит это сообщение об ошибке. По этому поводу я могу только посоветовать вам установить более свежую версию компилятора.
- no
space on
/tmp
Для процесса компиляции на различных этапах необходимо временное дисковое пространство; если его не хватает, компиляция прерывается. Поэтому вам может потребоваться очистить раздел, но будьте осторожны, т.к. могут зависнуть некоторые выполняющиеся программы (X-сервер, каналы и др.), если вы удалите некторые файлы. Вы должны знать, что вы делаете! Если
/tmp
является частью раздела, содержащего не только этот каталог (например, корневой раздел), найдите и удалите все файлыcore
. - make/configure
in infinite recursion
Зачастую это проблема со временем в вашей системе. Программе make необходимо знать дату в компьютере и дату проверяемых ею файлов. Она сравнивает даты и использует результат для того, чтобы определить, не является ли цель более старшей, чем зависимости.
Некоторые проблемы с датой могут привести к тому, что make будет бесконечно собирать сам себя (или будет вновь и вновь выполнять сборкуподдерева в бесконечной рекурсии). В этом случае применение touch (которая здесь используется для настройки проблемных файлов на текущую дату) обычно помогает решить проблему.
$ touch *
Или так (грубо, но эффективно):
$ find . | xargs touch
[33]
Проанализируйте сообщение об ошибке,
выданное make'ом.
Обычно последние строки должны содержать название каталога
(сообщение, типа make[1]: Leaving
directory `/home/queen/Project/foo'
).
Выберите сообщение с самым старшим номером. Чтобы убедиться в том,
что это именно тот каталог, зайдите в него и выполните make,
чтобы получить ту же самую ошибку.
[34] Файл, создаваемый системой, когда процесс пытается обратиться к области памяти, доступ к которой ему запрещён. Эти файлы используются для анализа причины такого поведения и устранения проблемы.
Конфигурирование |
Установка |