Ruby Packaging mini-HOWTO: различия между версиями

Материал из ALT Linux Wiki
Нет описания правки
мНет описания правки
Строка 1: Строка 1:
[[Category:Sisyphus]][[Category:HOWTO]]
[[Категория:Sisyphus]][[Категория:HOWTO]]
{{Stub}}
{{Stub}}


Основные правила сборки приложений и модулей ruby изложены в [[Ruby Policy|Ruby Packaging Policy]]. Цель же этого документа - об'яснить на простых примерах как следует поступать в различных ситуациях а также показать как можно собирать простые модули.
Основные правила сборки приложений и модулей ruby изложены в [[Ruby Policy|Ruby Packaging Policy]]. Цель же этого документа — об’яснить на простых примерах как следует поступать в различных ситуациях а также показать как можно собирать простые модули.


Я не рассматриваю rubygems, так как эта система включает в себя свой пакетный менеджер, не совместимый с дистрибутивным. Про отношение Debian к rubygems можно прочитать [http://pkg-ruby-extras.alioth.debian.org/rubygems.html тут], рекомендации апстриму изложены [http://pkg-ruby-extras.alioth.debian.org/upstream-devs.html тут]. У нас ситуация в общем аналогичная.
Я не рассматриваю rubygems, так как эта система включает в себя свой пакетный менеджер, не совместимый с дистрибутивным. Про отношение Debian к rubygems можно прочитать [http://pkg-ruby-extras.alioth.debian.org/rubygems.html тут], рекомендации апстриму изложены [http://pkg-ruby-extras.alioth.debian.org/upstream-devs.html тут]. У нас ситуация в общем аналогичная.


__TOC__
__TOC__
Строка 11: Строка 11:
=== Общие принципы сборки модулей ===
=== Общие принципы сборки модулей ===


Есть два способа сборки модулей. При помощи rubygems (который мы не рассматриваем по ряду причин), и "нативная" сборка, с помещением файлов в специальные каталоги, которые находятся в <tt>$LOAD_PATH</tt>.
Есть два способа сборки модулей. При помощи rubygems (который мы не рассматриваем по ряду причин), и «нативная» сборка, с помещением файлов в специальные каталоги, которые находятся в <tt>$LOAD_PATH</tt>.


Сборка пакета включает в себя:
Сборка пакета включает в себя:
Строка 20: Строка 20:
* генерацию документации в формате ri (class reference);
* генерацию документации в формате ri (class reference);


Модули устанавливаются в так называемый vendor dir. В ALT Linux это <tt>/usr/share/ruby/vendor_ruby/RUBY.VERSION</tt> и <tt>/usr/lib/ruby/RUBY.VERSION/ARCHITECTURE</tt>. Поскольку по умолчанию установка модулей идёт в site dir, при сборке пакета надо использовать модуль <tt>vendor_specific</tt>, вызывая интерпретатор ruby как <tt>ruby -rvendor_specific</tt>. Для этого есть макрос <tt>%ruby</tt>.
Модули устанавливаются в так называемый vendor dir. В ALT Linux это <tt>/usr/share/ruby/vendor_ruby/RUBY.VERSION</tt> и <tt>/usr/lib/ruby/RUBY.VERSION/ARCHITECTURE</tt>. Поскольку по умолчанию установка модулей идёт в site dir, при сборке пакета надо использовать модуль <tt>vendor_specific</tt>, вызывая интерпретатор ruby как <tt>ruby -rvendor_specific</tt>. Для этого есть макрос <tt>%ruby</tt>.


=== Внутри тарбола ===
=== Внутри тарбола ===
Строка 26: Строка 26:
Внутри тарбола с модулем (или программой) могут находиться следующие файлы и каталоги:
Внутри тарбола с модулем (или программой) могут находиться следующие файлы и каталоги:


* '''bin/''' - скрипты, будут установлены в <tt>%_bindir</tt>;
* '''bin/''' — скрипты, будут установлены в <tt>%_bindir</tt>;
* '''ext/''' - компилируемые модули (при использовании <tt>setup.rb</tt>), будут установлены в <tt>%ruby_sitearchdir</tt>;
* '''ext/''' — компилируемые модули (при использовании <tt>setup.rb</tt>), будут установлены в <tt>%ruby_sitearchdir</tt>;
* '''lib/''' - pure-ruby модули, будут установлены в <tt>%ruby_sitelibdir</tt>;
* '''lib/''' — pure-ruby модули, будут установлены в <tt>%ruby_sitelibdir</tt>;
* '''data/''' - произвольные данные(при использовании <tt>setup.rb</tt>), будут установлены в <tt>%_datadir/ИМЯМОДУЛЯ</tt>;
* '''data/''' — произвольные данные(при использовании <tt>setup.rb</tt>), будут установлены в <tt>%_datadir/ИМЯМОДУЛЯ</tt>;
* '''test/''' - unit-тесты;
* '''test/''' — unit-тесты;


Также как правило присутствует один или несколько "сценариев сборки", о них расскажу далее.
Также как правило присутствует один или несколько «сценариев сборки», о них расскажу далее.


=== Собираем модуль ===
=== Собираем модуль ===


Существует несколько, различного уровня "стандартности", способов сборки модулей ruby.
Существует несколько, различного уровня «стандартности», способов сборки модулей ruby.


==== <tt>extconf.rb</tt> AKA MkMf ====
==== <tt>extconf.rb</tt> AKA MkMf ====


Аналог configure, использует модуль <tt>mkmf</tt>, входящий в стандартную поставку ruby. Внутри скрипта проверяется наличие необходимых заголовочных файлов и библиотек, на выходе генерится Makefile, который обрабатывается стандартным make. Используется только в тех проектах, где есть бинарные модули. Если "рядом" с <tt>extconf.rb</tt> находится файл <tt>depend</tt>, его содержимое добавляется к <tt>Makefile</tt>. Исходные тексты и заголовочные файлы бинарного модуля как правило тоже лежат "рядом" с <tt>extconf.rb</tt>.
Аналог configure, использует модуль <tt>mkmf</tt>, входящий в стандартную поставку ruby. Внутри скрипта проверяется наличие необходимых заголовочных файлов и библиотек, на выходе генерится Makefile, который обрабатывается стандартным make. Используется только в тех проектах, где есть бинарные модули. Если «рядом» с <tt>extconf.rb</tt> находится файл <tt>depend</tt>, его содержимое добавляется к <tt>Makefile</tt>. Исходные тексты и заголовочные файлы бинарного модуля как правило тоже лежат «рядом» с <tt>extconf.rb</tt>.


Типичные секции <tt>%build</tt> и <tt>%install</tt> выглядят следующим образом:
Типичные секции <tt>%build</tt> и <tt>%install</tt> выглядят следующим образом:
Строка 55: Строка 55:
==== <tt>setup.rb</tt> имени Minero Aoki ====
==== <tt>setup.rb</tt> имени Minero Aoki ====


Скрипт сборки и установки общего назначения. Как правило используется для сборки и установки pure-ruby модулей. Имеет некоторое количество стандартных опций, может собирать бинарные модули, находящиеся в каталоге '''ext/''' (как правило там присутствует <tt>extconf.rb</tt>, см. выше).
Скрипт сборки и установки общего назначения. Как правило используется для сборки и установки pure-ruby модулей. Имеет некоторое количество стандартных опций, может собирать бинарные модули, находящиеся в каталоге '''ext/''' (как правило там присутствует <tt>extconf.rb</tt>, см. выше).


Типичные секции <tt>%build</tt> и <tt>%install</tt> выглядят следующим образом:
Типичные секции <tt>%build</tt> и <tt>%install</tt> выглядят следующим образом:
Строка 70: Строка 70:
==== <tt>install.rb</tt> ====
==== <tt>install.rb</tt> ====


Иногда это самописный скрипт, иногда встречается одна из первых версий <tt>setup.rb</tt>. Как правило используется только для установки pure-ruby модулей. Стандартных макросов для поддержки <tt>install.rb</tt> нет.
Иногда это самописный скрипт, иногда встречается одна из первых версий <tt>setup.rb</tt>. Как правило используется только для установки pure-ruby модулей. Стандартных макросов для поддержки <tt>install.rb</tt> нет.


==== <tt>Rakefile</tt> и остальные случаи ====
==== <tt>Rakefile</tt> и остальные случаи ====


Сценарий для <tt>rake</tt>. Обычно может иметь task'и <tt>build</tt> (если есть бинарные модули) и <tt>test</tt>, но последнее время не имеет task'а <tt>install</tt>. Зато использует <tt>rubygems</tt>.
Сценарий для <tt>rake</tt>. Обычно может иметь task’и <tt>build</tt> (если есть бинарные модули) и <tt>test</tt>, но последнее время не имеет task’а <tt>install</tt>. Зато использует <tt>rubygems</tt>.


Для вызова <tt>rake</tt> и <tt>rake install</tt> есть два стандартных макроса <tt>%rake</tt> и <tt>%rake_install</tt> соответственно.
Для вызова <tt>rake</tt> и <tt>rake install</tt> есть два стандартных макроса <tt>%rake</tt> и <tt>%rake_install</tt> соответственно.
Строка 89: Строка 89:
Далее используются макросы <tt>%ruby_config</tt>, <tt>%ruby_build</tt> и <tt>%ruby_install</tt>.
Далее используются макросы <tt>%ruby_config</tt>, <tt>%ruby_build</tt> и <tt>%ruby_install</tt>.


Очень часто в Rakefile включена поддержка создания .gem. Поскольку rubygems использовать при сборке пакетов нельзя, следует воспользоваться [http://pkg-ruby-extras.alioth.debian.org/upstream-devs.html рецептом из Debian].
Очень часто в Rakefile включена поддержка создания .gem. Поскольку rubygems использовать при сборке пакетов нельзя, следует воспользоваться [http://pkg-ruby-extras.alioth.debian.org/upstream-devs.html рецептом из Debian].


=== Пакуем документацию ===
=== Пакуем документацию ===


Документация в формате RI генерируется при помощи утилиты <tt>rdoc</tt>, находящейся в пакете <tt>ruby-tool-rdoc</tt>. Для этого существует стандартный макрос <tt>%rdoc</tt> предназначенный для использования в секции <tt>%install</tt> (обычно одной из последних строк). В качестве аргументов этого макроса перечисляются файлы и каталоги с исходниками и при необходимости другие опции утилиты <tt>rdoc</tt>.
Документация в формате RI генерируется при помощи утилиты <tt>rdoc</tt>, находящейся в пакете <tt>ruby-tool-rdoc</tt>. Для этого существует стандартный макрос <tt>%rdoc</tt> предназначенный для использования в секции <tt>%install</tt> (обычно одной из последних строк). В качестве аргументов этого макроса перечисляются файлы и каталоги с исходниками и при необходимости другие опции утилиты <tt>rdoc</tt>.


Для pure-ruby модулей как правило используется конструкция:
Для pure-ruby модулей как правило используется конструкция:
Строка 107: Строка 107:
</pre>
</pre>


Документацию желательно паковать в подпакет <tt>%name-doc</tt>. При этом паковать следует только документацию для основных классов модуля, описание расширений сторонних классов паковать не нужно.
Документацию желательно паковать в подпакет <tt>%name-doc</tt>. При этом паковать следует только документацию для основных классов модуля, описание расширений сторонних классов паковать не нужно.


=== Складываем файлы в пакеты ===
=== Складываем файлы в пакеты ===
Строка 115: Строка 115:
=== Добро пожаловать в реальный мир ===
=== Добро пожаловать в реальный мир ===


В теории всё выглядит красиво, однако на практике среднего размера модуль представляет собой "нечто", что может работать в любой помойке. Однако мы делаем не помойку, поэтому местечковые хаки нам не нужны.
В теории всё выглядит красиво, однако на практике среднего размера модуль представляет собой «нечто», что может работать в любой помойке. Однако мы делаем не помойку, поэтому местечковые хаки нам не нужны.


==== Не загрязняем <tt>$LOAD_PATH</tt> (<tt>$:</tt>) ====
==== Не загрязняем <tt>$LOAD_PATH</tt> (<tt>$:</tt>) ====
Строка 125: Строка 125:
</pre>
</pre>


Эта конструкция добавляет в <tt>$LOAD_PATH</tt> некоторый путь. Сделано это для того, чтобы модуль (или исполняемый скрипт) можно было использовать из любого места. Поскольку в нашем случае все файлы пакуются в стандартные места, подобные конструкции не нужны. В большинстве случаев такие конструкции можно безболезненно удалить.
Эта конструкция добавляет в <tt>$LOAD_PATH</tt> некоторый путь. Сделано это для того, чтобы модуль (или исполняемый скрипт) можно было использовать из любого места. Поскольку в нашем случае все файлы пакуются в стандартные места, подобные конструкции не нужны. В большинстве случаев такие конструкции можно безболезненно удалить.


==== Используем существующие модули и размаскируем зависимости ====
==== Используем существующие модули и размаскируем зависимости ====


Поскольку наша помойка не является "любой", её ТТХ нам известны. Например, известно что это Linux, есть Iconv и так далее. Поэтому специфичный код, предназначенный для работы на других платформах в наших пакетах не нужен (а иногда бывает и вреден, поскольку даже "мёртвый" код может порождать зависимости, которые в некоторых случаях превращаются в unmet'ы).
Поскольку наша помойка не является «любой», её ТТХ нам известны. Например, известно что это Linux, есть Iconv и так далее. Поэтому специфичный код, предназначенный для работы на других платформах в наших пакетах не нужен (а иногда бывает и вреден, поскольку даже «мёртвый» код может порождать зависимости, которые в некоторых случаях превращаются в unmet’ы).


Также мы можем превратить опциональную зависимость в явную. Пример:
Также мы можем превратить опциональную зависимость в явную. Пример:


<pre>
<pre>
Строка 144: Строка 144:
</pre>
</pre>


В данном случае '''всю''' эту сложную конструкцию можно заменить на одну строку <tt>require 'iconv'</tt>. Как бонус мы получаем зависимость на <tt>ruby(iconv)</tt> и полную функциональность данного модуля.
В данном случае '''всю''' эту сложную конструкцию можно заменить на одну строку <tt>require 'iconv'</tt>. Как бонус мы получаем зависимость на <tt>ruby(iconv)</tt> и полную функциональность данного модуля.


Реальные примеры можно посмотреть в пакете [http://git.altlinux.org/people/raorn/packages/?p=ruby-gettext.git ruby-gettext].
Реальные примеры можно посмотреть в пакете [http://git.altlinux.org/people/raorn/packages/?p=ruby-gettext.git ruby-gettext].
Строка 150: Строка 150:
==== Отрываем rubygems ====
==== Отрываем rubygems ====


В реальной жизни можно встретить множество вариантов использования rubygems. Вот самые распространённые:
В реальной жизни можно встретить множество вариантов использования rubygems. Вот самые распространённые:


Пример 1:
Пример 1:
Строка 193: Строка 193:
</pre>
</pre>


Этим мы убираем зависимость на rubygems и размаскируем скрытые зависимости. Таким образом наш модуль автоматически получает зависимсти на <tt>ruby(some/module)</tt> и <tt>ruby(some/other/module)</tt>.
Этим мы убираем зависимость на rubygems и размаскируем скрытые зависимости. Таким образом наш модуль автоматически получает зависимсти на <tt>ruby(some/module)</tt> и <tt>ruby(some/other/module)</tt>.


==== Файлы специального вида (темплейты и плагины) ====
==== Файлы специального вида (темплейты и плагины) ====


Очень часто модуль (или приложение) носит с собой какие-то данные, которые обычно находятся в каталоге с gem'ом. Выглядит это приблизительно вот так:
Очень часто модуль (или приложение) носит с собой какие-то данные, которые обычно находятся в каталоге с gem’ом. Выглядит это приблизительно вот так:


<pre>
<pre>
Строка 205: Строка 205:
</pre>
</pre>


В таком случае этот каталог (в нашем примере "<tt>plugins</tt>") помещается в <tt>/usr/share/ИМЯМОДУЛЯ</tt> а код заменяется на такой:
В таком случае этот каталог (в нашем примере «<tt>plugins</tt>») помещается в <tt>/usr/share/ИМЯМОДУЛЯ</tt> а код заменяется на такой:


<pre>
<pre>
Строка 215: Строка 215:
==== Потрошим новый пакет ====
==== Потрошим новый пакет ====


При сборке нового пакета следует пробежать глазами его код на тему вышеописанных конструкций. Начать можно с <tt>grep -r</tt> по каталогам <tt>lib/</tt> и <tt>bin/</tt> по паттернам '<tt>__FILE__</tt>', '<tt>ubygems</tt>', '<tt>LoadError</tt>', '<tt>\$:</tt>', '<tt>\$LOAD_PATH</tt>'.
При сборке нового пакета следует пробежать глазами его код на тему вышеописанных конструкций. Начать можно с <tt>grep -r</tt> по каталогам <tt>lib/</tt> и <tt>bin/</tt> по паттернам '<tt>__FILE__</tt>', '<tt>ubygems</tt>', '<tt>LoadError</tt>', '<tt>\$:</tt>', '<tt>\$LOAD_PATH</tt>'.

Версия от 10:25, 1 августа 2008

Stub.png
Данная страница находится в разработке.
Эта страница ещё не закончена. Информация, представленная здесь, может оказаться неполной или неверной.


Основные правила сборки приложений и модулей ruby изложены в Ruby Packaging Policy. Цель же этого документа — об’яснить на простых примерах как следует поступать в различных ситуациях а также показать как можно собирать простые модули.

Я не рассматриваю rubygems, так как эта система включает в себя свой пакетный менеджер, не совместимый с дистрибутивным. Про отношение Debian к rubygems можно прочитать тут, рекомендации апстриму изложены тут. У нас ситуация в общем аналогичная.


Общие принципы сборки модулей

Есть два способа сборки модулей. При помощи rubygems (который мы не рассматриваем по ряду причин), и «нативная» сборка, с помещением файлов в специальные каталоги, которые находятся в $LOAD_PATH.

Сборка пакета включает в себя:

  • компиляцию бинарных модулей (если они есть);
  • выполнение тестов (если они есть и их выполнение возможно в hasher);
  • установку файлов в соответствующие каталоги;
  • генерацию документации в формате ri (class reference);

Модули устанавливаются в так называемый vendor dir. В ALT Linux это /usr/share/ruby/vendor_ruby/RUBY.VERSION и /usr/lib/ruby/RUBY.VERSION/ARCHITECTURE. Поскольку по умолчанию установка модулей идёт в site dir, при сборке пакета надо использовать модуль vendor_specific, вызывая интерпретатор ruby как ruby -rvendor_specific. Для этого есть макрос %ruby.

Внутри тарбола

Внутри тарбола с модулем (или программой) могут находиться следующие файлы и каталоги:

  • bin/ — скрипты, будут установлены в %_bindir;
  • ext/ — компилируемые модули (при использовании setup.rb), будут установлены в %ruby_sitearchdir;
  • lib/ — pure-ruby модули, будут установлены в %ruby_sitelibdir;
  • data/ — произвольные данные(при использовании setup.rb), будут установлены в %_datadir/ИМЯМОДУЛЯ;
  • test/ — unit-тесты;

Также как правило присутствует один или несколько «сценариев сборки», о них расскажу далее.

Собираем модуль

Существует несколько, различного уровня «стандартности», способов сборки модулей ruby.

extconf.rb AKA MkMf

Аналог configure, использует модуль mkmf, входящий в стандартную поставку ruby. Внутри скрипта проверяется наличие необходимых заголовочных файлов и библиотек, на выходе генерится Makefile, который обрабатывается стандартным make. Используется только в тех проектах, где есть бинарные модули. Если «рядом» с extconf.rb находится файл depend, его содержимое добавляется к Makefile. Исходные тексты и заголовочные файлы бинарного модуля как правило тоже лежат «рядом» с extconf.rb.

Типичные секции %build и %install выглядят следующим образом:

%build
%ruby_configure <опции extconf.rb>
%make_build

%install
%make_install DESTDIR=%buildroot install

setup.rb имени Minero Aoki

Скрипт сборки и установки общего назначения. Как правило используется для сборки и установки pure-ruby модулей. Имеет некоторое количество стандартных опций, может собирать бинарные модули, находящиеся в каталоге ext/ (как правило там присутствует extconf.rb, см. выше).

Типичные секции %build и %install выглядят следующим образом:

%build
%ruby_config <опции setup.rb>
%ruby_build

%install
%ruby_install

install.rb

Иногда это самописный скрипт, иногда встречается одна из первых версий setup.rb. Как правило используется только для установки pure-ruby модулей. Стандартных макросов для поддержки install.rb нет.

Rakefile и остальные случаи

Сценарий для rake. Обычно может иметь task’и build (если есть бинарные модули) и test, но последнее время не имеет task’а install. Зато использует rubygems.

Для вызова rake и rake install есть два стандартных макроса %rake и %rake_install соответственно.

Если task install не определён или вообще отсутствует установочный скрипт (в случае pure-ruby модуля), можно использовать setup.rb из пакета ruby-tool-setup примерно следующим образом:

%prep
%setup
%patch -p1
cp %_datadir/ruby-setup/setup.rb .

Далее используются макросы %ruby_config, %ruby_build и %ruby_install.

Очень часто в Rakefile включена поддержка создания .gem. Поскольку rubygems использовать при сборке пакетов нельзя, следует воспользоваться рецептом из Debian.

Пакуем документацию

Документация в формате RI генерируется при помощи утилиты rdoc, находящейся в пакете ruby-tool-rdoc. Для этого существует стандартный макрос %rdoc предназначенный для использования в секции %install (обычно одной из последних строк). В качестве аргументов этого макроса перечисляются файлы и каталоги с исходниками и при необходимости другие опции утилиты rdoc.

Для pure-ruby модулей как правило используется конструкция:

%rdoc lib/

Если присутствуют бинарные модули:

%rdoc *.c lib/

Документацию желательно паковать в подпакет %name-doc. При этом паковать следует только документацию для основных классов модуля, описание расширений сторонних классов паковать не нужно.

Складываем файлы в пакеты

Pure-ruby модули помещаются в %ruby_sitelibdir, бинарные модули в %ruby_sitearchdir, документация в формате RI в %ruby_ri_sitedir (при этом файл %ruby_ri_sitedir/created.rid упаковывать не нужно).

Добро пожаловать в реальный мир

В теории всё выглядит красиво, однако на практике среднего размера модуль представляет собой «нечто», что может работать в любой помойке. Однако мы делаем не помойку, поэтому местечковые хаки нам не нужны.

Не загрязняем $LOAD_PATH ($:)

Очень часто в коде можно увидеть конструкции вида:

$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')

Эта конструкция добавляет в $LOAD_PATH некоторый путь. Сделано это для того, чтобы модуль (или исполняемый скрипт) можно было использовать из любого места. Поскольку в нашем случае все файлы пакуются в стандартные места, подобные конструкции не нужны. В большинстве случаев такие конструкции можно безболезненно удалить.

Используем существующие модули и размаскируем зависимости

Поскольку наша помойка не является «любой», её ТТХ нам известны. Например, известно что это Linux, есть Iconv и так далее. Поэтому специфичный код, предназначенный для работы на других платформах в наших пакетах не нужен (а иногда бывает и вреден, поскольку даже «мёртвый» код может порождать зависимости, которые в некоторых случаях превращаются в unmet’ы).

Также мы можем превратить опциональную зависимость в явную. Пример:

begin
  require 'iconv'
rescue LoadError
  module Iconv
    # Далее следует некоторый код, который в результате предоставляет API
    # похожий на API модуля iconv, возможно урезанный функционально.
  end
end

В данном случае всю эту сложную конструкцию можно заменить на одну строку require 'iconv'. Как бонус мы получаем зависимость на ruby(iconv) и полную функциональность данного модуля.

Реальные примеры можно посмотреть в пакете ruby-gettext.

Отрываем rubygems

В реальной жизни можно встретить множество вариантов использования rubygems. Вот самые распространённые:

Пример 1:

require 'rubygems'
require 'some/module'
require 'some/other/module'

Пример 2:

begin
  require 'rubygems'
  require 'some/module'
  require 'some/other/module'
rescue LoadError
  require 'some/module'
  require 'some/other/module'
end

Пример 3:

begin
  require 'some/module'
  require 'some/other/module'
rescue LoadError
  require 'rubygems'
  require 'some/module'
  require 'some/other/module'
end

Все эти три примера можно привести к одному виду:

require 'some/module'
require 'some/other/module'

Этим мы убираем зависимость на rubygems и размаскируем скрытые зависимости. Таким образом наш модуль автоматически получает зависимсти на ruby(some/module) и ruby(some/other/module).

Файлы специального вида (темплейты и плагины)

Очень часто модуль (или приложение) носит с собой какие-то данные, которые обычно находятся в каталоге с gem’ом. Выглядит это приблизительно вот так:

  def mock_framework_path(framework_name)
    File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "plugins", "mock_frameworks", framework_name))
  end

В таком случае этот каталог (в нашем примере «plugins») помещается в /usr/share/ИМЯМОДУЛЯ а код заменяется на такой:

  def mock_framework_path(framework_name)
    File.expand_path(File.join("/usr/share/ИМЯМОДУЛЯ/plugins/mock_frameworks", framework_name))
  end

Потрошим новый пакет

При сборке нового пакета следует пробежать глазами его код на тему вышеописанных конструкций. Начать можно с grep -r по каталогам lib/ и bin/ по паттернам '__FILE__', 'ubygems', 'LoadError', '\$:', '\$LOAD_PATH'.