Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта 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)

В большинстве случаев установлены следующие переменные:

  1. CC: это компилятор. Обычно это cc, синонимом которого в большинстве свободных систем является gcc. Если вы в нерешительности - используйте gcc.
  2. LD: это программа, используемая для обеспечения последнего этапа компиляции (см. раздел «Четыре этапа компиляции»). По умолчанию это программа ld.
  3. CFLAGS: это дополнительные аргументы, передаваемые компилятору на первом этапе компиляции. Среди них:
    • -I<путь>: сообщает компилятору, где искать дополнительные заголовочные файлы (напр.: -I/usr/X11R6/include разрешает добавление заголовков из каталога /usr/X11R6/include).
    • -D<символ>: определяет дополнительный символ; полезен для программ, компиляция которых зависит от определённых ранее символов (напр.: использование файла string.h, если определён HAVE_STRING_H).

    Часто строки компиляции выглядят следующим образом:

    $(CC) $(CFLAGS) -c foo.c -o foo.o
  4. LDFLAGS (или LFLAGS): это аргументы, используемые на последнем этапе компиляции. Среди них:
    • -L<путь>: определяет дополнительный путь для поиска библиотек (напр.: -L/usr/X11R6/lib).
    • -l<библиотека>: определяет дополнительную библиотеку, используемую на последнем этапе компиляции.

А что если... это не работает?

Не паникуйте, это может случится с любым. Вот наиболее общие случаи:

  1. 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, и если это всё равно помогает, проверьте, чтобы эта опция (см. предыдущий пункт) во время компиляции была добавлена в строку со сбоем.
    • Если это всё равно не помогло, обратитесь с просьбой помочь решить проблему к местному гуру или к сообществу свободного ПО (см. раздел «Техническая поддержка»).
  2. glloq.c:28: `struct foo' undeclared (first use this function)

    Структуры - это специальные типы данных, используемые всеми программами. Многие из них определяются системой в заголовочных файлах. Это означает, что проблема, несомненно, была вызвана отсутствием или неправильным использованием заголовочного файла. Правильный способ решения проблемы:

    • Попробуйте проверить, определена ли структура программой или системой. Решением является использование команды grep для того, чтобы увидеть, определена ли структура в одном из заголовков.

      Например, если вы находитесь в корне дистрибутива:

      $ find . -name '*.h'| xargs grep 'struct foo' | less

      На экран может быть выведено множество строк (например, каждый раз, когда функция использует определённую структуру этого типа). Если она присутствует, извлеките строку, в которой определена структура, «grep'нув» заголовочныйфайл.

      Определение структуры:

      struct foo {
          <содержимое структуры>
      };

      Проверьте, соответствует ли она той, что имеется у вас. Если да, то это значит, что заголовочный файл не включен в сбойный файл .c. Есть два решения:

      • добавьте строку #include "<имя_файла>.h" в начало сбойного файла .c.
      • или скопируйте определение структуры в начало этого файла (на самом деле это не совсем то, что надо, но, по крайне мере, зачастую это срабатывает).
    • Если нет, проделайте то же самое с системными заголовочными файлами (которые обычно находятся в каталогах /usr/include,/usr/X11R6/include или /usr/local/include). Но на этот раз используйте строку #include <<имя_файла>.h>.
    • Если эта структура всё-таки не существует, попробуйте выяснить, в какой из библиотек (т.е. наборе функций, собранных вместе в одном пакете) она должна была быть определена (взгляните на файл INSTALL или README, чтобы узнать, какие библиотеки используются программой и какие их версии требуются). Если версия нужной для программы библиотеки не соответствует той, что установлена в вашей системе - вам понадобится обновить эту библиотеку.
    • Если это всё ещё не помогает, проверьте, нормально ли работает эта программа с вашей архитектурой (некоторые программы ещё не были портированы во все системы UNIX®). Проверьте также, правильно ли вы сконфигурировали программу (например, когда выполняли команду configure) для своей архитектуры.
  3. parse error

    Это довольно сложная для решения проблема, т.к. зачастую это ошибка, находящаяся в определённой строке, но уже после того, как компилятор её обнаружил. Иногда это просто не определенный ранее тип данных. Если вы встречаете сообщение об ошибке следующего вида:

    main.c:1: parse error before `glloq_t
    main.c:1: warning: data definition has no type or storage class

    это означает, что не определен тип данных glloq_t. Решение этой проблемы более или менее похоже на решение предыдущей проблемы.

    [Note]

    Замечание

    Если мне не изменяет память, ошибка parse error может иметь место в старых библиотеках curses.

  4. no space left on device

    Эту проблему легко решить: недостаточно свободного дискового пространства для создания бинарного файла из исходного кода. Решение заключается в освобождении места на разделе с каталогом установки (удалите временные файлы или файлы с исходными текстами, удалите программы, которыми вы не пользуетесь). Рекомендуется распаковывать его не в /tmp, а в /usr/local/src, во избежание бесполезной траты пространства на разделе /tmp. Кроме того, размер этого каталога обычно ограничен несколькими десятками мегабайт вследствие дисковых квот (прим. переводчика). Проверьте, нет ли на вашем диске файлов core [34]. Если таковые имеются - удалите их или сделайте так, чтобы они были удалены в том случае, если они принадлежат другому пользователю.

  5. /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

      (если ваш шелл - bash).

    • Если это всё рано не помогает, проверьте, чтобы библиотека имела формат исполняемого файла (или ELF) при помощи команды file. Если это символическая ссылка, проверьте, «живая» ли это ссылка, и не указывает ли она на несуществующий файл (например, при помощи nm libglloq.so). Файл может иметь неверные разрешения (например, если вы используете учётную запись, отличную от root, и если библиотека защищена от чтения).
  6. 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 в строку компиляции, если он отсутствует.
    • можеть быть проблемная функция или несуществующая переменная. Попробуйте удалить её: отредактируйте проблемный исходный файл (его имя указано в начале сообщения об ошибке). Это не лучшее решение и оно может привести к непредвиденному поведению программы с нарушением сегментации при запуске и т.п.).
  7. Segmentation fault (core dumped)

    Иногда компилятор немедленно «вываливается» и выводит это сообщение об ошибке. По этому поводу я могу только посоветовать вам установить более свежую версию компилятора.

  8. no space on /tmp

    Для процесса компиляции на различных этапах необходимо временное дисковое пространство; если его не хватает, компиляция прерывается. Поэтому вам может потребоваться очистить раздел, но будьте осторожны, т.к. могут зависнуть некоторые выполняющиеся программы (X-сервер, каналы и др.), если вы удалите некторые файлы. Вы должны знать, что вы делаете! Если /tmp является частью раздела, содержащего не только этот каталог (например, корневой раздел), найдите и удалите все файлы core.

  9. make/configure in infinite recursion

    Зачастую это проблема со временем в вашей системе. Программе make необходимо знать дату в компьютере и дату проверяемых ею файлов. Она сравнивает даты и использует результат для того, чтобы определить, не является ли цель более старшей, чем зависимости.

    Некоторые проблемы с датой могут привести к тому, что make будет бесконечно собирать сам себя (или будет вновь и вновь выполнять сборкуподдерева в бесконечной рекурсии). В этом случае применение touch (которая здесь используется для настройки проблемных файлов на текущую дату) обычно помогает решить проблему.

    Например:

    $ touch *

    Или так (грубо, но эффективно):

    $ find . | xargs touch



[33] Проанализируйте сообщение об ошибке, выданное make'ом. Обычно последние строки должны содержать название каталога (сообщение, типа make[1]: Leaving directory `/home/queen/Project/foo'). Выберите сообщение с самым старшим номером. Чтобы убедиться в том, что это именно тот каталог, зайдите в него и выполните make, чтобы получить ту же самую ошибку.

[34] Файл, создаваемый системой, когда процесс пытается обратиться к области памяти, доступ к которой ему запрещён. Эти файлы используются для анализа причины такого поведения и устранения проблемы.


Пред. 

Уровень выше

 След.

Конфигурирование 

Начало

 Установка