Bash by example / Bash в примерах: Part 3: Exploring the ebuild system

← →
Английский оригинал Перевод на русский

Сожалеем, но текст оригинала доступен только зарегистрированным пользователям.

Введение в систему ебилдов.

undeceived 21.02.11 в 22:12

0
+1

Я с нетерпением ждал этой третьей и последней статьи цикла "Bash в примерах", потому что в первых двух частях мы разобрались в основах программирования и теперь наконец можем сосредоточиться на более интересных моментах, таких как разработка програм и дизайн приложений.

Для этой статьи я приготовил изрядную порцию примеров, исользуемых в реальной жизни. А именно в проекте, на разработку и поддержку которого я потратил многие часы: системы ебилдов в Gentoo Linux.

undeceived 21.02.11 в 22:35

0

Так как я являюсь создателем Gentoo Linux, а также человеком, создавшим Funtoo Linux - в число моих прямых обязанностей входит контроль того, что все пакеты операционной системы (похожие на пакеты RPM) правильно собраны и работают совместно без конфликтов. Как вы, вероятно, знаете, стандартная система Linux представляет из себя не единое унифицированное дерево исходников (как BSD), а состоит из примерно 25 с хвостиком основных пакетов, работающих совместно. Некоторые из пакетов включают в себя:

undeceived 21.02.11 в 22:45

0

Пакет Описание
linux Действующее ядро
util-linux Набор разнообразных Linux-программ
e2fsprogs Набор утилит для работы с файловой системой ext2
glibc Библиотека GNU C

Daemon786 09.02.11 в 10:38

0

Примечание:
Фанаты Gentoo, имейте в виду, что заявление выше значит именно это: "Я главный архитектор Gentoo Linux, операционной системы нового поколения, основанной на Linux, находящейся в настоящий момент в beta стадии. Одна из моих прямых обязанностей - контроль за тем, что все бинарные пакеты (типа RPM) правильно собраны и работают совместно без конфликтов". Я акцентирую на этом внимание потому, что одной из основных целей создание Gentoo - было предоставление бинартных пакетов, которые на самом деле работают.

undeceived 21.02.11 в 22:49

0

Каждый пакет входящий в тарболл поддерживаеться независимыми разработчиками, или командами разработчиков. Для создания дистрибутива, каждый пакет отдельно загружается, компилируется и упаковывается. Каждый раз когда пакет исправляется, обновляется или улучшается, компиляция и упаковка повторяются (это происходит довольно часто). Для исключения повторяющихся сложных действий при создании и обновлении пакетов, я создал ебилд систему, написанную полностью на Bash. Для увеличения ваших знаний Bash, я показываю применение распаковки и компилирования частей в ебилд системе, шаг за шагом. Объясняю каждое действие, а также почему оно имеет такой вид. В конце этой статьи, даже если вы имеете опыт крупномасштабных проектов в bash програмировании, вы также имеете возможность получить объяснения по созданию завершенной автоматически созданной системы.

bugzy 28.02.11 в 15:16

0

Почему bash?

Daemon786 08.02.11 в 14:22

0

Bash - существенный компонент системы ебилдов Gentoo Linux. Он был выбран в качестве основново языка ебилдов по ряду причин. Во-первых он имеет простой и знакомый синтаксис, что особенно хорошо подходит для вызова внешних программ.

zlyoha 02.05.11 в 12:02

0

Процесс развертывания

bugzy 01.03.11 в 14:22

0

Обзор процесса сборки

neumann16 10.05.11 в 08:04

0

Прежде чем мы рассмотрим систему ебилдов, давайте посмотрим что принимает участие в компиляции и инсталляции пакета. В нашем примере, мы будет рассматривать пакет "sed", являющийся стандартной GNU утилитой для потокового редактирования текста и входящий во все Linux дистрибутивы. В начале скачаем архив с исходными кодами (sed-3.02.tar.gz) (смотри Ресурсы). Мы будем хранить этот архив в /usr/src/distfiles, данную директорию будем использовать в значении переменной $DISTDIR. $DISTDIR это директория где находятся все наши оригинальные архивы с исходниками; это большое хранилище исходных кодов.

neumann16 10.05.11 в 08:12

0

Следующим нашим шагом будет создание временной директории work, в которой будут находиться разархивированные исходные коды. Мы будем ссылаться на эту директорию позже, используя переменную $WORKDIR. Перейдите в директорию в которой мы имеем право на запись и выполните следующие команды:

neumann16 10.05.11 в 08:30

0

$ mkdir work
$ cd work
$ tar xzf /usr/src/distfiles/sed-3.02.tar.gz

Daemon786 24.01.11 в 13:14

0

Когда развернеться архив тарбола, будет создан каталог sed-3.02, содержащий все ресурсы. Мы будем ссылаться на этот каталог позже с помощью переменной $SRCDIR. Для компиляции программы наберите следующее:

bugzy 01.03.11 в 14:21

0

Архив разархивируется, создав директорию sed-3.02, содержащую все исходные коды. Мы будем позже ссылаться на директорию sed-3.02, используя переменную $SRCDIR. Для компиляции программы введите следующее:

neumann16 10.05.11 в 08:41

0

$ cd sed-3.02
$ ./configure --prefix=/usr
(autoconf создаст make-файлы, это может занять некоторое время)

$ make

(пакет собирается из исходников, это также займет некоторое время)

neumann16 10.05.11 в 12:20

0

Мы пропустим шаг "make install", поскольку мы рассмотрим только шаги распаковки и компиляции в этой статье. Если мы захотели бы написать bash-скрипт для выполнения всех этих шагов, то он выглядел бы примерно так:

neumann16 10.05.11 в 12:37

0

#!/usr/bin/env bash

if [ -d work ]
then
# Удаление страых директорий если существуют
rm -rf work
fi
mkdir work
cd work
tar xzf /usr/src/distfiles/sed-3.02.tar.gz
cd sed-3.02
./configure --prefix=/usr
make

bugzy 28.02.11 в 17:44

0

Обобщение кода

bugzy 01.03.11 в 14:14

0

Хотя этот скрипт работает, он не очень гибкий. В основном bash-скрипт содержит только список всех команд, которые были набраны в командной строке. Хоть это решение и работает, неплохо было бы создать общий скрипт, который можно быстро настроить для распаковки и компиляции любого пакета, просто изменив несколько строк. Таким образом, он помогает создателям пакетов делать гораздо меньше работы во время добавления новых пакетов в дистрибутив. Давайте добъемся этого, используя множество различных переменных, делая наш скрипт более общим:

neumann16 10.05.11 в 13:24

0

#!/usr/bin/env bash

# P имя пакета

P=sed-3.02

# A имя архива

A=${P}.tar.gz

export ORIGDIR=pwd
export WORKDIR=${ORIGDIR}/work
export SRCDIR=${WORKDIR}/${P}

if [ -z "$DISTDIR" ]
then
# назначение переменной DISTDIR пути /usr/src/distfiles если не назначено раньше
DISTDIR=/usr/src/distfiles
fi
export DISTDIR

if [ -d ${WORKDIR} ]
then
# удаление старого рабочего каталога если существует
rm -rf ${WORKDIR}
fi

mkdir ${WORKDIR}
cd ${WORKDIR}
tar xzf ${DISTDIR}/${A}
cd ${SRCDIR}
./configure --prefix=/usr
make

bugzy 01.03.11 в 14:13

0

Мы добавили много переменных в скрипт, но он продолжает выполнять тоже самое. Хотя, сейчас для компиляции любого стандартного архива основанного на GNU autoconf, мы можем просто скопировать этот скрипт в новый файл (с соответствующим именем, означающим название нового пакета, который он компилирует), и затем изменить значения переменных $A и $P на нужные. Все остальные переменные автоматически принимают правильные значения, и скрипт работает как надо. Хоть это и удобно, есть еще одно улучшение, которое можно сделать с кодом скрипта. Данный код намного длиннее чем оригинальный "нетронутый" сценарий, который мы создали. Поскольку одной из целей для любого проекта должно стать снижение сложности для пользователя, было бы неплохо резко сократить код, или, по крайней мере лучше его организовать. Мы можем сделать это, выполнив изящный трюк - мы разделим код на два отдельных файла. Сохраните этот файл как sed-3.02.ebuild:

neumann16 10.05.11 в 13:57

0

#the sed ebuild file -- very simple!
P=sed-3.02
A=${P}.tar.gz

Daemon786 24.01.11 в 13:17

0

# Файл sed ebuild - очень просто!
P=sed-3.02
A=${P}.tar.gz

bugzy 28.02.11 в 17:48

1

# ебилд файл для sed -- очень простой!
P=sed-3.02
A=${P}.tar.gz

neumann16 10.05.11 в 14:02

0
+1

Наш первый файл тривиален, и содержит только те переменные окружения, которые должны быть изменены для различных пакетов. Теперь рассмотрим второй файл, который содержит мозг операции. Сохраните это в файл "ebuild" и сделайте его исполняемым:

neumann16 11.05.11 в 10:18

0

#!/usr/bin/env bash


if [ $# -ne 1 ]
then
echo "принимается один аргумент."
exit 1
fi

if [ -e "$1" ]
then
source $1
else
echo "ebuild файл $1 не найден."
exit 1
fi

export ORIGDIR=pwd
export WORKDIR=${ORIGDIR}/work
export SRCDIR=${WORKDIR}/${P}

if [ -z "$DISTDIR" ]
then
# присваиваем переменной DISTDIR значение /usr/src/distfiles если не было присвоено раньше
DISTDIR=/usr/src/distfiles
fi
export DISTDIR

if [ -d ${WORKDIR} ]
then
# удаление старого рабочего каталога если он существовал
rm -rf ${WORKDIR}
fi

mkdir ${WORKDIR}
cd ${WORKDIR}
tar xzf ${DISTDIR}/${A}
cd ${SRCDIR}
./configure --prefix=/usr
make

neumann16 11.05.11 в 10:25

0

Теперь когда мы разбили нашу систему сборки на два файла, я уверен, вам станет интересно как это работает. В принципе, для компиляции sed, наберите:

neumann16 10.05.11 в 17:55

0

$ ./ebuild sed-3.02.ebuild

Daemon786 24.01.11 в 13:18

0

После запуска "ebuild", он сначала пытается выполнить "source" переменной $1. Что это означает? Из предыдущей главы, напомню, что $1 является первым аргументом командной строки -- в этом случае, sed-3.02.ebuild. В bash, команда "source" считывает все инструкции из указанного файла, и выполняет их как если бы они сразу находились в файле, содержащем команду "source". Таким образом, "source ${1}" заставляет "ebuild" скрипт выполнить команды из файла sed-3.02.ebuild, которые определяют переменные $P и $A. Это изменение конструкции очень удобно, потому что если мы захотим собрать другую программу вместо sed, мы можем просто создать новый .ebuild файл и передать его в качестве аргумента для нашего "ebuild" скрипта. Таким образом, .ebuild файлы становятся очень простыми, в то время как мозг системы ебилдов содержется в одном месте -- в нашем "ebuild" скрипте. Мы можем обновить или расширить систему ебилдов просто редактируя "ebuild" скрипт, сохраняя детали реализации за пределами ebuild файлов. Вот пример ebuild файла для gzip:

neumann16 11.05.11 в 11:21

0

#другой действительно простой ebuild скрипт!
P=gzip-1.2.4a
A=${P}.tar.gz

neumann16 11.05.11 в 12:01

0

Добавление функциональности

neumann16 11.05.11 в 12:01

0

ОК, мы добились некоторого прогресса. Однако, есть некоторая дополнительная функциональность которую я бы хотел добавить. Я хочу чтобы ebuild скрипт принимал второй аргумент командной строки, который будет принимать значение compile, unpack или all. Этот второй аргумент сообщает ebuild скрипту какой шаг необходимо выполнить. Таким образом, я могу сказать ebuild скрипту разархивировать архив, но не компилировать его (на всякий случай мне нужно проверить исходный архив перед компиляцией). Для этого, я добавлю оператор case который будет проверять переменную $2, и делать различные вещи, основываясь на ее значении. Вот этот код:

neumann16 11.05.11 в 12:39

0

#!/usr/bin/env bash

if [ $# -ne 2 ]
then
echo "Пожалуйста укажите два аргумента - .ebuild файл и unpack, compile или all"
exit 1
fi


if [ -z "$DISTDIR" ]
then
# присваиваем переменной DISTDIR значение /usr/src/distfiles если не было присвоено раньше
DISTDIR=/usr/src/distfiles
fi
export DISTDIR

ebuild_unpack() {
#убеждаемся что мы находимся в нyжной директории
cd ${ORIGDIR}

if [ -d ${WORKDIR} ]
then
rm -rf ${WORKDIR}
fi

mkdir ${WORKDIR}
cd ${WORKDIR}
if [ ! -e ${DISTDIR}/${A} ]
then
echo "${DISTDIR}/${A} не доступно. Пожалуйста вначале скачайте архив."
exit 1
fi
tar xzf ${DISTDIR}/${A}
echo "Unpacked ${DISTDIR}/${A}."
#теперь исходники разархивированы правильно
}


ebuild_compile() {

#убеждаемся что мы находимся в нyжной директории
cd ${SRCDIR}
if [ ! -d "${SRCDIR}" ]
then
echo "${SRCDIR} не доступно -- пожалуйста, выполните вначале unpack."
exit 1
fi
./configure --prefix=/usr
make
}

export ORIGDIR=pwd
export WORKDIR=${ORIGDIR}/work

if [ -e "$1" ]
then
source $1
else
echo "Ebuild файл $1 не найден."
exit 1
fi

export SRCDIR=${WORKDIR}/${P}

case "${2}" in
unpack)
ebuild_unpack
;;
compile)
ebuild_compile
;;
all)
ebuild_unpack
ebuild_compile
;;
*)
echo "Пожалуйста укажите unpack, compile или all в качестве второго аргумента"
exit 1
;;
esac

neumann16 11.05.11 в 13:48

0

Мы сделали много изменений, поэтому давайте рассмотрим их. Во-первых, мы разместили шаги компиляции и распаковки в их собственные функции, и назвали их ebuild_compile () и ebuild_unpack (), соответственно. Это хороший шаг, так как код становится более сложным, и новые функции предоставляют некоторую модульность, которая помогает держать код более организовано. В первой строке каждой функции, я явно выполняю cd в нужный каталог, так как хочу быть увереным, потому что наш код становится более модульным, а не линейным, поэтому вероятно, что мы можем ошибиться и выполнить функцию в неправильном рабочем каталоге. Команды cd явно переносят нас в нужное место, и не дает нам сделать ошибку позже - это важный шаг - особенно, если вы будете удалять файлы внутри функции.

neumann16 12.05.11 в 06:04

0

Кроме того, я добавил полезную проверку в начало функции ebuild_compile(). Теперь, проверяется, что переменная $SRCDIR существует, и если ее нет, то появляется сообщение об ошибке, говорящее пользователю о необходимости вначале распаковать архив, а затем происходит выход. Если вы хотите, вы можете изменить это поведение так, что если $SRCDIR не существует, наши ebuild скрипты будут распаковать исходный архив автоматически. Вы можете сделать это, заменив функцию ebuild_compile () следующим кодом:

neumann16 12.05.11 в 06:09

0

ebuild_compile() {
# проверьте имеете ли вы права на каталог
directory
if [ ! -d "${SRCDIR}" ]
then
ebuild_unpack
fi
cd ${SRCDIR}
./configure --prefix=/usr
make
}

bugzy 01.03.11 в 14:26

0

ebuild_compile() {
#убеждаемся что мы находимся в правильной директории
if [ ! -d "${SRCDIR}" ]
then
ebuild_unpack
fi
cd ${SRCDIR}
./configure --prefix=/usr
make
}

neumann16 12.05.11 в 06:12

0

Одно из наиболее очевидных изменений в нашей второй версии ebuild скрипта это новый оператор case в конце кода. Этот оператор case просто проверяет второй аргумент командной строки и выполняет правильное действие, в зависимости от его значения. Если мы теперь введем:

neumann16 12.05.11 в 06:14

0

$ ebuild sed-3.02.ebuild

Daemon786 24.01.11 в 13:21

0

Мы действительно получим сообщение об ошибке. Ebuild теперь хочет чтобы ему сообщали, что ему делать:

neumann16 12.05.11 в 06:17

0

$ ebuild sed-3.02.ebuild unpack

Daemon786 24.01.11 в 13:22

0

или:

Daemon786 24.01.11 в 13:22

0

$ ebuild sed-3.02.ebuild compile

Daemon786 24.01.11 в 13:22

0

или:

Daemon786 24.01.11 в 13:23

0

$ ebuild sed-3.02.ebuild all

Daemon786 24.01.11 в 13:23

0

Важно!
Если второй аргумент будет не таким, как перечислено выше, то вы увидите сообщение об ошибке (поле * оператора case), и программа завершит работу.

neumann16 12.05.11 в 06:23

0
Минутку...

Следующая страница →