From Fedora Project Wiki
Line 52: Line 52:
 
The Ruby library files in a pure Ruby package '''must''' be placed into <code>%{ruby_vendorlibdir}</code>. The specfile '''must''' use this macro.
 
The Ruby library files in a pure Ruby package '''must''' be placed into <code>%{ruby_vendorlibdir}</code>. The specfile '''must''' use this macro.
  
{{Anchor|ruby_sitearch}}
+
{{Anchor|ruby_vendorarchdir}}
  
 
=== Ruby packages with binary content/shared libraries ===
 
=== Ruby packages with binary content/shared libraries ===
Line 77: Line 77:
 
Both RPM's and Gems use similar terminology --- there are specfiles, package names, dependencies etc. for both. To keep confusion to a minimum, whenever the term from the Gem world is meant, it is explicitly called the 'Gem specification'. An unqualified 'package' in the following always means an RPM.
 
Both RPM's and Gems use similar terminology --- there are specfiles, package names, dependencies etc. for both. To keep confusion to a minimum, whenever the term from the Gem world is meant, it is explicitly called the 'Gem specification'. An unqualified 'package' in the following always means an RPM.
  
* Spec files must contain definition of <code>%{gem_name}</code>, which is the name from the Gem's specification.
+
* Spec files '''must''' contain definition of <code>%{gem_name}</code>, which is the name from the Gem's specification.
 
* Packages that contain Ruby Gems '''must''' be called <code>rubygem-%{gem_name}</code>.
 
* Packages that contain Ruby Gems '''must''' be called <code>rubygem-%{gem_name}</code>.
 
* The <code>Source</code> of the package '''must''' be the full URL to the released Gem archive; the version of the package '''must''' be the Gem's version
 
* The <code>Source</code> of the package '''must''' be the full URL to the released Gem archive; the version of the package '''must''' be the Gem's version
Line 94: Line 94:
 
* The <code>%build</code> section of the specfile '''should''' be empty.
 
* The <code>%build</code> section of the specfile '''should''' be empty.
 
* The Gem '''must''' be installed into <code>%{gem_dir}</code>.
 
* The Gem '''must''' be installed into <code>%{gem_dir}</code>.
* If the Gem has a binary extension, it must be installed under <code>%{gem_extdir}</code> directory.
 
 
* The package '''must''' own the following files and directories:
 
* The package '''must''' own the following files and directories:
 
<pre>
 
<pre>
Line 102: Line 101:
 
%doc %{gem_docdir}
 
%doc %{gem_docdir}
 
</pre>
 
</pre>
* If the Gem only contains pure Ruby code, it '''must''' be marked as <code>BuildArch: noarch</code>. If the Gem contains binary content (e.g., for a database driver), it '''must''' be marked as architecture specific, and all architecture specific content '''must''' be moved from the <code>%{gem_instdir}</code> to the <code>%{gem_extdir}</code> during <code>%install</code>
+
* If the Gem only contains pure Ruby code, it '''must''' be marked as <code>BuildArch: noarch</code>. If the Gem contains binary content (e.g., for a database driver), it '''must''' be marked as architecture specific.
  
 
=== Ruby Gem with extension libraries written in C ===
 
=== Ruby Gem with extension libraries written in C ===
Line 108: Line 107:
 
When a Ruby Gem contains extension libraries written in C,
 
When a Ruby Gem contains extension libraries written in C,
 
* First, <code>%prep</code> stage '''must''' contain <code>%setup -q -c -T</code> to create the directory where C libraries are compiled.
 
* First, <code>%prep</code> stage '''must''' contain <code>%setup -q -c -T</code> to create the directory where C libraries are compiled.
* Then at %build stage the Ruby Gem '''must''' be installed under the directory created at %prep stage to get C libraries compiled under there.
+
* Then at <code>%build</code> stage the Ruby Gem '''must''' be installed under the directory created at <code>%prep</code> stage to get C libraries compiled under there.
* When <code>gem install</code> is used to install Gem file, using <code>-V</code> option is '''recommend''' to check if <code>CFLAGS</code> is correctly honored.
+
* During the <code>%install</code> section all architecture specific content '''must''' be moved from the <code>%{gem_instdir}</code> to the <code>%{gem_extdir}</code>.
* Finally at <code>%install</code> stage the whole tree under the directory created at %prep stage '''should''' be '''copied''' (not moved) to under <code>%{buildroot}%{gemdir}</code>.
+
** The package then must own <code>%{gem_extdir}</code> directory.
** When all tree under the directory created at %prep stage is moved to under <code>%{buildroot}</code>, <code>find_debuginfo.sh</code> will complain that the corresponding source files are missing.
+
* When <code>gem install</code> is used to install Gem file, using <code>-V</code> option is '''recommended''' to check if <code>CFLAGS</code> is correctly honored.
* Installed C codes (usually under <code>%{geminstdir}/etc</code>) '''may''' be removed even if <code>gem contents %{gemname}</code> reports that installed C codes should be found there.
+
* Installed C codes (usually under <code>%{gem_instdir}/ext</code>) '''may''' be removed even if <code>gem contents %{gem_name}</code> reports that installed C codes should be found there.
  
==== Note ====
+
=== Packaging for Gem and non-Gem use ===
The current guideline
 
<pre>
 
If the Gem contains binary content (e.g., for a database driver), it must be marked
 
as architecture specific, and all architecture specific content must be moved
 
from the %{gemdir} to the [#ruby_sitearch %{ruby_sitearch} directory] during %install
 
</pre>
 
must still apply.
 
  
=== Packaging for Gem and non-Gem use ===
+
{{admon/note|Legacy|Packaging for non-Gem use is no longer needed, as Ruby requires Rubygems by default.}}
  
If the same Ruby library is to be packaged for use as a Gem and as a straight Ruby library without Gem support, it '''must''' be packaged as a Gem first. To make it available to code that does not use Ruby Gems, a subpackage called <code>ruby-%{gemname}</code> '''must''' be created in the <code>rubygem-%{gemname}</code> package such that
+
If the same Ruby library is to be packaged for use as a Gem and as a straight Ruby library without Gem support, it '''must''' be packaged as a Gem first. To make it available to code that does not use Ruby Gems, a subpackage called <code>ruby-%{gem_name}</code> '''must''' be created in the <code>rubygem-%{gem_name}</code> package such that
  
* The subpackage '''must''' require <code>rubygem(%gemname) = %version</code>
+
* The subpackage '''must''' require <code>rubygem(%gem_name) = %version</code>
* The subpackage '''must''' provide <code>ruby(LIBRARY) = %version</code> where LIBRARY is the same  as in the [#ruby_naming general Ruby guideline]  above.
+
* The subpackage '''must''' provide <code>ruby(LIBRARY) = %{version}</code> where LIBRARY is the same  as in the [#ruby_naming general Ruby guideline]  above.
* All the toplevel library files of the Gem must be symlinked into <code>ruby_sitelib</code>.
+
* All the toplevel library files of the Gem must be symlinked into <code>%{ruby_vendorlibdir}</code>.
 
* The subpackage '''must''' own these symbolic links.
 
* The subpackage '''must''' own these symbolic links.
  
Line 140: Line 132:
 
...
 
...
 
%files -n ruby-activesupport
 
%files -n ruby-activesupport
%{ruby_sitelib}/active_support
+
%{ruby_vendorlibdir}/active_support
%{ruby_sitelib}/active_support.rb
+
%{ruby_vendorlibdir}/active_support.rb
 +
</pre>
 +
 
 +
=== Running tests ===
 +
 
 +
If there are tests available for the package (even separately, for example not included in the Gem, but available in the upstream repository), you '''must''' run them. The tests '''should not''' be run using Rake - Rake almost always draws in some unnecessary dependencies like hoe or gemcutter.
 +
 
 +
To run the tests using MiniTest (which is included in Ruby), you can usually use something like
 +
<pre>
 +
testrb -Ilib test
 +
</pre>
 +
 
 +
To run the tests using Test::Unit (you must use <code>BuildRequires: rubygem(test-unit)</code>), you can usually use something like
 +
<pre>
 +
testrb2 -Ilib test
 +
</pre>
 +
 
 +
To run the tests using RSpec >= 2 (you must use <code>BuildRequires: rubygem(rspec-core)</code>), you can usually use something like
 +
<pre>
 +
rspec -Ilib test
 
</pre>
 
</pre>
 +
  
 
=== Tips for Packagers ===
 
=== Tips for Packagers ===
  
 
Gems carry a lot of metadata; [http://rubyforge.org/projects/gem2rpm/ gem2rpm]  is a tool to generate an initial specfile and/or source RPM from a Gem. The generated specfile still needs some hand-editing, but conforms to 90% with this guideline.
 
Gems carry a lot of metadata; [http://rubyforge.org/projects/gem2rpm/ gem2rpm]  is a tool to generate an initial specfile and/or source RPM from a Gem. The generated specfile still needs some hand-editing, but conforms to 90% with this guideline.

Revision as of 08:32, 20 December 2011

Ruby Packaging Guidelines

Each Ruby package must indicate the Ruby ABI version it depends on with a line like

Requires: ruby(abi) = 1.9.1

Ruby packages must require ruby at build time with a BuildRequires: ruby, and may indicate the minimal ruby version they need for building.

Naming Guidelines

Note.png These naming guidelines only apply to ruby packages whose main purpose is providing a Ruby library; packages that mainly provide user-level tools that happen to be written in Ruby do not need to follow these naming guidelines, and should follow the general NamingGuidelines instead.

The name of a ruby extension/library package must be of the form ruby-UPSTREAM. If the upstream name UPSTREAM contains ruby, that should be dropped from the name. For example, the SQLite database driver for ruby is called sqlite3-ruby. The corresponding Fedora package should be called ruby-sqlite3, and not ruby-sqlite3-ruby.

A ruby extension/library package must indicate what it provides with a Provides: ruby(LIBRARY) = VERSION declaration in the spec file. The string LIBRARY should be the same as what is used in the require statement in a Ruby script that uses the library. The VERSION should be the upstream version of the library, as long as upstream follows a sane versioning scheme. For example, a Ruby script using the SQLite database driver will include it with require 'sqlite3'. The specfile for the corresponding Fedora package must contain a line Provides: ruby(sqlite3) = 1.1.0, assuming the package contains version 1.1.0 of the library.

Build Architecture and File Placement

The following only affects the files that the package installs into %{_libdir}/ruby/vendor_ruby (architecture specific) and %{_datadir}/ruby/vendor_ruby (architecture independent), i.e., Ruby library files. All other files in a Ruby package must adhere to the general Fedora Extras packaging conventions.

All non-gem ruby packages must require ruby-devel package at build time with a BuildRequires: ruby-devel.

align="bottom" style="color:#e76700;"
Macro Expanded path Usage
%{ruby_vendorarchdir} /usr/lib{64}/ruby/vendor_ruby Place for architecture specific (e.g. *.so) files.
%{ruby_vendorlibdir} /usr/share/ruby/vendor_ruby Place for architecture independent (e.g. *.rb) files.
%{ruby_sitearchdir} /usr/local/lib64/ruby/vendor_ruby Place for local architecture specific (e.g. *.so) files.
%{ruby_sitelibdir} /usr/local/share/ruby/vendor_ruby Place for local architecture independent (e.g. *.rb) files.


Warning.png
Site versus Vendor
Do not use %{ruby_sitelibdir} and %{ruby_sitearchdir} for packaging, as they are under local. Use %{ruby_vendorlibdir} and %{ruby_vendorarchdir}.

Pure Ruby packages

Pure Ruby packages must be built as noarch packages.

The Ruby library files in a pure Ruby package must be placed into %{ruby_vendorlibdir}. The specfile must use this macro.

Ruby packages with binary content/shared libraries

For packages with binary content, e.g., database drivers or any other Ruby bindings to C libraries, the package must be architecture specific.

The binary files in a Ruby package with binary content must be placed into %{ruby_vendorarchdir}. The Ruby files in such a package should be placed into %{ruby_vendorlibdir}. The specfile must use that path.

For packages which create C shared libraries using extconf.rb

export CONFIGURE_ARGS="--with-cflags='%{optflags}'"

should be used to pass CFLAGS to Makefile correctly. Also, to place the files to the correct folders during build, pass --vendor to extconf.rb like this:

extconf.rb --vendor

This applies to Ruby Gems, too.

Ruby Gems

Ruby Gems are Ruby's own packaging format. Gems contain a lot of the same metadata that RPM's need, making fairly smooth interoperation between RPM and Gems possible. This guideline ensures that Gems are packaged as RPM's in a way that ensures (1) that such RPM's fit cleanly with the rest of the distribution and (2) make it possible for the end user to satisfy dependencies of a Gem by installing the appropriate RPM-packaged Gem.

Both RPM's and Gems use similar terminology --- there are specfiles, package names, dependencies etc. for both. To keep confusion to a minimum, whenever the term from the Gem world is meant, it is explicitly called the 'Gem specification'. An unqualified 'package' in the following always means an RPM.

  • Spec files must contain definition of %{gem_name}, which is the name from the Gem's specification.
  • Packages that contain Ruby Gems must be called rubygem-%{gem_name}.
  • The Source of the package must be the full URL to the released Gem archive; the version of the package must be the Gem's version
  • The package must have a Requires on ruby(rubygems) and a BuildRequires on rubygems-devel
  • The package must provide rubygem(%{gem_name}) where gem_name is the name from the Gem's specification. For every dependency on a Gem named gemdep, the package must contain a Requires on rubygem(%{gemdep}) with the same version constraints as the Gem
  • The %prep section should contain the local gem install similar to this (assuming that the %{gem_name}-%{version}.gem is SOURCE0):
gem install \
	-V \
	--local \
        --install-dir .%{gem_dir} \
	--force \
	--rdoc \
	%{SOURCE0}
  • The %build section of the specfile should be empty.
  • The Gem must be installed into %{gem_dir}.
  • The package must own the following files and directories:
%{gem_instdir}
%{gem_cache}
%{gem_spec}
%doc %{gem_docdir}
  • If the Gem only contains pure Ruby code, it must be marked as BuildArch: noarch. If the Gem contains binary content (e.g., for a database driver), it must be marked as architecture specific.

Ruby Gem with extension libraries written in C

When a Ruby Gem contains extension libraries written in C,

  • First, %prep stage must contain %setup -q -c -T to create the directory where C libraries are compiled.
  • Then at %build stage the Ruby Gem must be installed under the directory created at %prep stage to get C libraries compiled under there.
  • During the %install section all architecture specific content must be moved from the %{gem_instdir} to the %{gem_extdir}.
    • The package then must own %{gem_extdir} directory.
  • When gem install is used to install Gem file, using -V option is recommended to check if CFLAGS is correctly honored.
  • Installed C codes (usually under %{gem_instdir}/ext) may be removed even if gem contents %{gem_name} reports that installed C codes should be found there.

Packaging for Gem and non-Gem use

Note.png
Legacy
Packaging for non-Gem use is no longer needed, as Ruby requires Rubygems by default.

If the same Ruby library is to be packaged for use as a Gem and as a straight Ruby library without Gem support, it must be packaged as a Gem first. To make it available to code that does not use Ruby Gems, a subpackage called ruby-%{gem_name} must be created in the rubygem-%{gem_name} package such that

  • The subpackage must require rubygem(%gem_name) = %version
  • The subpackage must provide ruby(LIBRARY) = %{version} where LIBRARY is the same as in the [#ruby_naming general Ruby guideline] above.
  • All the toplevel library files of the Gem must be symlinked into %{ruby_vendorlibdir}.
  • The subpackage must own these symbolic links.

As an example, for activesupport, the rubygem-activesupport package would have a subpackge ruby-activesupport:

%package -n ruby-activesupport
...
Requires: rubygem(activesupport) = %version
Provides: ruby(active_support) = %version  # The underscore is intentional, not a typo
...
%files -n ruby-activesupport
%{ruby_vendorlibdir}/active_support
%{ruby_vendorlibdir}/active_support.rb

Running tests

If there are tests available for the package (even separately, for example not included in the Gem, but available in the upstream repository), you must run them. The tests should not be run using Rake - Rake almost always draws in some unnecessary dependencies like hoe or gemcutter.

To run the tests using MiniTest (which is included in Ruby), you can usually use something like

testrb -Ilib test

To run the tests using Test::Unit (you must use BuildRequires: rubygem(test-unit)), you can usually use something like

testrb2 -Ilib test

To run the tests using RSpec >= 2 (you must use BuildRequires: rubygem(rspec-core)), you can usually use something like

rspec -Ilib test


Tips for Packagers

Gems carry a lot of metadata; gem2rpm is a tool to generate an initial specfile and/or source RPM from a Gem. The generated specfile still needs some hand-editing, but conforms to 90% with this guideline.